NAV Navbar
Logo
cURL C# Go Node.js PHP Python Ruby Java

Introduction

Welcome to the CoinAPI developer documentation. This document should contain all the information required to properly implement applications using our API.

There are 3 main interfaces that can be used to access CoinAPI:

API Communication Description
RESTful Request-response Stateless API providing the widest range of data, not capable of streaming, only pooling.
WebSocket Publish-subscribe Stateful API providing streaming of realtime market data.
FIX Publish-subscribe Stateful API providing streaming of realtime market data, widely adopted by the finance industry.

SDK

Our Software Development Kit (SDK) is available on GitHub at https://github.com/coinapi/coinapi-sdk. If possible then we are strongly recommending using our tested libraries available on GitHub, rather than creating new ones. However, if you decide to create your own implementation or to change existing one, then we encourage you to create Pull Request to our main repository with proposed changes, then we will able to include your code in our official repository for use by other users, effectively creating collaboration.

In repository you can find libraries or examples for languages or enviroments like:

Security

Encryption in CoinAPI is not optional. All communication to us is always encrypted using protocols that are considered best security practices.

Standards and conventions

This section represents used standards and conventions across all documents and API’s.

Variables naming

All variables are named using the Snake case (or snake_case) naming convention. This means that words are separated by a single underscore _ character, no spaces are used, and letters are lowercase.

Asset codes

ISO 4217 currency code standard is used for fiat money identifications. Cryptocurrency assets are identified using codes used by the general public or adopted by the majority of exchanges.

Numbers precision

Numbers in our platform can have maximum 19 digits overall, but no more than 9 decimal places. In cases when number representing aggregate value then we allowing 38 digits overall, but still no more than 9 decimal places.

Time

For all input and output time values ISO 8601 standard is used.

Format specifier Description
yyyy The year as a four-digit number.
MM The month, from 01 through 12.
dd The day of the month, from 01 through 31.
HH The hour, using a 24-hour clock from 00 to 23.
mm The minute, from 00 through 59.
ss The second, from 00 through 59.
fff The milliseconds in a date and time value.
fffffff The ten millionths of a second in a date and time value.

Input time values are parsed using the following formats as far as possible:

Output time values are formatted using the following patterns:

  1. yyyy-MM-ddTHH:mm:ss.fffffffZ
  2. yyyy-MM-dd

REST API

General

RESTful endpoint provides the widest range of data, based on HTTP protocol which works in Request-Reply scheme.

Endpoints

Production endpoint, requires API key for authentication and providing real data:
https://rest.coinapi.io/

We do not provide a mockup endpoint.

Authorization

To use resources that require authorized access, you will need to provide an API key to us when making HTTP requests.

There are 2 methods for passing the API key to us, you only need to use one:

  1. Custom authorization header named X-CoinAPI-Key
  2. Query string parameter named apikey

Custom authorization header

You can authorize by providing additional custom header named X-CoinAPI-Key and API key as its value.

Assuming that your API key is 73034021-0EBC-493D-8A00-E0F138111F41, then the authorization header you should send to us will look like:

X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41

Query string authorization parameter

You can authorize by providing an additional parameter named apikey with a value equal to your API key in the query string of your HTTP request.

Assuming that your API key is 73034021-0EBC-493D-8A00-E0F138111F41 and that you want to request all exchange rates from BTC asset, then your query string should look like this:

GET /v1/exchangerate/BTC?apikey=73034021-0EBC-493D-8A00-E0F138111F41

HTTP Requests

Each HTTP request must contain the header Accept: application/json as all our responses are in JSON format.

We encourage you to use the HTTP request header Accept-Encoding: deflate, gzip for all requests. This will indicate to us that we can deliver compressed data to you which on your side should be decompressed transparently.

HTTP Success

Successful HTTP responses have the status code 200 and the body in a format according to documentation of the requested resource.

HTTP Errors

Error message is returned in JSON structured like this:

{
    "message": "Invalid API key"
}

All HTTP requests with response status codes different to 200 must be considered as failed and you should expect additional JSON inside the body of the response with the error message encapsulated inside it as shown in the example. We use the following error codes:

Error Code Meaning
400 Bad Request – There is something wrong with your request
401 Unauthorized – Your API key is wrong
403 Forbidden – Your API key doesnt’t have enough privileges to access this resource
429 Too many requests – You have exceeded your API key rate limits
550 No data – You requested specific single item that we don’t have at this moment.

Request limits

X-RateLimit-Limit: 1000000
X-RateLimit-Remaining: 999989
X-RateLimit-Request-Cost: 1
X-RateLimit-Reset: 2018-01-22T00:00:00.0000000Z

Any authenticated endpoint will provide (in HTTP response headers) informations about the request limits associated with API Key.

HTTP Header Type Description
X-RateLimit-Limit int Request limit allocated in the time window.
X-RateLimit-Remaining int The number of requests left for the time window.
X-RateLimit-Request-Cost int The number of requests used to generate current HTTP response.
X-RateLimit-Reset timestring The remaining window before the rate limit resets

Output data format

By default we are using JSON output data format for all of our endpoints, you can control format of data by using output_format variable in query string parameters.

URL Parameters

Parameter Type Description
output_format string Output data format (optional, default value is json, possible values are json, xml or csv)
csv_include_header bool Ignore header line in CSV output? (optional, default value is true, true to include CSV header line, false otherwise)
csv_include_quotes bool Encapsulate strings with quotes in CSV output? (optional, default value is false, true to encapsulate all strings with ", false to leave them unquoted)
csv_exclude_col string Comma delimited list of column names to ignore in CSV output (optional, by default all columns are included)
csv_set_delimiter string Character that will be used as column delimiter in CSV output (optional, default value is ;)
csv_set_dec_mark string Character that will be used as decimal separator in CSV output (optional, default value is .)
csv_set_timeformat string Format for datetime type in CSV output or unix for unix timestamp (optional, default value is yyyy-MM-ddTHH:mm:ss.fffffffZ)
csv_set_newline string New line type (optional, default value is unix, possible values win, mac, unix)

Metadata

List all exchanges

curl https://rest.coinapi.io/v1/exchanges \
  --request GET 
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/exchanges");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/exchanges');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/exchanges'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/exchanges",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];

  response.on("data", function (chunk) {
    chunks.push(chunk);
  });

});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main() 
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/exchanges")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/exchanges")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/exchanges")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

[
  {
    "exchange_id": "BITSTAMP",
    "website": "https://www.bitstamp.net/",
    "name": "Bitstamp Ltd."
  },
  {
    "exchange_id": "BITFINEX",
    "website": "https://www.bitfinex.com/",
    "name": "Bitfinex"
  }
]

Get a detailed list of exchanges provided by the system.

HTTP Request

GET /v1/exchanges

Output variables

Variable Description
exchange_id Our exchange identifier
website Exchange website address
name Display name of the exchange

List all assets

curl https://rest.coinapi.io/v1/assets \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/assets");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/assets');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/assets'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/assets",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/assets")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/assets")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/assets")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

