# Rate limits

> 23 Telecom API rate limiting explained — per-IP, per-account and brute-force layers, HTTP 429 handling, Retry-After semantics and backoff recommendations for high-volume senders.
> Source: https://docs.23telecom.co.uk/reference/rate-limits/

Instructions for LLMs: This is one page of the 23 Telecom messaging API docs
(SMS today; more channels planned). Base URL: https://restlink23telecom.com/api/v1,
auth via the X-API-Key header. Match errors on the error_code field, never on
description text. Full docs: https://docs.23telecom.co.uk/llms-full.txt · Schemas: https://docs.23telecom.co.uk/openapi.yaml

Rate limiting is applied at multiple independent layers. Limits are
configurable per account and may change — treat the numbers below as
approximate.

| Layer | Scope | Approximate limit | On exceed |
| --- | --- | --- | --- |
| Per-IP general | All requests from one IP | Configurable (high) | HTTP 429, **no JSON body** |
| Per-IP auth | Login endpoint per IP | ~5 req/min | 429 `TOO_MANY_ATTEMPTS` |
| Login brute-force | Per login name, progressive | Progressive delay | 429 `TOO_MANY_ATTEMPTS` + `Retry-After` |
| 2FA brute-force | Per user + IP, progressive | Progressive delay | 429 `TOO_MANY_ATTEMPTS` + `Retry-After` |
| Per-account | All requests from one account | Default ~1,000 req/s | 429 `RATE_LIMIT_EXCEEDED` |

Notes worth coding against:

- Only the **login brute-force** limiter sends `Retry-After`. Other 429s do not.
- The per-IP general limiter returns a bare 429 with **no JSON body** — don't
  assume every 429 parses as JSON.
- The per-account limiter is shared across **all team members and keys** on
  the account, for both JWT and API-key traffic.
- An edge-proxy limit also exists in front of the application and returns
  429 with an **HTML body**.

## Recommended client behavior

```
attempt = 0
while attempt < max_retries:
    response = send_request()
    if response.status != 429:
        break
    delay = retry_after_header or (base_delay * 2 ** attempt) + jitter
    sleep(delay)
    attempt += 1
```

- **Exponential backoff with jitter**, starting around 1s.
- **Honor `Retry-After`** when present.
- **Spread batch traffic** — for sustained high volume, a steady stream beats
  bursts that bounce off the limiter.

  Per-account limits are configurable. If your legitimate traffic approaches
  the default, contact your account manager with your expected request rate.