> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ticktock.bet/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> API keys, scopes, sport allowlist, and error responses

## Tenant API key

Every REST and WebSocket call carries a tenant API key issued from the Client Portal. The key is scoped — what fields you see depends on which scopes are attached.

### REST

REST accepts either equivalent header:

```http theme={null}
GET /cs2/v1/matches HTTP/1.1
Host: ticktock.bet
X-API-Key: <your-key>
Accept: application/json
```

```http theme={null}
GET /v1/sports/en/sports HTTP/1.1
Host: ticktock.bet
x-access-token: <your-key>
Accept: application/xml
```

When both headers are present, they must contain the same key.

### WebSocket

Browsers can't set custom headers on the WS upgrade, so the key rides as a query parameter:

```
wss://ticktock.bet/cs2/v1/stream?api_key=<your-key>
```

### AMQP

Provisioned per tenant on request — see the [Messaging Feed](/odds-feed/amqp) page.

```
amqp://op-<slug>:<password>@mq.ticktock.bet:5672/<slug>
```

## Verify your key

The first call to make on any new key:

```bash theme={null}
curl -H "X-API-Key: <key>" https://ticktock.bet/v1/whoami
```

```json theme={null}
{
  "data": {
    "tenant_id": "…",
    "name": "Acme Sportsbook",
    "scopes": ["cs2:matches:list", "cs2:matches:read", "cs2:markets:read", "cs2:markets:settlements", "cs2:stream:matches", "cs2:stream:markets"],
    "sport_allowlist": ["cs2"],
    "rate_limit_rpm": 600
  }
}
```

If the scope list is shorter than expected, contact your account manager — your key may have been issued with a narrower bundle than your contract calls for.

## Sport allowlist

Each key declares which sport namespaces it can access — `cs2` (`/cs2/v1/*`) and `soccer` (`/soccer/v1/*`) today, with Dota 2 (`dota2`) rolling out. Only keys with that sport in their `sport_allowlist` reach those endpoints.

## Error responses

| Status | Meaning                                                                               |
| ------ | ------------------------------------------------------------------------------------- |
| `400`  | Both REST API-key headers were sent with different values                             |
| `401`  | Missing `X-API-Key` / `x-access-token` header (REST) or `api_key` query param (WS)    |
| `403`  | Key invalid, deactivated, lacks the required scope, or sport not in `sport_allowlist` |
| `404`  | Resource not found                                                                    |
| `406`  | `Accept` header negotiation failed (neither JSON nor XML accepted)                    |
| `429`  | Rate limit exceeded                                                                   |

Error body (JSON):

```json theme={null}
{ "detail": "Required scope 'cs2:markets:settlements' is not granted to this API key. Contact your account manager to extend the key's scopes." }
```

## Rate limiting

Default **600 req/min** per tenant key (configurable per contract). WebSocket connections aren't rate-limited — the server still applies fairness on a per-tenant basis.

When exceeded:

```
HTTP/1.1 429 Too Many Requests
Retry-After: 30
```

## Key rotation

Rotate from the [Client Portal](/getting-started/client-portal). Two modes:

* **Rotate** — issue a fresh secret, keep the same scopes. Old key invalidated immediately.
* **Revoke** — disable the key. No replacement issued.

Either way, the change takes effect within a second across all running services — no propagation delay.
