API Changelog

Kyan API Changelog

All notable changes to the Kyan API will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[1.11.0] - 2025-10-21

Added

  • New instruments WebSocket channel for real-time instrument list updates

    • Purpose: Receive immediate notifications when trading instruments are added or expire, keeping your application synchronized with available markets
    • Benefits: Eliminates need for polling /instruments endpoint, instant awareness of new trading opportunities, automatic cleanup of expired instruments
    • New capabilities: Subscribe to specific markets (BTC, ETH, ARB) or all markets, receive initial snapshot on subscription, get update timestamp with each event

    Example subscription (single market):

    {
      "type": "subscribe",
      "subscriptions": [
        {
          "channel": "instruments",
          "query": {
            "market": "BTC"
          }
        }
      ]
    }

    Example subscription (all markets):

    {
      "type": "subscribe",
      "subscriptions": [
        {
          "channel": "instruments",
          "query": {}
        }
      ]
    }

    Event data received:

    {
      "kind": "event",
      "type": "instruments",
      "timestamp_ms": 1677721600000,
      "data": {
        "updated_at": 1677721600000,
        "instruments": [
          "BTC_USDC-PERPETUAL",
          "BTC_USDC-31OCT25-130000-C",
          "BTC_USDC-31OCT25-130000-P",
          "BTC_USDC-31OCT25-135000-C",
          "BTC_USDC-31OCT25-135000-P"
        ]
      },
      "subscription": {
        "channel": "instruments",
        "query": {
          "market": "BTC"
        }
      }
    }

    Data fields:

    • updated_at: Unix timestamp in milliseconds
    • instruments: Array of instrument names currently available for trading

    Query parameters:

    • market (optional): Base token (BTC, ETH, or ARB). If omitted, subscribes to all markets

    Use cases:

    • Trading applications dynamically updating available instruments
    • Automated trading systems detecting new option expirations
    • Market monitoring tools tracking instrument lifecycle
    • Risk management systems responding to expired instruments

Changed

  • Breaking Change: Endpoint GET /instruments now returns object with timestamp instead of array

    Before:

    // Old response format
    const response = await fetch('/instruments?market=BTC');
    const instruments: string[] = await response.json();
    // Returns: ["BTC_USDC-PERPETUAL", "BTC_USDC-31OCT25-130000-C", ...]

    After:

    // New response format
    const response = await fetch('/instruments?market=BTC');
    const data: {
      updated_at: number;  // Unix timestamp in milliseconds
      instruments: string[];
    } = await response.json();
    // Returns: {
    //   updated_at: 1677721600000,
    //   instruments: ["BTC_USDC-PERPETUAL", "BTC_USDC-31OCT25-130000-C", ...]
    // }
    
    // Access instruments array
    const instruments = data.instruments;
    // Use timestamp for caching/change detection
    const lastUpdate = new Date(data.updated_at);  // Convert to Date object

    Benefits:

    • Cache optimization: Use updated_at timestamp (milliseconds) to implement efficient caching strategies
    • Change detection: Compare timestamps to determine if instrument list has changed
    • Synchronization: Coordinate REST API data with WebSocket instruments channel updates using the same timestamp
    • Better performance: Avoid unnecessary processing when instrument list hasn't changed

    Migration:

    1. Update response type to expect object instead of array
    2. Access instruments via data.instruments property
    3. Optionally implement caching using data.updated_at timestamp
    4. Consider migrating to WebSocket instruments channel for real-time updates
  • Breaking Change: Endpoint POST /limit response format simplified - matched field removed

    Before:

    // Old response format
    const response = await fetch('/limit', {
      method: 'POST',
      body: JSON.stringify([/* orders */])
    });
    const result: {
      posted: Array<Order>;
      matched: Array<Order>;  // Separate array for matched orders
      rejected: Array<Order>;
    } = await response.json();

    After:

    // New response format
    const response = await fetch('/limit', {
      method: 'POST',
      body: JSON.stringify([/* orders */])
    });
    const result: {
      posted: Array<Order>;   // Now includes both posted AND matched orders
      rejected: Array<Order>;
    } = await response.json();
    // Note: matched field no longer exists - matched orders are merged into 'posted' array

    Benefits:

    • Simplified response structure: Easier to process all successful orders in one array
    • Reduced complexity: No need to merge posted and matched arrays client-side
    • Clearer semantics: All successfully processed orders (whether posted to orderbook or immediately matched) are in posted

    Migration:

    1. Update response type to remove matched field
    2. Process all successful orders from the posted array (includes both posted and matched orders)
    3. If you need to distinguish matched orders, check the order_state field (will be filled or open)
    4. Remove any client-side code that separately processed the matched array

