---
agentTools:
  projectIndex: https://api-doc.hostex.io/llms.txt
---

# Rate Limits

# Rate Limits

Hostex applies rate limiting at three layers to keep the service stable
for everyone. Exceeding a limit returns `HTTP 200` with `error_code: 429`
in the body and a `Retry-After` header (in seconds).

***

## Layer 1 — Per-account limit

Applies to **all v3 endpoints combined**, keyed on your Hostex **account**
— not on the individual access token. Every token issued under the same
account shares one quota, whether you created it yourself in the dashboard
or it was granted through OAuth. Issuing a second token does **not** give
you a second allowance.

| Window     | Max requests |
| ---------- | ------------ |
| 1 minute   | 1,200        |
| 10 minutes | 6,000        |
| 1 hour     | 20,000       |
| 24 hours   | 100,000      |

These four are checked in parallel — you hit `429` as soon as **any** one
is breached.

### Per-token cap (opt-in)

On top of the account quota, an individual token can be capped tighter,
per minute and/or per hour. No token has such a cap unless Hostex sets one
— it exists so a single misbehaving integration can be reined in without
throttling every other integration on the same account.

The cap only ever tightens: the account and endpoint limits still apply on
top of it. When a per-token cap is what stopped the request, the response
carries `X-RateLimit-Scope: token`. If you believe one of your tokens has
been capped, contact support — the value is not readable through the API.

## Layer 2 — Per-account + per-endpoint limit

Applies to one endpoint at a time, keyed on `(account, route template)` —
same account scope as Layer 1.

The key is the **route template**, not the literal URL: every
`POST /v3/conversations/{id}` call shares one bucket regardless of which
thread id you pass. Fanning a burst across many ids does not spread it
across many buckets.

| Endpoint pattern                                                       | 1 min | 10 min | 1 h    | 24 h   |
| ---------------------------------------------------------------------- | ----- | ------ | ------ | ------ |
| `POST /v3/availabilities`                                              | 120   | —      | —      | —      |
| `POST /v3/listings/*` (prices / inventories / restrictions / calendar) | 120   | —      | —      | —      |
| `GET /v3/listings/airbnb/price_and_rules` (reads Airbnb in real time)  | 120   | —      | —      | —      |
| `POST /v3/reservations`                                                | 60    | —      | —      | —      |
| **All other endpoints**                                                | 600   | 3,000  | 10,000 | 50,000 |

A dash means that window is not enforced for that pattern (the
account-level limit still applies).

## Layer 3 — Per-thread throttle on `POST /conversations/{id}`

Sending a message to a guest is throttled per thread (independent of both the
account and per-token quotas), because OTAs aggressively rate-limit channel-side message
APIs and Hostex must shield the channel account from suspensions:

| Window     | Max messages per thread |
| ---------- | ----------------------- |
| 5 seconds  | 5                       |
| 60 seconds | 10                      |
| 30 minutes | 30                      |
| 2 hours    | 60                      |
| 24 hours   | 120                     |

All five are checked in parallel. Plan templates and HostGPT auto-replies
accordingly.

## Layer 4 — Failed-request quota

Separate from the request-count limits above, repeated **client errors** on
the same endpoint consume their own quota, keyed on `(account, route
template)`:

| Window   | Max failed requests |
| -------- | ------------------- |
| 1 hour   | 500                 |
| 24 hours | 2,000               |

Only `400` (bad request) and `404` (not found) count. These are the two
outcomes that will **never** succeed if you send the same request again —
so retrying them costs you and Hostex capacity while making no progress.

Deliberately **not** counted: `401`, `403`, `420` and `429`. In particular a
`429` never feeds this quota, so being throttled cannot extend your own
block.

When this quota is what stopped the request, the response carries
`X-RateLimit-Scope: endpoint_error` and:

```json
{"error_code":429,"error_msg":"Too many failed requests to this endpoint. These requests cannot succeed as sent; fix the request instead of retrying.","request_id":"RT..."}
```

The quota resets on the fixed window boundary like every other limit, and
successful calls to the same endpoint are unaffected until it is exhausted.
**The fix is to correct the request, not to wait and retry** — see
[Errors](./errors.md) for how to tell the two 404 cases apart.

***

## Response on rate-limit hit

```http
HTTP/1.1 200 OK
Retry-After: 60
X-RateLimit-Scope: user            # "user" = account-wide; also "endpoint", "token", "endpoint_error"
X-RateLimit-Window: 1m
X-RateLimit-Reason: user rate limit exceeded: 1200 requests per 1m

{"error_code":429,"error_msg":"Too Many Attempts.","request_id":"RT..."}
```

`X-RateLimit-Scope` names the **one** limit with the latest reset time. If
several are breached at once, only that one is reported; clearing it may
immediately reveal the next.

For Layer 3 (message throttle) the body explicitly tells you when to retry:

```json
{"error_code":429,"error_msg":"Too many requests. Try again in 60 seconds.","request_id":"RT..."}
```

***

## How to stay under the limit

1. **Always send a meaningful `User-Agent`** — e.g. `MyCleaningApp/1.2.3
   (contact@example.com)`. It helps Hostex bypass IP-level bot defences
   and lets the on-call team contact you about behaviour issues.
2. **Cache dictionary endpoints aggressively.** `GET /custom_channels`,
   `GET /income_items`, `GET /expense_items`, `GET /income_methods`,
   `GET /expense_methods`, `GET /tags`, `GET /groups` change rarely —
   refresh once an hour at most, not on every reservation create.
3. **Batch where possible.** `POST /listings/prices` accepts a list — one
   call per listing-day-range, not per day.
4. **Add jitter on retry.** When you get `429`, exponential backoff
   starting at the `Retry-After` value, plus ±25% random jitter, prevents
   thundering-herd against the next window.
5. **Don't tail webhooks with polling.** Subscribe to
   [Webhooks](https://api-doc.hostex.io/reference/webhook-useage-guide) instead of polling
   `GET /reservations` every minute — the events arrive in < 5 s.
6. **Use `id` filters when querying after a write.** Re-querying a single
   record via `GET /reservations?id=…` is far lighter than re-pulling the
   whole list to find the one you just changed.

***

## What is **not** a rate-limit

| Error                                                 | Looks like 429 but isn't                                                                                           |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `420 Subscription expired / Basic edition`            | Account-level issue. Do not retry — the host must take action in the portal.                                       |
| `429 Too many attempts.` from `/oauth/authorizations` | OAuth brute-force guard, not the user-level rate limit. Stop attempting for 10 minutes after >10 failed exchanges. |