Reference
Errors
Every refusal carries a stable code in data.code. Messages are for people and may change; branch on the code.
{
"statuscode": 409,
"message": "room type 412 has 0 left on 2026-12-21; 1 requested",
"data": {
"code": "NO_AVAILABILITY",
"details": {
"roomTypeId": 412,
"date": "2026-12-21",
"available": 0,
"requested": 1
}
}
}| Status | Code | What to do |
|---|---|---|
| 401 | API_KEY_INVALID | Check the header: Bearer zsk_live_… exactly as shown once. Ask the owner for a new key if it was never saved. |
| 401 | API_KEY_REVOKED | The owner revoked or rotated this key. Ask for the new one; nothing else will make it answer. |
| 503 | CONNECT_API_NOT_CONFIGURED | A server-side condition. Back off and retry later; it is not your key. |
| 403 | IP_NOT_ALLOWED | Your request came from an address outside the key's allowlist. Ask the owner to add your servers' public addresses. |
| 403 | SCOPE_MISSING | The key lacks the scope this route needs (details.needed). The owner grants it when editing the key. |
| 409 | PROPERTY_UNAVAILABLE | The property is deleted or a demo. Contact the owner. |
| 409 | CHANNEL_MANAGER_DISABLED | On a channel-manager route, the property's channel manager is off. Nothing would be pushed. Contact the owner. |
| 409 | PMS_NOT_AVAILABLE | On a booking route, the property runs the channel manager only. There is no PMS to put a booking in. |
| 400 | VALIDATION | The body or query did not match the schema; details lists each issue. Unknown fields are refused on purpose. |
| 400 | RANGE_INVALID | dateTo is before dateFrom, or the range is empty. |
| 400 | HORIZON | A night beyond today + horizonDays. Send it later. |
| 400 | TOO_MANY_UPDATES | More entries than maxUpdatesPerRequest. Split the request. |
| 400 | TOO_MANY_CELLS | The request names more cells (entity × night) than maxCellsPerRequest. Split it. |
| 400 | UNKNOWN_ROOM_TYPE | An id that is not this property's (details names it). Re-read GET /catalog. |
| 400 | UNKNOWN_RATE_PLAN | An id that is not this property's (details names it). Re-read GET /catalog. |
| 400 | CURRENCY_MISMATCH | Send money in the property's currency (GET /property). |
| 429 | RATE_LIMITED | Wait Retry-After seconds, then resend the same request. data.scope names the budget. |
| 422 | NOTHING_ACCEPTED | Every group was refused by the property's rate policy; details.rejected says why. |
| 404 | BATCH_NOT_FOUND | No such batch on this property. |
| 400 | IDEMPOTENCY_KEY_INVALID | x-idempotency-key must be 10–64 characters of [A-Za-z0-9_-]. |
| 409 | IDEMPOTENCY_KEY_REUSED | The same x-idempotency-key with a different body. Use a new key for a new request. |
| 409 | IDEMPOTENCY_IN_FLIGHT | The same request is being processed right now. Retry shortly. |
| 400 | STAY_INVALID | The stay is in the past, beyond the horizon, or longer than the maximum; details says which. |
| 400 | UNKNOWN_ROOM_TYPE_FOR_PLAN | The rate plan belongs to a different room type than the one named in the same entry. |
| 400 | OCCUPANCY_EXCEEDED | More adults or children than the room type takes (details carries the maximum). |
| 409 | NO_AVAILABILITY | A night is sold out (details names it). Nothing was written. Offer another date or room type. |
| 409 | EXTERNAL_REFERENCE_REUSED | Reserved for a reference clash across properties; today a repeat returns the same booking with 200. |
| 403 | PAYMENT_NOT_ALLOWED | A payment needs the bookings:payments scope. Send the booking without payment, or ask the owner for the scope. |
| 400 | PAYMENT_EXCEEDS_TOTAL | payment.amount is above the stay total. |
| 404 | BOOKING_NOT_FOUND | No such booking on this property, or not one the API created (desk and OTA bookings are never visible). |
| 409 | BOOKING_NOT_CANCELLABLE | The desk has checked the booking in (or otherwise moved it on). Ask the hotel to handle it. |
| 402 | MODULE_NOT_ENTITLED | The property's plan does not carry the product this route needs. The owner's billing contact can add it. |
Samples
Exactly what the server answers, from the contract.
{
"statuscode": 401,
"message": "Unauthorized",
"data": {
"code": "API_KEY_INVALID"
}
}{
"statuscode": 401,
"message": "Unauthorized",
"data": {
"code": "API_KEY_REVOKED"
}
}{
"statuscode": 403,
"message": "This API key may not be used from this address. The property owner restricts it to an allowlist.",
"data": {
"code": "IP_NOT_ALLOWED"
}
}{
"statuscode": 403,
"message": "This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.",
"data": {
"code": "SCOPE_MISSING",
"details": {
"needed": "bookings:write",
"held": [
"ari:read",
"ari:write"
]
}
}
}{
"statuscode": 409,
"message": "This property is not available to the API any more. Contact the property owner.",
"data": {
"code": "PROPERTY_UNAVAILABLE"
}
}{
"statuscode": 409,
"message": "This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.",
"data": {
"code": "CHANNEL_MANAGER_DISABLED"
}
}{
"statuscode": 409,
"message": "This property runs the channel manager only; there is no PMS to put a booking in.",
"data": {
"code": "PMS_NOT_AVAILABLE"
}
}{
"statuscode": 400,
"message": "updates[0].available: Expected number, received string",
"data": {
"code": "VALIDATION",
"details": [
{
"path": [
"updates",
0,
"available"
],
"message": "Expected number, received string"
}
]
}
}{
"statuscode": 400,
"message": "updates[0]: 2028-01-01 is beyond the horizon (last writable night is 2027-10-12, today + 365 days)",
"data": {
"code": "HORIZON"
}
}{
"statuscode": 400,
"message": "a request may name at most 5000 cells (entity × night); split the calendar into several requests",
"data": {
"code": "TOO_MANY_CELLS"
}
}{
"statuscode": 400,
"message": "rate plan(s) 77 do not belong to this property (see GET /catalog)",
"data": {
"code": "UNKNOWN_RATE_PLAN",
"details": {
"ratePlanIds": [
77
]
}
}
}{
"statuscode": 400,
"message": "rates must be sent in INR (got EUR)",
"data": {
"code": "CURRENCY_MISMATCH",
"details": {
"expected": "INR",
"got": "EUR"
}
}
}{
"statuscode": 429,
"message": "Too many requests on this API key. Slow down and retry after the Retry-After interval.",
"data": {
"code": "RATE_LIMITED"
}
}{
"statuscode": 422,
"message": "exceptions are switched off for this property — move the base rate instead",
"data": {
"code": "NOTHING_ACCEPTED",
"details": {
"rejected": [
{
"cells": 151,
"error": "exceptions are switched off for this property — move the base rate instead"
}
]
}
}
}{
"statuscode": 404,
"message": "Batch not found.",
"data": {
"code": "BATCH_NOT_FOUND"
}
}{
"statuscode": 400,
"message": "checkIn 2026-10-01 is in the past (today at the property is 2026-10-20)",
"data": {
"code": "STAY_INVALID",
"details": {
"today": "2026-10-20"
}
}
}{
"statuscode": 400,
"message": "rooms[0]: Deluxe takes at most 3 adults (got 4)",
"data": {
"code": "OCCUPANCY_EXCEEDED",
"details": {
"index": 0,
"roomTypeId": 412,
"maxAdults": 3
}
}
}{
"statuscode": 409,
"message": "room type 412 has 0 left on 2026-12-21; 1 requested",
"data": {
"code": "NO_AVAILABILITY",
"details": {
"roomTypeId": 412,
"date": "2026-12-21",
"available": 0,
"requested": 1
}
}
}{
"statuscode": 403,
"message": "This API key may not record payments. The property owner grants the bookings:payments scope.",
"data": {
"code": "PAYMENT_NOT_ALLOWED",
"details": {
"needed": "bookings:payments"
}
}
}{
"statuscode": 400,
"message": "payment.amount 30000.00 exceeds the stay total 27000.00",
"data": {
"code": "PAYMENT_EXCEEDS_TOTAL",
"details": {
"amount": "30000.00",
"total": "27000.00"
}
}
}{
"statuscode": 404,
"message": "Booking not found.",
"data": {
"code": "BOOKING_NOT_FOUND"
}
}{
"statuscode": 409,
"message": "Booking already checked in. Ask the hotel to handle it at the desk.",
"data": {
"code": "BOOKING_NOT_CANCELLABLE"
}
}{
"statuscode": 402,
"message": "This property's plan does not include the PMS.",
"data": {
"code": "MODULE_NOT_ENTITLED",
"details": {
"module": "PMS"
}
}
}{
"statuscode": 409,
"message": "This idempotency key was already used with a different request body.",
"data": {
"code": "IDEMPOTENCY_KEY_REUSED"
}
}Facts on this page (routes, samples, limits, codes) come from the API's public contract read live, Tue, 20 Oct 2026 13:10:41 GMT.