API Reference
The SDK covers order creation. Everything else you may want from your backend, such as looking up an order or listing settled payments, is a plain HTTP call against the same API. This section documents those endpoints.
Base URL
https://api.pay.peer.xyz
Every path on these pages is relative to that host and lives under /api/v1.
Authentication
Merchant endpoints take your API key in the X-API-Key header. The key lives under
Settings, Developer in the merchant dashboard; see
API keys and webhooks for rotation rules.
curl https://api.pay.peer.xyz/api/v1/merchants/me/orders \
-H "X-API-Key: $ZKPAY_API_KEY"
An API key reads and creates orders for your whole account. Send it only from a trusted backend, never from browser or mobile code.
Sandbox and live are separate accounts with separate keys. A sandbox key sees only sandbox
orders and payments, and a live key sees only live ones. A missing or unknown key returns
401 with the message Missing API key or Invalid API key.
One endpoint, get an order by id, takes no key at all. It is the read the hosted checkout page uses, and the order id is the only credential.
Response envelope
Every response, success or failure, is a JSON object with the same four fields:
{
"success": true,
"message": "Merchant orders retrieved",
"responseObject": { "...": "..." },
"statusCode": 200
}
| Field | Type | Description |
|---|---|---|
success | boolean | true for a 2xx response |
message | string | Written for a log line, not for matching |
responseObject | object | null | The payload. null on most failures |
statusCode | number | Mirrors the HTTP status |
A 400 from query or body validation carries the validation detail in responseObject:
{
"success": false,
"message": "Invalid request",
"responseObject": {
"formErrors": [],
"fieldErrors": { "limit": ["Number must be less than or equal to 100"] }
},
"statusCode": 400
}
Some failures also carry a top-level errorCode string you can branch on. The order
creation codes are listed under createCheckout errors.
Pagination
The order and payment lists page with two query parameters and report the total (list payments for an order returns every row for one order and takes neither):
| Parameter | Default | Max | Description |
|---|---|---|---|
page | 1 | — | 1-based page number |
limit | 20 | 100 | Rows per page |
The payload carries the rows, total matching rows across all pages, and the page and
limit that were applied. Rows are always newest first. A limit above 100 is rejected
with 400, not clamped.
Dates and amounts
Timestamps are ISO 8601 strings in UTC, for example 2026-09-03T10:15:42.318Z. Amounts are
decimal strings, never floats: "25" or "12.5" for USDC fields and "23.14" for fiat
fields. Trailing zeros are not preserved, so parse rather than string-compare.
Chain ids are decimal strings too, so Base is "8453".
Rate limits
The API allows 1200 requests per minute per source IP across all endpoints. Past that it
answers 429 with the message Too many requests and three headers:
| Header | Value |
|---|---|
x-retry-after | Seconds until you may retry |
x-rate-limit-remaining | Requests left in the current window |
x-rate-limiter-resets-at | ISO 8601 time the window resets |
Remediation endpoints add a per-merchant limit (30
actions and 120 reads per minute) with the same 429 shape.
There is no standard Retry-After header. Webhook deliveries are what tell you an order
changed; poll these endpoints for reconciliation, not as your primary signal.
Endpoints
| Endpoint | Auth | Documented at |
|---|---|---|
POST /api/v1/orders | API key | createCheckout |
GET /api/v1/merchants/me | API key | getMerchant |
POST /api/v1/merchants/me/quotes/availability | API key | checkQuoteAvailability |
GET /api/v1/merchants/me/orders | API key | List orders |
GET /api/v1/orders/{orderId} | None | Get an order by id |
GET /api/v1/merchants/me/payments | API key | List payments |
GET /api/v1/merchants/me/orders/{orderId}/payments | API key | List payments for an order |
POST /api/v1/merchants/me/orders/{orderId}/payments/{paymentId}/recreate | API key | Recreate |
POST /api/v1/merchants/me/orders/{orderId}/payments/{paymentId}/extend | API key | Extend |
POST /api/v1/merchants/me/orders/{orderId}/payments/{paymentId}/fulfill-sar | API key | Fulfill from a transaction id |
GET /api/v1/merchants/me/orders/{orderId}/actions/{actionId} | API key | Poll an action |
POST /api/v1/webhooks | API key | Webhook setup |
POST /api/v1/sandbox/test-order | Sandbox key | Let a coding agent integrate |
GET /api/v1/integration/status | API key | Let a coding agent integrate |
Cancelling an order and reading a single order through the merchant-scoped path need a dashboard session, so they are not available to an API key. Cancel from the dashboard.