Documentation

  • Complete REST API documentation updates

    • Updated /instruments endpoint OpenAPI schema with new InstrumentsData response type
    • Added detailed field descriptions for updated_at and instruments properties
    • Updated endpoint description to highlight new timestamp functionality
  • Complete WebSocket API documentation updates

    • Added detailed channel description for instruments channel
    • Added event data structures with field descriptions
    • Added subscription examples for both single market and all markets scenarios
    • Updated Available Channels table with new instruments entry
    • Updated Event Types table with instruments event
    • Added comprehensive use cases and implementation notes

[1.10.0] - 2025-10-14

Added

  • New mmp WebSocket channel for Market Maker Protection events

    • Purpose: Monitor when MMP (Market Maker Protection) is triggered, temporarily freezing an account's trading when risk thresholds are exceeded
    • Benefits: Real-time notifications of risk threshold violations, proactive risk management, automated trading pause awareness
    • New capabilities: Track freeze status, monitor freeze duration, filter by account or trading pair

    Example subscription:

    {
      "channel": "mmp",
      "query": {
        "smart_account_address": "0x1234567890abcdef1234567890abcdef12345678",
        "pair": "BTC_USDC"  // optional
      }
    }

    Event data received:

    {
      "kind": "event",
      "type": "mmp_triggered",
      "timestamp_ms": 1677721600000,
      "data": {
        "smart_account_address": "0xabCDEF1234567890ABcDEF1234567890aBCDeF12",
        "pair_symbol": "ETH_USDC",
        "frozen_until": 1677721660000,
        "frozen_duration_seconds": 60
      }
    }

    Query parameters:

    • smart_account_address (optional): Filter events for a specific smart account
    • pair (optional): Filter events for a specific trading pair (BTC_USDC, ETH_USDC, or ARB_USDC)

    Use cases:

    • Market makers monitoring their own MMP status
    • Risk management systems tracking protection triggers
    • Automated trading bots pausing operations during freeze periods
  • New bankruptcy WebSocket channel for account bankruptcy events

    • Purpose: Monitor when account equity becomes negative after liquidation attempts, representing losses absorbed by the insurance fund
    • Benefits: Real-time bankruptcy notifications, insurance fund impact tracking, systemic risk monitoring
    • New capabilities: Track bankruptcy events by market, monitor insurance fund utilization

    Example subscription:

    {
      "channel": "bankruptcy",
      "query": {
        "market": "ETH_USDC"  // optional
      }
    }

    Event data received:

    {
      "kind": "event",
      "type": "bankruptcy",
      "timestamp_ms": 1677721600000,
      "data": {
        "marginAccountId": "550e8400-e29b-41d4-a716-446655440000",
        "market": "ETH_USDC"
      }
    }

    Query parameters:

    • market (optional): Filter events by trading pair (BTC_USDC, ETH_USDC, ARB_USDC, or USDC_USDC)

    Use cases:

    • Risk managers monitoring systemic risk indicators
    • Insurance fund tracking and analysis
    • Market health monitoring and alerting

Documentation

  • Complete WebSocket API documentation updates
    • Added detailed channel descriptions for mmp and bankruptcy channels
    • Added event data structures with field descriptions
    • Added subscription examples with multiple query parameter combinations
    • Updated Available Channels table with new entries
    • Updated Event Types table with mmp_triggered and bankruptcy events

[1.9.0] - 2025-09-29

