
Common RateHawk API Errors and How to Fix Them
If you've built a production integration against RateHawk's (ETG's) B2B or Affiliate API, you've almost certainly hit a booking that returns something other than a clean ok. The difficulty isn't that RateHawk's API throws errors — every supplier API does — it's that each error means something different depending on which endpoint returned it, and getting that logic wrong either causes you to abandon bookings that were actually still processing, or to leave a customer hanging on one that has definitively failed.
This guide walks through the errors you'll actually encounter across the RateHawk booking lifecycle, grouped by the endpoint that produces them, along with the retry and failure-handling logic RateHawk's own integration guidance recommends.
Why RateHawk API Errors Need Endpoint-Specific Handling
RateHawk's booking flow runs across three sequential endpoints — booking/form, booking/finish, and booking/finish/status — and a shared set of error codes (timeout, unknown, and 5xx responses) behaves differently at each stage. Treating every timeout the same way, regardless of which call produced it, is the single most common source of RateHawk API errors turning into duplicate bookings or incorrectly abandoned orders.
Errors at the /booking/form/ Step
This is the first booking call, and it has its own retry rules. Several errors here are transient and expected to be retried on the same request; others should be treated as final failures immediately.
Retry until ok (up to 10 attempts, then restart search):
5xxstatus codestimeoutunknowndouble_booking_form— retry with a newpartner_order_idduplicate_reservation— retry with a newpartner_order_id
Stop immediately and show a failure:
contract_mismatchhotel_not_foundinsufficient_b2b_balancereservation_is_not_allowedrate_not_foundsandbox_restriction— this one is specific to the Test environment; it fires if you try to book a real hotel using a test API key rather than the fixed test hotel (hid 8473727)
Errors at the /booking/finish/ Step
Once booking/form returns ok, you move to booking/finish. The transient-error set (timeout, unknown, 5xx) carries over, but this time the correct response is to poll booking/finish/status rather than retry booking/finish itself.
Final failures unique to this step include booking_form_expired, rate_not_found, and return_path_required (missing for card-payment flows that need 3DS redirection).
Errors at the /booking/finish/status/ Step
This is where most of RateHawk's booking-specific error codes surface, and it's also the step people get wrong most often — because several of these errors look like they should be retried, but RateHawk explicitly documents them as final failure states.
Error | Meaning | Handling |
|---|---|---|
| 3D Secure authentication failed (not to be confused with status | Final failure |
| The hotel/room block could not be secured | Final failure |
| A booking limit was exceeded on the account or contract | Final failure |
| The room sold out between prebook and confirmation | Final failure |
| The underlying supplier rejected the booking | Final failure |
| Generic finish-step failure | Final failure |
| Booking is still being confirmed | Keep polling within your cut-off window |
A detail worth calling out explicitly because it trips up a lot of integrations: error: 3ds and status: 3ds are not the same thing. The status means the end-user still needs to complete card authentication. The error means that authentication attempt failed. Confusing the two either strands guests mid-payment or fails bookings that were still recoverable.
Webhook-Reported Errors
If you're relying on the booking status webhook instead of polling, the same transient errors apply but the fallback logic is different: on timeout, unknown, or a 5xx from booking/form or booking/start, you retry with a new partner_order_id (form step) or simply wait for the webhook (start step) — up to 10 attempts. If no webhook arrives within your configured timeout, treat the booking as unsuccessful rather than leaving it in limbo indefinitely.
The full set of errors that map to a Failed status across both the polling and webhook paths includes 3ds, block, book_limit, booking_finish_did_not_succeed, charge, decoding_json, endpoint_exceeded_limit, endpoint_not_active, endpoint_not_found, incorrect_credentials, invalid_auth_header, invalid_params, lock, no_auth_header, not_allowed, not_allowed_host, order_not_found, overdue_debt, provider, soldout, and unexpected_method.
Building This Into Your Integration Layer
The cleanest way to implement this in code is a dedicated error-classification layer that sits between your HTTP client and your booking service — not scattered if/else blocks at each call site. A simple version looks like this:
TRANSIENT_ERRORS = {"timeout", "unknown"}
FORM_STEP_RETRY_WITH_NEW_ID = {"double_booking_form", "duplicate_reservation"}
FINISH_STATUS_FINAL_FAILURES = {
"3ds", "block", "book_limit", "soldout", "provider",
"booking_finish_did_not_succeed", "charge", "not_allowed"
}
class RateHawkErrorClassifier:
def classify(self, endpoint: str, error: str | None, status_code: int, status: str | None = None):
if status_code >= 500 or error in TRANSIENT_ERRORS or status == "processing":
return "RETRY"
if endpoint == "booking/form" and error in FORM_STEP_RETRY_WITH_NEW_ID:
return "RETRY_NEW_PARTNER_ORDER_ID"
if endpoint == "booking/finish/status" and error in FINISH_STATUS_FINAL_FAILURES:
return "FAILED"
if status == "ok":
return "SUCCESS"
return "FAILED"
Wrapping this in a circuit breaker is worth doing too — if booking/form starts returning 5xx at volume, you want to trip the breaker and fall back to a queued retry rather than hammering an endpoint that's already degraded, which only extends your booking cut-off window and increases the odds of hitting booking_form_expired downstream.
Don't Skip the Sandbox and Test Environment Quirks
A meaningful share of "errors" reported by RateHawk integrators aren't really booking failures — they're environment mismatches. A few worth checking before you assume something is broken:
Sandbox and Test are separate environments; sandbox data used in Test (or vice versa) will produce errors that have nothing to do with your booking logic.
The Test environment only books a fixed demo hotel (
hid 8473727); trying to book anything else with a test key returnssandbox_restriction.now-type card payments and early check-in/late check-out upsells are unavailable in Sandbox — errors related to these features there are expected, not bugs.Test bookings should use refundable rates with a
free_cancellation_beforedate far enough out, or you'll hitinsufficient_b2b_balance.
Final Thoughts
Most RateHawk API errors aren't random — they're well-documented, endpoint-specific signals with a defined correct response. The integrations that handle them cleanly are the ones that classify errors by endpoint and treat "transient vs. final" as a first-class concept in their booking service, rather than retrying everything or failing everything by default.
At Teenva AI & Digital Ventures, we build exactly this kind of resilient supplier-abstraction layer for OTAs, TMCs, and DMCs integrating RateHawk alongside other bed banks — with proper retry logic, circuit breakers, and webhook handling built in from day one. If you're debugging a flaky RateHawk integration or building one from scratch, reach out to us at sales@teenvaai.com or +91 9572020107.




