Authorization
Bearer token — a session token for people, an API key for systems.
Developers
Endpoint-level reference for the REST API and webhook payloads.
Overview
The v1 surface is 208 operations across 41 resource areas — authentication, customers, wallets, ledger, assets, rewards, events, webhooks, AI, workflows and the rest. This page does not restate all of them; the generated document does that. What it states is the conventions every one of them shares.
Ten properties hold across the surface: RESTful, versioned, predictable, idempotent, permission-aware, multi-tenant, environment-aware, fully documented, OpenAPI compliant, stable. Every write declares the permission it requires, every financial operation declares idempotency, and every collection paginates the same way.
Base URLs
Headers
Two identify the caller, two scope the request, two are conditional. Nothing else is read from headers.
Bearer token — a session token for people, an API key for systems.
Which tenant the request acts on. Client-supplied and therefore never trusted: validated against the authenticated principal, rejected as organization_mismatch on failure.
sandbox or production. A key is scoped to one environment; a mismatch is environment_mismatch, never a silent switch.
Client-supplied correlation id, generated if absent. Echoed in every response and every error, and written to the request log.
Required on the write operations that declare idempotency. The same key with a different body is rejected as idempotency_key_reused.
Reported by official SDKs, for deprecation targeting.
Envelope
Success wraps the resource in data; failure carries a five-field error. Both carry meta.request_id, so a failed request is as traceable as a successful one.
// Success
{
"data": { "id": "cus_9f2…", "external_id": "user-0001" },
"meta": { "request_id": "req_b81…", "version": "v1" }
}
// Failure — the worked example from the specification
{
"error": {
"type": "validation_error",
"code": "customer_email_invalid",
"message": "Email is invalid.",
"details": { "field": "email" }
},
"meta": { "request_id": "req_b81…", "version": "v1" }
}A client switches on error.type for behaviour and on error.code for a message. The identifiers shown are illustrative shapes, not real records.
Conventions
Rate limits
Errors
Every one of the 84 registered codes belongs to a type, and the type fixes the HTTP status. An endpoint cannot declare a code that is not in the registry.
The request is malformed or violates a domain rule — an unbalanced ledger posting, an amount with too many decimal places.
No credentials, expired session, revoked key, or a required second factor.
Authenticated, but not permitted: a missing permission, a cross-tenant organization id, a wallet policy breach.
The resource does not exist — or is not visible in this organization and environment.
The request is valid but the state refuses it: a frozen wallet, a paused asset, an insufficient balance, a duplicate event.
An Idempotency-Key reused with a different body. A client bug, not a retry.
Too many requests. The one type where retrying unchanged is correct.
The request could not be completed. Retry with backoff.
Lifecycle
A deprecated endpoint says so in its Deprecation and Sunset response headers, and migration documentation is published before removal — never after.
The policy already has its first two cases. POST /ai/messages and POST /ai/search are marked deprecated in the v1 document with a sunset date of 2027-02-06, superseded by their conversation-scoped and knowledge-scoped replacements. Both remain in the document and keep working until that date — deprecated rather than deleted.
Artefacts
Reference
The OpenAPI document, Postman collection and generated types all exist today. Request access and tell us what you are building.