Guides/Errors & rate limits
Every error response uses the same shape, so you can handle them generically and branch on code only where you need to:
{"error": {"type": "invalid_request_error","code": "not_found","message": "Booking not found"}}
| code | type | meaning |
|---|---|---|
| missing_api_key | authentication_error | No Authorization header was sent. |
| invalid_api_key | authentication_error | The key doesn't match any active key. |
| rate_limited | rate_limit_error | Too many requests — see rate limits below. |
| plan_lacks_api_access | permission_error | The operator's plan doesn't include API access at all. |
| insufficient_scope | permission_error | The key doesn't carry the scope this endpoint needs. |
| subscription_inactive | permission_error | A :write scope was requested but the subscription has lapsed. |
| idempotency_key_conflict | invalid_request_error | The same Idempotency-Key was reused with a different request body. |
| not_found | invalid_request_error | The booking reference doesn't exist for this operator. |
| booking_rejected | invalid_request_error | Booking creation failed validation (e.g. no availability, missing waiver acceptance). |
| transition_rejected | invalid_request_error | The requested status isn't a valid transition from the booking's current status. |
| payment_link_rejected | invalid_request_error | Payment-link creation failed (e.g. amount exceeds the outstanding balance). |
Each API key is limited to 150 requests per minute, on a sliding window. Every response — success or error — carries these headers:
X-RateLimit-Limit — the limit (always 150 today).X-RateLimit-Remaining — requests left in the current window.X-RateLimit-Reset — Unix timestamp (seconds) for when the window resets.Known v1 limitation: read and write requests on the same key currently share ONE 150/min budget, not separate pools per scope — a burst of writes can eat into your read budget on the same key. A finer-grained limit is a possible future improvement, not built this pass.