# Rate limits

Every answer carries 3 headers, X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. A request over the limit gets 429 at once and is not charged.

## The three headers

- `X-RateLimit-Limit`: How many requests the account may make in the period.
- `X-RateLimit-Remaining`: How many are left now.
- `X-RateLimit-Reset`: When the count is full again, in Unix seconds.

An answer to a request without a valid credential does not carry them.

## What is limited

- The limit is the **account's**: all its keys share it.
- There are two limits: requests over time, and calls in progress at once.
- The limit in force is what the headers and `GET /v1/account` (its `rate`) say. It rises with an account's first top-up.
- The free routes with a key (`/v1/account`, `/v1/usage`, `/v1/calls/…`) draw on a separate count, so looking a call up never takes from the calls you pay for. The headers on those answers speak of that count.

```bash
curl "https://api.dataxapi.com/v1/account" \
  -H "Authorization: Bearer $DATAXAPI_API_KEY"
```

## Over the limit

A request over the limit gets 429 [`rate_limited`](https://dataxapi.com/docs/errors/#rate_limited) at once. It did not run and is not charged. `reason` says which limit it was.

| `reason` | What happened | How long to wait |
| --- | --- | --- |
| `rate` | Too many requests in the period. | The header `Retry-After`, in seconds; `retry_after_seconds` in the body is the same number. |
| `concurrency` | Too many of your calls are in progress. | No time is named: wait for one of your own calls to finish. |

When the platform a call reads from is limiting us, the answer is 503 [`upstream_busy`](https://dataxapi.com/docs/errors/#upstream_busy): not charged, and it carries `Retry-After` when a wait can be named.

## Retrying

The [SDKs](https://dataxapi.com/docs/sdk/) retry by themselves: twice by default (`maxRetries`, in Python `max_retries`), only what the service says may be retried, waiting as long as it says. A wait longer than a minute is not waited out: the error is thrown with the wait on it.

Over plain HTTP, the same in a few lines:

```ts
// One key for the call and every retry of it: a retry is then never charged twice.
const key = crypto.randomUUID();

async function call(url: string): Promise<unknown> {
  for (let attempt = 0; ; attempt += 1) {
    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.DATAXAPI_API_KEY}`, "Idempotency-Key": key },
    });
    const body = await response.json();
    if (response.ok) return body;
    if (body.retry !== "yes" || attempt >= 2) throw new Error(body.code);
    // The wait the service names, or 1, 2, 4 seconds when it names none.
    const seconds = body.retry_after_seconds ?? 2 ** attempt;
    await new Promise((done) => setTimeout(done, seconds * 1000));
  }
}
```

---

Catalog revision c48ce454ae6c4c65. [HTML version](https://dataxapi.com/docs/rate-limits/)
