Errors
Every error is a JSON envelope with a status, a human-readable message, and a stable machine-readable code where one applies.
The envelope
{
"error": {
"statusCode": 402,
"message": "Insufficient credit",
"code": "insufficient_credit"
}
}message is human-readable; code is stable and machine-readable. 429 responses also carry retryAfterSeconds and a Retry-After header, and 422 responses a details array. Failures raised before body parsing, a missing or invalid key or an oversized body, return a flat {"message", "code"} without the wrapper.
Status codes
| Status | Meaning | What to do |
|---|---|---|
| 400 | The request violates the model’s contract (an unsupported attribute, a value out of bounds). Nothing was charged. | Fix the request; the message names the offending field. |
| 401 | Missing, invalid, revoked or expired API key. | Check the Authorization header and the key’s status. |
402 insufficient_credit | The account’s available credit cannot cover the request’s worst case. | Add credit, or lower max_tokens to shrink the worst case. |
| 403 | The key or account is not allowed to do this: an endpoint outside the key’s scopes, a model missing from the allowlist, a spend limit or per-request cost cap that was hit, or a frozen account. | The code names the cause: insufficient_scope, key_spend_limit_exceeded, request_cost_limit_exceeded or account_not_active. Adjust the key’s limits or wait for the window to reset. |
| 404 | Unknown model, job or artifact, or one that belongs to another account. | Check the id against the catalog or your own resources. |
| 409 | Request state conflict; the request needs review rather than a blind retry. | Do not retry automatically; check the job or contact support. |
| 422 | The request body failed validation before dispatch. | The details array lists each field and what is wrong with it. |
429 + Retry-After | The key’s requests-per-minute limit was reached. | Wait for the seconds given in the Retry-After header. |
| 5xx / 503 | The platform or network cannot serve this right now, including no provider being available for the model. Nothing was charged. | Retry with backoff; check the model’s provider count on the catalog. |
Error code catalog
Every stable code, its status, and whether a retry can help. The same catalog is machine-readable in the OpenAPI spec.
| Code | Status | Retry |
|---|---|---|
content_policy_violation | 403 | — |
policy_review_unavailable | 503 | ✓ |
missing_api_key | 401 | — |
invalid_api_key | 401 | — |
insufficient_scope | 403 | — |
model_not_allowed | 403 | — |
key_spend_limit_exceeded | 403 | — |
request_cost_limit_exceeded | 403 | — |
retail_cost_limit_exceeded | 403 | — |
price_ceiling_exceeded | 403 | — |
account_not_active | 403 | — |
insufficient_credit | 402 | — |
invalid_content_length | 400 | — |
request_body_too_large | 413 | — |
contract_attribute_required | 400 | — |
invalid_request | 400 | — |
invalid_catalog_filter | 400 | — |
invalid_routing_control | 400 | — |
routing_control_not_public | 400 | — |
routing_control_not_supported_for_endpoint | 400 | — |
incompatible_routing_constraints | 400 | — |
validation_failed | 422 | — |
model_not_found | 404 | — |
job_not_found | 404 | — |
request_not_found | 404 | — |
artifact_not_found | 404 | — |
artifact_expired | 404 | — |
endpoint_not_supported | 404 | — |
token_count_unsupported | 400 | — |
token_count_failed | 503 | ✓ |
idempotency_in_flight | 409 | ✓ |
idempotency_conflict | 409 | — |
idempotency_replay_unavailable | 409 | — |
rate_limited | 429 | ✓ |
client_closed | 499 | — |
state_conflict | 502 | — |
upstream_error | 502 | ✓ |
capacity_unavailable | 503 | ✓ |
no_provider_satisfies_attestation_tier | 400 | — |
no_provider_satisfies_quant | 400 | — |
context_requirement_unavailable | 400 | — |
preferred_provider_unavailable | 503 | ✓ |
context_capacity_unavailable | 503 | ✓ |
no_provider_within_price_band | 503 | ✓ |
confidential_compute_unavailable | 503 | ✓ |
api_key_verification_unavailable | 503 | ✓ |
When a media request cannot run
Invalid custom size or unavailable estimate: return to a supported preset, then check width, height, steps and batch count against both the model contract and current provider capacity. A selectable model does not guarantee a provider can run every combination right now.
Missing LoRA or reference control: check whether this workflow offers the capability. Select an approved option or a compatible workflow; adding unsupported JSON fields does not enable it.
Insufficient credit: compare your available balance with the maximum hold, including other active requests. A price-ceiling rejection is different: review your routing or key limits against the tariff reference.
Failed or interrupted run: inspect the existing job and its error before submitting again. Completed work can still be charged. Save the job id, selected settings and error code when reporting an issue, and omit API keys and private input files.
Errors and your money
A request rejected before reaching a provider never charges. When an outcome is genuinely ambiguous, for example a connection lost mid-generation, the hold stays until the provider’s receipt resolves what was actually done; the receipt amount is what you pay, and a hold with no receipt is released.