Added

  • Future settlement projections in risk calculations (POST /calculate_user_risk)

    • New field: future_settlement_projections object containing risk metrics for future expiration dates
    • Benefits: Evaluate how portfolio risk evolves as options approach expiration, better risk planning for future scenarios
    • Capabilities: Each settlement date includes projected margin requirements (im, mm), risk components (matrix_risk, delta_risk, roll_risk), and complete Greeks

    Example response:

    {
      "status": "success",
      "data": {
        "pair": "ETH_USDC",
        "im": 1200.00,
        "mm": 1000.00,
        "greeks": { /* current greeks */ },
        "future_settlement_projections": {
          "2025-10-31": {
            "im": 1440.00,
            "mm": 1200.00,
            "matrix_risk": 960.00,
            "delta_risk": 180.00,
            "roll_risk": 60.00,
            "greeks": {
              "delta": 1.8,
              "gamma": 0.008,
              "vega": 90.0,
              "theta": -12.0,
              "rho": 4.5
            }
          }
        }
      }
    }
  • New orderbook_maker WebSocket channel for market makers

    • Purpose: Dedicated channel for market makers to monitor their own orders efficiently
    • Benefits: Initial snapshot of all maker's active orders, real-time updates for only that maker's activity, reduced bandwidth and processing overhead
    • Migration: Replaces the maker filter previously available in orderbook_options and orderbook_perps channels

    Example subscription:

    {
      "channel": "orderbook_maker",
      "query": {
        "maker": "0x1234567890abcdef1234567890abcdef12345678",
        "pair": "BTC_USDC"  // optional
      }
    }

    Events received:

    • Initial: ob_maker_orders event with all active orders
    • Ongoing: post_order and cancel_order events for that maker only
  • Session revocation enhancements (DELETE /session)

    • New capability: Delete all one-click trading sessions for an API key by omitting the x-one-click header
    • Benefits: Bulk session cleanup, simplified session management for applications with multiple sessions
    • Response: Returns count of revoked sessions

    Example - Revoke all sessions:

    // Without x-one-click header - revokes ALL sessions
    const response = await fetch('/session', {
      method: 'DELETE',
      headers: {
        'x-apikey': 'your-api-key'
        // No x-one-click header
      }
    });
    // Response: { "revokedSessions": 5 }
  • User tracking field in market order responses

    • New field: user_id added to POST market order responses for analytics and tracking
    • Benefits: Better order attribution, enhanced analytics capabilities, improved debugging
    • Location: Returned in response body after successful market order submission

Changed

  • Breaking Change: WebSocket maker filtering moved to dedicated channel

    • Removed: maker parameter no longer available in orderbook_options and orderbook_perps channels
    • Replacement: Use the new orderbook_maker channel for maker-specific filtering

    Before (deprecated):

    {
      "channel": "orderbook_options",
      "query": {
        "pair": "BTC_USDC",
        "maker": "0x1234..."  // No longer supported
      }
    }

    After (required):

    {
      "channel": "orderbook_maker",
      "query": {
        "maker": "0x1234...",  // Now in dedicated channel
        "pair": "BTC_USDC"
      }
    }

    Benefits: Better performance isolation, cleaner API design, optimized for market maker use cases

Updated

  • RFQ response requirements clarified
    • Clarification: RFQ responses must contain either all option orders OR exactly one perpetual order
    • Validation: Cannot mix options and perpetuals in the same RFQ response
    • Documentation: Enhanced examples and constraints in RFQ documentation

[1.8.1] - 2025-09-02

Added

  • WebSocket trade events now include order size and fill information
    • New fields: order_size and filled_amount added to all trade events
    • Benefits: Track partial fills and order completion status in real-time
    • Use case: Monitor order execution progress without additional API calls
    Example:
    ws.on('message', (msg) => {
      if (msg.type === 'trade') {
        const trade = msg.data;
        console.log(`Order ${trade.order_id}:`);
        console.log(`  Filled: ${trade.filled_amount} / ${trade.order_size}`);
        console.log(`  Completion: ${(trade.filled_amount / trade.order_size * 100).toFixed(2)}%`);
        
        if (trade.filled_amount === trade.order_size) {
          console.log('Order fully filled!');
        }
      }
    });

[1.8.0] - 2025-08-30

