NAV Navbar
code

Introduction

Welcome to Blockchain.com's Exchange API and developer documentation. These documents detail and give examples of various functionality offered by the API such as receiving real time market data, requesting balance information and performing trades.

View the full REST API documentation here.

To Get Started

Websocket API

The Websocket API can be used to receive market data and to interact with the trading system in real time. Every message is in a JSON format and trading messages use the FIX standard for naming of fields, and message types.

Each type of data is provided over a dedicated channel. Clients need to subscribe to all relevant channels they wish to receive real time updates from.

Authentication

# Simple python websocket client
# https://github.com/websocket-client/websocket-client
from websocket import create_connection
options = {}
options['origin'] = 'https://exchange.blockchain.com'
url = "wss://ws.blockchain.info/mercury-gateway/v1/ws"
ws = create_connection(url, **options)
msg = '{"token": "{API_SECRET}", "action": "subscribe", "channel": "auth"}'
ws.send(msg)
result =  ws.recv()
print(result)
# { "seqnum":0,
#   "event":"subscribed",
#   "channel":"auth",
#   "readOnly":false }
ws.close()

Interaction with the API will require an API key. To generate one, go to the API section of your Blockchain.com Exchange user settings. Each API key generated will be linked to your account. The only required information is a key name. Optionally you can set trading access, and IP address whitelisting.

Once your key is created you'll be shown an API Key and API Secret. Store the secret in a safe place because it will only be shown once.

Connection

The websocket endpoint is,

Environment URI
prod wss://ws.blockchain.info/mercury-gateway/v1/ws

In order to connect you have to add the following headers to the connection request

Environment Headers
prod Origin: https://exchange.blockchain.com

Requests

Each Message sent to the server will have at least 2 fields: action and channel.

Channel

A channel provides context about the type of data being communicated between the client and server. There are multiple channels available:

Channel Visibility Description
heartbeat anonymous Receive heartbeat messages
l2 anonymous Receive level 2 order book data (aggregated)
l3 anonymous Receive level 3 order book data (aggregated)
prices anonymous Receive candlestick market data
symbols anonymous Receive symbol messages
ticker anonymous Receive ticker messages
trades anonymous Receive trade execution messages
auth authenticated To authenticate a web socket connection
balances authenticated To receive balance updates
trading authenticated Submit & cancel orders, receive order snapshots and updates

Action

action describes what action to take for the provided channel. The following standard action's are supported by all channels (with the exception of the auth channel):

Action Description
subscribe Subscribe to the provided channel and attributes
unsubscribe Unsubscribe from the provided channel and attributes

A channel may expose other bespoke actions.

Response

Sequence Numbers

Each message sent from the server will contain a sequence number seqnum which will be incremented by 1 with each message. If the client receives a seqnum which has skipped one or more sequences, it indicates that a message was missed and the client is recommended to restart the websocket connection.

Event

In addition, each response field will contain an event field with the corresponding channel to indicate the purpose of the message. The following events are supported:

Event Type Description
subscribed admin The channel was successfully subscribed to
unsubscribed admin The channel was successfully unsubscribed to
rejected admin the last action for the channel was rejected. A text field will be provided about the reason for the reject
snapshot app A channel snapshot has been provided
updated app An update corresponding to the channel has occurred

Each time an action is applied to a channel, an administrative event is sent from the server to notify whether the action was applied successfully.

Data Types

All Messages use the standard JSON format. The following data types are supported:

Type Description Example
number Signed decimal number 1234.45
string UTF-8 encoded unicode string "Authentication Failed"
timestamp UTC Timestamps following the convention YYYY-MM-DDTHH:MM:SS.ssssssZ or YYYY-MM-DDTHH:MM:SS.000ssssssZ or YYYY-MM-DDT00:00:00Z

Fair usage and rate limits

{
  "event": "rejected",
  "text": "Connection throttling enabled, your messages will be ignored."
}

Currently there is a limit of 1200 messages per minute. If the limit is exceeded, you will receive a rejected event. After waiting a minute, normal functionality will resume and you will be able to send messages again.

Response data throttling and delays

The response and update messages are never delayed, clients will get every update as soon as it happens.

Anonymous Channels

Heartbeat

Subscribe to channel:

{
  "action": "subscribe",
  "channel": "heartbeat"
}

A heartbeat can be sent by the server by subscribing to the heartbeat channel.

Server response:

{
  "seqnum": 0,
  "event": "subscribed",
  "channel": "heartbeat"
}

The server will send confirmation of the subscription.

Snapshot Example:

{
  "seqnum": 1,
  "event": "updated",
  "channel": "heartbeat",
  "timestamp": "2019-05-31T08:36:45.666753Z"
}

Snapshot messages are sent every 5 seconds and have the following format:

L2 Order Book

