Overview
One gateway. Two execution modes. Zero floating-point math.
In Order Book Trading (OBT) mode the gateway exposes a live WebSocket order book. Subscribe to a pair, read the top-of-book price, and fire orders directly against the book — all in the same connection..
Live Book
Subscribe to real-time bid/ask snapshots for any supported pair.
Direct Orders
Send LIMIT or MARKET orders in-band over the same WebSocket.
Precision
12-decimal strings end-to-end. No silent rounding, ever.
In Request for Quote (RFQ) mode you first lock a price with a quote request, then execute against it before the TTL expires. The REST API handles the full lifecycle; a WebSocket connection receives push events for order and quote updates.
Price Lock
Quotes are locked for a client-specified window (up to 60 s).
Push Events
WebSocket streams order fills and quote expiries as they happen.
Precision
12-decimal strings end-to-end. No silent rounding, ever.
"10000.000000000000") for monetary values.
Parsing as float64 will silently corrupt your books.
Prerequisites
Get your credentials and generate an RSA key pair.
Contact your admin to request:
- api_key_id — UUID, e.g.
6536b3d3-5a3b-4e1a-910e-49478b9efe20 - RSA-2048 private key — used to sign challenges. Keep secret.
openssl genrsa -out client_private.pem 2048 openssl rsa -in client_private.pem \ -pubout -out client_public.pem # Share client_public.pem with your admin. # Keep client_private.pem secret — never commit or log it.
Authentication
5-step challenge-response handshake + Diffie-Hellman key exchange.
curl -X POST http://localhost:8080/api/v1/login/attempt \
-H "Content-Type: application/json" \
-d '{
"api_key_id": "6536b3d3-5a3b-4e1a-910e-49478b9efe20"
}'{
"session_id": "049c1bf2-0fff-4267-93ac-e78bf6d7f613",
"challenge": "<base64>",
"dh_base": "<base64>",
"dh_modulus": "<base64>",
"ttl_ms": 30000
}import base64, secrets, hashlib
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
import requests
API_KEY_ID = "6536b3d3-5a3b-4e1a-910e-49478b9efe20"
# Step 1
resp = requests.post("http://localhost:8080/api/v1/login/attempt",
json={"api_key_id": API_KEY_ID})
data = resp.json()
session_id = data["session_id"]
challenge = data["challenge"]
dh_modulus = data["dh_modulus"]
# Step 2 — Sign challenge
with open("client_private.pem", "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
challenge_bytes = base64.b64decode(challenge)
signature = private_key.sign(challenge_bytes, padding.PKCS1v15(), hashes.SHA256())
signature_b64 = base64.b64encode(signature).decode()
# Step 3 — DH keypair
RFC3526_PRIME = int("FFFFFFFF" * 32, 16) # group 14 (abbreviated)
priv_bytes = secrets.token_bytes(256)
client_priv = int.from_bytes(priv_bytes, 'big') % (RFC3526_PRIME - 3) + 2
client_pub = pow(2, client_priv, RFC3526_PRIME)
dh_key_b64 = base64.b64encode(client_pub.to_bytes(256, 'big')).decode()
# Step 4 — Confirm
resp = requests.post("http://localhost:8080/api/v1/login/confirm",
json={"session_id": session_id,
"signature": signature_b64,
"dh_key": dh_key_b64})
confirm = resp.json()
server_dh_pub = int.from_bytes(base64.b64decode(confirm["dh_key"]), 'big', signed=True)
# Step 5 — Derive shared secret
session_secret = pow(server_dh_pub, client_priv, RFC3526_PRIME).to_bytes(256, 'big')
print(f"Session: {session_id}")POST /api/v1/login/confirm
Content-Type: application/json
{
"session_id": "049c1bf2-0fff-4267-93ac-e78bf6d7f613",
"signature": "<base64-rsa-sig>",
"dh_key": "<base64-dh-pub>"
}{
"dh_key": "<server-base64-dh-pub>",
"keepalive_timeout_ms": 300000
}METHOD + urlPath + sortedQueryParams # sorted ascending by lowercase key + "X-Nonce=...&X-Session-Id=...&X-Timestamp=..." + requestBody # POST / PUT only # Example — WebSocket upgrade (no query, no body): CONNECT/v1/wsX-Nonce=abc&X-Session-Id=<uuid>&X-Timestamp=1700000000000
import hmac, hashlib, base64, uuid
from datetime import datetime
def sign_request(method, path, session_id, session_secret,
query="", body=""):
nonce = str(uuid.uuid4())
timestamp = str(int(datetime.now().timestamp() * 1000))
canonical = (method + path + query
+ f"X-Nonce={nonce}&X-Session-Id={session_id}"
+ f"&X-Timestamp={timestamp}" + body)
sig = hmac.new(session_secret, canonical.encode(), hashlib.sha384).digest()
return {
"X-Session-Id": session_id,
"X-Nonce": nonce,
"X-Timestamp": timestamp,
"X-Signature": base64.b64encode(sig).decode()
}Session Lifecycle
| Endpoint | Purpose |
|---|---|
POST /api/v1/keepalive?session_id=<uuid> | Reset inactivity timer. Call more frequently than keepalive_timeout_ms. |
POST /api/v1/logout?session_id=<uuid> | Destroy the session immediately. |
Request for Quote
RFQ Lock a price before executing.
POST /v1/rfq
X-Session-Id: 049c1bf2-...
X-Nonce: abc123
X-Timestamp: 1700000000000
X-Signature: <hmac>
{
"buy": "USDT",
"sell": "USD",
"amount": "10000.000000000000",
"referenced_unit": "USD",
"quote_for_seconds": 30
}{
"quote_id": "<uuid>",
"buy": "USDT",
"sell": "USD",
"referenced_amount": "10000.000000000000",
"quote_amount": "9150.000000000000",
"expires_at": "2024-01-01T00:00:30Z"
}# Sell 10,000 USD, receive USDT python lp_client.py rfq \ --buy USDT \ --sell USD \ --amount 10000 \ --unit USD \ --seconds 30 # --unit must match the value of --buy or --sell # --seconds defaults to 30 if omitted
Execute Order
RFQ Single endpoint, two modes. Quote-based references a prior RFQ; direct submits the whole order in one call.
POST /v1/orders
Idempotency-Key: 550e8400-...
X-Session-Id: ...
{
"quote_id": "QT-12345678",
"client_order_id": "my-order-001"
}POST /v1/orders
Idempotency-Key: 550e8400-...
X-Session-Id: ...
{
"instrument": "USD/EUR",
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "FOK",
"quantity": "10000.000000000000",
"price": "0.920000000000",
"client_order_id": "my-order-001"
}{
"order_id": "f0e1d2c3-...",
"client_order_id": "my-order-001",
"status": "FILLED",
"buy": "USDT",
"sell": "USD",
"amount": "10000.000000000000",
"lp_order_id": "",
"created_at": "2024-01-01T00:00:00Z",
"filled_at": "2024-01-01T00:00:01Z",
"filled_qty": "10000.000000000000",
"avg_price": "0.915000000000",
"last_fill_qty": "10000.000000000000",
"last_fill_price": "0.915000000000"
} List Orders
Paginated history with filters.
GET /v1/orders?status=FILLED&limit=20 X-Session-Id: ... X-Nonce: abc123 X-Timestamp: 1700000000000 X-Signature: ...
{
"orders": [
{
"order_id": "f0e1d2c3-...",
"client_order_id": "my-order-001",
"status": "FILLED",
"trade_id": "TR-987654",
"buy": "USD",
"sell": "EUR",
"amount": "9150.000000000000",
"filled_qty": "9150.000000000000",
"last_fill_qty": "9150.000000000000"
}
]
}Get Order
Single-order detail. Safe to poll indefinitely.
{
"order_id": "f0e1d2c3-...",
"client_order_id": "my-order-001",
"status": "FILLED",
"trade_id": "TR-987654",
"buy": "USD",
"sell": "EUR",
"amount": "9150.000000000000",
"balances": {
"USD": "59150.000000000000",
"EUR": "40850.000000000000"
},
"filled_qty": "9150.000000000000",
"last_fill_qty": "9150.000000000000"
}{
"order_id": "f0e1d2c3-...",
"status": "REJECTED",
"error_code": "INSUFFICIENT_BALANCE",
"error_message": "insufficient balance for USD"
}Cancel Order
Streaming mode only. Returns 204 No Content on success.
DELETE /v1/orders/550e8400-... X-Session-Id: ... X-Nonce: abc123 X-Timestamp: 1700000000000 X-Signature: ...
HTTP/1.1 204 No Content
{
"error": {
"code": "CONFLICT",
"message": "order cannot be cancelled: unsupported in quote mode",
"traceId": "<uuid>"
}
}Order Fills
Aggregated fill statistics for an order.
{
"fills": [
{
"order_id": "",
"filled_qty": "10000.000000000000",
"avg_price": "0.915000000000",
"last_fill_qty": "10000.000000000000",
"last_fill_price": "0.915000000000",
"transacted_at": "2024-01-01T00:00:01Z"
}
]
} Markets
All tradable pairs with minimum trade sizes.
GET /v1/markets X-Session-Id: ... X-Nonce: abc123 X-Timestamp: 1700000000000 X-Signature: ...
{
"markets": [
{ "pair": "USD/EUR", "minTradeSize": "100.00" },
{ "pair": "EUR/GBP", "minTradeSize": "100.00" },
{ "pair": "BTC/USD", "minTradeSize": "0.001" }
]
}WebSocket Connection
OBT Connect with HMAC-SHA384 headers.
import asyncio, websockets, uuid, hmac, hashlib, base64
from datetime import datetime
async def connect_ws(session_id, session_secret):
nonce = str(uuid.uuid4())
timestamp = str(int(datetime.now().timestamp() * 1000))
canonical = (f"CONNECT/v1/ws"
f"X-Nonce={nonce}&X-Session-Id={session_id}"
f"&X-Timestamp={timestamp}")
sig = hmac.new(session_secret, canonical.encode(), hashlib.sha384).digest()
headers = [
("X-Session-Id", session_id),
("X-Nonce", nonce),
("X-Timestamp", timestamp),
("X-Signature", base64.b64encode(sig).decode())
]
ws = await websockets.connect(
"ws://localhost:8080/v1/ws",
additional_headers=headers)
print("✓ Connected")
return wsSubscribe to Market Data
OBT Get real-time bid/ask snapshots for a trading pair.
import json
# Basic subscription
payload = {
"type": "subscribe",
"channel": "USDC/USD"
}
# Or with advanced options
payload = {
"type": "subscribe",
"channel": "USDC/USD",
"side": "BOTH",
"quantity": 0,
"subscription_request_type": "snapshot",
"type_book": "SPOT",
"agg_book": 0,
"market_depth": 0
}
await ws.send(json.dumps(payload)){
"type": "subscribe_ack",
"channel": "USDC/USD",
"code": 0,
"message": "Subscribed"
}{
"type": "market_update",
"channel": "BTC/USD",
"subscription_id": "550e8400-e29b-41d4-a716-446655440000",
"bids": [
["40000.000000000000", "0.500000000000"],
["39999.000000000000", "1.000000000000"],
["39998.000000000000", "2.000000000000"]
],
"asks": [
["40100.000000000000", "0.750000000000"],
["40101.000000000000", "1.500000000000"],
["40102.000000000000", "3.000000000000"]
],
"ttl": "3000",
"timestamp": "2026-06-24T21:20:00Z"
}Unsubscribe from Market Data
OBT Stop receiving market snapshots for a trading pair.
import json
payload = {
"type": "unsubscribe",
"channel": "USDC/USD",
"subscription_id": "685810ae-e9f6-4ab6-b298-ffd7099412ff",
"type_book": "SPOT"
}
await ws.send(json.dumps(payload)){
"type": "unsubscribe_ack",
"channel": "BTC/USD",
"subscription_id": "550e8400-e29b-41d4-a716-446655440000",
"code": 0,
"timestamp": "2026-06-24T21:21:00Z"
}Place Order
OBT Execute a trade via WebSocket.
import json, uuid
payload = {
"type": "order",
"client_order_id": "5318575b-179c-4cdc-9bce-7acfcf9d5d91",
"instrument": "BTC/USD",
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "FOK",
"quantity": "100.000000000000",
"price": "40000.000000000000"
}
await ws.send(json.dumps(payload))import json
# Market order - IOC recommended for better fill ratio
payload = {
"type": "order",
"client_order_id": "5318575b-179c-4cdc-9bce-7acfcf9d5d91",
"instrument": "BTC/USD",
"side": "BUY",
"order_type": "MARKET",
"time_in_force": "IOC",
"quantity": "100.000000000000"
}
await ws.send(json.dumps(payload))Cancel Order
import json
payload = {
"type": "cancel_order",
"instrument": "BTC/USD",
"client_order_id": "5318575b-179c-4cdc-9bce-7acfcf9d5d91"
}
await ws.send(json.dumps(payload)){
"type": "cancel_order_reject",
"client_order_id": "TRADER-CLI:1234567891245678912345678912345685412584125684264215842526542158412525252358256536042737",
"code": 400,
"status": "REJECTED",
"message": "Order is in final state: REJECTED",
"instrument": "USDT/USD",
"ts": 1783920110082
}Order Update Event
OBT Server-sent event when an order is placed or rejected.
{
"type": "order_update",
"client_order_id": "MONITOR:BACKEND-1783938574043",
"order_id": "A350vnCOSDC",
"status": "PENDING",
"instrument": "USDT/AED",
"side": "BUY",
"order_type": "MARKET",
"quantity": "100000000.000000000000",
"cum_qty": "0.000000000000",
"avg_price": "0.000000000000",
"timestamp": 1783938574610
}{
"type": "order_update",
"client_order_id": "MONITOR:BACKEND-1783938574043",
"order_id": "A350vnCOSDC",
"status": "PARTIALLY_FILLED",
"instrument": "USDT/AED",
"side": "BUY",
"order_type": "MARKET",
"quantity": "100000000.000000000000",
"price": "3.671304820000",
"cum_qty": "50000000.000000000000",
"avg_price": "3.669470080000",
"timestamp": 1783938574723
}{
"type": "order_update",
"client_order_id": "MONITOR:BACKEND-1783938574043",
"order_id": "A350vnCOSDC",
"status": "FILLED",
"instrument": "USDT/AED",
"side": "BUY",
"order_type": "MARKET",
"quantity": "100000000.000000000000",
"price": "3.671304820000",
"cum_qty": "100000000.000000000000",
"avg_price": "3.669470080000",
"timestamp": 1783938574840
}{
"type": "order_update",
"client_order_id": "TEST-IOC-1783943176881",
"order_id": "A330vnA8bWr",
"status": "CANCELLED",
"instrument": "USDT/USD",
"side": "BUY",
"order_type": "LIMIT",
"quantity": "1.012345670000",
"price": "1.100000000000",
"cum_qty": "1.000000000000",
"avg_price": "0.999016670000",
"timestamp": 1783943178030
}{
"type": "order_update",
"client_order_id": "MONITOR:BACKEND-1788870170681",
"order_id": "A330vtjd3LP",
"status": "REJECTED",
"instrument": "USDT/USD",
"side": "SELL",
"order_type": "MARKET",
"quantity": "10000000000.000000000000",
"price": "0.999633000000",
"leave_qty": "10000000000.000000000000",
"cum_qty": "0.000000000000",
"avg_price": "0.000000000000",
"message": "ORDER_REJECTED_SIZE Size above configured maximum",
"timestamp": 1788870171532
}Trade Update Event
OBT Server-sent event for fills and order state changes.
{
"type": "trade_update",
"order_id": "A330vnA8bWr",
"client_order_id": "TEST-IOC-1783943176881",
"trade_id": "A33S10vnA8bij",
"status": "PARTIALLY_FILLED",
"timestamp": 1783943177907,
"last_qty": "1.000000000000",
"last_price": "0.999016670000",
"cum_qty": "1.000000000000",
"avg_price": "0.999016670000",
"quantity": "1.012345670000",
"leave_qty": "0.012345670000",
"instrument": "USDT/USD",
"side": "BUY",
"order_type": "LIMIT",
"price": "1.100000000000"
}{
"type": "trade_update",
"order_id": "A350vmUxO05",
"client_order_id": "5318575b-179c-4cdc-9bce-7acfcf9d5d91",
"trade_id": "A350vmUxO05",
"last_qty": "50.000000000000",
"last_price": "40001.000000000000",
"cum_qty": "100.000000000000",
"avg_price": "40000.500000000000",
"quantity": "100.000000000000",
"leave_qty": "0.000000000000",
"status": "FILLED",
"instrument": "BTC/USD",
"side": "BUY",
"order_type": "LIMIT",
"price": "40000.000000000000",
"timestamp": "2026-06-24T21:25:10Z"
}Error Response
OBT Server-sent event when an order is rejected or a request fails validation.
{
"type": "error",
"client_order_id": "TRADER-CLI:1234567891245678912345678912345685412584125684264215842526542158412525252358256536042737",
"instrument": "USDT/USD",
"code": 50400,
"message": "Invalid request",
"ts": 1783920043240
}{
"type": "error",
"client_order_id": "5318575b-179c-4cdc-9bce-7acfcf9d5d91",
"instrument": "USDT/AED",
"code": 50101,
"message": "Invalid quantity format",
"ts": 1783920043240
}{
"type": "error",
"client_order_id": "MONITOR:BACKEND-1783938574043",
"instrument": "USDT/AED",
"code": 50103,
"message": "Insufficient balance for USDT",
"ts": 1783938574043
}List Orders
OBT Query order history with filters (REST endpoint).
GET /v1/orders?status=FILLED&limit=20 X-Session-Id: ... X-Nonce: abc123 X-Timestamp: 1700000000000 X-Signature: ...
{
"orders": [
{
"order_id": "a1b2c3d4-e5f6-47g8-h9i0-j1k2l3m4n5o6",
"client_order_id": "order-001",
"status": "FILLED",
"instrument": "USDC/USD",
"side": "BUY",
"order_type": "LIMIT",
"quantity": "1000.000000000000",
"price": "0.999900000000",
"leave_qty": "0.000000000000",
"buy": "1000",
"sell": "999.90",
"amount": "999.900000000000",
"lp_order_id": "A350vmUxO05",
"created_at": "2026-06-25T08:40:00Z",
"filled_at": "2026-06-25T08:40:02Z",
"cum_qty": "1000.000000000000",
"last_qty": "1000.000000000000",
"last_price": "0.999700000000",
"avg_price": "0.999700000000"
},
{
"order_id": "c3d4e5f6-g7h8-49i0-j1k2-l3m4n5o6p7q8",
"client_order_id": "order-002",
"status": "OPEN",
"instrument": "BTC/USDT",
"side": "BUY",
"order_type": "LIMIT",
"quantity": "0.250000000000",
"price": "42000.000000000000",
"leave_qty": "0.250000000000",
"lp_order_id": "B401wnVyP16",
"created_at": "2026-06-25T08:43:15Z"
}
],
"total_elements": 2,
"page": 1,
"limit": 20
}Get Order
OBT Single-order detail by ID (REST endpoint).
{
"order_id": "a1b2c3d4-e5f6-47g8-h9i0-j1k2l3m4n5o6",
"client_order_id": "order-001",
"status": "FILLED",
"instrument": "USDC/USD",
"side": "BUY",
"order_type": "LIMIT",
"quantity": "1000.000000000000",
"price": "0.999900000000",
"leave_qty": "0.000000000000",
"buy": "1000",
"sell": "999.90",
"amount": "999.900000000000",
"lp_order_id": "A350vmUxO05",
"created_at": "2026-06-25T08:40:00Z",
"filled_at": "2026-06-25T08:40:02Z",
"cum_qty": "1000.000000000000",
"last_qty": "1000.000000000000",
"last_price": "0.999700000000",
"avg_price": "0.999700000000"
}{
"order_id": "c3d4e5f6-g7h8-49i0-j1k2-l3m4n5o6p7q8",
"client_order_id": "order-002",
"status": "OPEN",
"instrument": "BTC/USDT",
"side": "BUY",
"order_type": "LIMIT",
"quantity": "0.250000000000",
"price": "42000.000000000000",
"leave_qty": "0.250000000000",
"lp_order_id": "B401wnVyP16",
"created_at": "2026-06-25T08:43:15Z"
}Order Fills
OBT Aggregated fill statistics for an order (REST endpoint).
[
{
"order_id": "A350vnCOSDC",
"trade_id": "A35S10vnCOS52",
"instrument": "USDT/AED",
"side": "BUY",
"order_type": "MARKET",
"quantity": "100000000.000000000000",
"filled_qty": "100000000.000000000000",
"avg_price": "3.669470080000",
"last_fill_qty": "50000000.000000000000",
"last_fill_price": "3.669470080000",
"transacted_at": 1783938574390
},
{
"order_id": "A350vnCOSDC",
"trade_id": "A35S10vnCOS51",
"instrument": "USDT/AED",
"side": "BUY",
"order_type": "MARKET",
"quantity": "100000000.000000000000",
"filled_qty": "50000000.000000000000",
"avg_price": "3.669470080000",
"last_fill_qty": "50000000.000000000000",
"last_fill_price": "3.669470080000",
"transacted_at": 1783938574341
}
]Balances
{
"balances": {
"USD": "100000.000000000000",
"EUR": "50000.000000000000",
"USDC": "25000.000000000000"
}
}Health Check
Always 200. Use for load balancer probes.
HTTP/1.1 200 OK Content-Type: text/plain OK
Readiness Check
Returns 503 if the LP circuit breaker is open.
HTTP/1.1 200 OK OK
HTTP/1.1 503 Service Unavailable LP unavailable
Prometheus Metrics
# HELP gateway_http_requests_total Total HTTP requests
# TYPE gateway_http_requests_total counter
gateway_http_requests_total{route="/v1/orders",status="200"} 1250
# HELP gateway_http_request_duration_seconds Latency histogram
# TYPE gateway_http_request_duration_seconds histogram
gateway_http_request_duration_seconds_bucket{le="0.050"} 1100
# HELP gateway_response_queue_depth Queue depth
# TYPE gateway_response_queue_depth gauge
gateway_response_queue_depth 12Time in Force
Execution behaviour after order submission.
| TIF | Behaviour |
|---|---|
FOKFill or Kill |
Limit: fill entirely at requested price or better, or reject. Market: fill entirely at TOB, or cancel — no partial fills. |
IOCImmediate or Cancel |
Limit: fill any available qty at price or better; cancel remainder. Market: fill any available qty at TOB (partial fills allowed); cancel unfilled. Recommended for market orders. |
GTCGood till Cancelled |
Limit: fill any available qty at price or better; remainder stays active until manually cancelled or fully filled. Market: fill any available qty at TOB (partial fills allowed); remainder stays active until manually cancelled or fully filled. |
Supported Trading Pairs
| Pair | Status | Min Trade |
|---|---|---|
USDC/USD | ✅ Active | 1000.00 |
USDT/USD | ✅ Active | 1000.00 |
BTC/USD | ✅ Active | 0.001 |
BTC/USDT | ✅ Active | 0.001 |
BTC/AED | ✅ Active | 0.001 |
USDT/AED | ✅ Active | 1000.00 |
Error Codes
OBT Numeric error codes returned in error events and rejection messages.
| Code | Message | Category |
|---|---|---|
50201 | Invalid market data message | Market Data |
50202 | Unknown symbol | Market Data |
50203 | Unsupported subscription type | Market Data |
50204 | Unsupported type book | Market Data |
50205 | Duplicated market data request id | Market Data |
50206 | Duplicate market data symbol | Market Data |
50250 | Invalid market data unsubscribe message | Subscription |
50251 | Invalid subscription id | Subscription |
50300 | Invalid new order single message | Order |
50301 | Unsupported side | Order |
50302 | Invalid quantity | Order |
50303 | Invalid order type | Order |
50304 | Invalid time in force | Order |
50305 | Missing time in force | Order |
50306 | Invalid price | Order |
50307 | Order throttling exceeded | Order |
50308 | Invalid time stamp | Order |
50400 | Invalid request | Request |
{
"type": "error",
"client_order_id": "5318575b-179c-4cdc-9bce-7acfcf9d5d91",
"instrument": "BTC/USD",
"code": 50302,
"message": "Invalid quantity",
"ts": 1783920043240
}Troubleshooting
Common errors and fixes when using the Python CLI or REST API.
| Error | Cause | Fix |
|---|---|---|
No active session | Not logged in or session file missing | Run login |
HTTP 401 UNAUTHORIZED | Session expired (5 min inactivity) | Re-run login |
HTTP 400 BAD_REQUEST | Missing or invalid field | Run python lp_client.py <cmd> --help |
HTTP 404 NOT_FOUND | Unknown order or quote ID | Check the ID |
HTTP 410 QUOTE_EXPIRED | Quote TTL elapsed before execution | Re-run rfq |
HTTP 503 LP_UNAVAILABLE | LP circuit breaker open | Retry after 30 seconds |
Expected Latencies
p50 and p99 from client perspective.
| Operation | p50 | p99 |
|---|---|---|
| Authentication (5 steps) | 100 ms | 200 ms |
| Market snapshot | 20 ms | 50 ms |
| Order placement ACK | 50 ms | 200 ms |
| Order fill | 200 ms | 500 ms |