Errors
Errors are deterministic and machine-readable. Branch on reason where there is one, and on status
otherwise — not on message text, which may be reworded.
The catalog
| Status | reason | Cause | Your move |
|---|---|---|---|
400 | — | Missing or malformed details; pax mismatch; seat-count mismatch | Fix the request. The message names every field at fault. |
401 | missing-api-key | No X-API-KEY header | Send the key. |
401 | invalid-api-key | Key resolves to nothing active | Check the key and the environment. |
403 | agent-suspended | Your agent is not ACTIVE | Contact GoHub. |
403 | not-entitled | You may not sell this vertical/supplier | Contact GoHub; do not retry. |
404 | — | Unknown quoteId, or a quote minted for another agent | Re-search. |
409 | — | Quote expired | Re-search for a new quote. |
409 | — | Order RECONCILING | Retry the same idempotency key. |
409 | insufficient-funds | PREPAID agent below its floor | Top up. Nothing was booked. |
422 | — | Supplier declined; order FAILED | Re-quote and try again. |
Validation happens before anything is spent
400s are raised before any funds move and before any supplier is called, so a malformed request
costs you nothing. The message names every field:
{
"status": 400,
"detail": "Missing required passenger/emergency fields for GoTaxi confirm: passengerNationality, emergencyContactNo"
}
Two error shapes
Auth rejections come from the edge and are a bare reason:
{ "reason": "invalid-api-key" }
Everything else is RFC 7807 application/problem+json,
with reason and any supporting figures as extension members:
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "Agent 42 is not entitled to TRANSPORT supplier 7",
"reason": "not-entitled"
}
Two that surprise people
404 on a quote you just received. Almost always expiry. It can also mean the quote belongs to
another agent — both return 404 deliberately, so quote ids cannot be probed.
403 not-entitled at booking, when search returned results. Entitlement filters search
silently, so an un-entitled offering does not appear there. If you cached a result across an
entitlement change, this is where it surfaces.