Added

  • WebSocket orderbook subscription filtering by maker address

    • New capability: Filter orderbook events (post_order, cancel_order, trade) by specific market maker address
    • Benefits: Reduces bandwidth usage by receiving only relevant orderbook updates, enables tracking specific market makers
    • Channels affected: orderbook_options, orderbook_perps

    Example:

    // Subscribe to orderbook events from a specific maker only
    const subscription = {
      channel: 'orderbook_options',
      query: {
        pair: 'BTC_USDC',
        maker: '0x1234567890abcdef1234567890abcdef12345678'
      }
    };
  • WebSocket orderbook snapshot skipping option

    • New capability: Skip initial orderbook snapshot when subscribing to orderbook channels
    • Benefits: Faster subscription initialization, reduced initial data transfer for clients that only need incremental updates
    • Use case: Ideal for applications that maintain their own orderbook state or only need real-time updates

    Example:

    // Subscribe without receiving initial orderbook state
    const subscription = {
      channel: 'orderbook_perps',
      query: {
        instrument_name: 'BTC_USDC-PERPETUAL',
        options: {
          skip_snapshot: true  // Only receive incremental updates
        }
      }
    };

Changed

  • WebSocket orderbook subscriptions now support optional pair parameter

    • Breaking Change: The pair parameter is now optional for orderbook_options and orderbook_perps channels
    • Benefits: Subscribe to all instruments across all markets in a single subscription, simplified market-wide monitoring

    Before:

    // Previously required to specify a pair
    const subscription = {
      channel: 'orderbook_options',
      query: {
        pair: 'BTC_USDC',  // Was required
        maturity: '29AUG25'
      }
    };

    After:

    // Now can subscribe to all markets at once
    const subscription = {
      channel: 'orderbook_options',
      query: {
        // pair is now optional - omit to receive all markets
        maturity: '29AUG25'  // Can filter by maturity across all pairs
      }
    };
    
    // Or subscribe to absolutely everything
    const subscribeToAll = {
      channel: 'orderbook_perps',
      query: {}  // Receives all perpetual orderbook events
    };

    Migration Guide:

    • Existing subscriptions with pair specified will continue to work unchanged
    • To subscribe to all markets, simply omit the pair parameter
    • Consider using the new maker filter or skip_snapshot option to manage data volume when subscribing broadly

[1.7.0] - 2025-08-27

🔄 Changed - RFQ Response Event Improvements

Breaking Change: WebSocket rfq_response Event Split into Two Distinct Events

The single rfq_response WebSocket event has been split into two semantically distinct events for improved clarity and event handling:

  • rfq_post_response: Emitted when a market maker posts a new response to an RFQ request with pricing
  • rfq_cancel_response: Emitted when a market maker cancels a previously posted RFQ response

Before:

// Single event type for both posting and cancelling
ws.on('message', (msg) => {
  if (msg.type === 'rfq_response') {
    // Had to check fills array to determine if it was a post or cancel
    if (msg.data.fills && msg.data.fills.length > 0) {
      // Handle new response
    } else {
      // Handle cancellation
    }
  }
});

After:

// Distinct event types for clearer handling
ws.on('message', (msg) => {
  if (msg.type === 'rfq_post_response') {
    // Handle new RFQ response with pricing
    const fills = msg.data.fills; // Always contains pricing data
    processPricing(fills);
  } else if (msg.type === 'rfq_cancel_response') {
    // Handle RFQ response cancellation
    const responseId = msg.data.response_id;
    removePricing(responseId);
  }
});

Benefits:

  • Clearer semantics: Event type immediately indicates the action without checking payload
  • Improved type safety: TypeScript users get better type inference for each event
  • Simplified event handling: No need to check fills array to determine event intent
  • Better observability: Easier to track and monitor different RFQ response actions

Migration Guide:

  1. Update WebSocket message handlers to check for rfq_post_response and rfq_cancel_response instead of rfq_response
  2. Remove any logic that checks the fills array to determine if it's a cancellation
  3. Handle each event type with its specific business logic

Note: RFQ cancellations are now properly emitted only on the rfq channel and no longer appear on orderbook channels.

