API Errors
Unified GetMyBot API error format, HTTP status code meanings, and safe retries of money operations through Idempotency-Key.
Di halaman ini
The API communicates errors using standard HTTP status codes and a consistent response body. Successful responses return data directly, without an envelope wrapper.
Error format
On error, the response body is a JSON object with a single error field containing a human-readable message:
{"error":"reaction not found"}
Treat the HTTP status code as the primary signal; use the error text for logs and user-facing hints.
Status codes
200 OK: request succeeded, data in the body.201 Created: a new resource was created (some POST endpoints).204 No Content: success with no body (some deletions).400 Bad Request: invalid request body or parameters.401 Unauthorized: token is absent, invalid, or expired; or the route is not accessible via a personal token.402 Payment Required: the action is blocked by a plan or quota (for example, custom media storage requires a premium plan).403 Forbidden: the token lacks the required scope for this route, or the token holder lacks the required account right (missing cabinet right, see The token's account).404 Not Found: the resource was not found or does not belong to you.409 Conflict: state conflict (for example, a duplicate unique value). Second meaning: a request with thisIdempotency-Keyis still in flight: see below.413 Payload Too Large: the body exceeds the limit (see rate limits). Requests carrying anIdempotency-Keyhave their own, lower threshold of 64 KiB.422 Unprocessable Entity: the body is syntactically valid but fails domain validation. Second meaning: the sameIdempotency-Keywas already used with a different body: see below.429 Too Many Requests: rate limit exceeded (see rate limits).500 Internal Server Error: internal server error; retry later.
How to handle errors
Treat 2xx codes as success. On 401/403, check your token, its scopes, and your account rights. On 429 and 5xx, retry with exponential backoff.
On 4xx (except 429) retrying the request unchanged is pointless: fix the request. With one exception: a 409 on a request carrying an Idempotency-Key does not mean "fix the request", it means "the same operation is running right now". Abandoning the operation here is exactly the wrong move: you would record as failed a payment or a broadcast that is going through. Retry with the same key, honouring the Retry-After in the response.
Retrying money operations: Idempotency-Key
An ordinary retry is safe for reads and dangerous for operations that cost something: a dropped connection does not tell you whether the request arrived. The Idempotency-Key header exists for exactly that: it makes a retry safe.
The key is a canonical UUID (lowercase, hyphenated), for example 9b1f0d4c-2f6a-4a5f-9a3f-1f2f3a4b5c6d. Any other encoding of the same value is refused with 400.
Where it applies
The header is optional but honoured on operations whose repetition costs money or starts a mass send:
POST /api/billing/topup: topping up the balance;POST /api/billing/subscribe: taking out a subscription;POST /api/bots/{botID}/reactions/{reactionID}/broadcast: starting a broadcast.
On two operator sends it is, on the contrary, mandatory: without it the request is refused with 400:
POST /api/bots/{botID}/users/{userID}/dialog/messages;POST /api/bots/{botID}/support/dialogs/{subscriberID}/templates.
On every other route the header is ignored. Do not treat it as universal duplicate protection: where it is not in the list above, a retry is simply a second request.
What the server answers
- Same key, same body, operation finished: the server returns the recorded answer of the first attempt: same status code, same body, plus an
Idempotent-Replay: trueheader. The operation happens once. The record is kept for a week. - Same key, operation still running:
409withRetry-After. Retry with the same key after that pause; a fresh key here is precisely what would create a second charge. - Same key, different body:
422. This guards against reusing a key for something else: the server cannot know which of the two bodies you meant. Take a new key. - Body over 64 KiB:
413. These operations send small bodies; that size means a client-side mistake.
Some answers are deliberately not recorded against the key: 5xx, 408, 425 and 429. They mean "the request was not acted on", so a retry with the same key does the work: as it should. Were they recorded, you would get your own refusal back on every later attempt for a week, and the operation could never be performed under that key.
How to use it
- Generate the UUID before the first attempt and store it with the task.
- Send the request with that key.
- On a dropped connection, timeout,
5xxor429, retry with the same key, not a new one. - On
409, wait out theRetry-Afterand retry with the same key. - Take a new key only for a genuinely different operation.
The classic mistake is generating a fresh key on every attempt. The header then looks configured while protecting against nothing: every attempt is a separate operation as far as the server is concerned.
Managed AI and workflow errors
Managed AI uses stable codes such as not_available, not_entitled, budget_exceeded,
rate_limited, provider_unavailable, and schema_validation_failed. Retry only errors marked
retryable and preserve the idempotency key. Never retry a 4xx or schema error as another provider
request.
Copilot can return stale_base; recreate the proposal against the current graph. Policy updates
can return 409 on an optimistic version conflict. Reaggregation and replay runs are bounded jobs:
poll their status instead of starting duplicates. Meta asset checks return actionable reason codes;
the API never includes upstream response bodies or access tokens in an error.
What's next
- Authorization and tokens:
401and403in detail. - Rate limits:
429and body size limits. - Interactive reference: which errors are possible for a specific endpoint.