JavaScript library
npm install @spavik/clientimport { Spavik } from '@spavik/client';
const spavik = new Spavik(); // reads SPAVIK_API_KEY
const model = await spavik.train('churn.csv', { target: 'churn' });
console.log(await model.predict({ plan: 'pro', seats: 12 }));No production dependency. Node 18 or later, and edge runtimes that provide fetch and WebCrypto. ESM and CommonJS.
The operations
| Call | Cost |
|---|---|
spavik.validate(data, { target }) | free |
spavik.train(data, { target }) | free |
spavik.backtest(data, { target, horizon }) | free |
spavik.forecast(data, { target, horizon }) | horizon x series |
spavik.models() | free |
spavik.usage() | free |
model.predict(rows) | the engine's credits per row, 1 on the default engine |
model.submitOutcomes(outcomes) | free |
model.performance(days) | free |
model.refresh() | free |
model.predictions() | free |
model.archive(), spavik.archive(modelId) | free |
spavik.restore(modelId) | free |
models() is an async iterator; models({ status: 'archived' }) lists what was set aside. A model knows its engine, its target and its features, the columns predict expects.
for await (const model of spavik.models()) console.log(model.id, model.name, model.features);validate() and backtest() say, for free, whether a table is worth training on and whether a series is worth forecasting, each with a verdict and the first thing to fix. archive() frees a model's slot in the plan without losing anything; spavik.restore(modelId) brings it back, by identifier. Same behaviour and same fields as the Python library.
Types
TypeScript types ship with the package. Autocompletion covers every operation, its options and the error classes, with no configuration.
The same refusals as Python
What the Python library refuses, this one refuses too, with the same message and at the same moment. A conformance suite replays one scenario across both, and across the MCP server.
await spavik.train(eightRows, { target: 'churn' });
// SpavikDataError: training needs at least 10 rows, 8 provided. Nothing was sent.Errors
import { SpavikCreditsExhausted } from '@spavik/client';
try {
await model.predict(rows);
} catch (exc) {
if (exc instanceof SpavikCreditsExhausted) {
console.error(exc.code, exc.balance, exc.requestId);
}
}Same classes as on the Python side, under the same names.
Webhooks
import { verifier } from '@spavik/client';
const event = await verifier(rawBody, request.headers, secret);Express:
app.post('/webhooks/spavik', express.raw({ type: 'application/json' }), async (req, res) => {
try {
await verifier(req.body, req.headers, process.env.SPAVIK_WEBHOOK_SECRET);
res.sendStatus(200);
} catch {
res.sendStatus(400);
}
});Hono:
app.post('/webhooks/spavik', async (c) => {
const body = await c.req.arrayBuffer();
await verifier(body, c.req.raw.headers, c.env.SPAVIK_WEBHOOK_SECRET);
return c.body(null, 200);
});Retries
new Spavik({ maxRetries: 1 }); // no retries
new Spavik({ backoff: (n) => n * 1000 }); // linear backoffDebugging
SPAVIK_LOG=debug node my-script.js