All pages
Powered by GitBook
1 of 12

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

API output

Market open and close

Digital asset exchanges operate approximately 24x7x365. For daily aggregated data, the opening price is calculated as the first trade at or after 00:00:00 UTC. The closing price is calculated as the last trade prior to 00:00:00 UTC.

Getting Started

Authentication

Each endpoint for the Market Data solution lives under its own hostname. You must include an API key in the header of every request you make. The format for the API key is:

X-Api-Key: <client-api-key>

API input

Header

When interacting with Kaiko HTTP APIs, you are expected to pass two pieces of information in a header:

  • Accept: application/json: API responses will be in JSON format.

  • Accept-Encoding: gzip: All our endpoints benefit from use of compression.

Timestamp input

All time parameters are in UTC time zone and returned in the following ISO 8601 datetime format:

YYYY-MM-DDThh:mm:ss.sssZ

For example:

2017-12-17T13:35:24.351Z

The "T" separates the date from the time. The trailing "Z" indicates UTC time.

Exchange codes

Find exchange codes here: .

Instrument codes

Find instrument codes here: .

Data versioning

Kaiko takes transparency and accountability very seriously. Therefore, our provided datasets are versioned. Dataset versioning is orthogonal to API versioning. Any potential breaking changes in results (e.g. semantical changes or corrections of historically incorrect data) will result in a new dataset version - no corrections or adjustments will be done in the dark. Addition of new data will not result in a new dataset version. Data is versioned on a per-base-data level.

The versioning is selected by selecting a base data set and a version. All current Market Data API endpoints take the commodity and data_version parameters.

By setting this to latest, you will get the most recent version. The returned version is always included in the query field and can be referred to if you would ever need to compare results, should we ever need to adjust historical data. over a request with version set to latest will preserve the current version across subsequent pagination requests.

We recommend using the most current version explicitly in production integrations as the

Timestamp

All Kaiko data is timestamped in the UTC time zone. All timestamps are returned as (the number of milliseconds elapsed since 1970-01-01 00:00:00.000 UTC). For metadata fields, times are also returned in millisecond-resolution ISO 8601 datetime strings in the same format as input for convenience.

latest
label might move at any time to a breaking change. For the
trades
and
order_book_snapshots
commodities the latest version is currently
v1

Paginating
millisecond Unix timestamps

Rate limiting

Our standard Rest API is limited to 6000 requests per API key per minute. If you query the API beyond that threshold, a 429 an error message will occur. If you'd like to discuss rate-limiting, please contact [email protected].

curl --compressed -H 'Accept: application/json' 'https://<api_hostname>/<endpoint>'

Error codes

All API responses are in JSON format. A result field, with a value of success or error is returned with each request. In the event of an error, a message field will provide an error message.

HTTP error codes

The Kaiko platform API uses the following error codes:

Error Code
Meaning

400

Envelope

All API responses are in JSON format. A result field, with a value of success or error is returned with each request. In the event of an error, a message field will provide an error message.

An access object is also echoed back. It contains two ranges of timestamps:

  • access_range: The time range for which the Client has access to the API

Pagination

For queries that result in a larger dataset than can be returned in a single response, a continuation_token field is included. Calling the same endpoint again with the continuation_token query parameter added will return the next result page. For convenience, a next_url field is also included, containing a URL that can be called directly to get the next page. Paginated endpoints also takes a page_size parameter that specifies the maximum number of items that should be included in each response. Only the first call should include page_size, all subsequent calls should only use continuation_token. Paginating over a request with set to latest will preserve the current version across subsequent pagination requests.

Parameters

Bad Request

401

Unauthorized -- You are not authenticated properly. See Authentication.

403

Forbidden -- You don't have access to the requested resource.

404

Not Found

405

Method Not Allowed

406

Not Acceptable

429

Rate limit reached

500

Internal Server Error -- We had a problem with our service. Try again later.

503

Service Unavailable -- We're temporarily offline for maintenance.

data_range : The time range of data the Client is authorized to access

Key
Data type
Description

access

{}

Time ranges of accesses.

data

[] | {}

Response result data.

message

string

Error message, if query was not successful.

query

{}

All handled query parameters echoed back.

Parameter
Required
Description

continuation_token

No

page_size

No

Maximum number of records to return in one response

Browsing pages when using Python

The following script can be used to browse pages in Python. Make sure to update your trade_url and X-Api-Key.

import http.client
import json
conn = http.client.HTTPSConnection("us.market-api.kaiko.io")
endpoint = "/v2/data/trades.v1/spot_exchange_rate/btc/usd"
params = "?interval=1h&start_time=2024-09-01T00:00:00.000Z&end_time=2024-09-10T00:00:00.000Z"
headers = {
    "X-Api-Key": "XXX",
    "Accept": "application/json"
}

