Skip to main content

Base URL

Everything tenant-scoped lives under /v1 and requires Authorization: Bearer <key>. Two surfaces do not:
  • POST /v1/signup — the one unauthenticated write. Registered ahead of the auth middleware.
  • /embed/* — gated by a short-lived embed JWT instead of an API key. See Live view.
Two route groups take the other bearer credential: /v1/workspaces and /v1/billing are session-only — driven by the dashboard, refusing API keys with 401. See dashboard sessions.

Conventions

application/json
Send content-type: application/json on every request with a body. Responses are JSON, except DELETE /v1/checkouts/{id} (empty 202) and the /embed routes (HTML and text/event-stream).
UUID v4
Checkouts, actions, buyer profiles, buyer sessions, API keys and webhook endpoints are all UUIDs. Merchant order ids on a receipt are the merchant’s own format — do not parse them.
ISO 8601, UTC
2026-07-29T09:14:31.190Z. Every timestamp field, everywhere.
{ amount, currency }
amount is a decimal string"42.10", never 42.1. currency is an ISO 4217 code and defaults to "USD" where you may omit it.
cursor
Checkouts, buyer profiles, API keys and webhook endpoints all return { data, nextCursor }, newest first. Pass nextCursor back as ?cursor=; null means the end. limit defaults to 20 and caps at 100.Checkouts and buyer profiles are genuinely paged. GET /v1/api-keys and GET /v1/webhooks are not — they answer the whole collection, with nextCursor: null and their original keys / endpoints arrays alongside data for callers written before the shapes converged. Read data.GET /v1/buyer-sessions is the exception that has not converged: it answers { sessions, vaultEnabled }, with no data and no cursor.
{ error: true, message }
Plus issues on validation failures, requiredScope on a scope refusal, sandboxMerchants on sandbox confinement, planCeilingUsd when maxCost exceeds the plan’s per-checkout ceiling. See Errors and limits.
<resource>.read | <resource>.write | *
Every route requires a scope derived from its path and method. write implies read on the same resource; a key issued without scopes holds *. See Authentication.
subject
A key may be bound to one of your end users at creation, after which it sees and creates only that person’s rows. subject is your own opaque id — 1 to 200 characters, "" is a 400 — accepted on POST /v1/api-keys, POST /v1/checkouts and POST /v1/buyer-profiles, filterable on GET /v1/checkouts?subject=, and present on the checkout.status_changed webhook payload. A key without one is tenant-wide. See End-user isolation.
unknown fields are a 400
The three create bodies that accept subject reject unrecognised top-level fields, so a misspelled subjectt fails loudly instead of returning 201 with an untagged row. target, constraints and metadata stay permissive inside.
Idempotency-Key header
POST /v1/checkouts only. A replay returns the original checkout with 200; the same key with a different body is 409. Keys are namespaced per (tenant, subject) and expire 24 hours after the checkout that claimed them was created. See Idempotency.

Machine-readable spec

The whole /v1 surface is described in OpenAPI 3.1. The spec lives at openapi.json in the root of the docs repository, and the Endpoints group in this tab is generated from it — so that group is the version that cannot drift from the schemas, and it is what to feed a code generator or an agent. The pages below are the hand-written companion: the same endpoints, with the reasoning a spec has no room for. Where the two disagree, the spec is right about shapes and these pages are right about why. The live-view embed (/embed/*) is not in the spec — it is browser-facing, authenticates with a minted JWT rather than an API key, and returns HTML and text/event-stream. See Live view.

Endpoints

Health

Signup

Checkouts

User actions

Buyer profiles

Buyer sessions

Webhooks

API keys

Usage

Workspaces (dashboard session only)

Billing (dashboard session only)

These are the routes behind the dashboard’s onboarding and billing pages — provisioning a workspace, choosing a plan, identity verification, the AUP, and the activation checklist. An API key on any of them is a 401, whatever its scopes. The flow they implement is documented in Going live.

Live view (embed-token auth)

Documented in Live view.
There is no SDK yet. Everything here is plain HTTP; the Quickstart has a complete TypeScript client in about a hundred lines of fetch, and Use Farthing from an LLM agent has the same thing shaped as model tools.