Skip to main content
The Crypto Checkout API is a REST API that accepts JSON request bodies and returns JSON responses. All requests to /api/v1/* require a Bearer token issued from your dashboard. The API follows conventional HTTP semantics — use the right method, check the status code, and parse the JSON body.

Base URL

Every endpoint is relative to your self-hosted instance:
https://your-domain.com/api/v1
The base URL is the domain you deployed Crypto Checkout to. There is no shared cloud instance — you own and operate the server.

Authentication

Attach your API key as a Bearer token on every request:
Authorization: Bearer ck_live_...
Keys come in two flavours:
PrefixEnvironmentBehaviour
ck_live_...LiveProcesses real on-chain payments
ck_test_...TestSandboxed — no real funds move
You can generate keys at /dashboard/api-keys on your instance. Each key carries one or more scopes (links:read, links:write, sessions:read, sessions:write, webhooks:read, webhooks:write, events:read). Requests that exceed the key’s granted scopes return a 403 permission error.
See the Authentication guide for step-by-step key setup and scope recommendations for common integration patterns.

Request Format

Content-Type
string
Set Content-Type: application/json on all POST and PATCH requests.
Timestamps
string (ISO 8601 UTC)
All timestamps in request bodies and query parameters must be ISO 8601 strings in UTC, e.g. 2024-11-01T12:00:00Z.
Monetary amounts
string
Fiat amounts (e.g. fiatAmount) are always decimal strings such as "10.00", never floats. This avoids floating-point precision errors — treat them as such in your own code too.

Response Format

Successful responses return 200 for reads (GET) and 201 for resource creation (POST). Every resource object includes an object field that identifies its type so you can pattern-match without relying on the endpoint path:
{
  "id": "a1b2c3...",
  "object": "payment_link",
  "title": "Coffee",
  ...
}
The object values in use are: payment_link, checkout_session, webhook_endpoint, event, and customer.

List responses

Most list endpoints return a cursor-based envelope:
{
  "data": [ ... ],
  "hasMore": true,
  "nextCursor": "01HXYZ..."
}
data
array
Array of resource objects for the current page.
hasMore
boolean
true when there are additional pages beyond this one.
nextCursor
string | null
Opaque cursor to pass as starting_after to fetch the next page. null when you have reached the last page.
The Customers endpoint uses a different, page-based envelope with total, page, and limit fields instead of hasMore and nextCursor. See the Customers API for details.

Pagination

Most list endpoints use cursor-based pagination. Pass starting_after with the nextCursor value from the previous response to advance through pages. The limit parameter controls page size (default 25, maximum 100).
# First page
curl "https://your-domain.com/api/v1/checkout_sessions?limit=25" \
  -H "Authorization: Bearer ck_live_..."

# Next page — pass the cursor from the previous response
curl "https://your-domain.com/api/v1/checkout_sessions?limit=25&starting_after=CURSOR" \
  -H "Authorization: Bearer ck_live_..."
Cursors are opaque strings. Do not parse or construct them yourself — always use the nextCursor value returned by the API exactly as-is.
The Customers endpoint is the exception: it uses page-based pagination with page and limit query parameters, and its response envelope includes a total count rather than a nextCursor.

Idempotency

All mutating endpoints (POST, PATCH, DELETE) accept an optional Idempotency-Key header. Supplying the same key within the 24-hour replay window returns the original response without executing the operation again, making it safe to retry on network failures.
curl -X POST "https://your-domain.com/api/v1/payment_links" \
  -H "Authorization: Bearer ck_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-abc-v1" \
  -d '{"title": "Order #ABC", "fiatAmount": "29.99"}'
Reusing an idempotency key with a different request body returns a 409 conflict error. If you need to make a different request, use a new key.

Rate Limiting

Requests are rate-limited per API key. When you exceed the limit the API responds with 429 and an error body whose type is rate_limited. Back off and retry using exponential backoff — see Error handling for recommended retry logic.

Live Mode vs Test Mode

Your API key prefix determines which environment you are operating in:
  • ck_live_... — live mode. Checkout sessions create real on-chain deposit addresses and process real ETH payments.
  • ck_test_... — test mode. All operations are sandboxed; no funds move and no blockchain activity occurs.
Never expose a live-mode key in client-side code or public repositories. Test-mode keys are safe for local development and CI.

Available Resources

ResourceDescription
Payment LinksReusable, shareable links that generate a checkout session on each visit
Checkout SessionsIndividual payment sessions tracking the full lifecycle of a transaction
Webhook EndpointsRegistered URLs that receive real-time event deliveries
EventsImmutable audit log of everything that happened in your account
CustomersCustomer records attached to sessions

OpenAPI Spec

A machine-readable OpenAPI 3.1 spec is available on your running instance:
GET https://your-domain.com/api/v1/openapi.json
An interactive UI rendered with Scalar is available at /docs on your instance. You can import the spec into any OpenAPI-compatible tool such as Postman, Insomnia, or code generators.