Errors
Business errors the Aggregator.gg API returns follow one envelope. You branch on a recognized machine code, log only fixed safe diagnostics, and retry only the failures that are actually transient. Several failure classes use flat bodies or endpoint-specific markers, including idempotency, free rounds and provider-access gates. Common exceptions are auth failures (401) and rate limiting (429). This page is the model; the catalogue of named error conditions lives in the Error reference.
Error model
Section titled “Error model”Errors carry four things:
- a stable code such as
E2001, unique per failure mode and safe to match on; - a type, the snake-case name of the same failure, still untrusted input;
- a message for humans, which may change between releases;
- optional details with extra context such as field names, limits, or identifiers.
Codes are grouped by family, so the first digits tell you where to look:
| Family | Area |
|---|---|
E1xxx |
Game providers: availability, launch, branding, assets |
E2xxx |
Games: lookup, enablement, jurisdiction |
E3xxx |
Sessions and player state |
E4xxx |
Transactions and wallet callbacks |
E5xxx |
Authentication, signatures, account deletion |
E6xxx |
Operator configuration and platform accounts |
E7xxx |
KYB and organization |
E8xxx |
Team members and invitations |
E9xxx |
Rate limiting |
EBxxx |
Billing |
EAxxx |
Affiliate program |
E0xxx |
Internal platform errors |
Two rules keep handlers stable:
- Match on
code, never onmessage. Messages change; codes do not. - Log HTTP status and an allowlisted code. Unknown codes, messages, details, response bodies and headers may contain credentials. Never log the raw error object. Use a locally generated correlation ID; include upstream request IDs in a support report only after validating and reviewing them for secrets. Code samples shows fixed diagnostics.
Response shape
Section titled “Response shape”{ "error": { "code": "E2001", "type": "game_not_found", "message": "Game Not Found", "details": {} }}| Field | Type | Description |
|---|---|---|
code |
string | Stable error code (E2001). Use for programmatic handling. |
type |
string | Snake-case name derived from the error enum. Do not log untrusted text directly. |
message |
string | Human-readable description. May include additional context. |
details |
object | Optional. Extra context such as field names, limits, or identifiers. Present only when relevant. |
The HTTP status carries the coarse class (4xx yours, 5xx ours), the code carries the precise cause. One status can map to many codes: a 403 can be a suspended provider (E1003), a jurisdiction block (E2003), or a self-excluded player (E3004), and each asks for a different reaction from your side.
Step check: use the protected-header request pattern on API keys for a nonexistent game ID and confirm the client recognizes E2001 with HTTP 404 without logging the raw body.
Auth failures return a flat body
Section titled “Auth failures return a flat body”An invalid, revoked, or missing API key does not produce the envelope. The live response to a bad Bearer token is:
{"error": "invalid_token", "message": "API key authentication failed"}There is no code or details field; do not require a request-ID header to classify the failure. The machine-readable signal is the HTTP 401 plus the error string (the WWW-Authenticate response header repeats error="invalid_token"). This mirrors the existing flat-body exception for 429 described in Rate limiting. The error reference still catalogues the auth conditions as E5002 (unrecognised key) and E5003 (expired key); those names identify the conditions, they just do not appear in this response body today. Match auth failures on the status code, and treat a 401 as terminal: fix the key in the cabinet rather than retrying.
Step check: run one request with a deliberately wrong key, for example AGGREGATOR_API_KEY=agg_invalid in front of any snippet from this hub, and confirm your client reports HTTP 401 with a fixed authentication-failed diagnostic, without copying upstream text.
Retryable failures
Section titled “Retryable failures”Retry only what the platform itself calls transient, with exponential backoff and jitter:
| Code | Meaning | Recovery guidance |
|---|---|---|
E0001 |
Unexpected server error | Use bounded retries with the same operation identity; escalate persistent or ambiguous outcomes with reviewed correlation evidence |
E0002 |
Database connectivity issue | Back off and recheck; no recovery-time guarantee |
E1002 |
Provider temporarily unreachable | Provider-side blip |
E1053 |
Provider launch timeout | Provider did not answer in time |
E1054 |
Provider launch endpoint down | Retry after a delay |
Most request/permission failures need a correction before retrying. HTTP 429 and 409 idempotency_in_progress are exceptions; 409 idempotency_conflict is not. Session errors or timeouts can leave an uncertain launch outcome: preserve the original key and body and reconcile before creating another operation. The table above names common transient conditions, not an exhaustive HTTP retry policy. Important cases:
E4001(402) carries two different meanings by context. On a wallet callback it is a declined bet, the player’s balance is short: answer as specified in Declining a bet and move on. OnPOST /v1/sessionsit means your organization’s credit balance hit its overdraft floor: new launches are refused until you top up credits in the cabinet. Both are business outcomes, not retry candidates; the error reference details the split.E4002(200) marks an idempotent replay of a transaction you already processed. Replay the original status and body for the same trusted integration/organization + provider + transaction identity; never a second movement.E9001(429) means a rate-limit bucket is exhausted. Read the reset signal from the headers and back off as described in Rate limiting; hammering through it only extends the wait.
Step check: test transient coded and flat errors, 429, in-progress/conflicting idempotency, malformed bodies and an ambiguous timeout using synthetic responses. Retries are bounded, preserve the key/body and respect pacing; exhausted or unknown money outcomes reach reconciliation rather than a new operation.
Troubleshooting
Section titled “Troubleshooting”Every call returns 401. Check the Authorization header: the scheme word Bearer, then the full agg_ key value, no quotes. The body is the flat {"error": "invalid_token", "message": "API key authentication failed"} described above, whether the key is unrecognised (the E5002 condition) or revoked; both are fixed in the cabinet, not by retrying. See API keys.
A 404 for an ID you can see in the cabinet. Sessions and games are scoped to your account and key. E3001 also fires when the session belongs to a different operator, and E2001 when the game exists but is not enabled for you. List with GET /v1/games and use the id values it returns.
You parsed the body but error is missing. You hit a transport-level failure (load balancer timeout, proxy error page) rather than an API error. Classify the HTTP status and operation before retrying; keep untrusted HTML out of diagnostics. For inbound wallet delivery, a malformed 200 or any other 2xx has the separate terminal-unknown behavior in Callbacks.
The same code keeps returning after a fix. Confirm you redeployed with the fix and that your retry queue is not replaying stale requests. Terminal errors replayed from a queue look exactly like a broken fix.