Market Makers

API Access

Dedicated API endpoints, rate limits, priority access, and technical specifications for LX market makers

Market Maker API Access

LX provides market makers with dedicated API infrastructure designed for high-frequency trading, including priority endpoints, elevated rate limits, and direct market access capabilities.

API Tiers

┌─────────────────────────────────────────────────────────────────────┐
│                    API ACCESS BY TIER                                │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Feature              │ Tier 1  │ Tier 2   │ Tier 3   │ Tier 4     │
│  ─────────────────────┼─────────┼──────────┼──────────┼────────────│
│  Rate Limit (req/s)   │ 1,000   │ 5,000    │ 20,000   │ Unlimited  │
│  WebSocket Streams    │ 10      │ 50       │ 200      │ Unlimited  │
│  Order Rate (ord/s)   │ 100     │ 500      │ 2,000    │ 10,000     │
│  Batch Orders         │ 10      │ 50       │ 200      │ 1,000      │
│  Dedicated Endpoint   │ No      │ Yes      │ Yes      │ Yes        │
│  Priority Queue       │ No      │ No       │ Yes      │ Yes        │
│  Co-location          │ No      │ No       │ Optional │ Included   │
│  FIX Protocol         │ No      │ No       │ Optional │ Included   │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Endpoints

Standard Endpoints (All Tiers)

ProtocolEndpointPortUse Case
RESThttps://api.lux.network443Orders, account data
WebSocketwss://ws.lux.network443Market data, orders
gRPCgrpc.lux.network9090High-performance streaming

Dedicated Endpoints (Tier 2+)

ProtocolEndpointPortLatency
RESThttps://mm-api.lux.network443<10ms
WebSocketwss://mm-ws.lux.network443<5ms
gRPCmm-grpc.lux.network9090<1ms

Priority Endpoints (Tier 3+)

ProtocolEndpointPortLatency
RESThttps://priority.lux.network443<1ms
WebSocketwss://priority-ws.lux.network443<500us
gRPCpriority-grpc.lux.network9090<100us
FIXfix.lux.network4433<100us

Co-location Endpoints (Tier 4)

ProtocolEndpointPortLatency
Direct10.0.1.x (assigned)Various<10us
FIX10.0.2.x (assigned)4433<10us

Authentication

API Key Authentication

# REST API
curl -X GET "https://mm-api.lux.network/v1/account" \
  -H "X-LX-API-KEY: your_api_key" \
  -H "X-LX-SIGNATURE: signature" \
  -H "X-LX-TIMESTAMP: 1702300800000"

Signature Generation

import hashlib
import hmac
import time

