These routes take a dashboard session (Authorization: Bearer <jwt> from signing in), not an API key. Most people use the dashboard screens instead.
API keys#
| Route | Does |
|---|---|
POST /merchant/api-keys |
Creates a key: { "name": "Production Server", "scopes": ["invoices:write", "invoices:read"], "environment": "live" } (name required, at least one scope; environment live or test, and when omitted the mode the account is in). Answers 201 { "apiKey", "id", "prefix", "scopes", "environment" } — apiKey is shown once and never stored |
GET /merchant/api-keys |
{ "keys": [ { "id", "name", "prefix", "scopes", "environment", "status", "createdAt", "lastUsedAt", "revokedAt" } ] } |
POST /merchant/api-keys/:id/revoke |
Invalidates the key at once (requests with it answer 401). Answers { "success": true } |
POST /merchant/api-keys/:id/rotate |
Creates a new key with the same name, scopes and mode and revokes the old one, atomically. Only an active key can be rotated. Answers 201 like create |
Invoices#
| Route | What it does |
|---|---|
POST /merchant/invoices/:id/simulate-payment |
The dashboard's Simulate payment button: the same as POST /invoices/:id/simulate-payment, for an account in Test mode |
Checkout buttons#
HTTP
POST /merchant/checkout-buttons # create
GET /merchant/checkout-buttons # list (each with an absolute payUrl)
GET /merchant/checkout-buttons/:id # one button
PATCH /merchant/checkout-buttons/:id # edit (not kind or config), or deactivate with { "active": false }
POST /merchant/checkout-buttons/:id/signing-secret # rotate the signing secret
DELETE /merchant/checkout-buttons/:id # delete| Field | Type | Required | Description |
|---|---|---|---|
kind |
"invoice" | "subscription" |
Yes | One-off payment or subscription signup |
label |
string | Yes | Your internal name (not shown to customers) |
config |
object | Yes | invoice: { chainId, assetType, assetContract (tokens only), amountDecimal, assetKey } — amount in base units is also accepted · subscription: { planId, subscriberRefField }. Cannot be changed after creation |
appearance |
object | No | { text, color } — button text and hex colour |
allowedFields |
array | No | [{ name, label, required }] — the reference fields the link may carry (at most 10; a name is a lowercase letter then up to 39 lowercase letters, digits or _; no duplicates) |
successUrl |
string | No | Absolute http(s) URL to send the customer after payment |
cancelUrl |
string | No | Absolute http(s) URL |
maxOpenInvoices |
number | No | Most unpaid invoices open at once for this button: a whole number from 1 to 1000 (default 20) |
allowedOrigins |
string[] | No | Up to 20 hostnames a press may come from; empty = any site |
requireSignature |
boolean | No | Refuse unsigned links. Always true for a subscription button |
The create response carries signingSecret once; no read returns it again. POST …/signing-secret issues a new one (shown once) and the old one stops verifying at once. Every button view carries allowedOrigins, requireSignature and hasSigningSecret.