getting-startedConventions

Conventions

Rules that hold across every endpoint in the Merchant API.

Content type

JSON request and response bodies use application/json. A response may include a charset=utf-8 parameter. Content-Encoding: gzip describes compression, not a different JSON shape. A 304 response has no body. WebSocket messages follow their own frame contract.

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": null
}
  • Pass next_cursor back as the cursor query param to fetch the next page.
  • next_cursor is null 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 current HTTP API uses /api/v1/merchant/.... This documentation does not specify a deprecation window or a release date for a future major version. The HTTP path version, WebSocket frame version, and OpenAPI specification format are separate version numbers.

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

Authenticated merchant requests are subject to a per-merchant budget. When the rate limiter is available, these headers describe the current burst window; do not require them on every response (for example, authentication failures):

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: 1 for the general burst window, 10 for the sustained window, and 60 for full dumps. General limits are 200 requests per second and 1,000 per 10 seconds; full dumps use a separate one-request-per-60-seconds limit, including conditional requests. Honor the header and use backoff with jitter. These REST request limits are separate from webhook delivery retries and WebSocket frame limits.