Getting StartedConventions

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/json

Money

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_id is 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_cursor back as the cursor query param to fetch the next page.
  • next_cursor is null (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.
  • limit defaults and caps differ per endpoint — consult each API reference page. Most listings default to 50 and cap at 200; /items/search is tighter (default 10, cap 50).

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: 187

When 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.