Skip to content

Errors and limits

Every error uses one envelope: an error object with a coarse type, a specific code, a human-readable message, an optional param, and the request_id that also appears in the X-Request-Id response header. Branch on type for control flow and on code for detail; never parse message.

error response
HTTP/1.1 402 Payment Required
Content-Type: application/json
X-Request-Id: req_3f9c2a1b7e6d5c4b3a2f1e0d

{
  "error": {
    "type": "insufficient_balance",
    "code": "insufficient_balance",
    "message": "Insufficient balance: this request costs $0.0250 but your balance is $0.0100. Top up in the console.",
    "request_id": "req_3f9c2a1b7e6d5c4b3a2f1e0d"
  }
}

Types and HTTP status

typeHTTPMeaning
invalid_request_error400Malformed or invalid body/query. `param` names the offending field when known.
authentication_error401Missing, malformed, revoked or expired API key.
insufficient_balance402Wallet cannot cover the quoted price. Top up or enable auto-recharge.
permission_error403Account is paused, suspended or closed.
not_found404No such job / model / endpoint.
idempotency_conflict409Idempotency-Key reused with a different request body.
content_blocked422Prompt, input image or generated output failed the content policy. Refunded.
rate_limit_error429Per-key request rate or per-account concurrency limit exceeded. See Retry-After.
capacity_error503Temporarily out of GPU capacity or moderation provider unavailable. Retry with backoff.
api_error500Unexpected server error. Quote the request id to support.

Common codes

codeMeaning
invalid_body / invalid_json / invalid_content_typeBody failed validation; must be JSON.
model_unavailableThe model id is unknown, disabled or does not support this operation.
invalid_api_keyBearer token missing or not recognized.
insufficient_balanceSee 402 above.
account_paused / account_suspended / account_closedAccount status prevents new jobs.
content_blocked_promptPrompt or negative prompt violates the content policy.
content_blocked_inputAn input image violates the content policy.
content_blocked_outputThe generated output failed the output gate; deleted, refunded, strike recorded.
rate_limitedToken bucket exhausted for this key (RateLimit-* headers show the budget).
concurrency_limitToo many in-flight jobs for the account (default 5).
capacityNo GPU capacity right now; retry after Retry-After seconds.

Rate limits

Each API key has a token bucket sized to the account’s requests-per-minute limit (default 60, refilling continuously). Every response includes RateLimit-Limit and RateLimit-Remaining; a 429 includes Retry-After in seconds. Separately, each account may have at most a set number of jobs in flight (max_concurrent_jobs, default 5) — exceeding it returns 429 with code = concurrency_limit. Both limits are visible on GET /v1/account and can be raised on request.

Idempotency

Send an Idempotency-Key header (any string up to 200 characters, unique per request) on POSTs. If a request with the same key and body was already accepted, the original job is returned with Idempotency-Replayed: true and you are not charged twice. Reusing a key with a different body returns 409 idempotency_conflict. Keys are scoped to your account and remembered for 24 hours.

Retry guidance

  • 429 and 503: retry with exponential backoff starting at Retry-After.
  • 5xx on a POST: retry with the same Idempotency-Key so a job is never created twice.
  • 402: stop and top up (or turn on auto-recharge in Billing).
  • 422 content_blocked: do not retry the same content; see the content policy.