Reference
Errors
One shape for every failure, whatever caused it, and a code that tells you what to do next.
What went wrong at a hotel's own system never reaches you in its own words — and neither does
which system it was. Every failure is translated into the set below before the response leaves
Gateway Stream, so you write one error handler rather than one per source. The detail is kept in
Gateway Stream's logs against the requestId.
The Error Shape
error.codestring required- A stable machine-readable code. Branch on this, never on the message.
error.messagestring required- A human-readable explanation. Wording may change; do not parse it.
error.requestIdstring optional- Identifies this exact request in Gateway Stream’s logs. Log it, and quote it when you ask about a failure.
error.detailsobject optional- Extra context, shaped per code — the expected and actual price on
price_changed, a retry delay onrate_limited, the booking id onsupplier_error.
Status Codes and What They Mean
- 400
validation_error - The request body or query is malformed.
detailssays which field. Fix the request — retrying it unchanged will fail identically. - 401
unauthorized - Missing
x-api-key, or a key that is unknown, inactive, or not present in the environment its prefix points at. - 404
not_found - No such resource for this key. Another client’s booking is indistinguishable from one that never existed, deliberately.
- 409
conflict - The request collided with the current state — most often a
price_changedbooking, or cancelling something already cancelled. - 409
rate_unavailable - The rate is gone: sold out, stop-sold or withdrawn since it was quoted. Search again.
- 410
rate_key_expired - The rate key is unknown, expired, or already spent. Rate keys live about 30 minutes and are single-use. Search again.
- 424
distributor_unavailable - The source behind this request has been switched off for the operation you attempted. Search again. Existing bookings can still be cancelled.
- 429
rate_limited - Too many requests for this key.
details.retryAfterSecondssays how long to wait. - 500
internal_error - Something broke at Gateway Stream. Safe to retry once after a pause; report it with the
requestIdif it persists. - 501
not_implemented - This operation is not available for this booking.
- 502
supplier_error - A call to the hotel’s own system failed or was refused. Distinct from
424: this was an attempt that failed, not a source already known to be off. The message never names it;details.bookingIdis set when a booking record was kept. - 502
cancel_outcome_unknown - A cancel reached the supplier and came back without a definite answer. The booking is deliberately left in
CANCEL_REQUESTED— confirm rather than resend. - 503
mode_unavailable - This deployment has no configuration for the environment your key points at — typically a live key against a sandbox-only deployment.
When a Hotel's System Fails
A booking or a cancel can fail at the hotel's own reservation system. You get the same shape as any error, with a generic message and — for a booking — the id of the record that was kept of the attempt.
What Is Safe to Retry
- Never retried unchanged:
400,401,404,501. The answer will not change. - Retry after fixing the cause:
409and410mean search again and present the new price before trying once more. Nothing was booked. - Retry after a delay:
429afterdetails.retryAfterSeconds;500and503with backoff. - Do not retry — reconcile: a
202 UNKNOWNbooking, or a502 cancel_outcome_unknown. Both mean the supplier's state is genuinely unknown, and a second attempt is how a duplicate reservation gets created.
Failures That Are Not Errors
Search and property listing ask several sources at once, and one of them failing does not fail
the call. You get a 200 with whatever arrived, and meta.complete reads false. Treat that as “there may be more”, not as
an empty result — Request conventions covers this.
A Handler to Start From
Branch on code rather than on status where the two differ: two
distinct 409s and two distinct 502s need different responses from your
application, and only the code tells them apart.