[
  {
    "asset_id": "BTC",
    "name": "Bitcoin",
    "type_is_crypto": 1
  },
  {
    "asset_id": "USD",
    "name": "US Dollar",
    "type_is_crypto": 0
  }
]

Get detailed list of assets.

HTTP Request

GET /v1/assets

Output variables

Variable Description
asset_id Our asset identifier. Superset of the ISO 4217 currency codes standard.
name Display name of the asset.
type_is_crypto Boolean value transported as integer; 1 for cryptocurrency assets, 0 otherwise.

List all symbols

curl https://rest.coinapi.io/v1/symbols \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/symbols");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/symbols');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/symbols'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/symbols",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/symbols")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/symbols")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/symbols")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

[
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "exchange_id": "BITSTAMP",
    "symbol_type": "SPOT",
    "asset_id_base": "BTC",
    "asset_id_quote": "USD"
  },
  {
    "symbol_id": "BITMEX_FTS_BTC_USD_170630",
    "exchange_id" : "BITMEX",
    "symbol_type": "FUTURES",
    "future_delivery_time": "2017-06-30T10:00:00.000000Z"
    "asset_id_base": "BTC",
    "asset_id_quote": "USD",
  },
  {
    "symbol_id": "DERIBIT_OPT_BTC_USD_170331_500_P",
    "exchange_id": "DERIBIT",
    "symbol_type": "OPTION",
    "option_type_is_call": false,
    "option_strike_price": 500.0,
    "option_contract_unit": 1,
    "option_exercise_style": "EUROPEAN",
    "option_expiration_time": "2017-03-31T10:00:00.000000Z",
    "asset_id_base": "BTC",
    "asset_id_quote": "USD"
  }
]

Get detailed list of all symbols.

HTTP Request

GET /v1/symbols?filter_symbol_id={filter_symbol_id}

URL Parameters

Parameter Type Description
filter_symbol_id string[] Comma or semicolon delimited parts of symbol identifier used to filter response. (optional, full list available here)

Common output variables

Variable Description
symbol_id Our symbol identifier, see table below for format description.
exchange_id Our identifier of the exchange where symbol is traded.
symbol_type Type of symbol (possible values are: SPOT, FUTURES or OPTION)
asset_id_base FX Spot base asset identifier, for derivatives it’s contact underlying (e.g. BTC for BTC/USD)
asset_id_quote FX Spot quote asset identifier, for derivatives it’s contract underlying (e.g. USD for BTC/USD)

Symbol identifier

Our symbol identifier is created using a pattern that depends on symbol type.

Type symbol_id pattern
SPOT {exchange_id}_SPOT_{asset_id_base}_{asset_id_quote}
FUTURES {exchange_id}_FTS_{asset_id_base}_{asset_id_quote}_{YYMMDD of future_delivery_time}
OPTION {exchange_id}_OPT_{asset_id_base}_{asset_id_quote}_{YYMMDD of option_expiration_time}_{option_strike_price}_{option_type_is_call as C/P}

Symbol types list (enumeration of symbol_type output variable)

Type Name Description
SPOT FX Spot Agreement to exchange one asset for another one (e.g. Buy BTC for USD)
FUTURES Futures contract FX Spot derivative contract where traders agree to trade fx spot at predetermined future time
OPTION Option contract FX Spot derivative contract where traders agree to trade right to require buy or sell of fx spot at agreed price on exercise date

Additional output variables for symbol_type = FUTURES

Variable Description
future_delivery_time Predetermined time of futures contract delivery date in ISO 8601

Additional output variables for symbol_type = OPTION

Variable Description
option_type_is_call Boolean value representing option type. true for Call options, false for Put options
option_strike_price Price at which option contract can be exercised
option_contract_unit Base asset amount of underlying spot which single option represents
option_exercise_style Option exercise style. Can be EUROPEAN or AMERICAN
option_expiration_time Option contract expiration time in ISO 8601

Exchange rates

Get specific rate

curl https://rest.coinapi.io/v1/exchangerate/BTC/USD \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/exchangerate/BTC/USD");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/exchangerate/BTC/USD');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/exchangerate/BTC/USD'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/exchangerate/BTC/USD",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/exchangerate/BTC/USD")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/exchangerate/BTC/USD")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/exchangerate/BTC/USD")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

{
  "time": "2017-08-09T14:31:18.3150000Z",
  "asset_id_base": "BTC",
  "asset_id_quote": "USD",
  "rate": 3260.3514321215056208129867667
}

Get exchange rate between pair of requested assets at specific or current time.

HTTP Request

GET /v1/exchangerate/{asset_id_base}/{asset_id_quote}?time={time}

URL Parameters

Parameter Type Description
asset_id_base string Requested exchange rate base asset identifier. Full list available here
asset_id_quote string Requested exchange rate quote asset identifier. Full list available here
time timestring Time at which exchange rate is calculated (optional, if not supplied then current rate is returned)

Output variables

Variable Description
time Time in ISO 8601 of the market data used to calculate exchange rate
asset_id_base Exchange rate base asset identifier
asset_id_quote Exchange rate quote asset identifier
rate Exchange rate between assets

Get all current rates

curl https://rest.coinapi.io/v1/exchangerate/BTC \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/exchangerate/BTC");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/exchangerate/BTC');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/exchangerate/BTC'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/exchangerate/BTC",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/exchangerate/BTC")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/exchangerate/BTC")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/exchangerate/BTC")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

{
  "asset_id_base": "BTC",
  "rates" : [
    {
      "time": "2017-08-09T14:31:37.0520000Z",
      "asset_id_quote": "USD",
      "rate": 3258.8875417798037784035133948
    },
    {
      "time": "2017-08-09T14:31:36.7570000Z",
      "asset_id_quote": "EUR",
      "rate": 2782.5255080599273092901331567
    },
    {
      "time": "2017-08-09T14:31:36.7570000Z",
      "asset_id_quote": "CNY",
      "rate": 21756.295595926054627342411501
    },
    {
      "time": "2017-08-09T14:31:36.7570000Z",
      "asset_id_quote": "GBP",
      "rate": 2509.6024203799580199765804823
    }
  ]
}

Get the current exchange rate between requested asset and all other assets.

HTTP Request

GET /v1/exchangerate/{asset_id_base}

URL Parameters

Parameter Type Description
asset_id_base string Requested exchange rates base asset identifier. Full list available here

Output variables

Variable Description
time Time in ISO 8601 of the market data used to calculate exchange rates
asset_id_base Base asset identifier for all rates
asset_id_quote Quote asset identifier of specific rate
rate Exchange rate between assets

OHLCV

API calls described in this section are related to downloading OHLCV (Open, High, Low, Close, Volume) timeseries data. Each data point of this timeseries represents several indicators calculated from transactions activity inside a time range (period).

List all periods

curl https://rest.coinapi.io/v1/ohlcv/periods \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/ohlcv/periods");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/ohlcv/periods');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/ohlcv/periods'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/ohlcv/periods",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/ohlcv/periods")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/ohlcv/periods")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/ohlcv/periods")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

