# Authentication

> Keys, headers and rate limits.

## The key [#the-key]

A key looks like `xd_live_` followed by 32 characters. It is shown once when created. Only a hash is stored on our side.
Send it in the `x-api-key` header, or as `Authorization: Bearer xd_live_...`.

A key is tied to one wallet. Several keys can share a wallet, for example one per environment.

## Rate limit [#rate-limit]

The limit is per account, shared by all its keys. It follows the total you have paid over the life of the
account, and it only goes up.

| Total paid   | Requests per second |
| ------------ | ------------------- |
| $0           | 1                   |
| $10 or more  | 20                  |
| $50 or more  | 50                  |
| $200 or more | 100                 |
| $600 or more | 200                 |

Five starter packs count the same as one builder pack. A small pack after a large one changes nothing.
Above the limit the API answers `429` with a `retry-after` header. Nothing is charged. Need more?
Write to [hello@xdataapi.io](mailto:hello@xdataapi.io).

### Read the headers instead of guessing [#read-the-headers-instead-of-guessing]

Every response carries the limit and what is left of it, so a client never has to
discover its ceiling by hitting it (RFC 9331):

```http
RateLimit: limit=20, remaining=19, reset=1
RateLimit-Policy: "per-second"; q=20; w=1
```

These are on refusals too, and on a `401`, where `RateLimit-Policy` quotes the rate
an account starts on. A `429` adds `Retry-After` in whole seconds.

The keyless endpoints — `GET /`, `/status`, `/healthz` and `/openapi.yaml` on
`api.xdataapi.io` — have their own ceiling of 10 requests per second per address,
reported under the policy name `public`. No key is needed for them and none is
counted against your account.

The limit counts requests. Cached and batch requests run at the full rate. Fresh data comes from X at
the pace of the account pool behind the API, so a burst of many distinct uncached reads takes longer
than the rate limit alone would suggest. Measured on 2026-09-20, shared by all customers:

| Fresh reads                           | Per second |
| ------------------------------------- | ---------- |
| Tweets, profiles, timelines           | about 30   |
| Search, threads, followers, following | about 12   |

These are floors from a burst test, and they rise as the pool grows. A response served from cache does
not count against them, and costs half.

## Check a key [#check-a-key]

```bash
curl https://api.xdataapi.io/v1/me -H "x-api-key: xd_live_..."
```

```json
{ "key_prefix": "xd_live_GPE4", "balance": 4895.5, "rate_limit_qps": 25 }
```

## Keep it secret [#keep-it-secret]

Never ship the key in a browser or a mobile app. Call the API from your server and put your own auth in front.
Revoke a leaked key in the [dashboard](https://xdataapi.io/dashboard) and create a new one.
