Errors & responses
Response envelopes, status codes, and how to handle every kind of failure.
Success responses
Successful responses are JSON. Most endpoints wrap their payload in a
data envelope:
{
"data": {
"pipelines": [ … ],
"total_count": 12
}
}Simple acknowledgements use a status envelope instead:
{ "status": "ok" }A few surfaces — inference, deployments — return their payload at the top level for compatibility with standard ML tooling. Each section's examples show the exact shape.
Status codes
| Code | Meaning |
|---|---|
200 | Success. |
201 | Created (e.g. a goal, a workspace). |
202 | Accepted — the work completes asynchronously; poll or subscribe for the result. |
400 | Malformed request: missing field, bad value, missing X-Workspace-Id. |
401 | Authentication failed: missing, invalid, expired, or revoked token. |
402 | Insufficient credits for a metered action. |
403 | Authenticated, but not allowed: workspace access, role permission, token scope, or a plan quota. |
404 | The resource doesn't exist (or isn't visible in this workspace). |
409 | Conflict — most commonly wrong_cell (see Authentication). |
5xx | Something failed on our side. Retry with backoff. |
The error envelope
Every error response — any status 400 and above — carries one canonical
shape:
{
"error": {
"code": "not_found",
"message": "No pipeline with that id in this workspace",
"details": { }
},
"status": "No pipeline with that id in this workspace"
}error.code— a stable, machine-readable code. Branch on this. Some are surface-specific (wrong_cell,insufficient_credits,ALREADY_DEPLOYED); the rest derive from the HTTP status (bad_request,unauthorized,forbidden,not_found,conflict,internal_error, ...).error.message— a human-readable description. Show this.error.details— surface-specific context: balances, ids, listing summaries, redirect URLs. Always an object, possibly empty.status— the same human-readable message, mirrored at the top level as a convenience.
Some surfaces include additional top-level keys next to the envelope
(for example the region redirect keys on wrong_cell); those are always
mirrored inside error.details, so reading the envelope alone is enough.
Credits and quota errors
Two distinct failures look similar but mean different things:
402insufficient credits — the action is metered and your balance can't cover it. Top up or reduce the run's scope.
{
"error": {
"code": "insufficient_credits",
"message": "This run costs 25 credits; balance is 10.",
"details": { "balance": 10 }
},
"status": "This run costs 25 credits; balance is 10."
}403quota reached — your plan caps this object type (goals, pipelines, deployments). Delete something or upgrade.
{
"error": {
"code": "forbidden",
"message": "Discovery goal limit reached. Your plan allows 3 goals per workspace.",
"details": { }
},
"status": "Discovery goal limit reached. Your plan allows 3 goals per workspace."
}See Billing for balances, costs, and per-plan quotas.
Retrying
5xxand network failures: retry with exponential backoff and jitter.409 wrong_cell: retry once againsterror.details.redirect_api_base_url, then cache it.202: not an error — poll the resource, or subscribe over Realtime and let the event come to you.4xxother than the above: don't retry unchanged — the request itself needs fixing.