Get full list of supported time periods available for requesting OHLCV timeseries data.

HTTP Request

GET /v1/ohlcv/periods

The above command returns JSON structured like this:

[
  {
    "period_id": "1SEC",
    "length_seconds": 1,
    "length_months": 0,
    "unit_count": 1,
    "unit_name": "second",
    "display_name": "1 Second"
  },
  {
    "period_id": "10DAY",
    "length_seconds": 864000,
    "length_months": 0,
    "unit_count": 10,
    "unit_name": "day",
    "display_name": "10 Days"
  },
  {
    "period_id": "2YRS",
    "length_seconds": 0,
    "length_months": 24
    "unit_count": 2,
    "unit_name": "year",
    "display_name": "2 Years"
  }
]

Available periods

Time unit Period identifiers
Second 1SEC, 2SEC, 3SEC, 4SEC, 5SEC, 6SEC, 10SEC, 15SEC, 20SEC, 30SEC
Minute 1MIN, 2MIN, 3MIN, 4MIN, 5MIN, 6MIN, 10MIN, 15MIN, 20MIN, 30MIN
Hour 1HRS, 2HRS, 3HRS, 4HRS, 6HRS, 8HRS, 12HRS
Day 1DAY, 2DAY, 3DAY, 5DAY, 7DAY, 10DAY
Month 1MTH, 2MTH, 3MTH, 4MTH, 6MTH
Year 1YRS, 2YRS, 3YRS, 4YRS, 5YRS

Output variables

Variable Description
period_id Period identifier, used in other API calls
length_seconds Seconds part of period length
length_months Months part of period length
unit_count Period length in units
unit_name Type of unit (second/minute/hour/day/month/year)
display_name Display name of period length

Latest data

curl https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/latest?period_id=1MIN \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/latest?period_id=1MIN");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/latest?period_id=1MIN');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/latest?period_id=1MIN'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/latest?period_id=1MIN",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/latest?period_id=1MIN")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/latest?period_id=1MIN")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/latest?period_id=1MIN")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

[
  {
    "time_period_start": "2017-08-09T14:31:00.0000000Z",
    "time_period_end": "2017-08-09T14:32:00.0000000Z",
    "time_open": "2017-08-09T14:31:01.0000000Z",
    "time_close": "2017-08-09T14:31:46.0000000Z",
    "price_open": 3255.590000000,
    "price_high": 3255.590000000,
    "price_low": 3244.740000000,
    "price_close": 3244.740000000,
    "volume_traded": 16.903274550,
    "trades_count": 31
  },
  {
    "time_period_start": "2017-08-09T14:30:00.0000000Z",
    "time_period_end": "2017-08-09T14:31:00.0000000Z",
    "time_open": "2017-08-09T14:30:05.0000000Z",
    "time_close": "2017-08-09T14:30:35.0000000Z",
    "price_open": 3256.000000000,
    "price_high": 3256.010000000,
    "price_low": 3247.000000000,
    "price_close": 3255.600000000,
    "volume_traded": 58.131397920,
    "trades_count": 33
  }
]

Get OHLCV latest timeseries data for requested symbol and period, returned in time descending order.

HTTP Request

GET /v1/ohlcv/{symbol_id}/latest?period_id={period_id}&limit={limit}

URL Parameters

Parameter Type Description
symbol_id string Symbol identifier of requested timeseries (full list available here)
period_id string Identifier of requested timeseries period (required, e.g. 5SEC or 2MTH, full list here)
include_empty_items bool Include items with no activity? (optional, default value is false, possible values are true or false)
limit int Amount of items to return (optional, mininum is 1, maximum is 100000, default value is 100, if the parameter is used then every 100 output items are counted as one request)

Output variables

Variable Description
time_period_start Period starting time (range left inclusive)
time_period_end Period ending time (range right exclusive)
time_open Time of first trade inside period range
time_close Time of last trade inside period range
price_open First trade price inside period range
price_high Highest traded price inside period range
price_low Lowest traded price inside period range
price_close Last trade price inside period range
volume_traded Cumulative base amount traded inside period range
trades_count Amount of trades executed inside period range

Historical data

curl https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/history?period_id=1MIN&time_start=2016-01-01T00:00:00 \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/history?period_id=1MIN&time_start=2016-01-01T00:00:00");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/history?period_id=1MIN&time_start=2016-01-01T00:00:00');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/history?period_id=1MIN&time_start=2016-01-01T00:00:00'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/history?period_id=1MIN&time_start=2016-01-01T00:00:00",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/history?period_id=1MIN&time_start=2016-01-01T00:00:00")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/history?period_id=1MIN&time_start=2016-01-01T00:00:00")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/ohlcv/BITSTAMP_SPOT_BTC_USD/history?period_id=1MIN&time_start=2016-01-01T00:00:00")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

[
  {
    "time_period_start": "2017-01-01T00:00:00.0000000Z",
    "time_period_end": "2017-01-02T00:00:00.0000000Z",
    "time_open": "2017-01-01T00:01:08.0000000Z",
    "time_close": "2017-01-01T23:59:46.0000000Z",
    "price_open": 966.340000000,
    "price_high": 1005.000000000,
    "price_low": 960.530000000,
    "price_close": 997.750000000,
    "volume_traded": 6850.593308590,
    "trades_count": 7815
  },
  {
    "time_period_start": "2017-01-02T00:00:00.0000000Z",
    "time_period_end": "2017-01-03T00:00:00.0000000Z",
    "time_open": "2017-01-02T00:00:05.0000000Z",
    "time_close": "2017-01-02T23:59:37.0000000Z",
    "price_open": 997.750000000,
    "price_high": 1032.000000000,
    "price_low": 990.010000000,
    "price_close": 1012.540000000,
    "volume_traded": 8167.381030180,
    "trades_count": 7871
  }
]

Get OHLCV timeseries data for requested symbol and period, returned in time ascending order.

HTTP Request

GET /v1/ohlcv/{symbol_id}/history?period_id={period_id}&time_start={time_start}&time_end={time_end}&limit={limit}

URL Parameters

Parameter Type Description
symbol_id string Symbol identifier of requested timeseries (full list available here)
period_id string Identifier of requested timeseries period (required, e.g. 5SEC or 2MTH, full list here)
time_start timestring Timeseries starting time in ISO 8601 (required)
time_end timestring Timeseries ending time in ISO 8601 (optional, if not supplied then the data is returned to the end or when count of result elements reaches the limit)
include_empty_items bool Include items with no activity? (optional, default value is false, possible values are true or false)
limit int Amount of items to return (optional, mininum is 1, maximum is 100000, default value is 100, if the parameter is used then every 100 output items are counted as one request)

Output variables

Variable Description
time_period_start Period starting time (range left inclusive)
time_period_end Period ending time (range right exclusive)
time_open Time of first trade inside period range
time_close Time of last trade inside period range
price_open First trade price inside period range
price_high Highest traded price inside period range
price_low Lowest traded price inside period range
price_close Last trade price inside period range
volume_traded Cumulative base amount traded inside period range
trades_count Amount of trades executed inside period range