Subscribe to channel:

{
  "action": "subscribe",
  "channel": "l2",
  "symbol": "BTC-USD"
}

Level 2 Order Book data is available through the l2 channel. This channel returns the volume available at each price. All the price levels are retrieved with this channel. Subscribing is done per symbol. Each entry in bids and asks arrays is a price level, along with its price (px), quantity (qty) and number of orders (num) attributes.

Server response:

{
  "seqnum": 1,
  "event": "subscribed",
  "channel": "l2",
  "symbol": "BTC-USD"
}

Snapshots:

{
  "seqnum": 2,
  "event": "snapshot",
  "channel": "l2",
  "symbol": "BTC-USD",
  "bids": [
    {
      "px": 8723.45,
      "qty": 1.45,
      "num": 2
    },
    {
      "px": 8124.45,
      "qty": 123.45,
      "num": 1
    }
  ],
  "asks": [
    {
      "px": 8730.0,
      "qty": 1.55,
      "num": 2
    },
    {
      "px": 8904.45,
      "qty": 13.66,
      "num": 2
    }
  ]
}

There is no ordering guarantee in bids and asks entries.

{
  "seqnum": 3,
  "event": "updated",
  "channel": "l2",
  "symbol": "BTC-USD",
  "bids": [
    {
      "px": 8723.45,
      "qty": 1.1,
      "num": 1
    }
  ],
  "asks": []
}

An update with qty equal to 0, means the price should be removed.

{
  "seqnum": 4,
  "event": "updated",
  "channel": "l2",
  "symbol": "BTC-USD",
  "bids": [
    {
      "px": 8723.45,
      "qty": 0.0,
      "num": 0
    }
  ],
  "asks": []
}

L3 Order Book

Subscribe to channel:

{
  "action": "subscribe",
  "channel": "l3",
  "symbol": "BTC-USD"
}

Level 3 Order Book data is available through the l3 channel. This channel returns all the order updates reaching the exchange; by applying the updates to the snapshot you can recreate the full state of the orderbook. Subscribing is done per symbol. Each entry in bids and asks arrays is an order, along with its id (id), price (px) and quantity (qty) attributes.

Server response:

{
  "seqnum": 1,
  "event": "subscribed",
  "channel": "l3",
  "symbol": "BTC-USD"
}

Example snapshot:

{
  "seqnum": 2,
  "event": "snapshot",
  "channel": "l3",
  "symbol": "BTC-USD",
  "bids": [
    {
      "id": "1234",
      "px": 8723.45,
      "qty": 1.1
    },
    {
      "id": "1235",
      "px": 8723.45,
      "qty": 0.35
    },
    {
      "id": "234",
      "px": 8124.45,
      "qty": 123.45
    }
  ],
  "asks": [
    {
      "id": "2222",
      "px": 8730.0,
      "qty": 0.65
    },
    {
      "id": "2225",
      "px": 8730.0,
      "qty": 0.9
    },
    {
      "id": "2343",
      "px": 8904.45,
      "qty": 8.66
    },
    {
      "id": "2353",
      "px": 8904.45,
      "qty": 5.0
    }
  ]
}

Updates will follow. An update with qty equal to 0, means the order should be removed.

{
  "seqnum": 3,
  "event": "updated",
  "channel": "l3",
  "symbol": "BTC-USD",
  "bids": [
    {
      "id": "1234",
      "px": 8723.45,
      "qty": 0
    }
  ],
  "asks": []
}

Prices

Subscribe to channel:

{
  "action": "subscribe",
  "channel": "prices",
  "symbol": "BTC-USD",
  "granularity": 60
}

To receive candlestick market data you can subscribe to the prices channel. Subscriptions are per symbol and granularity (in seconds) has to be specified. Supported granularity values are: 60, 300, 900, 3600, 21600, 86400

You can subscribe for multiple symbols but not for multiple granularities per symbol.

Server response:

{
  "seqnum": 0,
  "event": "subscribed",
  "channel": "prices",
  "symbol": "BTC-USD"
}

The server will send confirmation of the subscription.

Updated event on the prices channel:

{
  "seqnum": 2,
  "event": "updated",
  "channel": "prices",
  "symbol": "BTC-USD",
  "price": [1559039640, 8697.24, 8700.98, 8697.27, 8700.98, 0.431]
}

The price data is an array consisting of [timestamp, open, high, low, close, volume]

Symbols

To receive symbol updates, subscribe to the symbols channel. The server will send confirmation of the subscription. The next message on this channel will be a snapshot of the current symbol status.

When the symbol is not halted the auction data in the message may be blank.

When a symbol is in a halt state the auction data will populate as the book builds. When an opening time has been chosen, the auction-time field will show the opening time. Subsequent updates will be sent only if the symbol status changes in any way.

Field Description

