Errors
Error shape, codes, rate limits, and how to handle retries safely with idempotency keys.
Errors return a non-2xx status with a JSON body. error is always present. Where a refusal has a stable, machine-readable name it is in error_code; branch on that, not on the wording of error. A few older refusals put their code in error itself (unauthorized, billing_required, free_tier_exhausted, rate_limited, insufficient_scope).
The test-key allowance is counted in confirmed test bookings, not calls: searches and unconfirmed attempts never use it up. Once it is used up, search, availability and booking calls on test keys all return 402 free_tier_exhausted.
AgentCard payment
Codes from AgentCard bookings (payment_collection: "agentcard_external"). HTTP codes come back on the call; the rest appear as the failed booking's error_code.
vault_unavailableagentcard_disabledpayment_declinedpayment_approval_expiredpayment_outcome_unknownpayment_setup_failedpayment_replay_failedcard_declinedOther codes
missing_last_nameslot_not_offeredwrong_key_environmentorg_suspendedmodify_unsupportedsearch_failedavailability_failedno_search_providerbilling_check_unavailable, entitlement_check_unavailableSession codes (live_key_required, invalid_code, reconnect_required and others) are listed on Sessions. A booking whose provider failed is not an HTTP error: it comes back with status: "failed" and its own error_code; see Booking lifecycle.
Rate limits
Limits are per organization, shared by all its API keys, over a fixed 5-minute window. Every metered response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds until the window resets). Over the limit you get 429 rate_limited with a Retry-After header.
POST /v1/venues/searchPOST /v1/availability/searchPOST /v1/bookingsPOST /v1/bookings/{id}/continueGET /v1/bookings/{id}POST /v1/bookings/{id}/cancelPOST /v1/sessions, POST /v1/sessions/{id}/verifyGET /v1/sessions/{id}/card, GET /v1/sessions/cardRetrying safely
Send an Idempotency-Key header on POST /v1/bookings. Sending the same key again returns the booking it first created and starts nothing new; the key never expires and the body is not compared. Details are on Booking lifecycle. A 5xx or a timeout on create may still have made a booking: retry with the same key rather than a new one.