Spavik
GuidesGet started

Costs and credits

Understand prediction costs and read the available balance.

What is billed

Only predictions and forecasts consume credits. Training, evaluation, backtesting, reported outcomes, model refreshes, archiving, restoring and reads are free.

OperationCost
POST /v1/models, training0 credits
POST /v1/datasets/evaluate0 credits
POST /v1/models/{id}/predictScored rows × the model engine's credits per row
POST /v1/forecasthorizon × the serving engine's credits, per call, all series included
POST /v1/forecast/backtest0 credits
POST /v1/models/{id}/outcomes0 credits
POST /v1/models/{id}/refresh0 credits
Reads0 credits

For forecasting, horizon is the number of future steps requested for each series. On an engine charging one credit, one series with 56 historical observations and a horizon of 7 costs 7 credits. Five series with that horizon in one call also cost 7 credits, while producing 35 forecast values. Five separate calls at horizon 7 cost 35 credits in total. Historical input rows and returned quantiles do not multiply the charge. Use item_id to identify separate series (itemId in JavaScript).

For model predictions, read GET /v1/engines for the credits per row of the engine serving your model. A prediction does not necessarily cost one credit.

Read the available balance

GET /v1/usage returns predictions_remaining: the remaining monthly allowance plus the credit balance, counted in credits. The monthly allowance is used first, followed by the credit balance. The Free plan uses signup credits and has no monthly allowance.

Despite its name, this number counts credits, not rows: on an engine charging two credits per row, it scores half as many rows.

usage = spavik.usage()
print(usage["predictions_remaining"])

Billable responses can include X-Spavik-Predictions-Remaining, the same number after the call. The SDKs expose it as result.predictions_remaining in Python and result.predictionsRemaining in JavaScript. The header can be absent, including on a cached idempotent replay, so None or null means unknown, never unlimited. The API does not return the amount charged: the SDK's result.cost is 0 for a free operation and None or null for a billed one.

Balance responses are snapshots, and usage reports may be cached. Other calls can consume credits between reading a balance and submitting your next request.

When usage returns null

In a successful GET /v1/usage response, unlimited_usage: true and an explicit predictions_remaining: null denote an account without an enforced prediction credit limit. The current API applies this behavior to Enterprise accounts. It does not remove model, input-size or other technical limits.

This meaning is specific to that field and response. A missing field or header means availability is unknown. included_units_per_month: null does not imply unlimited usage: the Free plan also has no monthly allowance and spends its finite credit balance.

When the balance runs out

If available credits cannot cover an operation, the API returns 402 CREDITS_EXHAUSTED. These examples make a billable prediction and handle insufficient credits. Use model and rows from your application, or set MODEL_ID and prepare rows.json for REST. Inspect the error code and human-readable detail; the current API does not provide separate numeric balance and required fields in this error.

from spavik import SpavikCreditsExhausted

try:
    model.predict(rows)
except SpavikCreditsExhausted as exc:
    print(exc.code, exc.detail, exc.request_id)

Retry with idempotency

Send a unique Idempotency-Key on the original billable request and reuse it with the same endpoint and payload for retries. A stored successful response is replayed without another computation or charge while its record is retained. The default retention is 24 hours from the original request. After expiration, the same key can execute and charge again.

The SDKs generate a key per call and keep it during their automatic retries. Calling predict or forecast again creates a new logical request with a new key. It is not a replay of the previous SDK call.

ResponseWhat to do
REQUEST_IN_PROGRESSWait as directed by Retry-After; retain the original key and payload.
IDEMPOTENCY_KEY_REUSEDThe key was used with different input. Check the original request.
REQUEST_INTERRUPTEDThe outcome is uncertain. Stop automatic retries and inspect the request log or contact support.
IDEMPOTENCY_RESPONSE_UNAVAILABLEThe operation may have completed but its response could not be saved. Contact support with X-Spavik-Request-Id.

Do not create a new key to force execution after an uncertain outcome. An error or lost response does not prove that no charge occurred. Idempotency is protection for retries under these conditions, not a permanent guarantee against duplicate charges. See API conventions.

How is this guide?

Last updated on

On this page