Channels

The heartbeat channel

// Request
{
    "type": "subscribe",
    "channels": [{ "name": "heartbeat", "product_ids": ["ETH-EUR"] }]
}

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

// Heartbeat message
{
    "type": "heartbeat",
    "sequence": 90,
    "last_trade_id": 20,
    "product_id": "BTC-USD",
    "time": "2014-11-07T08:19:28.464459Z"
}

The status channel

// Request
{
    "type": "subscribe",
    "channels": [{ "name": "status"}]
}

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

// Status Message
{
    "type": "status",
    "products": [
        {
            "id": "BTC-USD",
            "base_currency": "BTC",
            "quote_currency": "USD",
            "base_min_size": "0.001",
            "base_max_size": "70",
            "base_increment": "0.00000001",
            "quote_increment": "0.01",
            "display_name": "BTC/USD",
            "status": "online",
            "status_message": null,
            "min_market_funds": "10",
            "max_market_funds": "1000000",
            "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": {}
        }
    ]
}

The 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.

{
    "type": "ticker",
    "trade_id": 20153558,
    "sequence": 3262786978,
    "time": "2017-09-02T17:05:49.250000Z",
    "product_id": "BTC-USD",
    "price": "4388.01000000",
    "side": "buy", // taker side
    "last_size": "0.03000000",
    "best_bid": "4388",
    "best_ask": "4388.01"
}

Please note that more information will be added to messages from this channel in the near future.

The level2 channel

The easiest way to keep a snapshot of the order book is to use the level2 channel.
It guarantees delivery of all updates, which reduce a lot of the overhead required when consuming the full channel.

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

When subscribing to the channel it will send a message with the type snapshot and the corresponding product_id.
bids and asks are arrays of [price, size] tuples and represent the entire order book.

{
  "type": "l2update",
  "product_id": "BTC-USD",
  "time": "2019-08-14T20:42:27.265Z",
  "changes": [
    [
      "buy",
      "10101.80000000",
      "0.162567"
    ]
  ]
}

Subsequent updates will 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.
Please note that size is the updated size at that price level, not a delta.
A size of "0" indicates the price level can be removed.

The user channel

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

The 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 level 2 channel.

Please note that messages can be dropped from this channel.
By using the heartbeat channel you can track the last trade id and fetch trades that you missed from the REST API.

The full channel

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

πŸ“˜

Note: If you are maintaining a level 2 order book, please consider switching to the level 2 channel.

An algorithm to maintain an up-to-date level 3 order book is described below.
Please note that you will rarely need to implement this yourself.

  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 will always result in a change to the order book.
Not all done or change messages will result in changing the order book.
These messages will be 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.
It simply indicates a new incoming order which as 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 which are not fully filled or 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 will be 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"
}

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"
}

Open

The order is now open on the order book.
This message will only be sent for orders which are not fully filled immediately.
remaining_size will indicate how much of the order is unfilled and going on the book.

πŸ“˜

There will be no open message for orders which will be filled immediately.
There will be 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.
Sent for all orders for which there was a received message.
This message can result from an order being canceled or filled.
There will be no more messages for this order_id after a done message.
remaining_size indicates how much of the order went unfilled; this will be 0 for filled orders.
market orders will not have a remaining_size or price field as they are never on the open order book at a given price.

πŸ“˜

A done message will be sent for received orders which are fully filled or canceled due to self-trade prevention.
There will be no open message for such orders.
done messages for orders which 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"
}

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.
This is the result of self-trade prevention adjusting the order size or available funds.
Orders can only decrease in size or funds.
change messages are sent anytime an order changes in size; this includes resting orders (open) as well as received but not yet open.
change messages are also sent when a new market order goes through self trade prevention and the funds for the market order have changed.

πŸ“˜

change messages for received but not yet open orders can be ignored when building a real-time order book.
The side field of a change message and price can be used as indicators for whether the change message is relevant if building from a level 2 book.

Any change message where the price is null indicates that the change message is for a market order.
Change messages for limit orders will always have a price specified.

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

Activate

An activate message is sent when a stop order is placed.
When the stop is triggered the order will be placed and go 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

// Request
{
    "type": "auction",
    "channels": [{ "name": "auctionfeed"}]
}

The auction channel will send information about the auction while the product is in auction mode.
For more details on the auction mode see the documentation section describing the level 1 book which contains information pertaining to products in auction mode.

// 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"
}