Real-Time tier · Reference card · API Academy

Real-Time.
One sheet.

Websocket connection shape, subscription channels, depth vs delta semantics, the rate-limit headers you’ll actually read, exponential-backoff math, and the error-class decision tree. Pin it; print it; come back to it.

Authentication: every request is HMAC-signed.

REST calls and websocket handshakes both carry the HMAC trio (lmts-api-key + lmts-timestamp + lmts-signature), computed per the scheme at docs.limitless.exchange/developers/authentication. The legacy X-API-Key / api_key shortcut is deprecated and no longer issued to new users.

01

Websocket connection

M07

HMAC handshake on the upgrade request, same three lmts-* headers as REST. See docs.limitless.exchange/developers/authentication.

// HTTP upgrade with HMAC headers wss://stream.limitless.exchange/v1 lmts-api-key: <apiKey> lmts-timestamp: 2026-05-07T18:23:11.482Z lmts-signature: <base64 HMAC-SHA256> // First server message { "type": "hello", "session": "…", "heartbeat_ms": 15000 }

Heartbeat. Server sends a ping every 15s. Reply with pong. Two missed pings → close + reconnect.

02

Subscriptions

M07
{ "op": "subscribe", "channel": "orderbook", "market": "arsenal-win-prem-25" } // Channels (TODO: verify) orderbook // bids + asks deltas trades // tape feed positions // your fills errors // server-side

One channel + market per subscribe. Multiplex by sending many subscribe ops on the same socket.

03

Snapshot vs delta

M08

First message after subscribe: full snapshot. Subsequent: delta updates.

// snapshot { kind: "snapshot", bids: [[0.55, 1200], …], asks: [[0.56, 800], …] } // delta { kind: "delta", bids: [[0.55, 0]], // removed asks: [[0.57, 500]] } // added

Sequence numbers. Each delta carries seq. If seq jumps, you missed a message → resubscribe for fresh snapshot.

04

Rate-limit headers

M09
X-RateLimit-Limitreq/window
X-RateLimit-Remainingreq left
X-RateLimit-Resetepoch when window resets
Retry-Afterseconds; only on 429

TODO: confirm Limitless’ tier limits (default / signed / market-maker).

05

Exponential backoff + jitter

M09
delay = min(cap, base × 2^attempt) + random(0, 1s) jitter

Defaults. base = 250ms, cap = 30s, maxAttempts = 8.

Jitter is non-optional. Without it, every client retries simultaneously and you create the reconnect storm you were trying to avoid.

06

Idempotency keys

M10

Every state-changing POST gets a client-side nonce (UUID v4 or timestamp+random).

POST /orders lmts-api-key: <apiKey> lmts-timestamp: … lmts-signature: <base64 HMAC-SHA256> X-Wallet-Signature: 0x… X-Wallet-Nonce: 1714683600 Idempotency-Key: 9b2d…

On 5xx: safely retry with the SAME idempotency key. The server dedupes; you don’t double-place.

Never reuse a key across different intents.

07

Error-class decision tree

M10
  • 4xx (client). Don’t retry. Fix the request shape, log loudly. 401 → re-sign / refresh key. 422 → validate.
  • 409 (conflict / nonce reuse). Refresh nonce, retry once. Hard-stop if it persists, you have a state bug.
  • 429 (rate limited). Honour Retry-After. Drop request rate by 50% in your local limiter for the next minute.
  • 5xx (server). Retry with exp backoff + jitter (idempotency key required). Cap at 8 attempts.
  • Network / timeout. Retry as 5xx. If a write was in-flight, the idempotency key prevents double-execute.
  • Websocket close. Reconnect with full backoff. Re-subscribe channels. Watch for sequence-number gaps in the next snapshot.
08

Real-time pitfalls

Cross-module
  1. Reconnect storms. One disconnect → thousands of clients reconnect simultaneously. Always add jitter; cap per-host concurrent reconnects at 1.
  2. Missed sequence numbers. If seq jumps, you missed a delta. Don’t patch silently, resubscribe to get a fresh snapshot.
  3. Bot keeps polling after rate-limit. Honour Retry-After. Local limiters should mirror the server’s view, not your wishful one.
  4. Idempotency key reuse. Generate once per intent, never per retry. Reuse-across-intents is how you accidentally double-place.
  5. Confusing 429 with 503. 429 says “you’re too fast” (slow down). 503 says “I’m down” (back off). Treat differently.
  6. Buffering deltas during reconnect. Drop the buffer; the snapshot is the source of truth. Old deltas applied after a snapshot will corrupt your local book.