Conventions
Rules that hold across every endpoint in the Merchant API.
Content type
All requests and responses are application/json; charset=utf-8 unless explicitly noted
(currently the only exception is GET /merchant/items/full-dump, which adds
Content-Encoding: gzip when the client advertises it).
Content-Type: application/jsonMoney
All money amounts are USD, JSON numbers, ≤ 2 decimals:
{ "available": 1234.56, "on_hold": 0 }Use a fixed-precision type (decimal.Decimal in Python, bignumber.js in Node, decimal
in C#). Floats are unsafe for accounting.
Timestamps
ISO 8601 UTC, Z suffix:
{ "created_at": "2026-05-05T16:00:00.000Z" }Never local time. Always parse as UTC.
Identifiers
- All resource IDs (
purchase_id,item_id,event_id, etc.) are UUIDs unless explicitly typed otherwise. custom_idis your string, length ≤ 100. Use a stable value from your system (e.g. your own internal order ID) so retries are idempotent.
Pagination
Listings use cursor pagination:
{
"items": [ /* ... */ ],
"next_cursor": "eyJjcmVhdGVkX2F0..."
}- Pass
next_cursorback as thecursorquery param to fetch the next page. next_cursorisnull(or omitted) when you have reached the end.- Do not parse or rely on the cursor’s contents — it is opaque and may change format.
limitdefaults and caps differ per endpoint — consult each API reference page. Most listings default to50and cap at200;/items/searchis tighter (default10, cap50).
Versioning
The API is versioned in the URL path: /api/v1/.... Breaking changes ship under a new
major version (/api/v2/...); v1 will continue to work in parallel during a deprecation
window.
Forward-compatible changes that we may make to v1 without notice:
- Adding new optional fields to responses.
- Adding new event types to webhooks (your handler must ignore unknown event types — see Webhooks → Event Catalogue).
- Adding new optional query parameters and request body fields.
Tolerate these on your side: parse JSON leniently, do not fail on unknown keys.
Rate limiting
Per-merchant request budget. Every /merchant/* response carries the current burst window:
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 187When the budget is exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 10{ "error": { "code": "MERCHANT_RATE_LIMITED", "message": "..." } }Retry-After is in seconds and varies by endpoint (1s burst, 10s sustained, longer for
heavier endpoints such as /items/full-dump). Honour it; layer exponential backoff with
jitter on top.