Added

v1.15.0 - 2026-01-31

Added

  • New WebSocket channel: position for real-time position updates

    Subscribe to receive position updates every second for your margin accounts with enriched market data including mark prices and Greeks.

    Subscription example:

    {
      "type": "subscribe",
      "subscriptions": [
        {
          "channel": "position",
          "query": {
            "account": "0x1234567890abcdef1234567890abcdef12345678",
            "market": "ETH"
          }
        }
      ]
    }

    Query parameters:

    • account (required): Smart account address
    • market (optional): Base token filter (BTC, ETH, ARB)

    Event payload:

    {
      "kind": "event",
      "type": "position",
      "timestamp_ms": 1705420800000,
      "data": {
        "margin_account": "550e8400-e29b-41d4-a716-446655440000",
        "market": "ETH",
        "positions": [
          {
            "instrument_name": "ETH_USDC-PERPETUAL",
            "size": 10.5,
            "average_price": 2450.00,
            "instrument_type": "perp",
            "mark_price": 2475.00,
            "current_funding_rate": 0.0001,
            "position_greeks": { "delta": 10.5 }
          }
        ]
      }
    }

    Benefits: Dedicated position channel provides 1-second updates with enriched market data, separate from account state events.

  • Account History V2 endpoint with cursor-based pagination

    Enhanced account history endpoint at /v2/account_history with standardized event structures, advanced filtering, and efficient cursor-based pagination.

    New features:

    • Cursor-based pagination via cursor and next_cursor fields
    • Sort order control (sort: asc/desc)
    • Event type filtering (event_types: trade, transfer, settlement, funding)
    • Action filtering (actions: buy, sell, deposit, withdrawal)
    • Transfer type filtering (transfer_type: internal, external)
    • Market/instrument filtering (markets: BTC, ETH, ARB)

    Request example:

    const params = new URLSearchParams({
      address: '0x1234...',
      event_types: 'trade,transfer',
      sort: 'desc',
      limit: '50',
    });
    const response = await fetch(`/v2/account_history?${params}`);
    const data = await response.json();
    
    // Paginate with cursor
    if (data.has_more) {
      const nextPage = await fetch(data.next_cursor_url);
    }

    Response structure:

    {
      "address": "0x1234...",
      "limit": 50,
      "returned": 50,
      "has_more": true,
      "next_cursor": "eyJ0aW1lc3RhbXAi...",
      "next_cursor_url": "https://api.kyan.sh/v2/account_history?...",
      "events": [
        {
          "id": "evt_001",
          "timestamp": 1705420800,
          "event_type": "trade",
          "margin_account_id": "...",
          "data": { /* event-specific data */ }
        }
      ]
    }

    Benefits: Efficient retrieval of large datasets, consistent event structures, and flexible filtering reduce client-side processing.

Changed

  • Breaking Change: account_state event no longer includes positions array

    The account_state WebSocket event payload has been streamlined to remove the positions field.

    Before:

    {
      "type": "account_state",
      "data": {
        "margin_account": 12345,
        "pair": "BTC_USDC",
        "im": 5000.0,
        "mm": 2500.0,
        "equity": 15000.0,
        "portfolio_greeks": { "delta": 0.45, "gamma": 0.0012, ... },
        "positions": [{ "instrument_name": "...", "size": 1.5, ... }]
      }
    }

    After:

    {
      "type": "account_state",
      "data": {
        "margin_account": 12345,
        "pair": "BTC_USDC",
        "im": 5000.0,
        "mm": 2500.0,
        "equity": 15000.0,
        "portfolio_greeks": { "delta": 0.45, "gamma": 0.0012, ... },
        "liquidation": false
      }
    }

    Migration: Subscribe to the new position channel for real-time position data with enriched market information.

    Benefits: Reduced payload size and bandwidth; position data now available via dedicated channel with 1-second updates.

  • Breaking Change: Order events now use batched array format

    WebSocket order events (post_order, cancel_order, update_order, edit_order) now deliver orders in arrays, allowing multiple orders per message.

    Before:

    {
      "type": "post_order",
      "data": {
        "order_id": "abc123",
        "instrument_name": "BTC_USDC-PERPETUAL",
        "amount": 1000,
        "price": 98500
      }
    }

    After:

    {
      "type": "post_order",
      "data": [
        {
          "order_id": "abc123",
          "instrument_name": "BTC_USDC-PERPETUAL",
          "amount": 1000,
          "price": 98500
        }
      ]
    }

    Migration:

    // Before
    if (event.type === 'post_order') {
      processOrder(event.data);
    }
    
    // After
    if (event.type === 'post_order') {
      for (const order of event.data) {
        processOrder(order);
      }
    }

    Benefits: Efficient batch delivery reduces message overhead for high-frequency order updates. Single-order events are delivered as single-element arrays for consistency.

  • New edit_order WebSocket event type

    When orders are edited via PATCH /limit, an edit_order event is now emitted on orderbook channels (orderbook_options, orderbook_perps, orderbook_maker).

    Event payload:

    {
      "type": "edit_order",
      "data": [
        {
          "order_id": "abc123",
          "instrument_name": "BTC_USDC-PERPETUAL",
          "price": 99000,
          "amount": 1500,
          "order_state": "open",
          "filled_amount": 0
        }
      ]
    }

    Note: The edited order retains its original order_id. Use this event to update local orderbook caches when order prices or sizes change.