Skip to content

Requests, Pagination, and Retries

Send JSON to https://api.trade8.xyz. Paths include the /v1/ version. Amounts, prices, rates, and leverage multipliers are decimal strings; counts and sequence numbers are integers. Timestamps use UTC RFC 3339, while signing timestamps use whole Unix seconds.

Public market and exchange GET responses use Cache-Control: public, max-age=300. Last-Modified records when the bundled exchange metadata was refreshed. Private responses and errors use Cache-Control: no-store.

Private reads and DELETE requests select account_id in the query. POST, PATCH, and PUT operations carry it in the JSON body. Transfers use from_account_id as the source account and require a key with access to both accounts. The key’s grants are checked on every request.

List endpoints return a named array and a pagination object:

{
"fills": [],
"pagination": {
"next_cursor": "cursor_example_next",
"has_more": true
}
}

Supply next_cursor as the next request’s cursor, keeping the other filters and page size unchanged. /v1/markets defaults to 10 instruments per page; other lists default to 50 records. The maximum limit is 200. Cursors are opaque and belong to that query. next_cursor: null and has_more: false mark the end.

Order, trade, fill, transfer, and deposit history sorts ascending by creation or execution time, with the record ID as a stable tie-breaker. Settlement history sorts by cycle_end, then settlement_id. Catalogs and current-state lists sort by their primary identifier. Catalog cursors also bind the snapshot revision; restart from the first page after a revision change. Cursors preserve the initial query’s result boundary while that traversal is active.

History filters use an inclusive start_time and exclusive end_time. When omitted, end_time is the first request time and start_time is 24 hours earlier. A cursor carries those boundaries forward. The status=open order query includes all open orders by default; time filters apply only when explicitly supplied.

import { request } from './rest-client.mjs';
const filters = {
account_id: 'acct_example_main',
start_time: '2026-08-31T00:00:00.000Z',
end_time: '2026-09-01T00:00:00.000Z',
limit: '100',
};
let cursor;
do {
const query = new URLSearchParams(filters);
if (cursor) query.set('cursor', cursor);
const page = await request('GET', `/v1/fills?${query}`);
for (const fill of page.fills) {
// Persist using fill_id as a unique key.
console.log(fill.fill_id, fill.venue, fill.fee_asset);
}
cursor = page.pagination.next_cursor;
} while (cursor);

Persist a timestamp and record ID alongside your cursor. If a cursor expires, restart with an overlapping time window and deduplicate records. See Stream Recovery for combining REST history with live events.

Every mutation requires Idempotency-Key, a string of 1–64 letters, digits, underscores, or hyphens. A key identifies a request within its account, HTTP method, and path. Keep it for retries of that operation. Trade8 retains the request identity and result for 24 hours.

The fingerprint includes the encoded query and exact request body. Reusing the key with different content returns IDEMPOTENCY_CONFLICT. Sign each retry with a fresh timestamp and the same idempotency key, query, and body. An in-progress request returns REQUEST_IN_PROGRESS; wait and reconcile before retrying.

client_order_id identifies the business order for the lifetime of the account. It remains useful after the idempotency window expires. Allocations and transfers use client_allocation_id and client_transfer_id for the same purpose. A key replay returns the original acknowledgement; a resource lookup returns current state.

  1. Keep the original request, client order ID, and idempotency key.
  2. Look up /v1/orders/by-client-id/{client_order_id}.
  3. If found, continue tracking that order and its fills.
  4. If absent and still within 24 hours, retry the exact request with the same idempotency key and a fresh signature.
  5. If the result remains uncertain after the retention window, reconcile order history and contact support before submitting a replacement.

A cancellation or amendment timeout follows the same pattern: read the existing order, inspect its revision and quantities, then decide whether another operation is needed.

Header Meaning
X-RateLimit-Limit Budget for the bucket used by this request
X-RateLimit-Remaining Remaining units in that bucket
X-RateLimit-Reset Bucket reset time as whole Unix seconds
Retry-After Seconds to wait after a 429 or temporary 503 response
X-Request-ID Identifier to include in a support report

REST limits are account-scoped. Order mutations consume an additional order budget. Batch requests consume one order unit per item. Read account limits for your configured capacity.

Honor Retry-After, add jitter to reconnects, and reconcile timed-out mutations before retrying. Cancel operations share the order budget, so reserve capacity for risk-reducing actions.

Account access

Jurisdiction Restriction

Trade8 is not available in your jurisdiction.

You can still explore the product and read the documentation.

Explore the Docs