# Errors, retries & idempotency

## HTTP errors



| Status | Meaning | Action |
| --- | --- | --- |
| 400 | Invalid input | Fix the request; no charge. |
| 401 | Missing, invalid or revoked bearer key | Check or rotate the key. |
| 402 | Insufficient units/balance or caller max_units exceeded | Check usage, authorized budget and dashboard balance. |
| 403 | Static access cap reached, or invalid browser origin | Contact support about hotel information access, or correct browser origin. |
| 404 | Hotel or quote session not found/expired | Check the ID; expired quote pages require a new search. |
| 409 | Idempotency key conflict or operation conflict | Reuse the same key only for the same body and endpoint. |
| 422 | No enabled provider mapping supports this request | Inspect mappings and occupancy; no provider call was billed. |
| 429 | Account minute or concurrency limit | Respect Retry-After; no charge. |
| 503 | No provider completed, provider/configuration unavailable, or billing confirmation pending | Retry safely as described below. |
| 504 | Operation deadline exceeded | Retry with the same Idempotency-Key; inspect credits_charged for an uncertain billing outcome. |





```json
{
  "error": {
    "code": "providers_unavailable",
    "message": "No provider completed the price request. No credits were charged. Retry later.",
    "credits_charged": false
  }
}
```



## Safe retries

Send a unique `Idempotency-Key` (at most 128 characters) for each intended operation. Keep the same key, endpoint and body for network timeouts or an uncertain outcome. Successful replays return the stored result for 24 hours without another debit. A replay keeps the original receipt and unit values with `usage.replayed: true`; count that receipt once when aggregating usage. A different body with the same key returns 409.

If `error.code` is `billing_confirmation_pending`, `credits_charged` can be null while the ledger recovers. Keep the same Idempotency-Key; do not generate a second key and risk starting another intended call.

Honor Retry-After on 429. Use bounded exponential backoff for temporary upstream failures. The default account allows one new hotel request at a time; avoid parallel fan-out across keys.

## A 200 can be partial

A provider can fail while others return useful results. Inspect `data.provider_results`, hotel-level provider statuses and `data.coverage`. Never turn a timeout or missing mapping into “no rooms available.” Completed no-availability responses are valid billed searches. Malformed supplier bodies are errors.

## Time budgets and failure isolation

Each hotel operation has a 30-second server deadline, including destination resolution, catalog access, provider work, grouping and persistence. Auto Suggest uses one shared 2.5-second window for suggestion and place resolution. Cold catalog recall starts with up to 8 seconds and may retry once for up to 4 seconds, capped by the operation deadline minus 17 seconds reserved for shopping and finalization. Warm queries return as soon as ready.

Supplier shopping has a 15-second phase. Public Expedia, Booking and Agoda HTTP calls use 4 seconds, matching Brek. Wholesale TGX receives up to 10 seconds to collect suppliers, matching Brek, plus up to 2 seconds for network/response handling. A shorter remaining operation budget reduces these limits. Retries share the first dispatch's deadline; they never reset the clock. Room requests reserve 8.5 seconds after shopping for GIATA (5 seconds, then at most a 3-second retry) and 2 seconds for finalization. Valid room prices survive unavailable mapping; unmatched rooms stay in safe provider-specific groups.

Each supplier fails independently. A supplier timeout does not turn successful competitors into a failed tool call. A complete provider outage returns an error without consuming a call. Missing optional star metadata stays unknown; unfiltered shopping continues. Explicit star filters use verified matches only. If some metadata could not be checked, `catalog_quality` and lower-bound coverage describe the limitation. If no candidate can be verified for that filter, retryable `star_classification_unavailable` is returned instead of false sold-out results.

## Diagnostics

`provider_results[].planned_requests` counts planned batches; `dispatched_requests` / `upstream_requests` count actual HTTP starts, including retries. Rejected work before dispatch has zero HTTP starts. `completed_requests`, `failed_requests` and `unstarted_requests` distinguish responses, unsuccessful attempts and batches never sent. A recovered retry can leave a complete result with a failed attempt in its history.

`batch_results[]` includes per-batch status, attempts, actual dispatches, `queue_ms`, `http_ms` and sanitized errors. Brek also exposes these in `source_results[]`, identified by 108/118/999 and 127 outside the US. Error `timeout_origin` distinguishes `supplier`, `client_http`, `source_queue`, `operation_deadline` and `client_cancel`. `stage` identifies the failing phase. `data.timings` reports catalog, quote, grouping and total service time. Supplier bodies, credentials and raw messages are excluded.

Source start rates are shared across developer, website and consumer clients and across HotelUse replicas: Expedia at most 6 starts/second, Booking/Agoda and Brek 108/118/999 at most 10, source 127 at most 2. Public and detailed calls use at most four workers per provider; wholesale listing uses six workers per source. Minute budgets are additional to these start limits. Temporary Brek failures may retry once inside the same budgets and do not add a HotelUse call charge.

The Claude and ChatGPT consumer connector has no fixed live-search quota per minute and no IP-based request quota by default. Shared platform egress IPs do not identify individual travelers. The service admits up to 12 concurrent uncached operations; identical in-process searches coalesce and brief response caches avoid repeated shopping. A global 12,000 MCP requests/minute circuit breaker protects control-plane overload. Reaching service concurrency or supplier capacity can still return a retryable 429 or partial provider coverage. This is service backpressure, not a paid plan or a consumer credit allowance.

Consumer supplier admission has a separate 4,320 upstream starts/minute budget within a 4,800 shared total; developers retain 480. The per-supplier start rates above remain unchanged and can constrain dense-city throughput before that minute budget. Higher ingress limits do not guarantee unlimited quote throughput. Optional per-minute and per-IP guards can be enabled by operators; zero disables them. These settings apply to /mcp/search only. Account billing and developer /mcp limits remain separate. Cancelling one subscriber does not cancel another subscriber's shared search.

## Report an issue

Include endpoint, request_id when returned, dates, currency, occupancy and provider status. Validation errors can occur before a request_id is issued. Remove API keys, cookies and personal details. [Contact support](mailto:leo@hoteluse.dev).

---

Canonical: https://www.hoteluse.dev/docs/errors-and-retries.html
Source: https://www.hoteluse.dev/docs/errors-and-retries.md
