Errors & Rate Limits

Error response shapes, the full HTTP status code table, rate limit behavior, and a retry strategy that works with Atlas Cloud.

Error response shapes

Atlas Cloud returns three different error shapes depending on which part of the API you call. Check the shape before writing a parser.

Used by the LLM protocol endpoints and the media generation endpoints:

{
  "code": 401,
  "msg": "unauthorized",
  "request_id": "…",
  "data": null
}

Every response carries an X-Request-ID header. Log it — it is the fastest way for support to trace a specific call.

HTTP status codes

StatusMeaningWhat to do
400Malformed request: unparseable body, missing model, wrong content type, invalid retention header, or an invalid webhook_urlFix the request. The msg field names the specific problem
401Authentication failed — key missing, unknown, or expiredCheck the key. Note that a wrong URL path also returns 401, so verify the endpoint too
402Insufficient balance, or a Coding Plan allowance that has run outTop up
403Account or user is not permitted — includes using a Coding Plan key on a model that does not accept oneCheck the key's scope, or contact support
404Resource not found. For models this also covers models that are not available to your accountCheck the model ID against the catalog
413Request body exceeds 50 MBSend a URL instead of inline Base64, or upload the file first
429Rate limit reachedBack off and retry — see below
451Blocked in your regionNot retryable
500Internal errorRetry once, then report with the request ID
503Temporarily unavailableRetry with backoff
504A synchronous request exceeded the maximum waitSwitch to the asynchronous flow and poll

A 401 does not always mean your key is wrong. The gateway authenticates before routing, so a typo in the path also produces 401 rather than 404. If a key works elsewhere, check the URL first.

Job-level error codes

When an asynchronous job fails, data.error_code carries a numeric platform code that is more specific than the HTTP status. For example, 1039 indicates the input was rejected by content moderation.

data.error holds a human-readable description. Log both, along with the prediction ID.

Rate limits

Rate limits apply per account and per model. Exceeding one returns 429.

LLM and media endpoints do not return X-RateLimit-Limit, X-RateLimit-Remaining, or Retry-After. You cannot read your remaining quota from response headers — implement backoff on the client instead.

The /public/v1 billing endpoints are the exception: their 429 responses do include Retry-After.

If you need higher limits for a production workload, contact us with your expected request volume and model mix.

Retry strategy

Retry on 429, 500, 503, and 504, plus network-level failures. Do not retry 400, 401, 402, 403, 404, or 451 — they will fail identically.

Retry read requests freely. Be careful with retrying generation submissions: a request that timed out may still have been accepted, and a blind retry can create — and bill for — a second job. Prefer submitting asynchronously and polling, so a lost response never means a lost job.

import time, random, requests

RETRYABLE = {429, 500, 503, 504}

def call_with_retry(url, payload, api_key, max_attempts=4):
    for attempt in range(max_attempts):
        response = requests.post(
            url,
            json=payload,
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=60,
        )
        if response.status_code not in RETRYABLE:
            return response

        if attempt == max_attempts - 1:
            break

        # Exponential backoff with jitter, so clients don't retry in lockstep
        delay = min(2 ** attempt, 30) * (0.5 + random.random() / 2)
        time.sleep(delay)

    return response

Streaming errors

When a streaming request fails before the stream opens, you get a normal HTTP error. Once the stream has started, the connection stays open and the error arrives as an event in the stream — so a 200 on a streaming call does not guarantee a complete response. Always handle mid-stream termination.

Streams may also contain SSE comment lines beginning with : as keep-alive signals. These are not data and must be ignored — most SSE clients do this for you, but hand-rolled parsers often do not.

Getting help

When reporting a problem, include:

  • The X-Request-ID header from the failing response
  • The prediction ID, for asynchronous jobs
  • The exact model ID and the timestamp

Reach us through Support.

Last updated on

On this page