Docs
Errors
What error codes does the Onrup API return?
Errors return a stable envelope with a namespaced code, a human message and optional detail. Branch on the code, never on the message — codes are part of the contract and messages are not.
The envelope
Codes are namespaced by the area they come from — auth, dataset, run, deployment, billing, quota, keys — and they are stable. Messages are written for humans and may be reworded; anything branching on a message will eventually break.
{
"error": {
"code": "billing.spend_limit_exceeded",
"message": "Estimated cost of $4.20 exceeds available headroom of $1.15.",
"detail": {
"estimated_cents": 420,
"available_cents": 115
}
}
}Which are worth retrying
| Situation | Retry? |
|---|---|
| 429 rate limited | Yes — after the interval in Retry-After, with backoff and jitter. |
| 503 capacity unavailable | Yes — Retry-After indicates when. Consider a different GPU class. |
| 5xx server error | Yes, with backoff. Use an idempotency key so a retry cannot duplicate work. |
| 402 spend limit exceeded | No. Raise the limit or wait for reservations to settle. |
| 422 validation failed | No. The report says what to fix. |
| 409 invalid state | No. Read the current state first; the transition is not legal from here. |
Use idempotency keys on mutations
Any call that starts work should carry an idempotency key. Without one, a client that times out cannot safely retry, because the first request may have succeeded and a second would start a second run.
Every code
| Code | HTTP | Meaning |
|---|---|---|
| auth.invalid_token | 401 | The bearer token is missing, malformed or expired. |
| auth.insufficient_scope | 403 | The key is valid but lacks the scope this route requires. |
| billing.compute_not_entitled | 403 | The current plan does not permit leasing compute. |
| billing.subscription_not_current | 403 | The subscription is past due; new work is blocked until it is settled. |
| billing.spend_limit_exceeded | 402 | The estimated cost would breach the spend limit, counting open reservations. |
| billing.invalid_estimate | 400 | The cost of this job could not be estimated, so it was not started. |
| dataset.validation_failed | 422 | The uploaded data did not pass validation. The report says why. |
| dataset.unsupported_format | 400 | The source format is not one of the accepted shapes. |
| run.invalid_state | 409 | The run is not in a state where this transition is legal. |
| run.template_incompatible | 400 | The template does not support this model, objective or dataset shape. |
| deployment.capacity_unavailable | 503 | No capacity in the requested GPU class right now. Retry-After indicates when to try again. |
| quota.exceeded | 409 | A concurrency or storage ceiling was reached. |
| keys.scope_invalid | 400 | An unknown scope was requested when creating a key. |
Start with the free tier
A magic link creates your account, your tenant and your first API key. No card until you ask for compute.