[1.6.1] - 2025-08-27

📝 Fixed - WebSocket Documentation Corrections

Corrected WebSocket Message kind Field Values

  • Fixed documentation to accurately reflect the WebSocket message kind field values used in the actual implementation
  • Previous documentation incorrectly showed uppercase values ("RESPONSE", "EVENT")
  • Corrected values now show lowercase as per the codebase ("response", "event")

Before (Incorrect):

{
  "kind": "RESPONSE", // ❌ Incorrect - uppercase
  "type": "auth",
  "id": "request-123",
  "timestamp_ms": 1677721600000,
  "success": true
}

After (Correct):

{
  "kind": "response", // ✅ Correct - lowercase
  "type": "auth",
  "id": "request-123",
  "timestamp_ms": 1677721600000,
  "success": true
}

Impact:

  • No functional changes to the WebSocket API behavior
  • Documentation only update to match actual implementation

[1.6.0] - 2025-08-20

✨ Added - Account History Endpoint

New Endpoint: GET /account_history for Complete Trading History

  • New public REST endpoint for retrieving comprehensive account trading history and events
  • Consolidated view: Access all trades and account events (deposits, withdrawals, settlements, funding) in a single request
  • Flexible filtering: Query by time range and limit results for efficient data retrieval
  • Complete audit trail: Track all account activity for reconciliation and analysis

Usage Example:

// Retrieve account history with optional filters
const response = await fetch('/account_history?' + new URLSearchParams({
  address: '0x9a2f0C371820e8BE3D64efb3E814808F231880ff',
  start_timestamp: '1704067200',  // Optional: Unix timestamp
  end_timestamp: '1704153600',    // Optional: Unix timestamp
  count: '100'                    // Optional: Max records to return
}));

const data = await response.json();
// Response structure
{
  address: '0x9a2f0C371820e8BE3D64efb3E814808F231880ff',
  history: {
    trades: [
      {
        trade_id: 'a1b2c3d4e5f678901234567890abcdef',
        instrument_name: 'BTC_USDC-29AUG25-106000-C',
        direction: 'buy',
        size: 1.5,
        average_price: 125.50,
        realised_pnl: -5.75,
        // ... full trade details including fees and greeks
      }
    ],
    account_events: [
      {
        action: 'deposit',  // Types: deposit, withdrawal, settlement, funding
        amount: 1000.0,
        symbol: 'USDC',
        timestamp: 1704067500,
        // ... complete event details
      }
    ]
  }
}

[1.5.0] - 2025-08-02

✨ Added - Enhanced Order Tracking

Optional User ID Field for Order Tracking

  • Added user_id field to all order types for enhanced tracking and analytics:
    • REST Endpoints: All limit orders (POST /limit), market orders (POST /market), combo orders (POST /combo), and RFQ orders
    • WebSocket Events: Trade events now include user_id field in data payload
    • Field Type: Optional string with maximum 36 characters
    • Use Cases: Custom order labeling, client-side tracking, analytics categorization, portfolio grouping

Migration Example:

// Before (existing functionality continues to work)
const limitOrder = {
  instrument_name: 'BTC_USDC-29AUG25-106000-C',
  type: 'good_til_cancelled',
  contracts: 1.5,
  direction: 'buy',
  price: 1000.5,
  // ... other required fields
};

// After (optional user_id field available)
const limitOrder = {
  instrument_name: 'BTC_USDC-29AUG25-106000-C',
  type: 'good_til_cancelled',
  contracts: 1.5,
  direction: 'buy',
  price: 1000.5,
  user_id: 'portfolio_a_trade_001', // New optional field
  // ... other required fields
};

Benefits:

  • Custom tracking: Label orders with your own identifiers for easier management
  • Portfolio organization: Group orders by strategy, client, or trading session
  • Analytics enhancement: Track performance metrics across custom categories
  • Backwards compatible: Existing code continues to work without changes

🔧 Changed - RFQ Validation and Rate Limiting

Breaking Change: RFQ Opposite Direction Requirement

  • RFQ responses now require opposite directions between taker requests and maker limit orders
  • Traditional market making: Takers request one direction, makers provide liquidity in the opposite direction
  • Enhanced validation: System validates direction compatibility before accepting RFQ responses

