Skip to Content
DocumentationErrors and limits

Errors and limits

Request errors return a non-2xx HTTP status and an error envelope:

{
  "code": 402,
  "error": {
    "message": "Insufficient balance. Please top up your account",
    "type": "PaymentRequired",
    "code": "insufficient_balance"
  }
}

Branch on the HTTP status and error.code, not on the English message.

HTTPCommon codeAction
400invalid_inputCorrect the model ID, fields, values, or conditional requirements.
401api_key_missing, api_key_invalidSend a valid API key.
402insufficient_balanceTop up before retrying. No task was created.
404task_not_found, generation_not_foundCheck the ID and owning account.
429unknown_errorBack off and retry with jitter.
500, 503unknown_errorRetry a limited number of times with exponential backoff.

Failed tasks

A media generation can be accepted and fail later. The status endpoint still returns HTTP 200, but data.status is failed and data.errorMessage contains a sanitized explanation. The charge is refunded automatically.

Do not submit a second paid generation merely because polling is slow. Retry only after the original task is terminal.

Rate limits

Every endpoint under /api/v1 shares one limit: 120 requests per minute. The window is a rolling 60 seconds and the counter is keyed on the calling IP address, not on the API key — several keys behind one address share the budget, and the count is pooled across our API replicas, so it is the same 120 wherever the request lands.

The limit is on request volume only. It is not a quota on generations, on concurrent tasks, or on spend; how much you can generate is bounded by your prepaid balance, and a queued generation costs nothing further while it runs.

Reading the headers

Every response carries the state of your window, so a client can pace itself without ever provoking a 429:

HeaderMeaning
X-RateLimit-LimitRequests allowed in the window (120).
X-RateLimit-RemainingAdvisory count of requests left before the limit is reached.
X-RateLimit-ResetSeconds until the window resets and the count clears.
Retry-AfterSent only on a 429: seconds to wait before retrying.
curl -sS -D - -o /dev/null https://api.apihubs.ru/api/v1/catalog
HTTP/2 200
x-ratelimit-limit: 120
x-ratelimit-remaining: 119
x-ratelimit-reset: 60

A worker can use X-RateLimit-Remaining to reduce the chance of a rate-limit error. The value is advisory: concurrent requests from the same IP can consume the final slot before the worker sends its next request.

When the limit is exceeded

The 121st request in the same rolling 60-second window returns HTTP 429 with the standard error envelope and a Retry-After header:

{
  "code": 429,
  "error": {
    "message": "ThrottlerException: Too Many Requests",
    "type": "Error",
    "code": "unknown_error"
  }
}

Branch on the HTTP status. Nothing was created and nothing was charged, so the request is safe to repeat once Retry-After seconds have passed.

Staying under the limit

Polling is what exhausts the budget in practice — a fleet of workers asking for task status every second reaches 120 requests a minute with two tasks in flight. In order of effectiveness:

  • Use webhooks. Pass webhook on generation/create and the finished task is delivered to you. This removes status polling entirely and is the single biggest reduction in request volume.
  • Back off while polling. Wait 5–10 seconds before the first status check, then widen the interval up to 30 seconds. A video generation takes minutes; polling it every second buys nothing.
  • Poll one task per request. Batch your own bookkeeping instead of re-checking every task in your queue on every tick.
  • Stop at a terminal status. succeeded and failed never change again.

If your workload genuinely needs a higher ceiling, ask — the limit exists to keep one client from crowding out the rest, not to cap legitimate throughput.

Retries and backoff

Retry with exponential backoff and random jitter, capped at a small number of attempts. Jitter matters as much as the backoff: without it, a batch of clients that hit the limit together retries together and hits it again.

  • Retry 429, connection failures, 500, and 503 with capped backoff.
  • Do not retry 400, 401, 402, or 404 unchanged — the outcome will be the same until the request itself changes.
  • Reconcile a timed-out create call before submitting another generation. A create that timed out on your side may still have been accepted and charged; check your task list rather than paying for a second one.
Errors and limits — API Hubs