Field Description
auction-price If the symbol is halted and will open on an auction, this will be the opening price.
auction-size Opening size
auction-time Opening time in HHMM format.
imbalance Auction imbalance. If > 0 then there will be buy orders left over at the auction price. If < 0 then there will be sell orders left over at the auction price.
status Symbol status; open, close, suspend, halt, halt-freeze.
base_currency The currency quantities are expressed in
base_currency_scale The number of decimals the currency can be split in
counter_currency The currency prices are expressed in
counter_currency_scale The number of decimals the currency can be split in
min_price_increment The price of the instrument must be a multiple of min_price_increment * (10^-min_price_increment_scale)
min_price_increment_scale The price of the instrument must be a multiple of min_price_increment * (10^-min_price_increment_scale)
min_order_size The minimum quantity for an order for this instrument must be min_order_size*(10^-min_order_size_scale)
min_order_size_scale The minimum quantity for an order for this instrument must be min_order_size*(10^-min_order_size_scale)
max_order_size The maximum quantity for an order for this instrument is max_order_size*(10^-max_order_size_scale). If this equal to zero, there is no limit
max_order_size_scale The maximum quantity for an order for this instrument is max_order_size*(10^-max_order_size_scale). If this equal to zero, there is no limit

Subscribe to channel:

{
  "action": "subscribe",
  "channel": "symbols"
}

Server response:

{
  "seqnum": 0,
  "event": "subscribed",
  "channel": "symbols"
}

Example symbol status:

{
  "seqnum": 1,
  "event": "snapshot",
  "channel": "symbols",
  "symbols": {
    "BTC-USD": {
      "base_currency": "BTC",
      "base_currency_scale": 8,
      "counter_currency": "USD",
      "counter_currency_scale": 2,
      "min_price_increment": 10,
      "min_price_increment_scale": 0,
      "min_order_size": 50,
      "min_order_size_scale": 2,
      "max_order_size": 0,
      "max_order_size_scale": 8,
      "lot_size": 5,
      "lot_size_scale": 2,
      "status": "halt",
      "id": 1,
      "auction_price": 0.0,
      "auction_size": 0.0,
      "auction_time": "",
      "imbalance": 0.0
    },
    "ETH-BTC": {
      "base_currency": "ETH",
      "base_currency_scale": 8,
      "counter_currency": "BTC",
      "counter_currency_scale": 8,
      "min_price_increment": 100,
      "min_price_increment_scale": 8,
      "min_order_size": 220001,
      "min_order_size_scale": 8,
      "max_order_size": 0,
      "max_order_size_scale": 8,
      "lot_size": 0,
      "lot_size_scale": 0,
      "status": "open",
      "id": 3,
      "auction_price": 0.0,
      "auction_size": 0.0,
      "auction_time": "",
      "imbalance": 0.0
    },
    "BTC-EUR": {
      "base_currency": "BTC",
      "base_currency_scale": 8,
      "counter_currency": "EUR",
      "counter_currency_scale": 2,
      "min_price_increment": 10,
      "min_price_increment_scale": 0,
      "min_order_size": 50,
      "min_order_size_scale": 2,
      "max_order_size": 0,
      "max_order_size_scale": 0,
      "lot_size": 0,
      "lot_size_scale": 0,
      "status": "closed",
      "id": 4,
      "auction_price": 0.0,
      "auction_size": 0.0,
      "auction_time": "",
      "imbalance": 0.0
    },
    "ETH-EUR": {
      "base_currency": "ETH",
      "base_currency_scale": 8,
      "counter_currency": "EUR",
      "counter_currency_scale": 2,
      "min_price_increment": 10,
      "min_price_increment_scale": 0,
      "min_order_size": 50,
      "min_order_size_scale": 2,
      "max_order_size": 500,
      "max_order_size_scale": 2,
      "lot_size": 0,
      "lot_size_scale": 0,
      "status": "open",
      "id": 5,
      "auction_price": 0.0,
      "auction_size": 0.0,
      "auction_time": "",
      "imbalance": 0.0
    },
    "ETH-USD": {
      "base_currency": "ETH",
      "base_currency_scale": 8,
      "counter_currency": "USD",
      "counter_currency_scale": 2,
      "min_price_increment": 5,
      "min_price_increment_scale": 0,
      "min_order_size": 50,
      "min_order_size_scale": 2,
      "max_order_size": 0,
      "max_order_size_scale": 0,
      "lot_size": 0,
      "lot_size_scale": 0,
      "status": "open",
      "id": 2,
      "auction_price": 0.0,
      "auction_size": 0.0,
      "auction_time": "",
      "imbalance": 0.0
    }
  }
}

Example not halted symbol:

{
  "seqnum": 1,
  "event": "updated",
  "channel": "symbols",
  "symbol": "BTC-USD",
  "auction-price": 0,
  "auction-size": 0,
  "auction-time": "",
  "imbalance": 0,
  "status": "open"
}

Example halted symbol:

{
  "seqnum": 1,
  "event": "updated",
  "channel": "symbols",
  "symbol": "BTC-USD",
  "auction-price": 4500.5,
  "auction-size": 220.125,
  "auction-time": "2230",
  "imbalance": -0.5,
  "status": "halt"
}

Ticker

Subscribe to channel:

{
  "action": "subscribe",
  "channel": "ticker",
  "symbol": "BTC-USD"
}

In order to receive ticker updates, ticker channel is available. Subscriptions are again per symbol. The server will send confirmation of the subscription.

Server response:

{
  "seqnum": 0,
  "event": "subscribed",
  "channel": "ticker"
}

Example ticker snapshot:

{
  "seqnum": 8,
  "event": "snapshot",
  "channel": "ticker",
  "symbol": "BTC-USD",
  "price_24h": 4988.0,
  "volume_24h": 0.3015,
  "last_trade_price": 5000.0
}

Trades

In order to receive trade updates on executions within each market across the Exchange, you can subscribe to the trades channel.

Subscriptions are again per symbol.

{
  "action": "subscribe",
  "channel": "trades",
  "symbol": "ETH-USD"
}

The server will send confirmation of the subscription.

{
  "seqnum": 0,
  "event": "subscribed",
  "channel": "trades",
  "symbol": "ETH-USD"
}

Example of a trade update:

{
  "seqnum": 21,
  "event": "updated",
  "channel": "trades",
  "symbol": "BTC-USD",
  "timestamp": "2019-08-13T11:30:06.100140Z",
  "side": "sell",
  "qty": 8.5e-5,
  "price": 11252.4,
  "trade_id": "12884909920"
}

Authenticated Channels

Authenticated

To authenticate a web socket connection, the client must subscribe to the auth channel passing a token field. Alternatively a client can provide the header cookie auth_token on a new connection and then authentication will take place immediately without the need to subscribing to auth channel.

If authentication is successful, the server will send an initial notification.

{
  "seqnum": 0,
  "event": "subscribed",
  "channel": "auth"
}

If authentication was unsuccessful, the server will send the following notification:

{
  "seqnum": 0,
  "event": "rejected",
  "channel": "auth",
  "text": "Authentication Failed"
}

Trading

The client can submit and cancel orders, as well as receive order executions, through the trading channel. The messages are in JSON format and the attribute names are using standardised FIX 4.2 Field names.

Below is a table showing the permitted FIX fields used as a JSON key for cancelling / creating an order:

Tag Field Type Mandatory Description Example
11 clOrdID string YES Reference field provided by client and cannot exceed 20 characters "ABC"
55 symbol string YES Blockchain symbol identifier "BTC-USD"
40 ordType string YES "market" for market "limit" for limit, "stop" for stop, "stopLimit" for stopLimit "limit"
59 timeInForce string YES "GTC" for Good Till Cancel, "IOC" for Immediate or Cancel, "FOK" for Fill or Kill, "GTD" Good Till Date "GTC"
54 side string YES "buy" for Buy, "sell" for Sell "buy"
38 orderQty number YES The order size in the terms of the base currency 10.23
44 price number required for limit and stopLimit order types The limit price for the order 0.12345
432 expireDate number required for GTD orders expiry date in the format YYYYMMDD 20190318
99 stopPx number required for limit and stopLimit order types Price to trigger the stop order 3500.12
110 minQty number Optional for all market orders and for limit orders with IOC timeInForce The minimum quantity required for an IOC fill 10.0
18 execInst string Optional for Limit Orders The order is placed with Add Liquidity Only (aka Post Only): it will not match liquidity immediately. It will be rejected instead of matching liquidity in the market. "ALO"

Below is a table representing the different permutations permitted for the FIX fields, with X indicating what can be added and where O is not required:

Market Limit Stop Stop Limit
clOrdID X X X X
symbol X X X X
ordType X X X X
timeInForce O X X X
side X X X X
orderQty X X X X
price X X
expireDate O
stopPx X X
minQty O O

The server can include the following additional FIX fields when notifying of an order update:

Tag Field Type Description Example
35 msgType string "8" for ExecutionReport, "9" for OrderCancelRejected "8"
150 execType string "0" for New, "4" for Canceled, "C" for Expired, "8" for Rejected, "F" for partial fill, "A" for Pending, "H" for Trade Break, "I" Order Status "O"
39 ordStatus string ‘cancelled’, ‘expired’, ...
37 orderID string The unique order id assigned by the exchange "11111111"
37 execID string Unique identifier for the execution "123456"
32 lastShares number The executed quantity for the order's last fill 0.5678
31 lastPx number The executed price for the last fill 3500.12
151 leavesQty string For Open and Partially Filled orders this is the remaining quantity open for execution. For Cancelled and Expired orders this is the quantity than was still open before cancellation/expiration. For Rejected order this is equal to orderQty. For other states this is always zero. 10.0
14 cumQty number The quantity of the order which has been filled 0.123345
60 transactTime string The time the transaction occurred "2019-08-13T13:15:35.000955868Z"
6 avgPx number Calculated the Volume Weighted Average Price of all fills for this order 345.33
1004 tradeId string The unique ID assigned to the order fill, also known as trade "77309432596"

state

Enumerated fields are defined as follows:

Name Description Example
pending Order is pending acceptance. Only applicable to stop and stop-limit orders
open Order has been accepted
rejected Order has been rejected Limit and market orders can get rejected if you have no balance to fill the order even partially.
cancelled Order has been cancelled A market order might get in state cancelled if you don’t have enough balance to fill it at market price. Both market orders and limit orders with IOC can have ordStatus ‘cancelled’ if there is no market for them, even without the user requesting the cancellation.
filled Order has been filled A limit order get in state cancelled after the user requested a cancellation.
partial Order has been partially filled
expired Order has been expired

type

Name Description
limit order which has a price limit
market order that will match at any price available in the market, starting from the best prices and filling up to the available balance
stop order which has a stop/trigger price, and when that price is reached, it triggers a market order
stopLimit order which has a stop price and limit price, and when the stop price is reached, it triggers a limit order at the limit price

timeInForce

To subscribe:

{
  "action": "subscribe",
  "channel": "trading"
}

To submit & cancel orders as well as receive live order updates, subscribe to the authenticated trading channel.

Server response:

{
  "seqnum": 1,
  "event": "subscribed",
  "channel": "trading"
}

The next message will be a snapshot of live orders for the logged on user"

{
  "seqnum": 3,
  "event": "snapshot",
  "channel": "trading",
  "orders": [
    {
      "orderID": "12891851020",
      "clOrdID": "78502a08-c8f1-4eff-b",
      "symbol": "BTC-USD",
      "side": "sell",
      "ordType": "limit",
      "orderQty": 5.0e-4,
      "leavesQty": 5.0e-4,
      "cumQty": 0.0,
      "avgPx": 0.0,
      "ordStatus": "open",
      "timeInForce": "GTC",
      "text": "New order",
      "execType": "0",
      "execID": "11321871",
      "transactTime": "2019-08-13T11:30:03.000593290Z",
      "msgType": 8,
      "lastPx": 0.0,
      "lastShares": 0.0,
      "tradeId": "0",
      "price": 15000.0
    }
  ]
}
Name Description
GTC Good Till Cancel. The order will rest on the order book until it is cancelled or filled
GTD Good Till Date. The order will reset on the order book until it is cancelled, filled, or expired
FOK Fill or Kill. The order is either completely filled or cancelled. No Partial Fills are permitted.
IOC Immediate or Cancel. The order is either a) completely filled, b) partially filled and the remaining quantity canceled, or c) the order is canceled.

Which TIF are supported. X for supported

Market Limit Stop Stop Limit
GTC X X X
GTD X X X
IOC X
FOK X

The trading channel supports the following additional actions:

Action Description
NewOrderSingle Creates an order
CancelOrderRequest Cancels an order
OrderMassCancelRequest Cancel multiple orders
OrderMassStatusRequest Snapshot of live orders

Cancel on disconnect

When subscribing to this channel, users can enable cancel on disconnect. This ensures that when the connection is disconnected, all live orders of the user will be cancelled.

To subscribe:

{
  "action": "subscribe",
  "channel": "trading",
  "cancelOnDisconnect": true
}

Server response:

{
  "seqnum": 1,
  "event": "subscribed",
  "channel": "trading",
  "cancelOnDisconnect": true
}

Once enabled, cancel on disconnect cannot be turned off for this connection. Even unsubscribing from trading channel will trigger a cancellation of all live orders.

The next message will be a snapshot of live orders for the logged on user"

{
  "seqnum": 3,
  "event": "snapshot",
  "channel": "trading",
  "orders": [
    {
      "orderID": "12891851020",
      "clOrdID": "78502a08-c8f1-4eff-b",
      "symbol": "BTC-USD",
      "side": "sell",
      "ordType": "limit",
      "orderQty": 5.0e-4,
      "leavesQty": 5.0e-4,
      "cumQty": 0.0,
      "avgPx": 0.0,
      "ordStatus": "open",
      "timeInForce": "GTC",
      "text": "New order",
      "execType": "0",
      "execID": "11321871",
      "transactTime": "2019-08-13T11:30:03.000593290Z",
      "msgType": 8,
      "lastPx": 0.0,
      "lastShares": 0.0,
      "tradeId": "0",
      "price": 15000.0
    }
  ]
}

Create a new order (NewOrderSingle)

Example creating a GTC limit order:

{
  "action": "NewOrderSingle",
  "channel": "trading",
  "clOrdID": "Client ID 3",
  "symbol": "BTC-USD",
  "ordType": "limit",
  "timeInForce": "GTC",
  "side": "sell",
  "orderQty": 10.0,
  "price": 3400.0,
  "execInst": "ALO"
}

This action creates an order using the provided fields as described above.

Each time an order changes state or has a match, an event will be sent from the server:

{
  "seqnum": 3,
  "event": "updated",
  "channel": "trading",
  "msgType": "8",
  "clOrdID": "Client ID 3",
  "orderID": "999999878",
  "ordStatus": "open",
  "execType": "0",
  "symbol": "BTC-USD",
  "side": "sell",
  "orderQty": 10.0,
  "ordType": "limit",
  "price": 3400.0,
  "transactTime": "2019-08-13T13:09:34.000659345Z",
  "leavesQty": 10.0,
  "cumQty": 0.0,
  "avgPx": 0.0
}

The next message will be a snapshot of live orders for the logged on user:

{
  "seqnum": 3,
  "event": "snapshot",
  "channel": "trading",
  "orders": [
    {
      "orderID": "12891851020",
      "clOrdID": "78502a08-c8f1-4eff-b",
      "symbol": "BTC-USD",
      "side": "sell",
      "ordType": "limit",
      "orderQty": 5.0e-4,
      "leavesQty": 5.0e-4,
      "cumQty": 0.0,
      "avgPx": 0.0,
      "ordStatus": "open",
      "timeInForce": "GTC",
      "text": "New order",
      "execType": "0",
      "execID": "11321871",
      "transactTime": "2019-08-13T11:30:03.000593290Z",
      "msgType": 8,
      "lastPx": 0.0,
      "lastShares": 0.0,
      "tradeId": "0",
      "price": 15000.0
    }
  ]
}

Examples

Example of a reply if your market order get filled:

{
  "seqnum": 5,
  "event": "updated",
  "channel": "trading",
  "orderID": "12891915594",
  "clOrdID": "b50112a2-9851-43ce-a",
  "symbol": "BTC-USD",
  "side": "sell",
  "ordType": "market",
  "orderQty": 0.001,
  "leavesQty": 0.0,
  "cumQty": 0.001,
  "avgPx": 11142.7,
  "ordStatus": "filled",
  "timeInForce": "GTC",
  "text": "Fill",
  "execType": "F",
  "execID": "11451022",
  "transactTime": "2019-08-13T13:50:02.000027480Z",
  "msgType": 8,
  "lastPx": 11142.7,
  "lastShares": 0.001,
  "tradeId": "12884910084"
}

Example of a response where your limit order is accepted and resting in the orderbook without fills:

{
  "seqnum": 3,
  "event": "updated",
  "channel": "trading",
  "orderID": "12895385711",
  "clOrdID": "ac3f50b0-ec1c-456f-9",
  "symbol": "BTC-USD",
  "side": "buy",
  "ordType": "limit",
  "orderQty": 0.001,
  "leavesQty": 0.001,
  "cumQty": 0.0,
  "avgPx": 0.0,
  "ordStatus": "open",
  "timeInForce": "GTC",
  "text": "New order",
  "execType": "0",
  "execID": "18389438",
  "transactTime": "2019-08-16T11:07:55.000648119Z",
  "msgType": 8,
  "lastPx": 0.0,
  "lastShares": 0.0,
  "tradeId": "0",
  "price": 10065.0
}

If your limit order get rejected you will get:

{
  "seqnum": 5,
  "event": "rejected",
  "channel": "trading",
  "text": "Invalid price",
  "clOrdID": "Client ID 3",
  "ordStatus": "rejected",
  "action": "NewOrderSingle"
}

or:

{
  "seqnum": 5,
  "event": "updated",
  "channel": "trading",
  "orderID": "-1",
  "clOrdID": "71bf645a-6619-499f-9",
  "symbol": "BTC-USD",
  "side": "sell",
  "ordType": "limit",
  "orderQty": 100.0,
  "leavesQty": 0.0,
  "cumQty": 100.0,
  "avgPx": 0.0,
  "ordStatus": "rejected",
  "timeInForce": "GTC",
  "text": "Insufficient Balance",
  "execType": "8",
  "execID": "0",
  "transactTime": "1970-01-01T00:00:00Z",
  "msgType": 8,
  "lastPx": 0.0,
  "lastShares": 0.0,
  "tradeId": "0",
  "price": 16000.3
}

or:

