api-reference/openapi.json — Mintlify renders one
page per endpoint automatically.
Base URLs
All endpoints are prefixed with
/api.
Authentication
The endpoints in this reference are public — no bearer token required. Identity is established at two layers:- Tenant scoping —
account_idonGET /events/publicfilters to your tenant’s events. Checkout endpoints scope implicitly through theticket_type_idyou pass (which belongs to an event, which belongs to your account). - Optional API key — for higher-trust integrations or rate-limit
increases, pass
X-Underpass-Api-Key: <key>(issued by UnderPass during onboarding). Not required for the public surface.
Response envelope
Every successful response is wrapped:data. Errors use a different shape:
code (stable identifier) rather than message (subject to copy
changes).
Rate limits
The public endpoints are rate-limited at the ingress layer. Default budget is generous for normal browsing patterns; if you hit a429, back off
with exponential delay and retry. Per-tenant limit increases are available
via the API key path — contact us.
Idempotency
POST /checkout/start is not idempotent on its own. If you retry a
checkout, you create a second order. Use the returned order_id to track
which one is in-flight; show a “creating order…” state while the call is
pending and don’t auto-retry on timeout — instead, fetch the order list
for the buyer’s email or treat it as failed.
For the next major version we plan to support an Idempotency-Key header
to make safe retries possible. Until then, gate the submit button.
SDK?
We don’t ship a polished SDK yet — the surface is small enough that plainfetch works well. TypeScript types are auto-generated from the OpenAPI
spec; we recommend openapi-typescript to
generate types in your own repo:

