General

Hello OUT

Example hello message for trades subscription to all symbols from COINBASE and ITBIT exchange and additional for 2 selected symbols from BITSTAMP and BITFINEX exchange:

{
  "type": "hello",
  "apikey": "73034021-THIS-IS-SAMPLE-KEY",
  "heartbeat": false,
  "subscribe_data_type": ["trade"],
  "subscribe_filter_symbol_id": [
    "BITSTAMP_SPOT_BTC_USD$",
    "BITFINEX_SPOT_BTC_LTC$",
    "COINBASE_",
    "ITBIT_"
    ]
}

Another example of a hello message for subscription to quotes related to the BTC or ETH assets:

{
  "type": "hello",
  "apikey": "73034021-THIS-IS-SAMPLE-KEY",
  "heartbeat": false,
  "subscribe_data_type": ["quote"],
  "subscribe_filter_asset_id": ["BTC", "ETH"]
}

Another example of a hello message for subscription to quotes related to the BTC/USD asset pair:

{
  "type": "hello",
  "apikey": "73034021-THIS-IS-SAMPLE-KEY",
  "heartbeat": false,
  "subscribe_data_type": ["quote"],
  "subscribe_filter_asset_id": ["BTC/USD"]
}

Another example of a hello message for subscription of all data types from all exchanges and symbols:

{
  "type": "hello",
  "apikey": "73034021-THIS-IS-SAMPLE-KEY",
  "heartbeat": false,
  "subscribe_data_type": ["trade", "quote", "book20"]
}

After your WebSocket connection is established, you must send us a Hello message which contains:

  • Stream preferences (Heartbeat and subscription details)
  • API key for authorization

If your message will be incorrect, we will send you error message and disconnect connection afterwards.

Hello message can be repeated, each one will cause subscription scope override without interruption of your WebSocket connection.

Hello message parameters

ParameterTypeDescription
typestringMessage type, must be equal to hello
apikeystringYour API key
heartbeatbooltrue to receive Heartbeat message every second, otherwise false
subscribe_data_typestring[]List of data types you want to receive (required, possible values listed in table below)
subscribe_filter_symbol_idstring[]Filter data to symbols whose identifiers match at least one of the listed prefixes. If symbol is ended with $ character then exact match is used instead of prefix match. (optional, if not provided then stream will not filtered by symbols)
subscribe_filter_asset_idstring[]Filter data to messages which are related to the at least one of the listed asset identifiers or to specific asset pair (e.g. BTC/USD) (optional, if not provided then stream will not be filtered by assets)
subscribe_filter_period_idstring[]Filter data to specific OHLCV periods (optional, if not provided then OHLCV stream will not be filtered by periods)
subscribe_filter_exchange_idstring[]Filter data to symbols from the listed exchange identifiers (optional, if not provided then stream will not be filtered by exchanges)
subscribe_update_limit_ms_quoteintMinimum delay in milliseconds between quote updates for the same symbol (optional)
subscribe_update_limit_ms_book_snapshotintMinumum delay in milliseconds between book snapshot (book5, book20, book50) updates for the same symbol (optional)
subscribe_update_limit_ms_exrateintMinumum delay in milliseconds between exchange rate updates for the same asset pair (optional)

Data types

Listed below are all allowed values for subscribe_data_type variables from hello message.

Data typeDescription
tradeExecuted transactions feed (order book matches)
quoteQuote updates feed (order book level 1)
bookOrder book snapshots and updates feed (order book level 2, full order book snapshot and real-time updates)
book5Order book snapshots feed (order book level 2, 5 best levels from each side of book)
book20Order book snapshots feed (order book level 2, 20 best levels from each side of book)
book50Order book snapshots feed (order book level 2, 50 best levels from each side of book)
ohlcvOHLCV updates per symbol on periods between 1SEC and 1MIN
exrateExchange rate updates (VWAP-24H)
assetAssets feed.
exchangeExchanges feed.
symbolSymbols feed.

Error handling

Example JSON error message is structured like this:

{
  "type": "error",
  "message": "Invalid API key"
}

You need to be prepared to receive an error message from us when you send something wrong; all errors are permanent and you should expect that the underlying WebSocket connection will be closed by us after sending an error message.

Limits

API access is subject to limits and n this section we will describe each limit.

Request limit / IP

X-WsRequestsPerIpLimit-Limit: 10
X-WsRequestsPerIpLimit-WindowSizeMs: 10000
X-WsRequestsPerIpLimit-Remaining: 0
X-WsRequestsPerIpLimit-RetryAfterMs: 564

We define WebSocket request as the event when the WebSocket upgrade on the HTTP is happening. The request limit restricts the number of maximum allowed newly initiated WebSocket connections per IP address in a time interval (sliding/rolling window ending at a specific moment) for your subscription. Limit prevents your client application from abusing the API by reconnecting in the loop without exponential backoff.

HTTP HeaderTypeDescription
X-WsRequestsPerIpLimit-LimitintValue of the limit quota allocated.
X-WsRequestsPerIpLimit-RemainingintValue of the limit quota left at the moment, counted from last WindowSizeMs milliseconds.
X-WsRequestsPerIpLimit-WindowSizeMsintWindow size on which the remaining value was calculated in milliseconds.
X-WsRequestsPerIpLimit-RetryAfterMsintThe number of milliseconds after which Remaining > 0. (exist only in case of the error)

Hello limit / IP

X-WsHelloPerIpLimit-Limit: 10
X-WsHelloPerIpLimit-WindowSizeMs: 10000
X-WsHelloPerIpLimit-Remaining: 0
X-WsHelloPerIpLimit-RetryAfterMs: 564

The hello limit restricts the number of maximum allowed hello messages per IP address in the time interval (sliding/rolling window ending at a specific moment) for your subscription. Limit prevents your client application from abusing the API by changing the scope of the subscription.

HTTP HeaderTypeDescription
X-WsHelloPerIpLimit-LimitintValue of the limit quota allocated.
X-WsHelloPerIpLimit-RemainingintValue of the limit quota left at the moment, counted from last WindowSizeMs milliseconds.
X-WsHelloPerIpLimit-WindowSizeMsintWindow size on which the remaining value was calculated in milliseconds.
X-WsHelloPerIpLimit-RetryAfterMsintThe number of milliseconds after which Remaining > 0. (exist only in case of the error)

Concurrency limit / APIKey

X-ConcurrencyLimit-Limit: 10
X-ConcurrencyLimit-Remaining: 5

The concurrency limit defines the number of maximum allowed concurrent websocket connections per APIKey at the current moment. Every new WebSocket connection increases the Concurrency limit against quota, and when it's closed, decreases it.

HTTP HeaderTypeDescription
X-ConcurrencyLimit-LimitintConcurrency limit allocated for your API key.
X-ConcurrencyLimit-RemainingintThe number of concurrent WebSocket connections available to be established in this moment for your API key.

Data buffering

Data buffering JSON error message is structured like this:

{
  "type": "error",
  "message": "Reached maximum allowed buffered messages for this connection."
}

The stream will send the data to the client as fast as possible; this can result in a high volume of data in cases where the subscription scope is broad. If our server cannot write data to the stream because of the TCP backpressure most likely caused by your client is not reading the data fast enough, or there is not enough network bandwidth available, we will buffer the messages to allow your client to catch up. However, when the buffer is full, a disconnect will be initiated from the server-side, and the buffered messages are dropped, and they will not be resent to the client.

One way to identify when your client is falling behind is to compare the CoinAPI time of the messages being received with your current time on the client and track this metric over time. Make sure your clock is synchronized correctly and do not have a drift.

The possible causes of the buffering are limited and are related to:

  • Bandwidth bottleneck, eg.
  • Internet connection instability
  • Not enough bandwidth to receive a full stream.
  • Network card or link saturation.
  • I am not receiving messages fast enough, eg.
  • Lack of the thread separation between the (a) receiving thread or (b) parsing or (c) processing operations.
  • No CPU affinity on the receiving thread.
  • CPU bottleneck on the receiving thread.
  • Infrequent collection of the data from the TCP stack.
  • Heap allocation per message and Garbage Collector pressure.

If your client is unable to receive messages fast enough because of the issues listed above, then these things will happen:

  1. Your client TCP stack will be full, and TCP window will be closed to inform us that you can't receive more data and we should not send to you
  2. Our TCP stack queue will be full because we couldn't send you more data
  3. We will internally create a limited queue of the messages to deliver when the channel is available again (this could cause the delay on the real-time data before the gaps will appear)
  4. If the queue is full, then we will disconnect you.

To minimize the occurrence of disconnects:

  • Make sure that your client is reading the stream fast enough. Typically you should not do any real processing work as you read the stream. Read the stream and hand the activity to another thread/process/data store to do your processing asynchronously.
  • Make sure that your data center has inbound bandwidth sufficient to accomodate large sustained data volumes as well as significantly larger spikes (e.g. 10x normal volume).

The current default queue size per connection is 131 072 messages.

For more information please google: TCP Flow Control.


Copyright 2022 COINAPI LTD or its affiliates. All rights reserved.
StatusPage: