GuidesAPI Reference
DocumentationLog In

Channels

Heartbeat Channel

To receive heartbeat messages for specific products every second, subscribe to the heartbeat channel. Heartbeats include sequence numbers and last trade IDs that can be used to verify that no messages were missed.

// Request
{
    "type": "subscribe",
    "channels": [
        {
            "name": "heartbeat",
            "product_ids": [
                "ETH-EUR"
            ]
        }
    ]
}
// Heartbeat message
{
  "type": "heartbeat",
  "sequence": 90,
  "last_trade_id": 20,
  "product_id": "BTC-USD",
  "time": "2014-11-07T08:19:28.464459Z"
}

Status Channel

❗️

Order Size Properties Removed

The properties base_max_size, base_min_size, max_market_funds were removed on June 30. The property, min_market_funds, has been repurposed as the notional minimum size for limit orders. See the Changelog.

The status channel sends all products and currencies on a preset interval.

// Request
{
  "type": "subscribe",
  "channels": [{ "name": "status"}]
}
// Status Message
{
  "type": "status",
  "products": [
    {
      "id": "BTC-USD",
      "base_currency": "BTC",
      "quote_currency": "USD",
      "base_increment": "0.00000001",
      "quote_increment": "0.01",
      "display_name": "BTC/USD",
      "status": "online",
      "status_message": null,
      "min_market_funds": "10",
      "post_only": false,
      "limit_only": false,
      "cancel_only": false,
      "fx_stablecoin": false
    }
  ],
  "currencies": [
    {
      "id": "USD",
      "name": "United States Dollar",
      "min_size": "0.01000000",
      "status": "online",
      "status_message": null,
      "max_precision": "0.01",
      "convertible_to": ["USDC"],
      "details": {}
    },
    {
      "id": "USDC",
      "name": "USD Coin",
      "min_size": "0.00000100",
      "status": "online",
      "status_message": null,
      "max_precision": "0.000001",
      "convertible_to": ["USD"],
      "details": {}
    },
    {
      "id": "BTC",
      "name": "Bitcoin",
      "min_size":" 0.00000001",
      "status": "online",
      "status_message": null,
      "max_precision": "0.00000001",
      "convertible_to": [],
      "details": {}
    }
  ]
}

Ticker Channel

The ticker channel provides real-time price updates every time a match happens. It batches updates in case of cascading matches, greatly reducing bandwidth requirements.

// Request
{
    "type": "subscribe",
    "product_ids": [
        "ETH-USD",
        "BTC-USD"
    ],
    "channels": ["ticker"]
}
// Ticker messsage
{
   "type":"ticker",
   "sequence":29912240,
   "product_id":"BTC-USD",
   "price":"40552.26",
   "open_24h":"40552.26",
   "volume_24h":"0.43526841",
   "low_24h":"40552.26",
   "high_24h":"40662.06",
   "volume_30d":"160.65999711",
   "best_bid":"40552.26",
   "best_ask":"40553.84",
   "side":"sell",
   "time":"2022-03-16T18:42:08.145773Z",
   "trade_id":131414,
   "last_size":"0.00002465"
}

Ticker Batch Channel

The ticker_batch channel provides latest price updates every 5000 milliseconds (5 seconds) if there is a change. It has the same JSON message schema as the ticker channel.

📘

The ticker_1000 channel has been renamed ticker_batch but you can use either name when subscribing.

// Request
{
    "type": "subscribe",
    "product_ids": [
        "ETH-USD",
        "BTC-USD"
    ],
    "channels": ["ticker_batch"]
}

Level2 Channel

The level2 channel guarantees delivery of all updates and is the easiest way to keep a snapshot of the order book. This channel also reduces the overhead required when consuming the full channel.

// Request
{
    "type": "subscribe",
    "product_ids": [
        "ETH-USD",
        "BTC-USD"
    ],
    "channels": ["level2"]
}

👍

Subscribe to the level2 channel to guarantee that messages are delivered and your order book is in sync.

