Rate limits, idempotency & errors
Every endpoint shares the same rules for rate limiting, safe retries, and error shapes. Learn these once and they apply across Discovery, Availability, and Bookings.
Rate limits
The default ceiling is 60 requests per minute per key. Every response carries the current budget, and a
429 tells you when to retry:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Your per-minute ceiling. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | Unix epoch (seconds) when the window resets. |
Retry-After | On a 429, seconds to wait before retrying. |
Need a higher limit? Contact [email protected].
Idempotency
Make retries safe on writes (POST / PATCH / DELETE) by sending a client-generated key:
Idempotency-Key: 5f9c2b7e-3a1d-4e88-9c0a-1b2c3d4e5f60 - The first request with a given key stores its response for 24 hours.
- A retry with the same key and body returns that stored response instead of acting twice.
- The same key with a different body returns
409 idempotency.key_reused. 5xxresponses aren't cached, so a retry can still succeed against a healthy instance.
Use a fresh UUID per logical operation (per booking, per cancellation).
Errors
Every error uses the same envelope. Match on code (stable) — never parse message, which can be reworded:
{
"error": {
"code": "validation.failed",
"message": "contact requires an identifier (email, phone, or an ID)",
"retryable": false
}
} retryable is a hint: generally true for 5xx and 429, false for other 4xx. Common codes:
| Code | HTTP | Meaning |
|---|---|---|
auth.invalid_key | 401 | Key missing, malformed, revoked, or expired. |
auth.insufficient_scope | 403 | Key lacks the scope this endpoint needs. |
auth.api_access_disabled | 403 | API access isn't enabled on the account. |
platform.mismatch | 403 | URL platform ≠ the platform configured on the location. |
validation.failed | 400 | Required field missing or body shape wrong (see issues[]). |
contact.not_found | 404 | Contact didn't resolve and autoCreateContact was false. |
idempotency.key_reused | 409 | Same idempotency key, different body. |
ratelimit.exceeded | 429 | Over 60 req/min — wait Retry-After. |
platform.circuit_open | 503 | The booking platform is erroring — breaker is open (below). |
Circuit breaker
If a booking platform throws 5+ server errors in 60 seconds, AutoSync opens a per-platform breaker for
5 minutes and returns 503 platform.circuit_open during that window. It auto-recovers — wait the indicated
Retry-After rather than looping retries.
Last updated July 2026