{
  "seqnum": 5,
  "event": "updated",
  "channel": "trading",
  "orderID": "0",
  "clOrdID": "12345678901234567890",
  "symbol": "BTC-USD",
  "side": "sell",
  "ordType": "limit",
  "orderQty": 0.001,
  "leavesQty": 0.001,
  "cumQty": 0.0,
  "avgPx": 0.0,
  "ordStatus": "rejected",
  "timeInForce": "GTC",
  "text": "Marketable AOL order",
  "execType": "8",
  "execID": "18331458",
  "transactTime": "2019-08-16T10:39:19.000525614Z",
  "msgType": 8,
  "lastPx": 0.0,
  "lastShares": 0.0,
  "tradeId": "0",
  "price": 100.3
}

If your market order get rejected you will get:

{
  "seqnum": 3,
  "event": "updated",
  "channel": "trading",
  "orderID": "-1",
  "clOrdID": "Client ID 3",
  "symbol": "BTC-USD",
  "side": "sell",
  "ordType": "market",
  "orderQty": 100.0,
  "leavesQty": 0.0,
  "cumQty": 100.0,
  "avgPx": 0.0,
  "ordStatus": "rejected",
  "timeInForce": "IOC",
  "text": "Insufficient Balance",
  "execType": "8",
  "execID": "0",
  "transactTime": "1970-01-01T00:00:00Z",
  "msgType": 8,
  "lastPx": 0.0,
  "lastShares": 0.0,
  "tradeId": "0",
  "minQty": 0.0
}

or:

{
  "seqnum": 1,
  "event": "updated",
  "channel": "trading",
  "orderID": "4561237891",
  "clOrdID": "Client ID 3",
  "symbol": "BTC-USD",
  "side": "buy",
  "ordType": "market",
  "orderQty": 3.0,
  "leavesQty": 3.0,
  "cumQty": 0.0,
  "avgPx": 0.0,
  "ordStatus": "cancelled",
  "timeInForce": "GTC",
  "text": "Met cash limit",
  "execType": "4",
  "execID": "1111111111",
  "transactTime": "2019-01-01T08:08:08.000888888Z",
  "msgType": 8,
  "lastPx": 0.0,
  "lastShares": 0.0,
  "tradeId": "0",
  "fee": 0.0
}

Cancel an order (CancelOrderRequest)

To cancel order:

{
  "action": "CancelOrderRequest",
  "channel": "trading",
  "orderID": "999999878"
}

Server response:

{
  "seqnum": 18,
  "event": "updated",
  "channel": "trading",
  "orderID": "999999878",
  "clOrdID": "Client ID 3",
  "symbol": "BTC-USD",
  "side": "sell",
  "ordType": "limit",
  "orderQty": 10.0,
  "leavesQty": 10.0,
  "cumQty": 0.0,
  "avgPx": 0.0,
  "ordStatus": "cancelled",
  "timeInForce": "GTC",
  "text": "Canceled by User",
  "execType": "4",
  "execID": "11397697",
  "transactTime": "2019-08-13T13:15:35.000955868Z",
  "msgType": 8,
  "lastPx": 0.0,
  "lastShares": 0.0,
  "tradeId": "0",
  "price": 3400.0
}

If the client gives an invalid orderId it will return a rejected cancellation:

{
  "seqnum": 18,
  "event": "rejected",
  "channel": "trading",
  "text": "Internal server error"
}

Mass order cancel request (OrderMassCancelRequest)

To cancel order:

{
  "action": "OrderMassCancelRequest",
  "channel": "trading"
}

Server response:

{
  "action": "OrderMassCancelRequest",
  "channel": "trading",
  "symbol": "BTC-USD"
}

Users have the ability to cancel all of their live orders at once by using this action. A symbol can be optionally specified to reduce the scope of this action. After requesting a mass cancel, execution reports for the affected orders will follow.

Mass order status request (OrderMassStatusRequest)

To cancel order:

{
  "action": "OrderMassStatusRequest",
  "channel": "trading"
}

Live orders can be listed at any point in time with this request. The subsequent response will contain a snapshot similar to the one received when subscribing to this channel.

Balances

To receive balances for a user, subscribe to the authenticated balances channel:

{
  "action": "subscribe",
  "channel": "balances"
}

Server response:

{
  "seqnum": 1,
  "event": "subscribed",
  "channel": "balances"
}

Snapshot of user balances (Zero balances are not sent in the initial snapshot):

{
  "seqnum": 2,
  "event": "snapshot",
  "channel": "balances",
  "balances": [
    {
      "currency": "BTC",
      "balance": 0.00366963,
      "available": 0.00266963,
      "balance_local": 38.746779155,
      "available_local": 28.188009155,
      "rate": 10558.77
    },
    {
      "currency": "USD",
      "balance": 11.66,
      "available": 0.0,
      "balance_local": 11.66,
      "available_local": 0.0,
      "rate": 1.0
    },
    {
      "currency": "ETH",
      "balance": 0.18115942,
      "available": 0.18115942,
      "balance_local": 37.289855013,
      "available_local": 37.289855013,
      "rate": 205.84
    }
  ],
  "total_available_local": 65.477864168,
  "total_balance_local": 87.696634168
}