The level2 channel sends a message with the type snapshot and the corresponding product_id. The properties bids and asks are arrays of [price, size] tuples and represent the entire order book.

{
  "type": "snapshot",
  "product_id": "BTC-USD",
  "bids": [["10101.10", "0.45054140"]],
  "asks": [["10102.55", "0.57753524"]]
}

Subsequent updates have the type l2update. The changes property of l2updates is an array with [side, price, size] tuples. The time property of l2update is the time of the event as recorded by our trading engine.

Single changes Array
{
  "type": "l2update",
  "product_id": "BTC-USD",
  "time": "2019-08-14T20:42:27.265Z",
  "changes": [
    [
      "buy",
      "10101.80000000",
      "0.162567"
    ]
  ]
}
Multiple changes Arrays
{
  "type": "l2update",
  "product_id": "BTC-USD",
  "changes": [
    [
      "buy",
      "22356.270000",
      "0.00000000"
    ],
    [
      "buy",
      "22356.300000",
      "1.00000000"
    ]
  ],
  "time": "2022-08-04T15:25:05.010758Z"
}

📘

The size property is the updated size at the price level, not a delta. A size of "0" indicates the price level can be removed.

Level2 Batch Channel

The level2_batch channel sends batches of level2 messages every 50 milliseconds (0.05 seconds). It has the same JSON message schema as the level2 channel. The time field correlates to the most recent message in the batch.

📘

The level2_50 channel has been renamed level2_batch but you can use either name when subscribing.

// Request
{
    "type": "subscribe",
    "product_ids": [
        "ETH-USD",
        "BTC-USD"
    ],
    "channels": ["level2_batch"]
}

👍

Use this level2 batched channel to get the same benefits as the level2 channel while minimizing the traffic.

User Channel

The user channel is a version of the full channel and only contains messages that include the authenticated user. Consequently, you need to be authenticated to receive any messages.

Matches Channel

If you are only interested in match messages, you can subscribe to the matches channel. This is useful when you're consuming the remaining feed using the level2 channel.

🚧

Messages can be dropped from this channel. Use the heartbeat channel to track the last trade ID and fetch trades that you missed from the REST API.

Full channel

The full channel provides real-time updates on orders and trades. These updates can be applied to a level3 order book snapshot to maintain an accurate and up-to-date copy of the exchange order book.

👍

If you are maintaining a level2 order book, use the level2 channel to guarantee that messages are delivered and your order book is in sync.

To maintain an up-to-date level3 order book:

  1. Send a subscribe message for the product(s) of interest and the full channel.
  2. Queue any messages received over the websocket stream.
  3. Make a REST request for the order book snapshot from the REST feed.
  4. Playback queued messages, discarding sequence numbers before or equal to the snapshot sequence number.
  5. Apply playback messages to the snapshot as needed (see below).
  6. After playback is complete, apply real-time stream messages as they arrive.

📘

All open and match messages always result in a change to the order book. Not all done or change messages result in changing the order book. These messages are sent for received orders which are not yet on the order book. Do not alter the order book for such messages, otherwise your order book will be incorrect.

The following messages are sent over the websocket stream in JSON format when subscribing to the full channel:

Received

A valid order has been received and is now active.

This message is emitted for every single valid order as soon as the matching engine receives it, whether it fills immediately or not.

The received message does not indicate a resting order on the order book. The received message indicates that a new incoming order has been accepted by the matching engine for processing. Received orders may cause match message to follow if they are able to begin being filled (taker behavior).

Self-trade prevention may also trigger change messages to follow if the order size needs to be adjusted. Orders that are not fully filled or that are canceled due to self-trade prevention, result in an open message and become resting orders on the order book.

Market orders (indicated by the order_type field) may have an optional funds field which indicates how much quote currency is used to buy or sell. For example, a funds field of 100.00 for the BTC-USD product would indicate a purchase of up to 100.00 USD worth of bitcoin.

Received message for limit order:

{
  "type": "received",
  "time": "2014-11-07T08:19:27.028459Z",
  "product_id": "BTC-USD",
  "sequence": 10,
  "order_id": "d50ec984-77a8-460a-b958-66f114b0de9b",
  "size": "1.34",
  "price": "502.1",
  "side": "buy",
  "order_type": "limit",
  "client-oid": "d50ec974-76a2-454b-66f135b1ea8c"
}

Received message for market order:

{
  "type": "received",
  "time": "2014-11-09T08:19:27.028459Z",
  "product_id": "BTC-USD",
  "sequence": 12,
  "order_id": "dddec984-77a8-460a-b958-66f114b0de9b",
  "funds": "3000.234",
  "side": "buy",
  "order_type": "market",
  "client-oid": "d50ec974-76a2-454b-66f135b1ea8c"
}

Open

The order is now open on the order book.

This message is only sent for orders that are not fully filled immediately. remaining_size indicates how much of the order is unfilled and going on the book.

📘

There is no open message for orders that are filled immediately. And there is no open message for market orders since they are filled immediately.

{
  "type": "open",
  "time": "2014-11-07T08:19:27.028459Z",
  "product_id": "BTC-USD",
  "sequence": 10,
  "order_id": "d50ec984-77a8-460a-b958-66f114b0de9b",
  "price": "200.2",
  "remaining_size": "1.00",
  "side": "sell"
}

Done

The order is no longer on the order book.

This message is sent for all orders for which there was a received message and can result from an order being canceled or filled.

There are no more messages for an order_id after a done message. remaining_size indicates how much of the order went unfilled; this is 0 for filled orders.

market orders do not have a remaining_size or price field as they are never on the open order book at a given price.

📘

A done message is sent for received orders that are fully filled or canceled due to self-trade prevention. There are no open messages for such orders. done messages for orders that are not on the book should be ignored when maintaining a real-time order book.

{
  "type": "done",
  "time": "2014-11-07T08:19:27.028459Z",
  "product_id": "BTC-USD",
  "sequence": 10,
  "price": "200.2",
  "order_id": "d50ec984-77a8-460a-b958-66f114b0de9b",
  "reason": "filled", // or "canceled"
  "side": "sell",
  "remaining_size": "0"
}

Cancel Reason

Done messages with reason=canceled (that are authenticated and that originated with you the user) return the reason in the cancel_reason field:

Supported cancel reasons are:

101:Time In Force
102:Self Trade Prevention
103:Admin
104:Price Bound Order Protection
105:Insufficient Funds
106:Insufficient Liquidity
107:Broker

Match

A trade occurred between two orders.

The aggressor or taker order is the one executing immediately after being received and the maker order is a resting order on the book.

The side field indicates the maker order side. If the side is sell this indicates the maker was a sell order and the match is considered an up-tick. A buy side match is a down-tick.

{
  "type": "match",
  "trade_id": 10,
  "sequence": 50,
  "maker_order_id": "ac928c66-ca53-498f-9c13-a110027a60e8",
  "taker_order_id": "132fb6ae-456b-4654-b4e0-d681ac05cea1",
  "time": "2014-11-07T08:19:27.028459Z",
  "product_id": "BTC-USD",
  "size": "5.23512",
  "price": "400.23",
  "side": "sell"
}

If authenticated, and you were the taker, the message would also have the following fields:

{
  ...
  "taker_user_id": "5844eceecf7e803e259d0365",
  "user_id": "5844eceecf7e803e259d0365",
  "taker_profile_id": "765d1549-9660-4be2-97d4-fa2d65fa3352",
  "profile_id": "765d1549-9660-4be2-97d4-fa2d65fa3352",
  "taker_fee_rate": "0.005"
}

Similarly, if you were the maker, the message would have the following:

{
  ...
  "maker_user_id": "5f8a07f17b7a102330be40a3",
  "user_id": "5f8a07f17b7a102330be40a3",
  "maker_profile_id": "7aa6b75c-0ff1-11eb-adc1-0242ac120002",
  "profile_id": "7aa6b75c-0ff1-11eb-adc1-0242ac120002",
  "maker_fee_rate": "0.001"
}

Change

An order has changed.

A change message can be the result of either a Self-trade Prevention (STP) or a Modify Order Request (beta):

👍

Beta Feature!

Modify Order Request is in beta and available for testing in your sandbox. See also: FIX Modify Order Request (G).

  • A Self-trade Prevention adjusts the order size or available funds (and can only decrease).
  • A Modify Order Request adjusts the order size or price.

change messages are sent anytime an order changes in size or price. This includes:

  • Orders that are open (resting)
  • Orders that are received but not yet open.
  • Market orders with funds changed from a Self-trade Prevention control.

📘

If you are building a real-time order book, you can ignore change messages for received but not yet open orders.

If you are building from a level2 book, the side and price fields to indicate whether the change message is relevant. STP Change messages for limit orders always have a price specified. STP change messages for market orders have no price (null) and a decrease in order size.

Example of a change messsage from a Self-trade Prevention action:

{
  "type": "change",
  "reason":"STP",
  "time": "2014-11-07T08:19:27.028459Z",
  "sequence": 80,
  "order_id": "ac928c66-ca53-498f-9c13-a110027a60e8",
  "side": "sell",
  "product_id": "BTC-USD",
  "old_size": "12.234412",
  "new_size": "5.23512",
  "price": "400.23"
}

Example of a change message from a Modify Order Request:

{
  "type": "change",
  "reason":"modify_order",
  "time": "2022-06-06T22:55:43.433114Z",
  "sequence": 24753,
  "order_id": "c3f16063-77b1-408f-a743-88b7bc20cdcd",
  "side": "buy",
  "product_id": "ETH-USD",
  "old_size": "80",
  "new_size": "80",
  "old_price": "7",
  "new_price": "6"
}

Activate

An activate message is sent when a stop order is placed.

When the stop is triggered the order is placed and goes through the order lifecycle.

{
  "type": "activate",
  "product_id": "test-product",
  "timestamp": "1483736448.299000",
  "user_id": "12",
  "profile_id": "30000727-d308-cf50-7b1c-c06deb1934fc",
  "order_id": "7b52009b-64fd-0a2a-49e6-d8a939753077",
  "stop_type": "entry",
  "side": "buy",
  "stop_price": "80",
  "size": "2",
  "funds": "50",
  "private": true
}

Auction Channel

The auction channel sends information about the auction while the product is in auction mode.

Auction messages provide the most recent indicative quote disseminated during the auction. Indicative quote messages are sent on an interval basis (about once a second) during the collection phase of an auction. The indicative quote includes information about the tentative price and size affiliated with the completion.

The open price and size indicate the aggregate size of all the orders eligible for crossing, along with the price used for matching all the orders as the auction enters the opening state. The best bid and ask price and size fields indicate the anticipated BBO upon entering full trading or limit only after the matching has completed.

Because indicative quotes are sent on an interval, values are not firm. The price may change in between two quote updates: (1) in between two normal quote update intervals, or (2) in between the last normal quote update interval and the final indicative quote that occurs when the book transitions from auction mode to full trading.

See Get product book in the API Reference for more details on the level 1 book and products in auction mode.

// Request
{
  "type": "subscribe",
  "channels": [{ "name": "auctionfeed", "product_ids": ["LTC-USD"] }]
}
// Auction Message
{
    "type": "auction",
    "product_id": "LTC-USD",
    "sequence": 3262786978,
    "auction_state": "collection",
    "best_bid_price": "333.98",
    "best_bid_size": "4.39088265",
    "best_ask_price": "333.99",
    "best_ask_size": "25.23542881",
    "open_price": "333.99",
    "open_size": "0.193",
    "can_open": "yes",
    "timestamp": "2015-11-14T20:46:03.511254Z"
}