API reference
The AOA public API error format: stable codes and HTTP statuses, which requests to retry and which to fix, and why not to build logic on message.
Errors come in the same envelope as successful responses. The code field is a stable machine value, and that’s what to branch your logic on. The message field is meant for people and can change.
{
"error": {
"code": "conflict",
"message": "Залишилось лише 3 квитки"
}
}| Code | HTTP | When it happens |
|---|---|---|
bad_request | 400 | Invalid request data: an unknown category, a quantity outside 1–20, a missing Idempotency-Key. |
unauthorized | 401 | The key is missing where it’s required, wrong or revoked. |
forbidden | 403 | The key is valid but lacks the required scope. Also an attempt to look at someone else’s order. |
not_found | 404 | The event or order doesn’t exist, or the event isn’t published. |
conflict | 409 | The current state blocked the action: not enough tickets, payments not set up for the event. |
gone | 410 | The event existed but was deleted. Unlike 404, retrying never makes sense. |
rate_limited | 429 | The rate limit has run out. |
internal_error | 500 | A failure on our side. You can retry after a pause. |
| Code | Retry? |
|---|---|
rate_limited | Yes, after Retry-After. |
internal_error | Yes, with a growing pause, up to 3 attempts. |
conflict | Only after checking the current numbers: a plain retry won’t help. |
bad_request | No. Fix the request. |
unauthorized | No. The problem is the key. |
forbidden | No. The key needs more scopes. |
not_found | No. |
gone | No. Remove the event from your catalog. |
const response = await fetch(url, options);
const body = await response.json();
if (body.error) {
switch (body.error.code) {
case 'rate_limited':
// Wait for Retry-After and retry
break;
case 'conflict':
// Not enough seats: show the current numbers
break;
case 'unauthorized':
case 'forbidden':
// A problem with the key: don't retry
break;
default:
// Log it and show a generic message
}
}Don’t parse message
code only.This isn’t a failure. The event organizer hasn’t connected payments yet, so a ticket can’t be sold. Free events work normally in the meantime. Mark such an event as unavailable for sale: retrying won’t change anything.
Requesting someone else’s paymentId returns 404, not 403. That’s deliberate: otherwise anyone could find out which orders exist by trying identifiers one by one.
A draft or hidden event also returns 404, even though it technically exists. The API only shows published public events.