Error response shape
Every non-2xx response from the Sabee API returns a JSON body with a single top-level error object containing a numeric status, a stable code string, and a message intended for logs and debugging rather than for display to end users.
{
"error": {
"status": 422,
"code": "SB-2001",
"message": "rate_plan_id 'rp_missing' does not exist or is archived."
}
} Build your error handling against the code field, not the message text — the message wording may be refined over time for clarity, but codes are stable within API version v1 per the versioning policy described in the API reference. New Sabee-specific codes may be introduced over time as the API surface grows, but an existing code's meaning is never repurposed for a different failure — if you see a code not listed on this page, treat it as a generic error of the corresponding HTTP status rather than assuming a specific cause.
Standard HTTP status codes
| Status | Meaning | Description |
|---|---|---|
| 400 | Bad Request | The request body or query parameters are malformed or fail schema validation. |
| 401 | Unauthorized | Missing, malformed, or invalid API key in the Authorization header. |
| 403 | Forbidden | The API key is valid but lacks permission for this resource or action. |
| 404 | Not Found | The requested resource ID does not exist on this account. |
| 409 | Conflict | The request conflicts with the current state of the resource, e.g. a double-booking attempt. |
| 422 | Unprocessable Entity | The request is well-formed JSON but fails business-rule validation. |
| 429 | Too Many Requests | Rate limit exceeded for this API key — see the rate limits page. |
| 500 | Internal Server Error | An unexpected error occurred on Sabee's side. Safe to retry once. |
| 502 | Bad Gateway | An upstream dependency (often an OTA channel) returned an invalid response. |
| 503 | Service Unavailable | Sabee is temporarily unavailable, usually during a scheduled maintenance window. |
| 504 | Gateway Timeout | An upstream dependency did not respond in time. Safe to retry with backoff. |
As a general rule, 4xx codes indicate a problem with the request itself — fix the request before retrying. 5xx codes indicate a problem on Sabee's side or an upstream dependency, and are generally safe to retry with exponential backoff, ideally using the same idempotency-key pattern described in the API reference so a retried write doesn't create a duplicate.
Sabee-specific error codes
Sabee-specific codes give you more precision than the HTTP status alone. Several map to more than one HTTP status depending on context — for example, SB-1002 can surface as a 429 on a direct API call or as informational context inside a channel.error webhook payload.
| Code | Name | Typical HTTP status | Description |
|---|---|---|---|
SB-1001 | Reservation conflict | 409 | Requested room type/dates have no availability, usually a race between two near-simultaneous bookings. |
SB-1002 | Channel throttled | 429/502 | A connected OTA is rate-limiting Sabee's sync requests; retried automatically, informational when seen on a webhook. |
SB-1003 | Channel credentials invalid | 403 | The stored OTA credentials were rejected; the channel needs re-authentication in the dashboard. |
SB-2001 | Invalid rate plan | 422 | The referenced rate_plan_id does not exist, is archived, or is not attached to the given room type. |
SB-2002 | Rate plan restriction violated | 422 | The requested stay violates a minimum-stay, closed-to-arrival or closed-to-departure rule on the rate plan. |
SB-3001 | Insufficient permission | 403 | The API key's scope does not include write access to this resource type. |
SB-3002 | Property scope mismatch | 403 | The resource belongs to a different property than the one this API key is scoped to. |
SB-4001 | Guest profile locked | 409 | The guest profile is mid-merge with a duplicate record and is temporarily read-only. |
SB-4002 | Invalid guest contact | 422 | The supplied email or phone number failed format validation. |
SB-5001 | Invoice already finalized | 409 | An attempt was made to modify line items on an invoice that has already been sent or paid. |
SB-5002 | Currency mismatch | 422 | The requested amount's currency does not match the property's configured billing currency. |
SB-6001 | Webhook endpoint unreachable | n/a | The registered webhook URL failed to respond during the most recent delivery attempt or test. |
Full examples
A reservation conflict, the most common write-path error, looks like this:
HTTP/1.1 409 Conflict
{
"error": {
"status": 409,
"code": "SB-1001",
"message": "Room type rt_204 has no availability for 2026-09-14 to 2026-09-17."
}
} An insufficient-permission error, common when a read-only reporting key attempts a write:
HTTP/1.1 403 Forbidden
{
"error": {
"status": 403,
"code": "SB-3001",
"message": "API key 'sk_live_...a91f' does not have write scope for reservations."
}
} A rate-plan restriction violation, common when a booking widget doesn't pre-validate minimum-stay rules client-side:
HTTP/1.1 422 Unprocessable Entity
{
"error": {
"status": 422,
"code": "SB-2002",
"message": "rate_plan_id 'rp_flex_bb' requires a minimum stay of 2 nights; 1 night requested."
}
} An invoice modification conflict, common when an integration tries to adjust line items after the invoice has already been emailed:
HTTP/1.1 409 Conflict
{
"error": {
"status": 409,
"code": "SB-5001",
"message": "invoice inv_30291 is finalized and cannot be modified. Issue a credit note instead."
}
} Client-side handling
A robust integration typically branches on three tiers rather than handling every code individually: retryable server-side errors (500, 502, 503, 504, and 429 with backoff per rate limits), non-retryable client errors that need a code fix or a user-facing message (400, 404, 409, 422), and permission errors that indicate a configuration problem rather than a transient issue (401, 403). For the Sabee-specific codes layered on top, we recommend mapping the handful you actually act on programmatically — most integrations only need special handling for SB-1001 (show the guest alternative dates), SB-1002/SB-1003 (surface a channel health alert to reception), and SB-5001 (redirect to the credit-note flow instead of a raw PATCH) — and treating every other code as a generic, loggable failure. Trying to special-case all twelve Sabee codes individually in client code is usually more maintenance overhead than the marginal handling improvement is worth.
Logging matters as much as branching. Store the full error object — status, code and message — alongside the request that triggered it, including the idempotency key if one was sent, so a support conversation with the Sabee team can reproduce the exact failure rather than working from a paraphrased description. Most support tickets that reference an unclear error resolve faster once the raw JSON body is shared directly, since the message field often contains the specific identifier (a room type, rate plan or invoice ID) that explains the failure precisely.