Trades

This section describes calls related to executed transactions data, also known as matched orders data or active data.

JSON structure

Trades related commands return JSON structured like this:

[
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "time_exchange": "2013-09-28T22:40:50.0000000Z",
    "time_coinapi": "2017-03-18T22:42:21.3763342Z",
    "uuid": "770C7A3B-7258-4441-8182-83740F3E2457",
    "price": 770.000000000,
    "size": 0.050000000,
    "taker_side": "BUY"
  },
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "time_exchange": "2013-09-28T23:12:59.0000000Z",
    "time_coinapi": "2017-03-18T22:42:21.3763342Z",
    "uuid": "1EA8ADC5-6459-47CA-ADBF-0C3F8C729BB2",
    "price": 770.000000000,
    "size": 0.050000000,
    "taker_side": "SELL"
  }
]

Output variables

Variable Description
symbol_id Our symbol identifier, format is documented here
time_exchange Time of trade reported by exchange
time_coinapi Time when coinapi first received trade from exchange
uuid Our trade unique identifier in form of UUIDv4
price Price of the transaction
size Base asset amount traded in the transaction
taker_side Aggressor side of the transaction (BUY/SELL/BUY_ESTIMATED/SELL_ESTIMATED/UNKNOWN)

Possible taker_side values

If exchange has not reported who was aggressor side of transaction, we will classify who most probably was based on current market view.

taker_side Description
BUY Exchange has reported that transaction aggressor was buying
SELL Exchange has reported that transaction aggressor was selling
BUY_ESTIMATED Exchange has not reported transaction aggressor, we estimated that more likely it was buying
SELL_ESTIMATED Exchange has not reported transaction aggressor, we estimated that more likely it was selling
UNKNOWN Exchange has not reported transaction aggressor and we have not estimated who it was

Current data

To get current last trade for all symbols, use Quotes current data as it includes last trade information.

Latest data

curl https://rest.coinapi.io/v1/trades/latest \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/trades/latest");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/trades/latest');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/trades/latest'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/trades/latest",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/trades/latest")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/trades/latest")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/trades/latest")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

Get latest trades from all symbols up to 1 minute ago or get latest trades from a specific symbol without time limitation. Latest data is always returned in time descending order.

HTTP Request

  1. GET /v1/trades/latest?limit={limit}&filter_symbol_id={filter_symbol_id}
  2. GET /v1/trades/{symbol_id}/latest?limit={limit}

URL Parameters

Parameter Type Description
symbol_id string Symbol identifier for requested timeseries (full list available here)
limit int Amount of items to return (optional, mininum is 1, maximum is 100000, default value is 100, if the parameter is used then every 100 output items are counted as one request)
filter_symbol_id string[] Comma or semicolon delimited parts of symbol identifier used to filter response. (optional, full list available here)

Historical data

curl https://rest.coinapi.io/v1/trades/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00 \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/trades/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/trades/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/trades/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/trades/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/trades/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/trades/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/trades/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

Get history transactions from specific symbol, returned in time ascending order.

HTTP Request

GET /v1/trades/{symbol_id}/history?time_start={time_start}&time_end={time_end}&limit={limit}

URL Parameters

Parameter Type Description
symbol_id string Symbol identifier for requested timeseries (full list available here)
time_start timestring Starting time in ISO 8601 (required)
time_end timestring Timeseries ending time in ISO 8601 (optional, if not supplied then the data is returned to the end or when result elements count reaches the limit)
limit int Amount of items to return (optional, mininum is 1, maximum is 100000, default value is 100, if the parameter is used then every 100 output items are counted as one request)

Quotes

This section describes calls related to quotes data, also known as quotes or passive level 1 data.

Current data

curl https://rest.coinapi.io/v1/quotes/current \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/quotes/current");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/quotes/current');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/quotes/current'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/quotes/current",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/quotes/current")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/quotes/current")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/quotes/current")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

[
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "time_exchange": "2013-09-28T22:40:50.0000000Z",
    "time_coinapi": "2017-03-18T22:42:21.3763342Z",
    "ask_price": 770.000000000,
    "ask_size": 3252,
    "bid_price": 760,
    "bid_size": 124,
    "last_trade": {
        "time_exchange": "2017-03-18T22:42:21.3763342Z",
        "time_coinapi": "2017-03-18T22:42:21.3763342Z",
        "uuid": "1EA8ADC5-6459-47CA-ADBF-0C3F8C729BB2",
        "price": 770.000000000,
        "size": 0.050000000,
        "taker_side": "SELL"
    }
  },
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "time_exchange": "2013-09-28T22:40:50.0000000Z",
    "time_coinapi": "2017-03-18T22:42:21.3763342Z",
    "ask_price": 770.000000000,
    "ask_size": 3252,
    "bid_price": 760,
    "bid_size": 124,
    "last_trade": {
        "time_exchange": "2017-03-18T22:42:21.3763342Z",
        "time_coinapi": "2017-03-18T22:42:21.3763342Z",
        "uuid": "1EA8ADC5-6459-47CA-ADBF-0C3F8C729BB2",
        "price": 770.000000000,
        "size": 0.050000000,
        "taker_side": "SELL"
    }
  }
]

Get current quotes for all symbols or for a specific symbol.

HTTP Request

  1. GET /v1/quotes/current?filter_symbol_id={filter_symbol_id}
  2. GET /v1/quotes/{symbol_id}/current

URL Parameters

Parameter Type Description
filter_symbol_id string[] Comma or semicolon delimited parts of symbol identifier used to filter response. (optional, full list available here)

Output variables

Variable Description
symbol_id Our symbol identifier, format documented here
time_exchange Exchange time of order book
time_coinapi CoinAPI time when order book received from exchange
ask_price Best asking price
ask_size Volume resting on best ask
bid_price Best bidding price
bid_size Volume resting on best bid
last_trade Last executed transaction, variables described in trades section

Latest data

curl https://rest.coinapi.io/v1/quotes/latest \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/quotes/latest");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/quotes/latest');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/quotes/latest'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/quotes/latest",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/quotes/latest")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/quotes/latest")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/quotes/latest")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

[
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "time_exchange": "2013-09-28T22:40:50.0000000Z",
    "time_coinapi": "2017-03-18T22:42:21.3763342Z",
    "ask_price": 770.000000000,
    "ask_size": 3252,
    "bid_price": 760,
    "bid_size": 124
  },
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "time_exchange": "2013-09-28T22:40:50.0000000",
    "time_coinapi": "2017-03-18T22:42:21.3763342",
    "ask_price": 770.000000000,
    "ask_size": 3252,
    "bid_price": 760,
    "bid_size": 124
  }
]

Get latest quote updates up to 1 minute ago or get updates for a specific symbol without time limit. Latest data is always returned in time descending order.

HTTP Request

  1. GET /v1/quotes/latest?limit={limit}&filter_symbol_id={filter_symbol_id}
  2. GET /v1/quotes/{symbol_id}/latest?limit={limit}

URL Parameters

Parameter Type Description
symbol_id string Symbol identifier of requested timeseries (full list available here)
limit int Amount of items to return (optional, mininum is 1, maximum is 100000, default value is 100, if the parameter is used then every 100 output items are counted as one request)
filter_symbol_id string[] Comma or semicolon delimited parts of symbol identifier used to filter response. (optional, full list available here)

Output variables

Variable Description
symbol_id Our symbol identifier, format documented here.
time_exchange Exchange time of order book
time_coinapi CoinAPI time when order book received from exchange
ask_price Best asking price
ask_size Volume resting on best ask
bid_price Best bidding price
bid_size Volume resting on best bid

Historical data

curl https://rest.coinapi.io/v1/quotes/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00 \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/quotes/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/quotes/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/quotes/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/quotes/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/quotes/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/quotes/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/quotes/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

The above command returns JSON structured like this:

[
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "time_exchange": "2013-09-28T22:40:50.0000000Z",
    "time_coinapi": "2017-03-18T22:42:21.3763342Z",
    "ask_price": 770.000000000,
    "ask_size": 3252,
    "bid_price": 760,
    "bid_size": 124
  },
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "time_exchange": "2013-09-28T22:40:50.0000000",
    "time_coinapi": "2017-03-18T22:42:21.3763342",
    "ask_price": 770.000000000,
    "ask_size": 3252,
    "bid_price": 760,
    "bid_size": 124
  }
]

Get historical quote updates within requested time range, returned in time ascending order.

HTTP Request

GET /v1/quotes/{symbol_id}/history?time_start={time_start}&time_end={time_end}&limit={limit}

URL Parameters

Parameter Type Description
symbol_id string Symbol identifier for requested timeseries (full list available here)
time_start timestring Starting time in ISO 8601 (required)
time_end timestring Timeseries ending time in ISO 8601 (optional, if not supplied then the data is returned to the end or when result elements count reaches the limit)
limit int Amount of items to return (optional, mininum is 1, maximum is 100000, default value is 100, if the parameter is used then every 100 output items are counted as one request)

Output variables

Variable Description
symbol_id Our symbol identifier, format documented here.
time_exchange Exchange time of order book
time_coinapi CoinAPI time when order book received from exchange
ask_price Best asking price
ask_size Volume resting on best ask
bid_price Best bidding price
bid_size Volume resting on best bid

Order book

This section describes calls related to order book data, also known as books or passive level 2 data.

JSON structure

Order book related commands return JSON structured like this:

[
  {
    "symbol_id": "BITSTAMP_SPOT_BTC_USD",
    "time_exchange": "2013-09-28T22:40:50.0000000Z",
    "time_coinapi": "2017-03-18T22:42:21.3763342Z",
    "asks": [
      {
        "price": 456.35,
        "size": 123
      },
      {
        "price": 456.36,
        "size": 23
      },
      ... cut ...
    ],
    "bids": [
      {
        "price": 456.10,
        "size": 42
      },
      {
        "price": 456.09,
        "size": 5
      },
      ... cut ...
    ]
  }
]

Output variables

Variable Description
symbol_id Our symbol identifier, format documented here.
time_exchange Exchange time of order book
time_coinapi CoinAPI time when order book received from exchange
asks Best 20 ask levels in order from best to worst
bids Best 20 bid levels in order from best to worst
price Price of bid/ask
size Volume resting on bid/ask level in base amount

Current data

curl https://rest.coinapi.io/v1/orderbooks/current \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/orderbooks/current");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/orderbooks/current');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/orderbooks/current'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/orderbooks/current",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/orderbooks/current")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/orderbooks/current")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/orderbooks/current")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

Get current order book snapshot for all or a specific symbol.

HTTP Request

  1. GET /v1/orderbooks/current?filter_symbol_id={filter_symbol_id}&limit_levels={limit_levels}
  2. GET /v1/orderbooks/{symbol_id}/current?limit_levels={limit_levels}

URL Parameters

Parameter Type Description
filter_symbol_id string[] Comma or semicolon delimited parts of symbol identifier used to filter response. (optional, full list available here)
limit_levels int Maximum amount of levels from each side of the book to include in response (optional)

Latest data

curl https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/latest \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/latest");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/latest');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/latest'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/latest",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/latest")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/latest")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/latest")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

Get latest order book snapshots for a specific symbol, returned in time descending order.

HTTP Request

GET /v1/orderbooks/{symbol_id}/latest?limit={limit}&limit_levels={limit_levels}

URL Parameters

Parameter Type Description
symbol_id string Symbol identifier of requested timeseries (full list available here)
limit_levels int Maximum amount of levels from each side of the book to include in response (optional)
limit int Amount of items to return (optional, mininum is 1, maximum is 100000, default value is 100, if the parameter is used then every 100 output items are counted as one request)

Historical data

curl https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00 \
  --request GET
  --header "X-CoinAPI-Key: 73034021-0EBC-493D-8A00-E0F138111F41"
var client = new RestClient("https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00");
var request = new RestRequest(Method.GET);
request.AddHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
  'X-CoinAPI-Key' => '73034021-0EBC-493D-8A00-E0F138111F41'
));

try {
  $response = $request->send();
  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>
import requests
url = 'https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00'
headers = {'X-CoinAPI-Key' : '73034021-0EBC-493D-8A00-E0F138111F41'}
response = requests.get(url, headers=headers)
const https = require('https');

var options = {
  "method": "GET",
  "hostname": "rest.coinapi.io",
  "path": "/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00",
  "headers": {'X-CoinAPI-Key': '73034021-0EBC-493D-8A00-E0F138111F41'}
};

var request = https.request(options, function (response) {
  var chunks = [];
  response.on("data", function (chunk) {
    chunks.push(chunk);
  });
});

request.end();
import (
  "gopkg.in/resty.v0"
)

func main()
{
    resp, err := resty.R().
      SetHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41").
      Get("https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00")
}
require 'uri'
require 'net/http'

url = URI("https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-CoinAPI-Key"] = '73034021-0EBC-493D-8A00-E0F138111F41'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://rest.coinapi.io/v1/orderbooks/BITSTAMP_SPOT_BTC_USD/history?time_start=2016-01-01T00:00:00")
  .post(body)
  .addHeader("X-CoinAPI-Key", "73034021-0EBC-493D-8A00-E0F138111F41s")
  .build();

Response response = client.newCall(request).execute();

Get historical order book snapshots for a specific symbol within time range, returned in time ascending order.

HTTP Request

GET /v1/orderbooks/{symbol_id}/history?time_start={time_start}&time_end={time_end}&limit={limit}&limit_levels={limit_levels}

URL Parameters

Parameter Type Description
symbol_id string Symbol identifier for requested timeseries (full list available here)
time_start timestring Starting time in ISO 8601 (required)
time_end timestring Timeseries ending time in ISO 8601 (optional, if not supplied then the data is returned to the end or when result elements count reaches the limit)
limit_levels int Maximum amount of levels from each side of the book to include in response (optional)
limit int Amount of items to return (optional, mininum is 1, maximum is 100000, default value is 100, if the parameter is used then every 100 output items are counted as one request)

WebSocket API

General

WebSocket endpoint provides real-time market data streaming which works in Subscribe-Publish communication model. After establishing a WebSocket connection with us, you will need to send a Hello message documented below.

If everything is correct, we will provide you with a continuous stream of real-time market data updates.

Endpoint

Production endpoint, requires API key for authentication and providing real data:
wss://ws.coinapi.io/v1/

We do not provide a mockup endpoint for WebSocket protocol.

Hello

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-0EBC-493D-8A00-E0F138111F41",
  "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-0EBC-493D-8A00-E0F138111F41",
  "heartbeat": false,
  "subscribe_data_type": ["quote"],
  "subscribe_filter_asset_id": ["BTC", "ETH"]
}

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