def generate_signature(api_secret: str, method: str, path: str,
                       body: str, timestamp: int) -> str:
    """Generate HMAC-SHA256 signature for API requests."""

    message = f"{timestamp}{method}{path}{body}"
    signature = hmac.new(
        api_secret.encode('utf-8'),
        message.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()

    return signature

# Example
api_secret = "your_secret_key"
timestamp = int(time.time() * 1000)
method = "POST"
path = "/v1/orders"
body = '{"symbol":"BTC-USD","side":"buy","price":"50000","size":"1"}'

signature = generate_signature(api_secret, method, path, body, timestamp)

WebSocket Authentication

// Connect and authenticate
const ws = new WebSocket('wss://mm-ws.lux.network');

ws.onopen = () => {
  const timestamp = Date.now();
  const signature = generateSignature(apiSecret, timestamp);

  ws.send(JSON.stringify({
    type: 'auth',
    apiKey: apiKey,
    timestamp: timestamp,
    signature: signature
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  if (data.type === 'auth_success') {
    console.log('Authenticated successfully');
    // Subscribe to channels
    ws.send(JSON.stringify({
      type: 'subscribe',
      channels: ['orderbook.BTC-USD', 'trades.BTC-USD', 'orders']
    }));
  }
};

Rate Limits

Request Rate Limits

Endpoint TypeTier 1Tier 2Tier 3Tier 4
Public (market data)100/s500/s2,000/sUnlimited
Private (account)50/s250/s1,000/s5,000/s
Orders (submit)100/s500/s2,000/s10,000/s
Orders (cancel)200/s1,000/s5,000/s20,000/s
Batch operations10/s50/s200/s1,000/s

Rate Limit Headers

HTTP/1.1 200 OK
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4987
X-RateLimit-Reset: 1702300860
X-RateLimit-Window: 1s

Rate Limit Exceeded Response

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please retry after 0.5 seconds.",
    "retryAfter": 500,
    "limit": 5000,
    "window": "1s"
  }
}

Burst Handling

TierBurst AllowanceRecovery Rate
Tier 12x for 5 seconds100 req/s
Tier 23x for 10 seconds500 req/s
Tier 35x for 30 seconds2,000 req/s
Tier 4No limitN/A

Order Management API

Place Order

import requests

def place_order(symbol: str, side: str, order_type: str,
                price: str, size: str) -> dict:
    """Place a new order."""

    endpoint = "https://mm-api.lux.network/v1/orders"

    body = {
        "symbol": symbol,
        "side": side,         # "buy" or "sell"
        "type": order_type,   # "limit", "market", "post_only"
        "price": price,
        "size": size,
        "timeInForce": "GTC", # "GTC", "IOC", "FOK"
        "clientOrderId": "mm_order_12345"
    }

    headers = get_auth_headers("POST", "/v1/orders", json.dumps(body))

    response = requests.post(endpoint, json=body, headers=headers)
    return response.json()

# Example
order = place_order("BTC-USD", "buy", "limit", "50000.00", "1.5")
print(f"Order ID: {order['orderId']}")

Batch Orders (Market Makers)

def batch_place_orders(orders: list) -> dict:
    """Place multiple orders atomically."""

    endpoint = "https://mm-api.lux.network/v1/orders/batch"

    body = {
        "orders": [
            {
                "symbol": "BTC-USD",
                "side": "buy",
                "type": "limit",
                "price": "49990.00",
                "size": "2.0",
                "clientOrderId": "bid_1"
            },
            {
                "symbol": "BTC-USD",
                "side": "sell",
                "type": "limit",
                "price": "50010.00",
                "size": "2.0",
                "clientOrderId": "ask_1"
            }
        ]
    }

    headers = get_auth_headers("POST", "/v1/orders/batch", json.dumps(body))
    response = requests.post(endpoint, json=body, headers=headers)
    return response.json()

# Batch limits by tier:
# Tier 1: 10 orders/batch
# Tier 2: 50 orders/batch
# Tier 3: 200 orders/batch
# Tier 4: 1000 orders/batch

Cancel All Orders

def cancel_all_orders(symbol: str = None) -> dict:
    """Cancel all open orders, optionally filtered by symbol."""

    endpoint = "https://mm-api.lux.network/v1/orders/cancel-all"

    body = {}
    if symbol:
        body["symbol"] = symbol

    headers = get_auth_headers("DELETE", "/v1/orders/cancel-all", json.dumps(body))
    response = requests.delete(endpoint, json=body, headers=headers)
    return response.json()

# Response
{
    "cancelledOrders": 42,
    "failedCancels": 0,
    "timestamp": 1702300800000
}

Mass Quote Update

def mass_quote_update(quotes: list) -> dict:
    """Update multiple quotes atomically (MM-only endpoint)."""

    endpoint = "https://mm-api.lux.network/v1/mm/mass-quote"

    body = {
        "quoteId": "quote_batch_123",
        "quotes": [
            {
                "symbol": "BTC-USD",
                "bidPrice": "49990.00",
                "bidSize": "5.0",
                "askPrice": "50010.00",
                "askSize": "5.0"
            },
            {
                "symbol": "ETH-USD",
                "bidPrice": "2995.00",
                "bidSize": "50.0",
                "askPrice": "3005.00",
                "askSize": "50.0"
            }
        ]
    }

    headers = get_auth_headers("POST", "/v1/mm/mass-quote", json.dumps(body))
    response = requests.post(endpoint, json=body, headers=headers)
    return response.json()

Market Data API

Order Book Snapshot

def get_orderbook(symbol: str, depth: int = 100) -> dict:
    """Get order book snapshot."""

    endpoint = f"https://mm-api.lux.network/v1/orderbook/{symbol}"
    params = {"depth": depth}

    response = requests.get(endpoint, params=params)
    return response.json()

# Response
{
    "symbol": "BTC-USD",
    "timestamp": 1702300800000,
    "bids": [
        ["49990.00", "5.23"],
        ["49985.00", "10.50"],
        ...
    ],
    "asks": [
        ["50010.00", "4.85"],
        ["50015.00", "8.20"],
        ...
    ]
}

WebSocket Market Data

// Subscribe to L2 order book updates
ws.send(JSON.stringify({
  type: 'subscribe',
  channel: 'orderbook',
  symbol: 'BTC-USD',
  depth: 50  // Top 50 levels
}));

// L2 update message
{
  "type": "orderbook_update",
  "symbol": "BTC-USD",
  "timestamp": 1702300800001,
  "bids": [
    {"price": "49990.00", "size": "5.23", "action": "update"}
  ],
  "asks": [
    {"price": "50009.00", "size": "0.00", "action": "delete"}
  ],
  "sequence": 12345678
}

// L3 order-by-order updates (Tier 3+)
{
  "type": "orderbook_l3",
  "symbol": "BTC-USD",
  "timestamp": 1702300800001,
  "orders": [
    {
      "orderId": "ord_abc123",
      "side": "buy",
      "price": "49990.00",
      "size": "2.50",
      "action": "add"
    }
  ],
  "sequence": 12345679
}

Trade Feed

// Subscribe to trades
ws.send(JSON.stringify({
  type: 'subscribe',
  channel: 'trades',
  symbol: 'BTC-USD'
}));

// Trade message
{
  "type": "trade",
  "symbol": "BTC-USD",
  "tradeId": "trade_xyz789",
  "price": "50000.00",
  "size": "1.5",
  "side": "buy",     // Taker side
  "timestamp": 1702300800002,
  "makerOrderId": "ord_maker_123",
  "takerOrderId": "ord_taker_456"
}

FIX Protocol (Tier 3+)

Connection Details

ParameterValue
Hostfix.lux.network
Port4433 (TLS required)
FIX Version4.4
Heartbeat30 seconds
Reset SequenceDaily at 00:00 UTC

FIX Session Configuration

# FIX Session Config
[SESSION]
BeginString=FIX.4.4
SenderCompID=MM_FIRM_001
TargetCompID=LXDEX
HeartBtInt=30
ReconnectInterval=5
SocketConnectHost=fix.lux.network
SocketConnectPort=4433
UseDataDictionary=Y
DataDictionary=LX_FIX44.xml

Sample FIX Messages

# New Order Single (D)
8=FIX.4.4|9=178|35=D|49=MM_FIRM_001|56=LXDEX|34=123|52=20241210-12:00:00.000|
11=clord_001|55=BTC-USD|54=1|38=1.5|40=2|44=50000.00|59=0|10=234|

# Execution Report (8)
8=FIX.4.4|9=245|35=8|49=LXDEX|56=MM_FIRM_001|34=456|52=20241210-12:00:00.001|
37=ord_123|11=clord_001|17=exec_001|150=0|39=0|55=BTC-USD|54=1|38=1.5|
44=50000.00|14=0|6=0|151=1.5|10=178|

# Order Cancel Request (F)
8=FIX.4.4|9=145|35=F|49=MM_FIRM_001|56=LXDEX|34=124|52=20241210-12:00:01.000|
41=clord_001|11=clord_002|55=BTC-USD|54=1|10=089|

gRPC API

Service Definition

syntax = "proto3";

package lx.dex.v1;

service TradingService {
  // Orders
  rpc PlaceOrder(PlaceOrderRequest) returns (PlaceOrderResponse);
  rpc CancelOrder(CancelOrderRequest) returns (CancelOrderResponse);
  rpc BatchPlaceOrders(BatchPlaceOrdersRequest) returns (BatchPlaceOrdersResponse);
  rpc MassQuoteUpdate(MassQuoteRequest) returns (MassQuoteResponse);

  // Streaming
  rpc StreamOrderBook(StreamOrderBookRequest) returns (stream OrderBookUpdate);
  rpc StreamTrades(StreamTradesRequest) returns (stream Trade);
  rpc StreamOrders(StreamOrdersRequest) returns (stream OrderUpdate);
}

message PlaceOrderRequest {
  string symbol = 1;
  string side = 2;
  string type = 3;
  string price = 4;
  string size = 5;
  string time_in_force = 6;
  string client_order_id = 7;
}

message PlaceOrderResponse {
  string order_id = 1;
  string client_order_id = 2;
  string status = 3;
  int64 timestamp = 4;
}

gRPC Client Example

package main

import (
    "context"
    "log"

    pb "github.com/luxfi/dex/proto/v1"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
)

func main() {
    // Connect with TLS
    creds, _ := credentials.NewClientTLSFromFile("ca.crt", "mm-grpc.lux.network")
    conn, err := grpc.Dial("mm-grpc.lux.network:9090", grpc.WithTransportCredentials(creds))
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    client := pb.NewTradingServiceClient(conn)

    // Place order
    resp, err := client.PlaceOrder(context.Background(), &pb.PlaceOrderRequest{
        Symbol:        "BTC-USD",
        Side:          "buy",
        Type:          "limit",
        Price:         "50000.00",
        Size:          "1.5",
        TimeInForce:   "GTC",
        ClientOrderId: "grpc_order_001",
    })

    log.Printf("Order placed: %s", resp.OrderId)
}

Performance Optimization

Best Practices

  1. Use Batch Operations

    • Combine multiple orders in single request
    • Reduces round trips and improves throughput
  2. Persistent Connections

    • Reuse HTTP/2 connections
    • Keep WebSocket connections alive with heartbeats
  3. Local Caching

    • Cache static data (symbols, tick sizes)
    • Use incremental order book updates
  4. Message Compression

    • Enable gzip for REST
    • Use binary protocols (gRPC, FIX) for lowest latency

Latency Benchmarks

OperationStandardDedicatedPriorityCo-location
Order Submit10ms2ms500us50us
Order Cancel5ms1ms200us20us
Mass Quote15ms3ms800us80us
Book Snapshot20ms5ms1ms100us

Error Handling

Error Codes

CodeDescriptionAction
INVALID_API_KEYAPI key not recognizedCheck credentials
SIGNATURE_INVALIDSignature verification failedCheck signing logic
RATE_LIMIT_EXCEEDEDToo many requestsImplement backoff
INSUFFICIENT_BALANCENot enough fundsDeposit or reduce size
INVALID_PRICEPrice outside limitsCheck tick size
MARKET_CLOSEDMarket not tradingWait for market open
ORDER_NOT_FOUNDOrder ID doesn't existVerify order ID
DUPLICATE_CLIENT_IDClient order ID reusedUse unique IDs

Retry Strategy

import time
from functools import wraps

def retry_with_backoff(max_retries=3, base_delay=0.1):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except RateLimitError:
                    delay = base_delay * (2 ** attempt)
                    time.sleep(delay)
                except (ConnectionError, TimeoutError):
                    delay = base_delay * (2 ** attempt)
                    time.sleep(delay)
            raise MaxRetriesExceeded()
        return wrapper
    return decorator

Support

API Support Channels

TierSupport ChannelResponse Time
Tier 1Email24 hours
Tier 2Slack, Email4 hours
Tier 3Slack, Phone1 hour
Tier 4Dedicated Team, Phone15 minutes

Technical Contacts


API specifications subject to change. Last updated: December 2024