Each time the balance changes, a new snapshot event will be sent from the server; this channel has only ‘snapshot’ event, not ‘updates’

{
  "seqnum": 19,
  "event": "snapshot",
  "channel": "balances",
  "balances": [
    {
      "currency": "BTC",
      "balance": 0.00266963,
      "available": 0.00166963,
      "balance_local": 28.188009155,
      "available_local": 17.629239155,
      "rate": 10558.77
    },
    {
      "currency": "USD",
      "balance": 22.18,
      "available": 10.52,
      "balance_local": 22.18,
      "available_local": 10.52,
      "rate": 1.0
    },
    {
      "currency": "ETH",
      "balance": 0.18115942,
      "available": 0.18115942,
      "balance_local": 37.289855013,
      "available_local": 37.289855013,
      "rate": 205.84
    }
  ],
  "total_available_local": 65.439094168,
  "total_balance_local": 87.657864168
}

REST Endpoints

Query single order status

Example request:

GET https://api.blockchain.com/exchange/order/21745988181

Response:

{
  "orderId": 21745988181,
  "gwOrderId": 2789221636,
  "clOrdId": "d7402f75314a4cf1webd",
  "symbol": "ETH-BTC",
  "ordType": "limit",
  "timeInForce": "GTC",
  "side": "buy",
  "orderQty": 1.0,
  "minQty": 0.0,
  "cumQty": 0.0,
  "price": 0.015797,
  "stopPx": 0.0,
  "ordStatus": "cancelled",
  "expireDate": 20200414,
  "execID": "537374697",
  "avgPx": 0.0
}

In order to look up the status of a single order, users can utilize the following endpoint.

Item Description
URL https://api.blockchain.com/exchange/order/{orderId}
HTTP Method GET
Required headers Cookie: auth_token={apiKey}

Users can authenticate using API keys, by providing a cookie named auth_token with the value set to their API key.

View whitelisted addresses

Example request:

GET https://api.blockchain.com/exchange/beneficiaries

Response:

{
  "capabilities": [
    {
      "currency": "BTC",
      "address": true,
      "xpub": false,
      "existingBeneficiaryOnly": false,
      "fiat": false
    },
    {
      "currency": "ETH",
      "address": true,
      "xpub": false,
      "existingBeneficiaryOnly": false,
      "fiat": false
    }
  ],
  "enabled": true,
  "enabledAt": "2020-05-08T11:41:32.664Z",
  "whitelisted": [
    {
      "id": "298907ac-07df-47ab-93d5-5594e019813b",
      "address": "******************************2v7b",
      "agent": {
        "account": "",
        "address": null,
        "code": null,
        "country": null,
        "name": null,
        "recipient": null,
        "routingNumber": null
      },
      "currency": "BTC",
      "state": "ACTIVE",
      "name": "My Ledger Device",
      "whitelisted": true,
      "fiat": false
    }
  ]
}

In order to see the list of whitelisted beneficiaries, users can utilize the following endpoint.

Item Description
URL https://api.blockchain.com/exchange/beneficiaries
HTTP Method GET
Required headers Cookie: auth_token={apiKey}

Users can authenticate using API keys, by providing a cookie named auth_token with the value set to their API key.

Create A Withdrawal

Example request:

POST https://api.blockchain.com/exchange/withdrawals
{
    "currency": "BTC",
    "amount": "0.0001",
    "beneficiary": "3ff5bc82-b118-45b3-b468-9697be208bdf"
}

Response:

{
    "id": "1941fcdd-d16a-4b5a-998e-f58f5862af88",
    "user": "e9307d88-bd92-4fdf-840c-7e30fbb0bbd7",
    "product": "MERCURY",
    "amount": {
        "symbol": "BTC",
        "value": "0.0001"
    },
    "fee": {
        "symbol": "BTC",
        "value": "0.0005"
    },
    "state": "NONE"
}

In order to create a withdrawal via api, users can utilize the following endpoint.

Item Description
URL https://api.blockchain.com/exchange/withdrawals
HTTP Method POST
Required headers Cookie: auth_token={apiKey}

Users can authenticate using API keys, by providing a cookie named auth_token with the value set to their API key.

Request Parameters

Parameter Description
currency The ticker symbol for the withdrawal currency e.g. "BTC
amount The amount of the withdrawal as a decimal e.g. 1.231
beneficiary The id of your beneficiary for this currency, which can be retrieved by using the /beneficiaries endpoint