{
  "type": "hello",
  "apikey": "73034021-0EBC-493D-8A00-E0F138111F41",
  "heartbeat": false,
  "subscribe_data_type": ["trade", "quote", "book20"]
}

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

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

Parameter Type Description
type string Message type, must be equal to hello
apikey string Your API key
heartbeat bool true to receive Heartbeat message every second, otherwise false
subscribe_data_type string[] List of data types you want to receive (required, possible values listed in table below)
subscribe_filter_symbol_id string[] Filter data to symbols whose identifiers match at least one of the listed prefixes (optional, if not provided then stream will not filtered by symbols)
subscribe_filter_asset_id string[] Filter data to symbols which are related to the at least one of the listed asset identifiers (optional, if not provided then stream will not be filtered by assets)

Data types

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

Data type Description
trade Executed transactions feed (order book matches)
quote Quote updates feed (order book level 1)
book Order book snapshots and updates feed (order book level 2, full order book snapshot and real-time updates)
book5 Order book snapshots feed (order book level 2, 5 best levels from each side of book)
book20 Order book snapshots feed (order book level 2, 20 best levels from each side of book)
book50 Order book snapshots feed (order book level 2, 50 best levels from each side of book)

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.

Messages

Trades

Trade message JSON is structured like this:

{
  "type": "trade",
  "symbol_id": "BITSTAMP_SPOT_BTC_USD",
  "sequence": 2323346,
  "time_exchange": "2013-09-28T22:40:50.0000000Z",
  "time_coinapi": "2017-03-18T22:42:21.3763342Z",
  "uuid": "770C7A3B-7258-4441-8182-83740F3E2457",
  "price": 770.000000000,
  "size": 0.050000000,
  "taker_side": "BUY"
}

Trade message is sent for every executed transaction (orderbook match).

Message variables

Variable Description
type Message type, always trade
symbol_id Our symbol identifier, format documented here
sequence Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection.
time_exchange Time of trade reported by exchange
time_coinapi Time when coinapi first received trade from exchange
uuid Our unique trade identifier in form of UUIDv4
price Price of the transaction
size Base asset amount traded in transaction
taker_side Aggressor side of the transaction (BUY/SELL/BUY_ESTIMATED/SELL_ESTIMATED/UNKNOWN)

Possible taker_side values

If exchange has not reported who the aggressor side of the transaction was, then we will classify who it most probably was based on current market view.

taker_side Description
BUY Exchange has reported that transaction aggressor was buying
SELL Exchange has reported that transaction aggressor was selling
BUY_ESTIMATED Exchange has not reported transaction aggressor, we estimated that more likely it was buying
SELL_ESTIMATED Exchange has not reported transaction aggressor, we estimated that more likely it was selling
UNKNOWN Exchange has not reported transaction aggressor and we have not estimated who it was

Quotes

Quote message JSON is structured like this:

{
  "type": "quote",
  "symbol_id": "BITSTAMP_SPOT_BTC_USD",
  "sequence": 2323346,
  "time_exchange": "2013-09-28T22:40:50.0000000Z",
  "time_coinapi": "2017-03-18T22:42:21.3763342Z",
  "ask_price": 770.000000000,
  "ask_size": 3252,
  "bid_price": 760,
  "bid_size": 124
}

Quote message is sent for each update on orderbook first best bid or ask level.

Message variables

Variable Description
type Message type, always quote
symbol_id Our symbol identifier, format documented here.
sequence Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection.
time_exchange Exchange time of orderbook
time_coinapi CoinAPI time when orderbook received from exchange
ask_price Best asking price
ask_size Volume resting on best ask
bid_price Best bidding price
bid_size Volume resting on best bid

Book

A Book message is sent for each snapshot or update of the order book. After subscription to this data type is initialized, we immediately start delivering updates to the order book and at least one snapshot will be provided as soon as possible with the nearest update of the book.

{
  "type": "book",
  "symbol_id": "BITSTAMP_SPOT_BTC_USD",
  "sequence": 2323346,
  "time_exchange": "2013-09-28T22:40:50.0000000Z",
  "time_coinapi": "2017-03-18T22:42:21.3763342Z",
  "is_snapshot": true,
  "asks": [
    {
      "price": 456.35,
      "size": 123
    },
    {
      "price": 456.36,
      "size": 23
    },
    ... cut ...
  ],
  "bids": [
    {
      "price": 456.10,
      "size": 42
    },
    {
      "price": 456.09,
      "size": 5
    },
    ... cut ...
  ]
}

Message variables

Variable Description
type Message type, always book
symbol_id Our symbol identifier, format documented here.
sequence Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection.
time_exchange Exchange time of orderbook
time_coinapi CoinAPI time when orderbook received from exchange
is_snapshot Is message a snapshot? If true then all bid and ask levels are listed, otherwise only changed since the last message.
asks All ask levels for snapshot message, otherwise only changed ask levels since the last message.
bids All bid levels for snapshot message, otherwise only changed bid levels since the last message
price Price of bid/ask
size Volume resting on bid/ask level in base amount

Book5

A Book5 message is sent for each update on orderbook first 5 best bid or ask levels.

{
  "type": "book5",
  "symbol_id": "BITSTAMP_SPOT_BTC_USD",
  "sequence": 2323346,
  "time_exchange": "2013-09-28T22:40:50.0000000Z",
  "time_coinapi": "2017-03-18T22:42:21.3763342Z",
  "asks": [
    {
      "price": 456.35,
      "size": 123
    },
    {
      "price": 456.36,
      "size": 23
    },
    ... cut ...
  ],
  "bids": [
    {
      "price": 456.10,
      "size": 42
    },
    {
      "price": 456.09,
      "size": 5
    },
    ... cut ...
  ]
}

Message variables

Variable Description
type Message type, always book5
symbol_id Our symbol identifier, format documented here.
sequence Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection.
time_exchange Exchange time of orderbook
time_coinapi CoinAPI time when orderbook received from exchange
asks Best 5 ask levels in order from best to worst
bids Best 5 bid levels in order from best to worst
price Price of bid/ask
size Volume resting on bid/ask level in base amount

Book20

A Book20 message is sent for each update on orderbook first 20 best bid or ask levels.

