Reference
Errors and retries
Every error is an HTTP status and one error object. Branch on its code, show its message, quote its request_id to support.
Error format
400 Bad Request
{
"error": {
"code": "invalid_request",
"message": "Invalid request body.",
"request_id": "req_0ee311b4334e4b118a94c7d1c48577fd",
"category": "validation",
"retryable": false,
"retry_after_seconds": null,
"next_action": "fix_input",
"details": {
"errors": [
{
"path": "prompt",
"loc": [
"prompt"
],
"message": "must have required property 'prompt'",
"type": "required"
}
]
}
}
}| Field | Meaning |
|---|---|
code | Stable and machine-readable. Branch on this, not on the message. |
message | For people. |
request_id | Also in the x-sume-request-id header. |
retryable | true when the same request can succeed later. |
retry_after_seconds | How long to wait first, when known; also the retry-after header. |
next_action | fix_input, authenticate, retry, inspect_events… |
details | Extra facts, such as the failing fields in details.errors[]. |
Codes
| Status | code | Meaning | Retry |
|---|---|---|---|
| 400 | bad_request | The body is not valid JSON. | No, fix the body |
| 400 | invalid_request | A field is missing or wrong; details.errors[] names it. | No, fix the field |
| 401 | unauthorized | No key, or the key is wrong or revoked. | No |
| 402 | insufficient_credits | The balance cannot cover the price; details has required_usd and available_usd. | After a top-up |
| 402 | organization_wallet_not_provisioned | A team workspace has no funded balance yet. | After a top-up |
| 403 | insufficient_scope | The key lacks the scope this route needs. | No |
| 404 | not_found | No such job or model in your workspace. | No |
| 409 | idempotency_conflict | The Idempotency-Key was used for a different request. | No, use a new key |
| 409 | job_not_completed | You read a result before the job finished. | Yes, poll first |
| 409 | job_not_cancelable | Generation has started. | No |
| 413 | payload_too_large | The request body is too big. | No |
| 429 | queue_full | Your workspace has as many jobs in flight as it may. | After a job ends |
| 429 | rate_limited | Too many requests for this key in the window. | Yes, after retry-after |
| 500 | internal_error | A fault on Sume's side. | Yes, with backoff |
| 503 | database_busy | A short overload. | Yes, after retry-after |
Retrying safely
- Retry reads (status, result, list) after a network error, a
429or a5xx, with exponential backoff and jitter. Honourretry-after. - Retry a generate request only with the same
Idempotency-Key. - Do not retry
401,403,404or a400you have not fixed.
Idempotency
A network error after a submit leaves you unsure whether the job exists. Send an Idempotency-Key on every generate request and reuse it on retry:
Header
Idempotency-Key: 9816bc88-9791-43a1-86c2-876dc7c544e8- 1–255 printable ASCII characters. A UUID per request is the simple choice.
- The same key with the same body returns the original job with
idempotency_hit: true, charged once. - The same key with a different body answers
409 idempotency_conflict.
Failed jobs
A job that ends failed is not an HTTP error. The submit succeeded; the job's error object (same fields as above) says what went wrong, and its price is refunded. A model refusing a prompt on content grounds reports public_reason: "content_policy_rejected".