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}
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:
{"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 for how to tell the two 404 cases apart.
Response on rate-limit hit
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:
{"error_code":429,"error_msg":"Too many requests. Try again in 60 seconds.","request_id":"RT..."}
How to stay under the limit
- Always send a meaningful
User-Agent— e.g.MyCleaningApp/1.2.3 ([email protected]). It helps Hostex bypass IP-level bot defences
and lets the on-call team contact you about behaviour issues. - Cache dictionary endpoints aggressively.
GET /custom_channels,
GET /income_items,GET /expense_items,GET /income_methods,
GET /expense_methods,GET /tags,GET /groupschange rarely —
refresh once an hour at most, not on every reservation create. - Batch where possible.
POST /listings/pricesaccepts a list — one
call per listing-day-range, not per day. - Add jitter on retry. When you get
429, exponential backoff
starting at theRetry-Aftervalue, plus ±25% random jitter, prevents
thundering-herd against the next window. - Don't tail webhooks with polling. Subscribe to
Webhooks instead of polling
GET /reservationsevery minute — the events arrive in < 5 s. - Use
idfilters when querying after a write. Re-querying a single
record viaGET /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. |