{
  "type": "book20",
  "symbol_id": "BITSTAMP_SPOT_BTC_USD",
  "sequence": 2323346,
  "time_exchange": "2013-09-28T22:40:50.0000000Z",
  "time_coinapi": "2017-03-18T22:42:21.3763342Z",
  "asks": [
    {
      "price": 456.35,
      "size": 123
    },
    {
      "price": 456.36,
      "size": 23
    },
    ... cut ...
  ],
  "bids": [
    {
      "price": 456.10,
      "size": 42
    },
    {
      "price": 456.09,
      "size": 5
    },
    ... cut ...
  ]
}

Message variables

Variable Description
type Message type, always book20
symbol_id Our symbol identifier, format documented here.
sequence Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection.
time_exchange Exchange time of orderbook
time_coinapi CoinAPI time when orderbook received from exchange
asks Best 20 ask levels in order from best to worst
bids Best 20 bid levels in order from best to worst
price Price of bid/ask
size Volume resting on bid/ask level in base amount

Book50

A Book50 message is sent for each update on orderbook first 50 best bid or ask levels.

{
  "type": "book50",
  "symbol_id": "BITSTAMP_SPOT_BTC_USD",
  "sequence": 2323346,
  "time_exchange": "2013-09-28T22:40:50.0000000Z",
  "time_coinapi": "2017-03-18T22:42:21.3763342Z",
  "asks": [
    {
      "price": 456.35,
      "size": 123
    },
    {
      "price": 456.36,
      "size": 23
    },
    ... cut ...
  ],
  "bids": [
    {
      "price": 456.10,
      "size": 42
    },
    {
      "price": 456.09,
      "size": 5
    },
    ... cut ...
  ]
}

Message variables

Variable Description
type Message type, always book50
symbol_id Our symbol identifier, format documented here.
sequence Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection.
time_exchange Exchange time of orderbook
time_coinapi CoinAPI time when orderbook received from exchange
asks Best 50 ask levels in order from best to worst
bids Best 50 bid levels in order from best to worst
price Price of bid/ask
size Volume resting on bid/ask level in base amount

Heartbeat

Heartbeat message JSON is structured like this:

{
  "type": "hearbeat"
}

Heartbeat message is sent to you every time there is one second of silence in communication between us, if you agreed on this feature in Hello message.

FIX API

General

Financial Information eXchange (FIX) protocol is an electronic communications protocol initiated in 1992 for international real-time exchange of information related to the securities transactions and markets. You can use it to receive real-time market data from us and it’s an alternative to WebSocket protocol.

Endpoint

FIX client configuration file:

[DEFAULT]
ConnectionType=initiator
ReconnectInterval=2
FileStorePath=store
FileLogPath=log
StartTime=00:00:00
EndTime=00:00:00
UseDataDictionary=Y
DataDictionary=FIX44.xml
SocketConnectHost=fix.coinapi.io
SocketConnectPort=3301
SSLEnable=Y
SSLServerName=fix.coinapi.io
SSLValidateCertificates=Y
SSLCheckCertificateRevocation=Y
LogoutTimeout=5
ResetOnLogon=Y

[SESSION]
BeginString=FIX.4.4
SenderCompID=YOUR_API_KEY
TargetCompID=COINAPI
HeartBtInt=1

Our production endpoint configuration parameters:

Parameter Value
Hostname fix.coinapi.io
Port 3301
TLS encryption Required
Protocol version FIX.4.4 (XML FIX Specification can be downloaded here: FIX44.xml)
Gateway timezone UTC

We recommend using our SDK or listed client libraries depending on your language requirements:

Language Libraries
C++ https://github.com/quickfix/quickfix
C# https://github.com/coinapi/coinapi-sdk/tree/master/csharp-fix
https://github.com/connamara/quickfixn
Java https://github.com/quickfix-j/quickfixj
Python https://github.com/quickfix/quickfix/tree/master/src/python
Ruby https://github.com/quickfix/quickfix/tree/master/src/ruby
Go https://github.com/quickfixgo/quickfix

Security

Stunnel configuation:

[COINAPI]
client = yes
accept = 3301
connect = fix.coinapi.io:3301
verify = 3

Communication with our FIX gateway is secured by TLS protocol. If your FIX protocol implementation does not support establishing a connection over a secure channel, you must use a proxy between your client and our FIX gateway to unbundle encryption. We recommend stunnel as a proxy if a secure connection can’t be established directly from your client.

Messages

All FIX messages are equipped with Standard Header and Trailer, below we will describe what is required in them in accordance with FIX 4.4, the standard that we use.

Standard Header

Tag Name Description
8 BeginString FIX.4.4
9 BodyLength Message length, in bytes, forward to the CheckSum <10> field
35 MsgType Defines message type
49 SenderCompID Assigned value used to identify message sender
56 TargetCompID Assigned value used to identify message receiver
34 MsgSeqNum Integer message sequence number
52 SendingTime Time of message transmission always expressed in UTC (Universal Time Coordinated, also known as “GMT”)

Standard Trailer

Tag Name Description
10 CheckSum Three byte, simple checksum. Always the last field in a message, i.e. serves, with the trailing , as the end-of-message delimiter. Always defined as three characters

Logon (A)

8=FIX.4.4|9=97|35=A|34=1|49=COINAPI|52=20170503-22:00:56.743|56=73034021-0EBC-493D-8A00-E0F138111F41|98=0|108=1|10=245|

First message sent by the client to CoinAPI FIX Gateway after connection to initiate a FIX session. After successful authorization, server will respond with same message type and start delivering market data messages to you.

Tag Name Description
49 SenderCompID Your API key
56 TargetCompID COINAPI
108 HeartBtInt 1 (seconds)
98 EncryptMethod 0

Logout (5)

Message sent by any side to close established session. If received, should be sent back unchanged to confirm session termination.

Trades (X)

Market Data - Incremental Refresh message, representing new executed transaction.

8=FIX.4.4|9=241|35=X|34=2|49=COINAPI|52=20170503-22:00:57.123|56=73034021-0EBC-493D-8A00-E0F138111F41|268=1|279=0|269=2|278=845FD430-4157-4E45-B28E-50F0F577AC37|55=COINBASE_SPOT_BTC_USD|270=1512.22000000|271=0.10000000|272=20170503|273=22:00:56.995|282=BUY|10=197|
public void OnMessage(QuickFix.FIX44.MarketDataIncrementalRefresh msg, SessionID s)
{
    for (int idx = 0; idx < msg.NoMDEntries.getValue(); idx ++)
    {
        var trade = new QuickFix.FIX44.MarketDataIncrementalRefresh.NoMDEntriesGroup();
        msg.GetGroup(idx + 1, trade);

        Console.WriteLine($"Trade {trade.MDUpdateAction} @ {trade.Symbol}:");
        Console.WriteLine($" ID: {trade.MDEntryID}");
        Console.WriteLine($" Date: {trade.MDEntryDate}");
        Console.WriteLine($" Time: {trade.MDEntryTime}");
        Console.WriteLine($" Px: {trade.MDEntryPx}");
        Console.WriteLine($" Size: {trade.MDEntrySize}");
        Console.WriteLine($" TakerSide: {trade.MDEntryOriginator}");
    }
    Console.WriteLine($"--------------------------------------------------");
}
Tag Name Description
268 NoMdEntries Number of trades in the message
=> 279 MDUpdateAction Type of Market Data update action, always 0 (NEW)
=> 269 MDEntryType Type of Market Data entry, always 2 (Trade)
=> 278 MDEntryID Our unique trade identifier in the form of UUIDv4
=> 55 Symbol Our Symbol identifier (full list available here)
=> 270 MDEntryPx Trade price
=> 271 MDEntrySize Trade size in base amount
=> 272 MDEntryDate Date of the trade reported by the exchange
=> 273 MDEntryTime Time of the trade reported by the exchange with milliseconds
=> 282 MDEntryOriginator Aggressor side of the transaction (BUY/SELL/BUY_ESTIMATED/SELL_ESTIMATED/UNKNOWN)