Before:

// Previously allowed (incorrect market making)
const rfqResponse = {
  fills: [
    [
      {
        instrument_name: 'BTC_USDC-29AUG25-106000-C',
        contracts: 1.5,
        direction: 'buy',
      }, // Taker request
      {
        instrument_name: 'BTC_USDC-29AUG25-106000-C',
        contracts: 1.5,
        direction: 'buy', // Same direction - previously allowed but incorrect
        price: 2500.0,
        // ... other limit order fields
      },
    ],
  ],
};

After:

// Now required (correct market making)
const rfqResponse = {
  fills: [
    [
      {
        instrument_name: 'BTC_USDC-29AUG25-106000-C',
        contracts: 1.5,
        direction: 'buy',
      }, // Taker request
      {
        instrument_name: 'BTC_USDC-29AUG25-106000-C',
        contracts: 1.5,
        direction: 'sell', // Opposite direction - now required
        price: 2500.0,
        // ... other limit order fields
      },
    ],
  ],
};

Benefits:

  • Correct market making: Ensures proper liquidity provision patterns
  • Reduced errors: Prevents mismatched trading pairs that could lead to unintended positions
  • Market integrity: Aligns with traditional finance market making principles

WebSocket Rate Limiting Scope Change

  • Rate limiting changed from per-API-key to per-session for WebSocket connections
  • Independent limits: Each WebSocket connection now has its own 15 requests/minute limit
  • Same endpoints affected: get_ob_state_by_instruments and get_ob_state_by_market

Before:

// All connections using the same API key shared a single rate limit
// If you had 3 WebSocket connections with the same API key,
// they collectively shared 15 requests/minute

After:

// Each WebSocket connection gets its own independent rate limit
// 3 WebSocket connections = 3 × 15 = 45 total requests/minute

Benefits:

  • Better scalability: Multiple connections per API key don't interfere with each other
  • Fairness: Each connection gets full rate limit allocation
  • Simplified management: Rate limits tied to connection lifecycle rather than API key usage

[1.4.0] - 2025-07-26

✨ Added - New Endpoint and Enhanced Features

New REST Endpoint: Index Price Retrieval

  • Added GET /index_price endpoint for retrieving current index prices
    • Supported markets: BTC, ETH, ARB
    • Data source: Real-time Chainlink oracle feeds via WebSocket streaming
    • Response format: Direct numerical value (e.g., 106500.25)
    • Authentication: API key required
    • Use cases: Portfolio valuation, risk management, strategy analysis, settlement reference

WebSocket Rate Limiting Implementation

  • Added per-API-key rate limiting for market data WebSocket messages:
    • get_ob_state_by_instruments: 15 requests per minute per API key
    • get_ob_state_by_market: 15 requests per minute per API key
  • Enhanced error responses with reset time and remaining request information
  • Sliding window algorithm with 60-second windows for fair usage distribution

WebSocket Documentation Enhancements

  • Added comprehensive timestamp format clarification:
    • Event wrapper timestamps (timestamp_ms): 13-digit milliseconds for event ordering
    • Data payload timestamps (timestamp): Usually 13-digit milliseconds for data-specific times
    • Creation timestamps (creation_timestamp): 10-digit seconds for order/request creation

🔧 Changed - Rate Limiting and Performance

WebSocket Rate Limiting Behavior

  • Rate limits now apply per API key instead of global limits
  • Enhanced rate limit responses include specific reset timing and remaining request counts
  • Alternative guidance provided encouraging subscription-based real-time updates over polling

[1.3.0] - 2025-07-17

✨ Added - API Documentation Enhancements

Enhanced API Documentation Structure

  • Added Key Identifier Types section to main API documentation explaining order_id vs trade_id relationship
  • Created comprehensive developer guide (order_id_vs_trade_id.md) with detailed trading scenarios and examples

Enhanced Batch Order Constraints

  • Added detailed constraint documentation for limit order batching:
    • All orders must be from the same maker
    • All orders must be for the same market (BTC, ETH, or ARB)
  • Added comprehensive examples showing valid and invalid batch configurations
  • Enhanced error response documentation with specific rejection reasons and examples

