
# Rate Limit

Each endpoint carries a request ceiling. Exceeding it is refused with HTTP `429` and `code: 100000429`, and every response tells you how much of the current budget is left, so you can pace against it rather than discover it.

## Request ceilings

Every endpoint carries a per-second ceiling, counted **per endpoint, per client IP address**:

| Endpoint group                                                      | Ceiling               |
| ------------------------------------------------------------------- | --------------------- |
| **Content** — `destinations`, `hotelsMetadata`, `hotelStaticDetail` | 100 requests / second |
| **Search** — `hotelList`, `hotelRates`                              | 100 requests / second |
| **Transactions** — `checkAvail`, `book`, `cancel`                   | 10 requests / second  |
| **Orders** — `queryOrders`, `orderVoucher`                          | 50 requests / second  |
| **Authentication** — `POST /api/auth/ticket`                        | 5 requests / second   |

Each group is a separate budget, and so is each endpoint within it: spending your HotelList allowance does not touch HotelRates or QueryOrders. The window is one rolling second — a ceiling of 10/second is ten calls in any given second, not 600 fired at once at the top of the minute.

**Transactions are the tight one, and deliberately so.** CheckAvail, Book and Cancel each reach a live supplier gateway, so the burst being capped is the supplier's capacity rather than ours, and several of them rate-limit us in turn. Pace those three; the search and content endpoints are served from our own catalogue and are an order of magnitude more generous.

**Authentication is the low one, and it should never bind.** A correctly built integration mints one ticket and reuses it until `expiresAt` — see [Cache your ticket](#handling-a-429) below. If you are anywhere near 5 tickets per second, you are re-authenticating per call.

The ceiling is applied before authentication, so malformed and unauthenticated calls consume it too. Exceeding it returns HTTP `429` with `code: 100000429`.

Every response carries the state of this counter, so you never have to infer it:

```http
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 6
X-RateLimit-Reset: 1
Retry-After: 1
```

`X-RateLimit-Limit` is the ceiling for the endpoint you just called and `X-RateLimit-Remaining` is what is left of it in the current second — read them to pace yourself rather than discovering the limit by hitting it. `X-RateLimit-Reset` is the seconds until the window rolls over, so with a one-second window it is 1. `Retry-After` is sent **only** on a `429`; honour it rather than guessing.

> **Sizing note.** A search-to-book sequence spends one request from each of several separate budgets, so the ceiling that governs your throughput is the tightest one you touch — in practice the 10/second on CheckAvail and Book. Size your worker pool against that number rather than against the search ceiling, and see [Need a higher ceiling?](#need-a-higher-ceiling) if your volumes need more.

## Handling a 429

1. **Read the envelope, not just the status.** A refusal arrives as HTTP `429` with `code: 100000429`; `msg` names what was exceeded.
2. **Honour `Retry-After`.** It is on every refusal. Back off exponentially — start there and double, with jitter — rather than retrying immediately.
3. **Never retry a `Book` call blindly.** Reuse the same `customerReferenceNo` so the retry is deduplicated rather than producing a second reservation. See [Error handling](/hotel-api/docs/guides/error-handling).
4. **Cache your ticket.** Requesting a fresh ticket per call is the most common self-inflicted cause of a 429, and ticket issuance carries the lowest ceiling on the API (5/second). Mint one, cache it, and refresh shortly before `expiresAt`.
5. **Reuse the session.** Carry `Session-Id` through a search-to-book sequence instead of starting a new search for each step.

Test and production enforce the same ceilings: `https://api-test.ttdbooking.com` runs the same code as `https://api.ttdbooking.com`, so a client that behaves in test behaves in production.

## Need a higher ceiling?

The ceilings above are platform figures rather than per-account settings, so raising one is something we agree and deploy — not a switch we flip for a single credential. Send your expected volumes (peak requests per second on the transactional endpoints, and daily search and booking counts) to [integrations@ttdbooking.com](mailto:integrations@ttdbooking.com) before you build against a number, and we will tell you where you stand rather than let you find out in production.

---

Full API reference: [developer.ttdbooking.com/hotel-api/docs](https://developer.ttdbooking.com/hotel-api/docs)