Possible MDEntryOriginator values

If exchange has not reported who the aggressor side of the transaction was, we will classify who it most probably was based on current market view.

taker_side Description
BUY Exchange has reported that transaction aggressor was buying
SELL Exchange has reported that transaction aggressor was selling
BUY_ESTIMATED Exchange has not reported transaction aggressor, we estimated that more likely it was buying
SELL_ESTIMATED Exchange has not reported transaction aggressor, we estimated that more likely it was selling
UNKNOWN Exchange has not reported transaction aggressor and we have not estimated who it was

Orderbooks (W)

Market Data - Snapshot/Full Refresh message, representing update of orderbook snapshot limited to 20 best ask and bid levels.

8=FIX.4.4|9=2814|35=W|34=7|49=COINAPI|52=20170503-22:35:18.590|56=73034021-0EBC-493D-8A00-E0F138111F41|55=COINBASE_SPOT_BTC_EUR|268=40|269=1|270=1397.84000000|271=0.25620000|272=20170503|273=22:35:18.408|269=1|270=1397.85000000|271=0.24000000|272=20170503|273=22:35:18.408|269=1|270=1397.86000000|271=0.50000000|272=20170503|273=22:35:18.408|269=1|270=1399.96000000|271=0.08000000|272=20170503|273=22:35:18.408|269=1|270=1399.98000000|271=0.11000000|272=20170503|273=22:35:18.408|269=1|270=1399.99000000|271=0.93340628|272=20170503|273=22:35:18.408|269=1|270=1400.0|271=4.37155883|272=20170503|273=22:35:18.408|269=1|270=1401.22000000|271=0.11000000|272=20170503|273=22:35:18.408|269=1|270=1401.23|271=0.01|272=20170503|273=22:35:18.408|269=1|270=1402.12|271=0.10000000|272=20170503|273=22:35:18.408|269=1|270=1402.60000000|271=5.30086000|272=20170503|273=22:35:18.408|269=1|270=1402.68000000|271=0.11000000|272=20170503|273=22:35:18.408|269=1|270=1402.69|271=0.02000000|272=20170503|273=22:35:18.408|269=1|270=1404.0|271=1.0|272=20170503|273=22:35:18.408|269=1|270=1404.01000000|271=0.47000000|272=20170503|273=22:35:18.408|269=1|270=1405.0|271=0.24577401|272=20170503|273=22:35:18.408|269=1|270=1405.07|271=0.01264284|272=20170503|273=22:35:18.408|269=1|270=1405.11|271=0.01943044|272=20170503|273=22:35:18.408|269=1|270=1405.61000000|271=1.68316924|272=20170503|273=22:35:18.408|269=1|270=1405.67000000|271=4.13101588|272=20170503|273=22:35:18.408|269=0|270=1396.00000000|271=0.73076211|272=20170503|273=22:35:18.408|269=0|270=1395.82000000|271=0.31000000|272=20170503|273=22:35:18.408|269=0|270=1395.81000000|271=4.07759372|272=20170503|273=22:35:18.408|269=0|270=1395.47000000|271=0.40000000|272=20170503|273=22:35:18.408|269=0|270=1395.01000000|271=0.56000000|272=20170503|273=22:35:18.408|269=0|270=1395.00000000|271=0.05000000|272=20170503|273=22:35:18.408|269=0|270=1394.34000000|271=0.50000000|272=20170503|273=22:35:18.408|269=0|270=1393.79000000|271=0.02000000|272=20170503|273=22:35:18.408|269=0|270=1393.78000000|271=0.10000000|272=20170503|273=22:35:18.408|269=0|270=1393.50000000|271=0.10000000|272=20170503|273=22:35:18.408|269=0|270=1393.23000000|271=0.13000000|272=20170503|273=22:35:18.408|269=0|270=1393.11000000|271=1.00000000|272=20170503|273=22:35:18.408|269=0|270=1393.02000000|271=0.33524135|272=20170503|273=22:35:18.408|269=0|270=1393.00000000|271=0.50000000|272=20170503|273=22:35:18.408|269=0|270=1392.52000000|271=0.02000000|272=20170503|273=22:35:18.408|269=0|270=1392.51000000|271=0.11000000|272=20170503|273=22:35:18.408|269=0|270=1392.50000000|271=0.10000000|272=20170503|273=22:35:18.408|269=0|270=1392.36000000|271=2.62000000|272=20170503|273=22:35:18.408|269=0|270=1392.31000000|271=0.02000000|272=20170503|273=22:35:18.408|269=0|270=1392.01000000|271=0.41000000|272=20170503|273=22:35:18.408|10=075|
public void OnMessage(QuickFix.FIX44.MarketDataSnapshotFullRefresh msg, SessionID s)
{
    for (int idx = 0; idx < msg.NoMDEntries.getValue(); idx++)
    {
        var level = new QuickFix.FIX44.MarketDataSnapshotFullRefresh.NoMDEntriesGroup();
        msg.GetGroup(idx + 1, level);

        Console.WriteLine($"Orderbook {level.MDEntryType} @ {msg.Symbol}:");
        Console.WriteLine($" Date: {level.MDEntryDate}");
        Console.WriteLine($" Time: {level.MDEntryTime}");
        Console.WriteLine($" Px: {level.MDEntryPx}");
        Console.WriteLine($" Size: {level.MDEntrySize}");
    }
}
Tag Name Description
55 Symbol Our Symbol identifier (full list available here)
268 NoMdEntries Number of levels in the orderbook, max 40
=> 269 MDEntryType Type Market Data entry 0 (Bid), 1 (Offer)
=> 270 MDEntryPx Price level of the orderbook level
=> 271 MDEntrySize Volume resting on this orderbook level
=> 272 MDEntryDate Date of the orderbook reported by the exchange
=> 273 MDEntryTime Time of the orderbook reported by the exchange with milliseconds

Heartbeat (0)

8=FIX.4.4|9=87|35=0|34=13|49=COINAPI|52=20170503-22:21:27.545|56=73034021-0EBC-493D-8A00-E0F138111F41|10=048|

Message sent by any side after defined amount of seconds in communication silence.