Hospitality Commerce API
Error Catalog

Error Catalog

All error codes with HTTP status, remediation, and recovery actions.

Machine-readable version: GET /.well-known/errors returns this catalog as JSON.

Envelope shape

{
  "error": {
    "code": "hold_expired",
    "message": "The hold TTL elapsed …",
    "detail": { "hold_id": "h_01HW…", "expired_at": "2026-04-15T19:03:11.000Z" },
    "remediation": "Create a new quote via POST /v1/quotes, then a new hold.",
    "retry_after": null,
    "docs_url": "https://docs.agenthotel.dev/errors#hold_expired",
    "trace_id": "9f8e…",
    "next_actions": [{ "rel": "quote", "method": "POST", "href": "/v1/quotes" }]
  }
}

Validation (400)

CodeRemediation
validation_failedInspect detail.field_errors, fix every listed path, retry.

Authentication (401)

CodeRemediation
unauthenticatedInclude a valid agent API key or bearer token.
delegation_requiredAttach a valid JWT as X-Delegated-User.
delegation_invalidCheck detail.reason, retry with fresh token.
delegation_issuer_unknownContact tenant admin to register the issuer.

Payment (402)

CodeRemediation
payment_failedVerify token, retry with new token, or surface detail.provider_message.

Authorization (403)

CodeRemediation
forbiddenRequest elevated credentials or call within granted scopes.
resource_access_deniedAsk admin to grant access to the specific resource.
principal_kind_not_allowedRe-authenticate with a credential of the required kind.

Not found (404)

CodeThrown byRemediation
property_not_foundquotes, propertiesSearch again for valid IDs.
room_type_not_foundquotesCall GET /v1/properties/{id}.
rate_plan_not_foundquotesCall GET /v1/properties/{id}.
quote_not_foundholdsCreate a fresh quote.
hold_not_foundbookingsCreate new quote + hold.
booking_not_foundbookings, cancelConfirm ID and tenant context.
oversell_incident_not_foundadminRefresh oversell queue.
agent_not_foundadminList agents via GET /v1/admin/agents.
credential_not_foundadminList credentials via GET /v1/admin/agents/{id}.
booking_authorization_not_foundadminCreate fresh authorization.
delegation_issuer_not_foundadminList issuers via GET /v1/admin/delegation-issuers.

Conflict (409)

CodeThrown byRemediation
idempotency_conflictAny idempotent POSTReplay original body or use fresh key.
allocation_failedholdsRequote; try alternative dates/rooms.
allotment_exhaustedholdsTry different date or room type.
oversell_not_detectedadminRefresh data before retrying.
quote_mismatchbookingsRecreate quote → hold → booking chain.
hold_not_activebookingsCreate new quote + hold.
booking_not_cancellablecancelInspect state first.
booking_not_modifiablemodifyFall back to staff support.
booking_modification_price_changemodifyAsk staff or choose same-length dates.
authorization_requiredbookingsCreate authorization first.
booking_authorization_invalidbookingsInspect detail.reason, refresh.
no_capturable_paymentadmin refundNo captured payment.
payment_not_refundableadmin refundOnly captured/partially_refunded payments.
refund_exceeds_remainingadmin refundReduce to detail.remaining.
property_not_promotableadminFix detail.reasons pre-conditions.
policy_not_found_for_rate_planquotesContact tenant admin.

Expired (410)

CodeRemediation
quote_expiredCall POST /v1/quotes again.
hold_expiredCreate new quote + hold. Room may be unavailable.

Rate limit (429)

CodeRemediation
rate_limitedBack off for retry_after seconds.

Server (500) / Upstream (502) / Gateway timeout (504)

CodeStatusRemediation
internal_error500Retry with backoff, cite trace_id.
payment_provider_error502Retry with backoff or try alternative payment method.
notification_delivery_failed502Primary operation may have succeeded. Retry notification.
payment_timeout504Provider didn't respond in time — charge may or may not have captured. Retry with the same Idempotency-Key; the provider deduplicates. If timeouts persist, try an alternative payment method.

payment_timeout is thrown by POST /v1/bookings when Stripe, PayPal, or VNPay exceeds the 10-second request budget. Because the outcome is ambiguous, safe recovery requires replay with the original idempotency key — do not generate a new key, which could double-charge.

Webhooks

CodeStatusRemediation
webhook_endpoint_not_found404List endpoints via GET /v1/admin/webhooks.
webhook_delivery_not_found404Check DLQ via deliveries endpoint.
webhook_delivery_not_replayable409Wait for in-flight delivery to complete.

On this page