This example uses Pandas for convenience. If you're unfamiliar with them, use the standard Python example.

version

"taker_side_sell" Explained

For Centralized Exchange(CEX) taker_side_sell takes the value of true when a taker's sell order fills a maker's buy order and false when a taker's buy order fills a maker's sell order.

For Decentralized Exchanges (DEX) using Automatic Market Maker (AMM) protocols, the liquidity pool contract is considered the maker. The entity executing a transaction against the liquidity pool is the taker.

If an exchange does not appear below, it can be assumed that all data we provide is normalized correctly.

For exchanges where we were unable to confirm as reporting data from either a taker or a maker's perspective, we have included the notation mapping from the exchange's trade direction field to our taker_side_sell field. This is necessary so that researchers who want to further study trade direction can make their own conclusions. For exchanges that classify trade direction differently or exclude the field entirely, we also include the notation mapping and a short explanation for how their variable differs.

Furthermore, there are some trades of the Australian Exchange

import requests
import pandas as pd

trade_url = "https://us.market-api.kaiko.io/v3/data/trades.v1/exchanges/usp3/spot/usdc-weth/trades?start_time=2022-11-01T00:00:00.000Z&end_time=2022-12-01T00:00:00.000Z"
headers = {"X-Api-Key": "XXX","Accept": "application/json"}
output = requests.get(trade_url, headers = headers).json()
df = pd.DataFrame(output["data"])

while "next_url" in output:
        output = requests.get(output["next_url"], headers = headers).json()
        df_to_add = pd.DataFrame(output["data"])
        print(df_to_add)
        df= pd.concat([df, df_to_add])
print(df)
all_trades = []
next_url = endpoint + params
while next_url:
conn.request("GET", next_url, headers=headers)
response = conn.getresponse()
data = json.loads(response.read().decode("utf-8"))
all_trades.extend(data.get("data", []))
print(f"Fetched {len(data.get('data', []))} datapoints. Total: {len(all_trades)}")
next_url = data.get("next_url", "").replace("https://us.market-api.kaiko.io", "")
if not next_url:
break
conn.close()
print(f" datapoints fetched: {(all_trades)}")

result

string

success if query successful, error otherwise.

time

string

The current time at our endpoint.

timestamp

long

The current time at our endpoint.

Independent Reserve
, where we cannot decide if it is the taker buy or taker sell. As such, it is the only exchange that has 3 values, which are
true
,
false
and
unknown
, in the field
taker_side_sell
.

Finally, we have made a couple of errors in classifying exchanges as "maker" or "taker", typically early on in the process of developing taker_side_sell. Rather than switch our trade reporting after years of data collection, we have simply marked exchanges where the inverse of the notation stated should be applied. For these exchanges, researchers should be aware that when taker_side_sell: false, the inverse should be assumed.

Unconfirmed, Misclassified or Absent Trade Direction Field

Exchange

Exchange Notation

Kaiko taker_side_sell: true equivalent to:

Comment

BTCBox

"type": "buy" or "sell"

inverse notation: "type": "sell"

Inverse, but confirmed perspective from exchange.

Liquid (Quoine)

taker_side: "buy" or "sell"

inverse notation: taker_side: "buy"

Inverse, but confirmed perspective from exchange.

Bithumb

"type": "bid" or "ask"

inverse notation: "type": "bid"

Inverse, but confirmed perspective from exchange.

Coinone

"is_ask": "0"(if seller is taker)/"1"(if seller is maker)

inverse notation: "is_ask": "1"

Inverse, confirmed from exchange but slightly different notation format

Bitstamp

type: 0 (buy) or 1 (sell)

type: 1

Unconfirmed perspective from exchange

Bit-Z

"s": "buy" or "sell"

"s": "sell"

Unconfirmed perspective from exchange

EXX

type": "buy" or "sell"

type: "sell"

Unconfirmed perspective from exchange

CEX.io

type: "buy" or "sell"

type: "sell"

Unconfirmed perspective from exchange

Yobit

"type": "bid" or "ask"

"type": "bid"

Unconfirmed perspective from exchange

itBit

None

Always returns true

No buy/sell field

Korbit

None

Always returns null

No buy/sell field

Coinflex

None

Always returns null

No buy/sell field

Independent Reserve

"Side": "Buy" or "Sell"

"Side": "Sell"

Some trades have "Unknown"

AsiaNext

None

Always returns false

No buy/sell field provided