API reference

One endpoint. Nine quantiles.

Authenticate with an API key, send observations, receive a median forecast and quantile bands. Two endpoints, one auth header, one error envelope.

Working in n8n? The VecTime node does all of this for you — rows in, forecast rows out, no HTTP node to wire up.

Authentication

Send your key as a bearer token. X-API-Key is accepted as an alternative for clients that reserve the Authorization header.
http
Authorization: Bearer vct_live_xxxxxxxxxxxxxxxxxxxxxxxx
# or
X-API-Key: vct_live_xxxxxxxxxxxxxxxxxxxxxxxx
Keys are stored as a peppered HMAC — we cannot recover a lost key, only issue a new one. Treat vct_live_* keys as production credentials and keep them server-side.
POST

/v1/forecast

Forecast one or many series in a single model pass.
FieldTypeRequiredDescription
seriesnumber[] | number[][]YesThe historical observations, oldest first, evenly spaced. Pass a flat array for one series or an array of arrays to batch. Each series needs at least 2 points; anything longer than your plan's context window is rejected rather than silently truncated.
horizonintegerYesHow many future steps to predict. Capped by your plan's max horizon.
quantilesbooleanNoReturn the nine decile quantiles alongside the median. Defaults to true on plans that include quantiles.
Response quantile keys are q10q90 in steps of 10, where q50 equals point. mean is the distribution mean, which differs from the median on skewed series.

Examples

Python
python
import os, requests
resp = requests.post(
"https://api.vectime.cloud/v1/forecast",
headers={"Authorization": f"Bearer {os.environ['VECTIME_API_KEY']}"},
json={
# A single series, or a list of series to batch them in one call.
"series": [[412, 430, 455, 471, 502, 538, 561, 590]],
"horizon": 12,
"quantiles": True,
},
timeout=120,
)
resp.raise_for_status()
out = resp.json()
median = out["forecasts"][0]["point"]
p10 = out["forecasts"][0]["quantiles"]["q10"]
p90 = out["forecasts"][0]["quantiles"]["q90"]
TypeScript
typescript
const res = await fetch("https://api.vectime.cloud/v1/forecast", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VECTIME_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
series: [[412, 430, 455, 471, 502, 538, 561, 590]],
horizon: 12,
quantiles: true,
}),
});
if (res.status === 429) {
// Rate limited: honour the server's own backoff hint.
const wait = Number(res.headers.get("Retry-After") ?? 1);
await new Promise((r) => setTimeout(r, wait * 1000));
}
const { forecasts } = await res.json();
GET

/v1/models

Reports the active model plus the ceilings your plan applies, so a client can discover limits instead of hard-coding them.

Rate limits and quota

Limits are enforced per API key with a token bucket: you may spike up to your plan's burst size, then settle at the sustained per-minute rate. Every response carries the current state.
http
RateLimit-Limit: 60 # requests per minute on this plan
RateLimit-Remaining: 41 # tokens left in the bucket right now
RateLimit-Reset: 19 # seconds until the bucket is full again
X-Quota-Limit: 50000 # monthly call allowance
X-Quota-Used: 12043 # calls consumed this UTC month
Retry-After: 2 # only on 429

Errors

Every failure uses the same envelope.
json
{
"error": {
"code": "horizon_limit_exceeded",
"message": "horizon 500 exceeds your plan's maximum of 128",
"details": { "max_horizon": 128, "plan": "starter" }
}
}
StatusCodeMeaning
401missing_api_key / invalid_api_key / revoked_api_keyThe key is absent, unknown, or revoked. Not retryable.
402quota_exceededThe monthly call quota is spent. Upgrade, or wait for the UTC month to roll over.
403account_suspendedThe account is suspended. Contact support.
422invalid_requestThe payload is malformed — a non-finite value, an empty series, horizon < 1.
422horizon_limit_exceeded / context_limit_exceeded / series_limit_exceededThe request is larger than your plan allows. `details` carries the actual ceiling.
429rate_limit_exceededToo many requests per minute. Retry after the seconds given in Retry-After.
503model_unavailableThe model is still warming up. Retryable within a few seconds.
502inference_failedThe forecasting backend failed. Retry with backoff; the call is not billed.