Order Cancellation Requirements

  • Made market field required in CancelAllOrdersRequest schema (breaking change for order cancellation)
  • Updated endpoint description to clarify market-specific cancellation behavior

[1.2.0] - 2025-01-10

⚠️ Removed - WebSocket Method

Deprecated get_last_trades_by_instrument WebSocket Method

The get_last_trades_by_instrument WebSocket method has been removed. This method was previously used to retrieve historical trade data through the WebSocket connection.

Migration Guide

Use the REST API endpoint instead:

// Before (WebSocket)
ws.send(
  JSON.stringify({
    type: 'get_last_trades_by_instrument',
    instrument_name: 'BTC_USDC-29AUG25-106000-C',
    start_timestamp: 1677721600000,
    end_timestamp: 1677808000000,
  }),
);

// After (REST API)
const response = await fetch(
  `/last_trades_by_instrument?instrument_name=${instrumentName}&start_timestamp=${startTimestamp}&end_timestamp=${endTimestamp}`,
  {
    headers: {
      'x-apikey': API_KEY,
      'Content-Type': 'application/json',
    },
  },
);
const trades = await response.json();

Benefits

  • Better Performance: REST API is optimized for historical data queries
  • Caching: REST responses can be cached by CDNs and browsers
  • Simpler Integration: No need to maintain WebSocket connection for historical data
  • Standard HTTP: Use familiar HTTP methods and status codes for error handling

📚 Enhanced - Order Submission Documentation

Improved Code Examples and Field Clarifications

Enhanced the order submission documentation with clearer examples and important field requirements:

  1. Signature Requirements: Clearly documented that both signature andsignature_deadline are required when not using one-click sessions
  2. Separate Examples: Added distinct examples for options and perpetual orders showing the correct field usage
  3. Field Clarifications:
    • Options orders use contracts field
    • Perpetual orders use amount field
    • The taker field is optional and defaults to zero address (any taker)

New Code Examples

// Options Order Example
const optionsOrder = {
  instrument_name: 'BTC_USDC-29AUG25-106000-C',
  type: 'good_til_cancelled',
  contracts: 1.5, // For options
  direction: 'buy',
  price: 2500,
  // ... other fields
};

// Perpetuals Order Example
const perpsOrder = {
  instrument_name: 'BTC_USDC-PERPETUAL',
  type: 'good_til_cancelled',
  amount: 10000, // For perpetuals
  direction: 'buy',
  price: 45000,
  // ... other fields
};

🔧 Enhanced - Error Response Documentation

Detailed Validation Error Structure

Order rejection responses now include detailed validation error information when the rejection reason is "invalid request":

{
  "rejected_orders": [
    {
      "order_id": "abc123",
      "reason": "invalid request",
      "error": [
        {
          "instancePath": "/orders/0/contracts",
          "schemaPath": "#/properties/contracts/minimum",
          "keyword": "minimum",
          "params": { "limit": 0 },
          "message": "must be >= 0"
        }
      ]
    }
  ]
}

Benefits

  • Precise Error Location: instancePath shows exactly which field failed validation
  • Clear Error Messages: Human-readable messages explain what went wrong
  • Faster Debugging: Developers can quickly identify and fix validation issues

[1.1.1] - 2025-01-09

🔧 Fixed - API Header Standardization

API Key Header Casing

Standardized the API key header name to use consistent lowercase formatting:

Before:

X-APIKey: your-api-key-here

After:

x-apikey: your-api-key-here

Migration Guide

Update your API requests to use the lowercase header:

// Before
const response = await fetch('/instruments?market=ETH', {
  headers: {
    'X-APIKey': API_KEY,
    'Content-Type': 'application/json',
  },
});

// After
const response = await fetch('/instruments?market=ETH', {
  headers: {
    'x-apikey': API_KEY,
    'Content-Type': 'application/json',
  },
});

Benefits

  • Consistent Header Casing: All headers now follow lowercase convention
  • HTTP/2 Compatibility: Lowercase headers are required for HTTP/2
  • Framework Alignment: Matches standard practices across modern APIs

