Access
API Authentication
Customers authenticate the HZURA Sports API and HZURA Casino API with an API key. The calling IP must match that customer's CIDR allow-list. Casino routes always require the key. Sports routes can also admit a legacy public-IP policy with no key.
API key
Admin-managed customers receive an API key. Send it on every sports or casino call except GET /api/v1/health.
The key is shown once when it is generated. Store it on the server that calls the API. Do not put it in a browser bundle, a mobile app, or source control.
| Header | Required | Rule |
|---|---|---|
Authorization: Bearer <key> | API-key accounts | Preferred. If both headers are present, this value is the key. |
X-Api-Key: <key> | API-key accounts | Used when Authorization is absent or is not Bearer. |
Accept: application/json | Recommended | Responses are JSON either way. |
GET /api/v1/sports HTTP/1.1
Host: api.hzura.com
Authorization: Bearer YOUR_API_KEY
Accept: application/json- A present
Authorization: Bearervalue wins overX-Api-Key, including when the bearer token is empty. - An empty bearer token or an empty
X-Api-Keyis still treated as a supplied key. The request does not fall through to legacy IP access. - Other
Authorizationschemes are ignored. A legacy IP client can send an unrelated Authorization header and still be matched by IP. - A missing key, an empty supplied key, an unknown key, a disabled customer, and a CIDR miss all return
403ip_not_allowedwith messageClient address is not allowed.
Customer identification
The API key resolves the customer. Callers do not send customer_id or customerId. Casino catalog, launch, and wallet use that resolved customer only.
Sports sport lists and rate limits also come from the customer policy when a key is supplied. GET /api/v1/sports returns the sports that policy allows.
IP and CIDR access
The address that must match is the public IP the API sees for the caller, after trusted-proxy forwarding. Hostnames, including ngrok domains, are not an access control.
For an API-key customer, that IP must fall inside allowed_cidrs for the customer. An empty CIDR list denies every request. Register the stable public egress IP of each server that will call the API before integration.
127.0.0.1, a Docker bridge address, or a home NAT address is not a production server IP.
Legacy keyless sports access
If the request supplies no API key, sports routes can still be admitted by an enabled public-IP policy. That policy is an exact client IP, not a customer record. It can allow a sport list and its own rate limit.
This path is current public behavior for sports only. It does not identify a casino customer, so casino games, launch, and wallet reject it with 403 ip_not_allowed.
Sports and Casino
| Route | API key | Calling IP | Rate limit |
|---|---|---|---|
GET /api/v1/health | Not required | Not checked | Not applied |
| Sports routes | Required for API-key accounts. Omitted only for a legacy IP policy. | Customer CIDR, or the legacy IP policy | Per customer when a key is used. Per IP for a legacy client. |
| Casino games, launch, and wallet | Required. The key selects the customer. | That customer's CIDR allow-list | Not applied. Casino paths do not return rate_limited. |
Unknown paths under the public API still require admission. A caller who is not allowed receives ip_not_allowed rather than not_found.
GET /metrics is an operator metrics endpoint. It is not a client JSON route and is not covered here.
Security notes
- Call the API over HTTPS.
- Treat the API key as a secret. Rotate it with the operator if it is exposed.
- Policies can change without an API restart. A loaded policy is reused for one second, so a change is visible on the next read after that.
- A valid sport that is not on the client policy is
403sport_not_allowed. An unknown sport key is400invalid_sport. - Casino can be disabled for an otherwise valid key. That is
403casino_access_disabled, which is distinct fromip_not_allowed. - Launch and wallet bodies reject unknown JSON fields. Do not send provider credentials or a return URL.
- The numeric rate-limit budget is configured per client. It is not a fixed public number. On
429, wait for theRetry-Afterheader, in seconds.