General Info
REST Basic Info
- The REST base URL referenced in this document:
https://api-sepolia.p99.world/api/v1(testnet). - All endpoint responses are JSON.
- All times and timestamps are UNIX time. Spot endpoints use seconds unless explicitly noted as
tsending in milliseconds (the public-trade websocket push andGET /spot/tradestsfield are milliseconds — the only millisecond-precision timestamps in the spot API). - All numeric amounts (prices, balances, quantities) are returned as strings to preserve precision.
Authentication
/spot/* and /admin/spot/* endpoints sit behind the project-wide auth middleware. Three schemes are accepted:
| Scheme | Header | Use for |
|---|---|---|
| Bearer JWT | Authorization: Bearer <JWT> | All /spot/* endpoints (read + write). |
| API Key (HMAC-SHA256) | X-MBX-APIKEY: <api_key> + ?timestamp=<ms>&signature=<hex> | All /spot/* endpoints except POST /spot/transfer and POST /spot/withdraw/request (those reject API-key callers with 403 API Key permission denied). |
| Admin API Key | X-API-Key: <ADMIN_API_KEY> | All /admin/spot/* endpoints. |
GET /wallet/tokens is public (no auth required). All GET /spot/* market-data endpoints (/spot/markets, /spot/depth, /spot/trades, /spot/klines, /spot/ticker/24hr, /spot/health) are public too.
HMAC Signing
The HMAC scheme is Binance-compatible:
payload = query_string_without_signature + body_string
signature = hex( HMAC_SHA256(secret_key, payload) )
final_url = ${BASE}${PATH}?<query>×tamp=<ms>&signature=<hex>
timestampis in milliseconds, must be within±5000 msof server time.- For
GET/DELETE: parameters go in the query string, body is empty. - For
POST: timestamp goes in the query string, parameters in a JSON body. The signature payload istimestamp=<ms>concatenated with the raw JSON body bytes.
See POST /api-keys for issuing user API keys (uses the perp-side endpoint; the keys returned work for spot too).
Endpoint Conventions
- For
GET/DELETEendpoints, parameters must be sent in the query string. - For
POSTendpoints, parameters are sent in a JSON body. Thetimestampquery parameter (HMAC scheme) is the only thing in the query string for these. - There is no requirement for parameter ordering.
- Symbol matching is case-sensitive — use
DFUSDT, notdfusdt.
Response Envelope
GET /wallet/tokens uses the project-standard envelope:
{ "success": true, "data": [...], "error": null, "timestamp": 1778312000 }
The other spot endpoints currently return data directly (bare object / array) on success. Errors are {"error": "<STRING_CODE>"} plus the relevant HTTP status.
HTTP Return Codes
| Status | Meaning |
|---|---|
200 | Success. |
400 | Request validation or engine pre-check failed. Body has error with a string code (see Error Codes). |
401 | Auth failed: missing / invalid JWT, missing / wrong HMAC signature, or expired timestamp. |
403 | Forbidden: API-key calling a JWT-only endpoint, or addressing another user's resource. |
404 | Resource not found (or hidden because it belongs to another user). |
409 | Conflict: market in halted status. |
410 | Gone: market in delisted status. |
503 | Engine unavailable: spot trading disabled, ENGINE_BUSY (mpsc backlog full), or ENGINE_RESTARTING (recovery in progress). Transient — retry with backoff. |
500 | Server fault: usually DB_ERROR. |
Rate Limits
- No per-user weight limits are enforced today (MVP). Plan for
~50 req/sper user across all/spot/*endpoints. - The matching engine has an internal mpsc backlog; if it fills, place / cancel / status return
503 ENGINE_BUSY. Retry with exponential backoff (200 ms → 400 ms → 800 ms, max 5 retries).
Conventions in this Documentation
- Each endpoint page lists HTTP method + path, auth scheme(s), request parameters (with type & whether required), a response example, and a cURL + Python snippet.
- Parameter types:
STRING,NUMBER,DECIMAL(string-encoded for precision),BOOL,LONG(unix timestamp). - Order amounts shown in examples assume the testnet
DFUSDTmarket (tick_size=0.0001,lot_size=0.01,min_notional=1).