🔧 Fixed - WebSocket Event Types

Corrected Event Type Naming

Fixed inconsistent event type naming in WebSocket documentation:

Before:

{
  "type": "withdraw",
  "action": "withdraw"
}

After:

{
  "type": "withdrawal",
  "action": "withdrawal"
}

Migration Guide

Update your WebSocket event handlers:

// Before
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  if (message.type === 'withdraw') {
    // Handle withdrawal event
  }
};

// After
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  if (message.type === 'withdrawal') {
    // Handle withdrawal event
  }
};

Benefits

  • Consistency: Event types now match the implementation and enum definitions
  • Clarity: "withdrawal" is more descriptive than "withdraw"
  • Type Safety: Consistent naming improves TypeScript integration

[1.1.0] - 2025-01-04

🚀 Enhanced - Account State Endpoint

Improved Risk & Market Data

The /account_state/{account} endpoint now provides significantly more detailed information to support advanced trading strategies and risk management.

Breaking Changes

  • Response Structure Flattened: The summary wrapper object has been removed. Account state fields are now directly accessible at the root level of each margin account.

    Before:

    {
      "margin_accounts": [
        {
          "pair": "ETH_USDC",
          "summary": {
            "equity": 10500.0,
            "im": 2000.0,
            "mm": 1500.0,
            "pnl": 500.0
          },
          "positions": [...]
        }
      ]
    }

    After:

    {
      "margin_accounts": [
        {
          "pair": "ETH_USDC",
          "timestamp": 1677721600000,
          "margin_account": 12345,
          "equity": 10500.0,
          "im": 2000.0,
          "mm": 1500.0,
          "unrealised_pnl": 500.0,
          // ... additional fields
          "positions": [...]
        }
      ]
    }

New Response Fields

  • timestamp: Unix timestamp when the account state was calculated
  • margin_account: Unique margin account identifier
  • matrix_risk: Portfolio risk matrix component for comprehensive risk assessment
  • delta_risk: Delta risk component measuring directional exposure
  • roll_risk: Roll risk component for near-expiry option positions
  • portfolio_greeks: Portfolio-level Greeks aggregation
    • delta: Portfolio delta exposure
    • gamma: Portfolio gamma exposure
    • vega: Portfolio vega exposure
    • theta: Portfolio theta (time decay)
    • rho: Portfolio rho (interest rate sensitivity)

Enhanced Position Data

Positions now include real-time market data and risk metrics:

For Options:

  • instrument_type: Always "option" for option positions
  • mark_price: Current mark price of the option
  • mark_iv: Mark implied volatility
  • mark_interest: Mark interest rate used in pricing
  • position_greeks: Position-level Greeks
    • delta, gamma, theta, vega, rho

For Perpetuals:

  • instrument_type: Always "perp" for perpetual positions
  • mark_price: Current mark price of the perpetual
  • current_funding_rate: Current funding rate
  • position_greeks: Position-level Greeks
    • delta

Migration Guide

Update your code to access account state fields directly:

// Before
const equity = accountState.margin_accounts[0].summary.equity;
const im = accountState.margin_accounts[0].summary.im;

// After
const equity = accountState.margin_accounts[0].equity;
const im = accountState.margin_accounts[0].im;

// New capabilities
const portfolioGreeks = accountState.margin_accounts[0].portfolio_greeks;
const riskBreakdown = {
  matrix: accountState.margin_accounts[0].matrix_risk,
  delta: accountState.margin_accounts[0].delta_risk,
  roll: accountState.margin_accounts[0].roll_risk,
};

Benefits

  • Better Risk Management: Detailed risk component breakdown enables more sophisticated risk monitoring
  • Real-time Market Data: Position-level mark prices and Greeks for accurate P&L calculation
  • Reduced API Calls: Mark prices and Greeks available directly without additional requests
  • Enhanced Analytics: Portfolio-level Greeks aggregation for portfolio analysis
  • Streamlined Integration: Simplified response structure reduces parsing complexity

For questions or support, please contact our development team or visit our documentation.