Added

v1.12.0 - 2025-11-27

Added

  • New update_order WebSocket event for tracking order fill progress

    • Purpose: Receive real-time notifications when orders are partially or completely filled, enabling precise order state tracking without polling
    • Benefits: Instant visibility into order execution, reduced API calls, accurate fill tracking for IOC orders
    • New capabilities: Track partial fills, monitor order state transitions, synchronize local order state with exchange

    When emitted:

    • After a partial fill (order remains open with updated filled_amount)
    • After a complete fill (order state changes to filled)
    • When IOC (Immediate-or-Cancel) orders are partially filled and reinstated

    Event data structure:

    {
      "kind": "event",
      "type": "update_order",
      "timestamp_ms": 1732713600000,
      "data": {
        "instrument_name": "BTC_USDC-31DEC25-100000-C",
        "type": "good_til_cancelled",
        "contracts": 10.0,
        "direction": "buy",
        "price": 2500.0,
        "post_only": false,
        "mmp": false,
        "liquidation": false,
        "maker": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
        "taker": "0x0000000000000000000000000000000000000000",
        "order_id": "abc123def456...",
        "user_id": "user_123",
        "order_state": "open",
        "filled_amount": 3.5,
        "creation_timestamp": 1732713500000,
        "chain_id": 421614,
        "deadline": 1732800000,
        "signature": "0x..."
      },
      "subscription": {
        "channel": "orderbook",
        "query": {
          "instrument_name": "BTC_USDC-31DEC25-100000-C"
        }
      }
    }

    Key features:

    • Complete order state: Event contains the full order object with all fields, not just changes
    • No delta processing: Use the filled_amount and order_state directly without calculating deltas
    • Book building compatible: The complete order state allows maintaining accurate orderbook representation

    Use cases:

    • Trading applications tracking order execution progress
    • Market makers monitoring fill rates
    • Order management systems maintaining accurate order state
    • Analytics systems tracking order lifecycle events

