Conventions
Every endpoint of the LEXX API follows the same small set of rules. Read this page once and nothing in the reference will surprise you.
The response envelope
Every successful response is an object with exactly two top-level keys:
{
"data": { "...": "the payload — object, array, or null" },
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": 1743360060000,
"version": "v2.0"
}
}
meta fields:
| Field | Always present? | Meaning |
|---|---|---|
requestId |
✅ | Unique ID of this request (UUID). Log it — it is the first thing LEXX support asks for |
timestamp |
✅ | Server time of the response, Unix milliseconds |
version |
✅ | API version, currently "v2.0" |
idempotencyKey |
on mutating requests | Echo of your X-Idempotency-Key header on a successful POST/DELETE — see Idempotency |
Errors use a different envelope — same idea, different keys:
{
"error": { "code": "RATE_LIMITED", "status": 429, "message": "Rate limit exceeded…" },
"meta": { "requestId": "550e8400-e29b-41d4-a716-446655440005" }
}
All codes and handling advice: Errors.
🧬 The one legacy exception:
GET /pingresponds in the v1 envelope{ "status": "success", "data": { "message": "pong", "timestamp": … } }. Every other endpoint uses the v2 shapes above.
Money is strings
All monetary values — prices, quantities, balances, PnL — are string-encoded decimals:
{ "asset": "USDT", "free": "10450.50", "locked": "2500.00" }
JSON numbers are IEEE-754 floats; 0.1 + 0.2 !== 0.3 is not a rounding style you want in
order quantities. Handle the strings with a decimal type:
// JavaScript — keep as string, do math with a decimal library
import Big from "big.js"; // or decimal.js / bignumber.js
const free = new Big(balance.free); // never: parseFloat(balance.free)
# Python
from decimal import Decimal
free = Decimal(balance["free"]) # never: float(balance["free"])
And symmetrically: when sending amounts (quantity, price, amount, …), send strings —
"quantity": "0.001", not "quantity": 0.001.
One documented exception:
- Bot configuration knobs that are not money — percentages, counts, millisecond
durations (
trailingDelta,timeFrame, filter thresholds, …) — are plain numbers, as defined per-field in the bot guides.
Time is Unix milliseconds
Every timestamp in the API — request header X-LEXX-TIMESTAMP, from/to/startTime/
endTime parameters, orderTime, updateTime, WebSocket ts, bot Fn.Format keys — is
Unix time in milliseconds (1743360060000), UTC.
The only two seconds-based values in the whole API are the rate-limit headers:
X-RateLimit-Reset(Unix seconds) andRetry-After(seconds to wait). Everything else is milliseconds.
There are no ISO-8601 dates anywhere in requests or responses.
Identifiers
Order IDs are LEXX-generated client order IDs; the exchange’s native numeric ID is never exposed. The format depends on the exchange:
| Exchange | Order id format |
|---|---|
| binance-spot | x-MTB46TF3-{uid} |
| binance-futures | x-MZ8FjHFm-{uid} |
| OKX (spot/futures/swap) | lexxO{uid} (no dashes) |
| Bybit | lexx-{uid} |
Orders created by a bot append the run ID as a final segment: x-MZ8FjHFm-{uid}_{runId}.
An order’s ID is stable for its whole lifetime; a split (and any modify-style operation)
cancels the original and creates new orders with new IDs.
Bots have an id (stable) and, while running, a runId (new for every start). Both appear
in bot endpoints and in the botStatus WebSocket channel.
Pagination
The API pages by time window:
GET /orders/trades—startTime/endTime(Unix ms) +limit(1–500, default 100; out-of-range values are silently clamped — no error). Page by shifting the time window: request the next window starting at the timestamp of the last record you received.GET /orders,GET /bots— intentionally unpaginated (bounded, served from live state).
Remember the query string is part of the request signature.
Request bodies
- JSON only, with
Content-Type: application/json. - Serialize compactly (no pretty-printing) — the body string is part of your signature and the signed bytes must equal the sent bytes.
- Bodies are capped at 100 KB; larger requests are rejected with
413 PAYLOAD_TOO_LARGE.
Response headers
Every response carries the rate-limit trio X-RateLimit-Limit / X-RateLimit-Remaining /
X-RateLimit-Reset; 429 adds Retry-After. How to self-throttle with them:
Rate limits.
Verified against API spec v2.0.0 · 2026-07-11