Get started
Three minutes, from key to first prediction.
1. An API key
API keys carry the sk-spv-api- prefix. Create one from the dashboard, or through the API once signed in.
export SPAVIK_API_KEY="sk-spv-api-..."
export SPAVIK_BASE_URL="https://spavik-gateway-test-bnp1bedb.ew.gateway.dev"The secret is returned once, at creation. It is never shown again.
Environment
The URL above is the test environment. The libraries read it from SPAVIK_BASE_URL, and every example in these docs refers to it.
2. Check the data, then a model
validate says, for free, whether the table holds and what to fix first. Creating a model is then training it: the data goes in the same call.
report = spavik.validate("churn.csv", target="churn")
print(report["trial"]["verdict"]["message"]) # Accuracy of 0.83, against 0.50 for the majority class.from spavik import Spavik
spavik = Spavik()
model = spavik.train("churn.csv", target="churn")
print(model.id)import { Spavik } from '@spavik/client';
const spavik = new Spavik();
const model = await spavik.train('churn.csv', { target: 'churn' });
console.log(model.id);curl -X POST $SPAVIK_BASE_URL/v1/models \
-H "X-API-Key: $SPAVIK_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"target":"churn","data":[{"plan":"pro","seats":12,"churn":0}, ...]}'Training needs at least ten rows and a target that takes at least two values. It costs no credit.
3. Predict
r = model.predict({"plan": "pro", "seats": 12, "tickets_90d": 3})
print(r.lignes[0]) # {'prediction': 0, 'proba_0': 0.87, 'proba_1': 0.13}
print(r.cout, r.solde)One scored row is one credit on the default engine. Each prediction carries a request_id: keep it, it is how you report what really happened.
4. Close the loop
This is what separates a model from a service that improves. Report what actually happened, then fold it in.
model.submit_outcomes([
{"request_id": "1bc55e5c-...", "actual": 1}, # by identifier
{"features": {"plan": "free", "seats": 2}, "actual": 0}, # or by features
])
model.performance(days=30) # the verdict: holding, weak or dropped
model.refresh() # folds the outcomes in, if the model holdsactual carries the value that was actually observed. Each outcome attaches either by the request_id of the original prediction, or by its full features. The library refuses an outcome that has neither, locally, before any call.
Batch your outcomes: one call is one batch, and on a model set to auto-update, a batch triggers an integration.
For a time series
forecast persists nothing: no model, no identifier.
p = spavik.forecast("sales.csv", target="sales", horizon=7)
p.points # [{'date': '2026-08-01', 'sales_prediction': 118.4, 'quantile_0.1': ...}, ...]
p.csv # the CSV as returned by the API
p.cout # 7 creditsThe API returns the forecast as CSV; the library splits it into rows, quantiles included. The series must have at least as many points as the requested horizon, and preferably several times more.
Next
- Authentication, the two ways to identify yourself
- Costs and credits, what is billed and what is not
- Python library
- MCP server, for agents