Response shape
Success:redirectUrl, and a free order returns free: true. Paginated lists return data, total, page, pages, hasNext, hasPrev.
Error:
Status codes
Machine codes
Selectedcode values worth handling in code:
New codes may appear — treat an unknown
code according to its statusCode.
Validation
The API rejects invalid data before processing it. Fields outside the schema are ignored and types are converted automatically (e.g. numbers from the query string). Lists acceptpage and limit; limit is clamped to a safe maximum (usually 100).
Rate limits
The whole REST API has a global limit per real client IP. Production configuration: 200 requests per minute (RATE_LIMIT_MAX=200, RATE_LIMIT_WINDOW=60000); the platform operator can change both values.
Sensitive routes have additional, stricter fixed windows, counted per IP and route:
Login routes have their own brute-force limits. Payment webhooks are protected per provider and shop while keeping the provider’s retry semantics.
Counters for sensitive routes are shared through Redis across API instances. If Redis is briefly unavailable, each instance keeps a bounded in-memory counter — protection doesn’t disappear, it just becomes per-instance.
Retries
Retry only429, 500, 503 and network errors. Don’t retry 400, 401, 403, 404.
- If a
429response has aRetry-Afterheader, wait that many seconds. Not every response has it (stricter per-route limits don’t send it) — then use backoff. - Exponential backoff with jitter: e.g. 1 s, 2 s, 4 s ± random 0–500 ms, a few attempts at most.
- Never retry immediately in a loop — it only extends the block.
Idempotency
Creating an order (POST /orders, and from 3.0 also POST /storefront/v1/shops/<shopId>/checkout) requires an Idempotency-Key header:
- a random value of 32–128 chars (
A-Z a-z 0-9 _ -), e.g. a UUID without dashes or base64url; - generate it once per purchase attempt and reuse it only when retrying the identical request;
- a retry with the same key and the same body returns the same order instead of creating a second one;
- the same key with a different body →
409 IDEMPOTENCY_KEY_REUSED; a closed attempt →409 CHECKOUT_ATTEMPT_CLOSED.
Next
API with a key
Keys, scopes and your first request.
Webhooks
Discord notifications and payment-provider webhooks.