v1.16.0 - 2026-02-13
Added
-
New endpoint:
POST /heartbeatfor automatic order cancellation (dead man's switch)Automated trading systems can now send periodic heartbeat pings. If no heartbeat is received within the configured timeout, all open orders for the maker are automatically cancelled.
Request example:
// With EIP-712 signature const response = await fetch('/heartbeat', { method: 'POST', headers: { 'x-apikey': API_KEY, 'Content-Type': 'application/json' }, body: JSON.stringify({ maker: '0xYourAddress', timeout: 60, // Cancel all orders if no ping within 60 seconds signature: '0x...', signature_deadline: Math.floor(Date.now() / 1000) + 30 }) }); // With one-click session (no signature needed) const response = await fetch('/heartbeat', { method: 'POST', headers: { 'x-apikey': API_KEY, 'x-one-click': SESSION_HASH, 'Content-Type': 'application/json' }, body: JSON.stringify({ maker: '0xYourAddress', timeout: 60 }) });Replay protection: When using signatures,
signature_deadlinemust be strictly greater than the last accepted deadline for the maker (deadline monotonicity). Deadlines are bounded to 30 seconds in the future.Benefits: Prevents stale orders from sitting on the book when trading bots crash or lose connectivity.
-
New EIP-712 signature type:
HeartbeatType8th signature type added for signing heartbeat pings:
const HeartbeatType = [ { name: 'deadline', type: 'uint256' }, { name: 'maker', type: 'address' }, { name: 'timeout', type: 'uint256' }, ]; -
WebSocket server message envelope fields:
message_idandseq_idAll server messages now include two new fields for reliability:
message_id(string): UUID v4 unique to each message — use for deduplicationseq_id(number): Monotonically increasing per connection, starting at 1 — use for gap detection
{ "kind": "event", "type": "trade", "timestamp_ms": 1677721600000, "message_id": "550e8400-e29b-41d4-a716-446655440000", "seq_id": 42, "data": { ... } }Benefits: Enables reliable message processing — detect missed messages via
seq_idgaps and avoid processing duplicates viamessage_id. -
New WebSocket message type:
resendfor message recoveryWhen a gap in
seq_idis detected, request the server to re-deliver missed messages:{ "type": "resend", "begin_seq_id": 10, "end_seq_id": 15 }- Maximum range: 100 messages per request
- Messages are cached per connection with limited capacity (LRU eviction) and TTL
- Resent messages retain their original
seq_idandmessage_id - Rate limited: 5 requests per 10 seconds
Benefits: Enables reliable, lossless event processing without requiring full resubscription after brief network hiccups.
-
New error codes for enhanced validation feedback
Three new error codes added to
StandardError:SIGNATURE_DEADLINE_STALE— Signature deadline is not strictly greater than the last accepted deadline (replay protection)ONE_CT_USER_MISMATCH— One-click trading session was created by a different address than the maker/taker in the requestVALUE_INVALID— A request field has an invalid value (e.g., heartbeat timeout out of range)
Changed
-
Breaking Change: Market and combo trade responses simplified
The
unprocessedOrdersandrejectedOrdersfields have been removed fromPOST /marketandPOST /comboresponses.Before:
{ "fillResult": { ... }, "filledOrders": [...], "rejectedOrders": [...], "unprocessedOrders": [...] }After:
{ "fillResult": { ... }, "filledOrders": [...] }Migration: Remove references to
rejectedOrdersandunprocessedOrdersfrom response handling code. All successfully processed orders appear infilledOrders.Benefits: Cleaner response structure — these fields were vestigial and always empty in practice.
-
PATCH /limitnow triggers IOC matching for non-post-only orders crossing the marketWhen editing a non-post-only order to a price that crosses the market (e.g., buy price above best ask), the order triggers immediate matching against resting orders (IOC-style). The order's
filled_amountresets to 0 and the new size is used for matching.Before: Edited orders that crossed the market were rejected.
After: Non-post-only edited orders that cross the market are immediately matched. Post-only orders crossing the market are still rejected with
post only violation.Benefits: More flexible order editing for aggressive traders — modify orders without needing to cancel and re-submit.
-
Price and size increment validation now applies to liquidation orders
Liquidation orders are no longer exempt from price and size increment constraints. All orders (including
liquidation: true) must comply with the same increment rules returned byGET /api/v1/exchange_info.Benefits: Consistent validation across all order types ensures orderbook integrity.
-
Account history endpoint sorting enhanced
The
sortparameter has been replaced with two parameters:sortKey: Field to sort by —timestamp(default) orrealized_pnlsortOrder: Direction —desc(default) orasc
Response now includes
total_countandtotal_pageswhen available.Before:
GET /account_history?address=0x...&sort=descAfter:
GET /account_history?address=0x...&sortKey=timestamp&sortOrder=desc GET /account_history?address=0x...&sortKey=realized_pnl&sortOrder=ascMigration: Replace
sortparameter withsortKey+sortOrder.Benefits: Sort by realized P&L for performance analysis; total counts enable proper pagination UI.
-
POST /calculate_user_riskresponse:future_settlement_projectionsnow requiredThe
future_settlement_projectionsfield is now always present in the response (previously optional). -
WebSocket rate limit corrections
Message Type Rate Limit Window (corrected) subscribe10 requests 1 second (was documented as 10 seconds) unsubscribe10 requests 1 second (was documented as 10 seconds) unsubscribe_all1 request 1 second (was 10 req/10s)
Documentation
- Added
POST /heartbeatendpoint to OpenAPI specification - Added
HeartbeatTypeas 8th EIP-712 signature type to signatures guide - Added
resendmessage type with full request/response examples to WebSocket documentation - Added server message envelope fields (
message_id,seq_id) section to WebSocket documentation - Added gap detection example code to WebSocket documentation
- Updated rate limit table with
resendentry and corrected windows - Clarified WebSocket heartbeat note: "no WebSocket-level ping/pong" vs REST heartbeat endpoint