Changed

  • Rate limiting now enforced per API key owner instead of per session

    Before:

    // Old behavior: Each WebSocket connection had independent rate limits
    const ws1 = new WebSocket('wss://api.premia.io');  // Separate rate limit
    const ws2 = new WebSocket('wss://api.premia.io');  // Separate rate limit
    // Each connection could send full quota of requests

    After:

    // New behavior: All connections using same API key share rate limits
    const ws1 = new WebSocket('wss://api.premia.io');  // Shared rate limit pool
    const ws2 = new WebSocket('wss://api.premia.io');  // Shared rate limit pool
    // Total requests across all connections must stay within limits

    Benefits:

    • Fair resource allocation: Prevents rate limit circumvention via multiple connections
    • Better system stability: More predictable load patterns
    • Account-level control: Rate limits align with API key ownership

    Rate limit details:

    Message TypeRate LimitWindowScope
    auth1 request1 secondPer client IP address
    get_instruments1 request1 secondPer API key owner
    get_ob_state_by_instruments5 requests20 secondsPer API key owner

    Rate limit exceeded response:

    {
      "kind": "response",
      "id": "req-123",
      "type": "rate_limit_exceeded",
      "data": {
        "message": "Rate limit exceeded. Please try again later.",
        "retry_after_seconds": 15
      }
    }

    Migration:

    1. Review applications with multiple WebSocket connections using the same API key
    2. Implement request coordination across connections to share rate limit quota
    3. Consider consolidating multiple connections if possible
    4. Handle rate_limit_exceeded responses with exponential backoff using retry_after_seconds
    5. Monitor rate limit errors to optimize request patterns
  • Breaking Change: Orderbook bids/asks arrays now include order_id as third element

    Before:

    // Old format: [price, amount]
    const orderbook = await fetch('/order_book?instrument_name=BTC_USDC-PERPETUAL');
    const data = await orderbook.json();
    
    // Process bids/asks
    data.bids.forEach(([price, amount]) => {
      console.log(`Bid: ${amount} @ ${price}`);
      // No way to identify specific orders
    });

    After:

    // New format: [price, amount, order_id]
    const orderbook = await fetch('/order_book?instrument_name=BTC_USDC-PERPETUAL');
    const data = await orderbook.json();
    
    // Process bids/asks with order tracking
    data.bids.forEach(([price, amount, orderId]) => {
      console.log(`Bid: ${amount} @ ${price} (Order: ${orderId})`);
      // Can now track specific orders and match with update_order events
    });

    Example REST response:

    {
      "timestamp": 1732713600,
      "instrument_name": "BTC_USDC-PERPETUAL",
      "index_price": 98500.00,
      "bids": [
        [98450.00, 2.5, "order_abc123"],
        [98400.00, 1.8, "order_def456"],
        [98350.00, 3.2, "order_ghi789"]
      ],
      "asks": [
        [98550.00, 1.9, "order_jkl012"],
        [98600.00, 2.1, "order_mno345"],
        [98650.00, 1.5, "order_pqr678"]
      ],
      "best_bid_price": 98450.00,
      "best_ask_price": 98550.00
    }

    Example WebSocket snapshot:

    {
      "kind": "snapshot",
      "type": "orderbook",
      "timestamp_ms": 1732713600000,
      "data": {
        "bids": [
          [98450.00, 2.5, "order_abc123"],
          [98400.00, 1.8, "order_def456"]
        ],
        "asks": [
          [98550.00, 1.9, "order_jkl012"],
          [98600.00, 2.1, "order_mno345"]
        ]
      },
      "subscription": {
        "channel": "orderbook",
        "query": {
          "instrument_name": "BTC_USDC-PERPETUAL"
        }
      }
    }

    Benefits:

    • Order tracking: Match orderbook levels with specific limit orders
    • Event correlation: Connect update_order events with orderbook state
    • Enhanced analytics: Track order lifecycle from placement to fill
    • Better debugging: Identify specific orders causing issues

    Migration:

    1. Update array destructuring to include third element: [price, amount, orderId]
    2. Update TypeScript types: Array<[number, number, string]>
    3. Utilize order_id to correlate with update_order and post_order events
    4. Update any hardcoded array length checks from 2 to 3
    5. Test orderbook rendering with new three-element format
  • Enhanced skip_snapshot query parameter behavior for orderbook subscriptions

    Before:

    // Old behavior: skip_snapshot only prevented initial snapshot
    {
      "type": "subscribe",
      "subscriptions": [{
        "channel": "orderbook",
        "query": {
          "instrument_name": "BTC_USDC-PERPETUAL",
          "skip_snapshot": true  // Skip initial snapshot only
        }
      }]
    }
    // Would still receive snapshot if re-subscribing to same instrument

    After:

    // New behavior: skip_snapshot prevents duplicate snapshots
    {
      "type": "subscribe",
      "subscriptions": [{
        "channel": "orderbook",
        "query": {
          "instrument_name": "BTC_USDC-PERPETUAL",
          "skip_snapshot": true  // Skip snapshot for duplicate subscriptions
        }
      }]
    }
    // Server detects duplicate subscriptions and skips redundant snapshots
    // Still receive post_order, cancel_order, and update_order events

    Benefits:

    • Reduced bandwidth: Eliminates redundant snapshot data for duplicate subscriptions
    • Faster reconnection: Re-subscribe without downloading full orderbook again
    • Efficient multi-instrument: Subscribe to multiple instruments without snapshot overhead

    Use cases:

    1. Connection recovery: Re-subscribe after brief disconnect without re-downloading full orderbook
    2. Dynamic subscriptions: Add/remove instruments while maintaining existing subscriptions
    3. Bandwidth optimization: Minimize data transfer for high-frequency subscription updates

    Migration:

    • No changes required for existing implementations
    • Consider using skip_snapshot: true when re-subscribing to reduce bandwidth
    • Ensure application can handle orderbook updates without initial snapshot state

Documentation

  • Complete WebSocket API documentation updates

    • Added update_order event to Event Types table
    • Added comprehensive update_order event documentation section with examples
    • Updated rate limiting section with new per-owner enforcement and complete rate limit table
    • Updated rate limit response format to match current JSON structure
    • Updated orderbook array format examples throughout documentation
    • Added "Orderbook Array Format" explanation section
    • Enhanced skip_snapshot parameter description with duplicate detection behavior
  • Complete REST API documentation updates

    • Updated /order_book endpoint OpenAPI schema for 3-element bids/asks arrays
    • Modified Orderbook.yaml schema to include order_id as third element
    • Updated array type definitions to [number, number, string] format
    • Added descriptive comments explaining the three-element tuple structure