Errors
API Errors
Failed HZURA Sports API and Casino API requests return { "error", "message" }. Match on error. Messages are static and do not include keys, player input, SQL, or upstream bodies.
Error document
{
"error": "event_not_found",
"message": "Event not found"
}| Field | Meaning |
|---|---|
error | Stable machine-readable code. |
message | Static sentence for that code. |
GET /api/v1/health does not use this document. A healthy process returns { "status": "ok", "redis": "ok" } with HTTP 200. If either store checked by that route does not answer, it returns HTTP 503 with { "status": "degraded", "redis": "unreachable" }.
Rate-limit responses add a Retry-After header. The body stays { "error": "rate_limited", "message": "Too many requests" }.
Status codes
| HTTP | error | Message | When |
|---|---|---|---|
| 400 | invalid_sport | Unsupported sport. Supported sports: cricket, football, tennis, horse-racing, greyhound-racing | {sport} is not one of the supported sport keys. |
| 400 | invalid_event_id | Event id must be a positive integer | {eventId} is not a positive integer of at most 20 digits. 0 is rejected. |
| 400 | invalid_query | Query parameters are not valid | A games filter is empty, too long, or the query could not be read. |
| 400 | invalid_page | Page must be a positive integer | page is present but not a positive integer. Omitting it uses page 1. |
| 400 | invalid_limit | Limit must be between 1 and 100 | limit is not an integer from 1 to 100. |
| 400 | unsupported_currency | Currency is not enabled for this API client | On the games list, the currency is not in the customer allow-list. On launch, it does not match the established player or customer currency, ignoring case. On the wallet, a different three-letter uppercase currency does not equal the player's currency. Lowercase wallet currency text is invalid_wallet instead. |
| 400 | invalid_provider | Provider filter is not valid | provider is not a provider id in the runtime catalog. |
| 400 | invalid_category | Category filter is not valid | category is not a category id in the runtime catalog. |
| 400 | invalid_launch | Launch request is not valid | The launch body, game id, or JSON document is not usable. Unknown fields are rejected. |
| 400 | invalid_wallet | Wallet request is not valid | The wallet body, amount, currency text, or operation is not usable. A rollback amount that does not equal the original amount uses this code. |
| 400 | player_not_configured | Player country or currency is not configured | The customer has no usable country, default currency, or ll_RR launch locale, so a new player cannot be stored. |
| 403 | ip_not_allowed | Client address is not allowed | The caller was not admitted. For an API key this covers a missing, empty, or unknown key, a disabled customer, and a CIDR miss. For a legacy sports client it covers an IP with no enabled policy. Casino calls with no customer also use this code. The body does not say which check failed. |
| 403 | sport_not_allowed | This sport is not enabled for this API client | The sport key is valid, but this client's policy does not include it. |
| 403 | casino_access_disabled | Casino access is not enabled | The API key identified a customer, but casino is off or the customer is not active in the casino catalog. |
| 403 | game_not_available | Game is not available | The game exists but is not launchable for this customer, currency, language, device, or demo request. |
| 404 | not_found | Route not found | The path is unknown. The caller must already be admitted; an unadmitted caller receives ip_not_allowed instead. |
| 404 | event_not_found | Event not found | The event id is not in that sport's published catalog. |
| 404 | odds_not_found | Odds are not available for this event | The event is in the catalog, but no odds payload is stored for it. |
| 404 | game_not_found | Game not found | The game id is not in the runtime casino catalog. |
| 404 | player_not_found | Player not found | No player mapping exists for this customer and player_id. Launch creates the mapping. The wallet does not. |
| 404 | wallet_transaction_not_found | Wallet transaction not found | Rollback named a transaction this customer does not have for that player. |
| 405 | method_not_allowed | Method not allowed | The path exists, but the HTTP method does not. |
| 409 | insufficient_balance | Wallet balance is not sufficient | A debit, or a rollback of a credit, cannot reserve the amount. The provider is not called. |
| 409 | wallet_idempotency_conflict | Wallet transaction does not match the original request | This transaction_id was already used for a different player, operation, amount, currency, or rollback reference. |
| 409 | wallet_transaction_pending | Wallet transaction is still in progress | The same idempotency key is still pending after a provider timeout. Repeating it does not call the provider again. |
| 409 | wallet_already_rolled_back | Wallet transaction is already rolled back | A new rollback targets an original transaction that is already reversed. |
| 409 | wallet_transaction_not_reversible | Wallet transaction cannot be rolled back | The original transaction is pending, failed, a rollback, or otherwise not reversible. |
| 413 | payload_too_large | Request payload too large | A launch or wallet JSON body is larger than 8 KiB. |
| 429 | rate_limited | Too many requests | This sports client used its budget for the current window. The response includes Retry-After. Casino paths do not use this limiter. |
| 500 | internal_error | Internal server error | An unexpected failure while building a response. |
| 502 | malformed_upstream_data | Upstream data could not be read | A stored catalog or odds payload could not be parsed. |
| 502 | launch_authentication_failed | Game launch could not be authenticated | The game provider rejected the launch credential request. The message stays generic. |
| 502 | launch_failed | Game launch failed | The provider rejected the launch or returned no usable URL. |
| 502 | wallet_provider_failed | Wallet transaction failed | The provider rejected the wallet operation. A debit reservation is released. Repeating the same transaction_id returns this failure. |
| 503 | security_config_unavailable | Service is temporarily unavailable | Client or API-key policy could not be read, so the request is refused. |
| 503 | catalog_unavailable | Event data is not available yet, retry shortly | The sport catalog has not been published yet. |
| 503 | redis_unavailable | Upstream data store is unavailable | The data store could not be reached. |
| 503 | casino_catalog_unavailable | Casino catalog is not available yet, retry shortly | The casino catalog could not be loaded. |
| 503 | launch_not_configured | Game launch is not available | Launch is not configured on this process. |
| 503 | player_store_unavailable | Player identity is not available | The player mapping store could not be read or written. |
| 503 | wallet_not_configured | Casino wallet is not available | The wallet or its provider client is not configured. |
| 503 | wallet_store_unavailable | Casino wallet is not available | The wallet ledger could not be read or written. |
| 504 | redis_timeout | Upstream data store timed out | A sports data-store command, including the sportsbook rate-limit counter, did not answer in time. Casino catalog reads do not return this code. |
| 504 | launch_unavailable | Game launch is temporarily unavailable | The launch provider did not answer, or the connection failed. Launch does not move the wallet, so the same request can be retried. |
| 504 | wallet_provider_timeout | Wallet transaction is temporarily unavailable | The provider did not answer. The transaction stays pending. This is not success. |
Authentication
Admission failures use one code. A bad key and a CIDR miss look the same, so the response cannot be used to probe which check failed.
| HTTP | error | Surface |
|---|---|---|
| 403 | ip_not_allowed | Sports and Casino |
Validation
The path, query, or JSON body is not usable. Fix the request before retrying it.
| HTTP | error | Surface |
|---|---|---|
| 400 | invalid_sport | Sports |
| 400 | invalid_event_id | Sports |
| 400 | invalid_query | Casino |
| 400 | invalid_page | Casino |
| 400 | invalid_limit | Casino |
| 400 | unsupported_currency | Casino |
| 400 | invalid_provider | Casino |
| 400 | invalid_category | Casino |
| 400 | invalid_launch | Casino |
| 400 | invalid_wallet | Wallet |
| 400 | player_not_configured | Casino |
| 405 | method_not_allowed | All routes |
| 413 | payload_too_large | Casino launch and wallet |
Not found
The route, event, game, player, or wallet transaction is not available to this caller.
| HTTP | error | Surface |
|---|---|---|
| 404 | not_found | All guarded routes |
| 404 | event_not_found | Sports |
| 404 | odds_not_found | Sports |
| 404 | game_not_found | Casino |
| 404 | player_not_found | Wallet |
| 404 | wallet_transaction_not_found | Wallet |
Wallet conflicts and idempotency
The ledger refused the operation. Repeating a pending or conflicting key does not start a second provider call.
| HTTP | error | Surface |
|---|---|---|
| 409 | insufficient_balance | Wallet |
| 409 | wallet_idempotency_conflict | Wallet |
| 409 | wallet_transaction_pending | Wallet |
| 409 | wallet_already_rolled_back | Wallet |
| 409 | wallet_transaction_not_reversible | Wallet |
Rate limits
Sports routes share one per-client window. Honour Retry-After. Casino routes do not consume that limiter and do not return rate_limited.
| HTTP | error | Surface |
|---|---|---|
| 429 | rate_limited | Sports |
Upstream
The service could not use a stored payload or the game provider rejected the call.
| HTTP | error | Surface |
|---|---|---|
| 500 | internal_error | All routes |
| 502 | malformed_upstream_data | Sports |
| 502 | launch_authentication_failed | Casino |
| 502 | launch_failed | Casino |
| 502 | wallet_provider_failed | Wallet |
Availability
Retry later with the same request. A wallet timeout is the exception: the row stays pending.
| HTTP | error | Surface |
|---|---|---|
| 503 | security_config_unavailable | Sports and Casino |
| 503 | catalog_unavailable | Sports |
| 503 | redis_unavailable | Sports and Casino |
| 503 | casino_catalog_unavailable | Casino |
| 503 | launch_not_configured | Casino |
| 503 | player_store_unavailable | Casino |
| 503 | wallet_not_configured | Wallet |
| 503 | wallet_store_unavailable | Wallet |
| 504 | redis_timeout | Sports |
| 504 | launch_unavailable | Casino |
| 504 | wallet_provider_timeout | Wallet |
Retries
| Response | What to do |
|---|---|
| 400 | Fix the request. Do not retry it unchanged. |
403 ip_not_allowed | Confirm the API key and the server public IP. Do not guess which check failed. |
429 rate_limited | Wait the Retry-After seconds. Sports routes only. |
409 insufficient_balance | Do not retry until the balance can cover the amount. |
409 wallet_idempotency_conflict | Do not change the body under that transaction_id. |
409 wallet_transaction_pending or 504 wallet_provider_timeout | Do not send a new transaction_id for the same bet. Repeating the original key reports that it is still pending. |
502 wallet_provider_failed | The operation was rejected. Repeating the same key returns that failure. A new business attempt needs a new transaction_id. |
504 launch_unavailable | Safe to retry the same launch. Launch does not move the wallet. |
| 503 catalog or store errors | Retry later with the same request. |