Skip to main content

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"
Server-side only

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
}
FieldTypeDescription
successbooleantrue for a 2xx response
messagestringWritten for a log line, not for matching
responseObjectobject | nullThe payload. null on most failures
statusCodenumberMirrors 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):

ParameterDefaultMaxDescription
page11-based page number
limit20100Rows 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:

HeaderValue
x-retry-afterSeconds until you may retry
x-rate-limit-remainingRequests left in the current window
x-rate-limiter-resets-atISO 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

EndpointAuthDocumented at
POST /api/v1/ordersAPI keycreateCheckout
GET /api/v1/merchants/meAPI keygetMerchant
POST /api/v1/merchants/me/quotes/availabilityAPI keycheckQuoteAvailability
GET /api/v1/merchants/me/ordersAPI keyList orders
GET /api/v1/orders/{orderId}NoneGet an order by id
GET /api/v1/merchants/me/paymentsAPI keyList payments
GET /api/v1/merchants/me/orders/{orderId}/paymentsAPI keyList payments for an order
POST /api/v1/merchants/me/orders/{orderId}/payments/{paymentId}/recreateAPI keyRecreate
POST /api/v1/merchants/me/orders/{orderId}/payments/{paymentId}/extendAPI keyExtend
POST /api/v1/merchants/me/orders/{orderId}/payments/{paymentId}/fulfill-sarAPI keyFulfill from a transaction id
GET /api/v1/merchants/me/orders/{orderId}/actions/{actionId}API keyPoll an action
POST /api/v1/webhooksAPI keyWebhook setup
POST /api/v1/sandbox/test-orderSandbox keyLet a coding agent integrate
GET /api/v1/integration/statusAPI keyLet 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.