NAV Navbar

Introduction

Welcome to the Caspian API v1! You can use our API to access Caspian API endpoints, which can get various information about market data.

We also keep a changelog with all notable changes made to the Caspian API, therefore the documentation would be up to date. Please do not forget to take a look over the Changelog section too at every new release in order to take in consideration the new notable changes.

Authentication

An access token is required in order to interact with the data APIs. This can be obtained by sending an HTTP request as described below.

Request

Request URL: https://sandbox.api.caspian.tech/v1/auth/authenticate
Request Method: POST
Content-Type: application/json
Content:
{
     "type:" string,
     "payload:" object
}

Authentication request example:

{
  "type": "Key",
  "payload": {
    "accessKeyID": "<YOUR_ACCESS_KEY_ID>",
    "secretAccessKey": "<YOUR_SECRET_ACCESS_KEY>"
  }
}

where:

Response

Authorization successful

Here is a sample response:

{
  "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJWMVFIVFFQSjAxOTIxQzNNREZIWSIsImlzcyI6IkNhc3BpYW4gVGVjaCIsImV4cCI6MTY0ODg4NzI1N30.MmJ7ZTr9mSK-bsgNif5HyjU8Z9__WGTN_oGvUxdZ3XI",
  "expiration": "2018-07-25T15:34:11.536123"
}

Status Code: 200
Content-Type: application/json
Content:
{
       "accessToken": string,
       "expiration": string
}

where:

Bad Request

Meaning: The request body contains an invalid JSON or it is missing the required attributes.
Status Code: 400
Content-Type: application/json
Content:
{
       "code": int,
       "message": string
}

Posible values for code:

Unauthorized

Meaning: Incorrect credentials or key.
Status Code: 401
Content: N/A

Internal Server Error

Meaning: The request is properly formatted but the server was unable to fulfill it due to an internal error.
Status Code: 500
Content-Type: application/json
Content: {
       "code": int,
       "message": string
}

Real-time Data

The following section describes the interaction between a client application and the Real-time Data service, using web socket technology. In order to use this service, a token must first be obtained, as described in the authentication section.

Connection initialization

Target URL: wss://sandbox.api.caspian.tech/v1/mdata/realtime/stream
When establishing the websocket connection, the user must supply the access token via one of the following ways:

Connection initialization example

Target URL: wss://sandbox.api.caspian.tech/v1/mdata/realtime/stream?access_token=dummyAccessToken
  1. By setting the HTTP header Authorization
  2. Authorization: ${accessToken}
  3. By adding the accessToken parameter in the URL
  4. wss://sandbox.api.caspian.tech/v1/mdata/realtime/stream?access_token=${accesToken}

If the token is not specified or if it's invalid/ expired, the websocket connection will be closed by the server with one of the following reasons mentioned in the CloseState (see RFC 6455 on protocol details):

Once the connection is established successfully, the user can proceed with sending requests to the service. The connection will be closed by the service when the token expires (please see Authentication Response section for the token expiration time). In order to keep the old connection alive, user must generate a new valid token and make a Token Refresh request as described in Token Refresh section. The Token Refresh request will replace the token used for the current connection with the newly generated one. If the Token Refresh request succeeds (please see Token Refresh Response section) the connection lifetime will be extended according with the new token.

Messages Format

Both outbound and inbound messages are formatted using JSON standard.

Every outbound & inbound JSON message follows the following format:
{
       "requestId": string,
       "type": string,
       "payload": object
}

where:

For outbound messages, the requestId value will be the same as the one used in generating the request (except for the ProtocolError. Those are returning the requestId as "N/A").

Inbound Messages

Subscribe

Request streaming data for a symbol.
Message Payload

Examples
Here is a code sample for Level1:

{
    "requestId": "96113dcc-734d-42d3-b347-965a4218e0a2",
    "type": "Subscribe",
    "payload": {
        "symbol": "FX-BTC/USD=GEMINI",
        "type": "Level1"
    }
}

Here is a code sample for Level2:

{
    "requestId": "1e668db8-0eab-4468-8c50-bbae26b73de2",
    "type": "Subscribe",
    "payload": {
        "symbol": "FUT-BTC/JPY-2018JUN30=BITFLYER",
        "type": "Level2"
    }
}

{
       "symbol": string,
       "symbolType": string, // (optional)
       "type": string,
       "numberOfLevels": integer, // (optional)
       "conflation": string // (optional)
}

Where:

Associated Outbound Message Types

Unsubscribe

Description
Terminate an active streaming request, based on the original request ID
Message Payload

Example

{
    "requestId": "45953af9-e9fc-4809-8974-fb1badc022ee",
    "type": "Unsubscribe",
    "payload": {
        "subscribeRequestId": "96113dcc-734d-42d3-b347-965a4218e0a2"
    }
}

{
       "subscribeRequestId": string
}

where:

Associated Outbound Message Types

Token Refresh

Description
Replace the expiring token with the newly generated one Message Payload

Examples

{
  "requestId": "96113dcc-734d-42d3-b347-965a4218e0a2",
  "type": "TokenRefresh",
  "payload": {
    "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJSZWFsVGltZUFQSSIsImlzcyI6IkNhc3BpYW4gVGVjaCIsImV4cCI6MTY0MTg5OTE0NH0.0YItnz0Uwc3Gf11IKHAuzeO_c5N1LZb__S51OQwh-NY"
  }
}

{
       "accessToken": string
}

where:

Associated Outbound Message Types

Outbound Messages

ProtocolError

Description
Sent by the service when a received message is not properly formatted. The requestId of this message is always N/A.
Message Payload

Example

{
    "requestId": "N/A",
    "type": "ProtocolError",
    "payload": {
        "code": 100,
        "message": "Request was not properly formatted as JSON"
    }
}

{
       "code": int,
       "message": string
}

where:

SubscribeResponse

Description
Sent by the service to confirm the status of a subscription received from the user.
Message Payload

Example

{
    "requestId": "96113dcc-734d-42d3-b347-965a4218e0a2",
    "type": "SubscribeResponse",
    "payload": {
        "code": 200,
        "message": "All OK"
    }
}

{
       "code": int,
       "message": string
}

where:

UnsubscribeResponse

Description
Sent by the service to confirm the status of an unsubscription received from the user.
Message Payload

Example

{
    "requestId": "45953af9-e9fc-4809-8974-fb1badc022ee",
    "type": "UnsubscribeResponse",
    "payload": {
        "code": 300,
        "message": "All OK"
    }
}

{
       "code": int,
       "message": string,
}

where:

Level1

Example

{
    "requestId": "96113dcc-734d-42d3-b347-965a4218e0a2",
    "type": "Level1",     
    "bboStream": "connected",
    "tradeStream": "connected",
    "payload":
    {
        "ask": 7641.12630702,
        "askSize": 8.793364,
        "bid": 7631.49215744,
        "bidSize": 0.27087741,
        "bboExchangeTimestamp": "2018-06-08T08:13:44.653000",
        "bboCaspianTimestamp": "2018-06-08T08:13:44.683000",
        "tradePrice": 7641.14468713,
        "tradeSize": 0.00826056,
        "tradeExchangeTimestamp": "2018-06-08T08:13:46.653000",
        "tradeCaspianTimestamp": "2018-06-08T08:13:46.683000"
    }
}

Description
Contains Level1 data updates for a subscription made by the client.
The initial update could contain only a part of the fields mentioned according to their availability.
A recurrent case is when BBO fields are available, but not the Trade fields, therefore only the available fields would be shown.

The Level1 JSON message follows the following format:
{
       "requestId": string,
       "type": string,
       "bboStream": string,
       "tradeStream": string,
       "payload": object
}

where:

Message Payload

Example exchangeSpecificInfo

{
    "requestId": "96113dcc-734d-42d3-b347-965a4218e0a3",
    "type": "Level1",
    "payload":
    {
        "exchangeSpecificInfo":
        {
            "buy_child_order_acceptance_id": "JRF20181210-133622-783108",
            "sell_child_order_acceptance_id": "JRF20181210-133622-670019",
            "side": "BUY"
        }
    }
}

{
       "ask": double,
       "askSize": double,
       "bid": double,
       "bidSize": double,
       "bboExchangeTimestamp": string,
       "bboCaspianTimestamp": string,
       "tradePrice": double,
       "tradeSize": double,
       "tradeExchangeTimestamp": string,
       "tradeCaspianTimestamp": string,
       "tradeId": string,
       "exchangeSpecificInfo": {
            string : string
            ...
       }
}

where:

Level2

Description
Contains Level2 data updates for a subscription made by the client. The payload is an array of objects. First update may include only the stream status field with an empty payload. The client should expect the next non-empty payload messages to contain the Level2 actual array of objects necessary for constructing the depth.

The Level2 JSON message follows the following format:
{
       "requestId": string,
       "type": string,
       "exchangeTimestamp": string,
       "caspianTimestamp": string,
       "depthStream": string,
       "payload": object
}

where:

Message Payload

Example

{
    "requestId": "45953af9-e9fc-4809-8974-fb1badc022ee",
    "type": "Level2",
    "exchangeTimestamp": "2018-06-08T08:13:46.653000",
    "caspianTimestamp": "2018-06-08T08:13:46.683000",
    "depthStream": "connected",
    "payload": [
        {
            "price": 74999,
            "size": 2,
            "side": "ask"
        },
        {
            "price": 74681,
            "size": 0.55,
            "side": "bid"
        },
        {
            "price": 73101,
            "size": 0,
            "side": "bid"
        }
    ]
}

[
   {
       "price": double,
       "size": double,
       "side": string
   }
]

where:

TokenRefreshResponse

Description
Sent by the service to confirm the status of a TokenRefresh request.
Message Payload

Example

{
    "requestId": "96113dcc-734d-42d3-b347-965a4218e0a2",
    "type": "TokenRefreshResponse",
    "payload": {
        "code": 200,
        "message": "All OK"
    }
}

{
       "code": int,
       "message": string
}

where:

Reference Data

Exchanges

Description

An endpoint to return all available exchanges.

Request

Request URL: https://sandbox.api.caspian.tech/v1/refdata/exchanges
Request Method: GET

Possible responses

Success

Status Code: 200
Content-Type: application/json
Content:

Example response:

[
  {
    "name": "BitMEX",
    "code": "BITMEX"
  },
  {
    "name": "Coin Market Cap",
    "code": "COINMKTCAP"
  },
  {
    "name": "Gemini",
    "code": "GEMINI"
  }
]

[
  {
     "name:" string,
     "code:" string
  },
  {
     "name:" string,
     "code:" string
  },
    ...
  {
     "name:" string,
     "code:" string
  }
]

Where:

Internal Server Error

Here is a sample of a response:

{
  "code": 5001,
  "message": "Could not access the database"
}

Meaning: The request is properly formatted but the server was unable to fulfill it due to an internal error.
Status Code: 500
Content-Type: application/json
Content:
{
       "code": int,
       "message": string
}

Products

Description

An endpoint to return all products of a certain exchange.

Request

Request URL: https://sandbox.api.caspian.tech/v1/refdata/products
Request Method: POST
Content-Type: application/json
Content:

Example:

{
    "exchanges": ["GEMINI"]
} 

{
     "exchanges": [
      string
    ]
}

where:

Response

Success

Status Code: 200
Content-Type: application/json
Content:

Here is a sample of Success response:

[
  {
    "caspianCode": "FX-ETH/USD=GEMINI",
    "ccyFrom": "ETH",
    "ccyTo": "USD",
    "toraMarket": "FX.NULL.FOREX.GEMINI.NUL",
    "toraCode": "FX.NULL.FOREX.GEMINI.NUL.ETHUSD",
    "description": "Ethereum - US Dollar - FX pair",
    "lotSize": "0.000001",
    "nativeCode": "ethusd",
    "tickRule": ",,0.01",
    "pseudoCode": "ETHUSD=GEMINI",
    "createdTime": "2018-01-18T03:13:55.000000",
    "updatedTime": "2019-11-28T15:56:30.204000",
    "exchange": "GEMINI"
  }
]

[
  {
       "toraCode": string,
       "toraMarket": string,
       "caspianCode": string,
       "lotSize": string,
       "pseudoCode": string,
       "createdTime": string,
       "updatedTime": string,
       "ccyFrom": string,        "ccyTo": string,
       "nativeCode": string,
       "tickRule": string,
       "description": string,
       "exchange": string,
       "multiplier": string,
       "lastTradingDate": string,
       "expireDate": string,        "type": string,
       "strike": string,
       "underlyingCaspianCode": string,
       "nativeCode_v2": string
  }
]

Bad Request

Here is a sample of a Bad Request response:

{
  "code": 4001,
  "message": "No exchange specified"
}

Meaning: The request body contains an invalid JSON or it is missing the required attributes.
Status Code: 400
Content-Type: application/json
Content:
{
       "code": int,
       "message": string
}

Internal Server Error

Here is a sample of Internal Server Error response:

{
  "code": 5001,
  "message": "Could not access the database"
}

Meaning: The request is properly formatted but the server was unable to fulfill it due to an internal error.
Status Code: 500
Content-Type: application/json
Content:
{
       "code": int,
       "message": string
}

Details of a product

Description

An endpoint to get the details of a certain product.

Request

Request URL: https://sandbox.api.caspian.tech/v1/refdata/product/${caspianProduct}
Request Method: GET
Content-Type: application/json
Content:

Request example for caspian code "FX-LTC/ETH=GEMINI":

https://sandbox.api.caspian.tech/v1/refdata/product/FX-LTC/ETH=GEMINI

Response

Success

Status Code: 200
Content-Type: application/json
Content:

Here is a sample of Success response:

[ 
  {
    "caspianCode": "FX-LTC/ETH=GEMINI",
    "ccyFrom": "LTC",
    "ccyTo": "ETH",
    "toraMarket": "FX.NULL.FOREX.GEMINI.NUL",
    "toraCode": "FX.NULL.FOREX.GEMINI.NUL.LTCETH",
    "description": "Litecoin - Ethereum - FX pair",
    "lotSize": "1",
    "nativeCode": "ltceth",
    "pseudoCode": "LTCETH=GEMINI",
    "createdTime": "2018-10-13T00:24:04.000000",
    "updatedTime": "2019-11-28T15:56:30.269000",
    "exchange": "GEMINI"
  }
]

[
  {
       "toraCode": string,
       "toraMarket": string,
       "caspianCode": string,
       "lotSize": string,
       "pseudoCode": string,
       "createdTime": string,
       "updatedTime": string,
       "ccyFrom": string,        "ccyTo": string,
       "nativeCode": string,
       "tickRule": string,
       "description": string,
       "exchange": string,
       "multiplier": string,
       "lastTradingDate": string,
       "expireDate": string,        "type": string,
       "strike": string,
       "underlyingCaspianCode": string,
       "nativeCode_v2": string
  }
]

Bad Request

Here is a sample of a Bad Request response:

{
  "code": 4001,
  "message": "No product specified"
}

Meaning: The request body contains an invalid JSON or it is missing the required attributes.
Status Code: 400
Content-Type: application/json
Content:
{
       "code": int,
       "message": string
}

Internal Server Error

Here is a sample of Internal Server Error response:

{
  "code": 5001,
  "message": "Could not access the database"
}

Meaning: The request is properly formatted but the server was unable to fulfill it due to an internal error.
Status Code: 500
Content-Type: application/json
Content:
{
       "code": int,
       "message": string
}

Changelog

All notable changes to this project are documented here.

2020-06-10

Added

2019-02-20

Added

Changed

FAQ

There might be 2 causes for this:

1) There is a heartbeat mechanism. The server will send ping frames that should be handled at client level library.
In case PINGs are not acknowledge, the session will get disconnected. Make sure those pings are handled,
otherwise is needed to handle the PING frames and acknowledge them with PONG frames.

2) Slow clients are disconnected as a result of the threshold setted for accumulated messages.

Please discuss this with your Caspian representative.

Supported exchanges: Binance, Bitfinex, Bitflyer, Bithumb, Bitmex, Bitstamp, Bittrex, BTCC, CEX, Coinbase Pro (GDAX),
CoinOne, Deribit, Gemini, Hitbtc, Huobi, ItBit, Korbit, Kraken, Kucoin, Liquid, OKEx, Poloniex

The API is down on Sunday between 00:15 and 00:16 GMT.

Every timestamp is represented as GMT.

Please discuss these details with your Caspian representative.

The access token expires after 24 hours. You have to obtain a new access token following the steps described in section
Authentication - REST

New fields could be added without prior notice. The implementation should be resilient to such changes.

For questions not covered in this FAQ please send an email to api@caspian.tech.

Errors

The Caspian API uses the following error codes:

Error Code Meaning
100 Request not properly formatted as JSON
101 No requestId found in the message
102 No type found in the message
103 Unknown type
104 No accessToken found in the message
105 No subscribeRequestId found in the message
199 Server could not process the request
200 All OK
201 Duplicated Request ID
202 Invalid subscription symbol
203 Invalid subscription type
204 Another subscription already exists
205 Not authorized
206 Subscription limit reached
207 Invalid symbol type
208 Invalid number of levels
209 Symbol type not currently supported
300 All OK
301 Subscription not found
302 Duplicated requestId
400 Bad Request
401 Unauthorized
500 Internal Server Error
3000 Access token not found
3001 Supplied token is not valid
3002 Token has expired
3003 The handler for this session was not found
3004 Internal issue
3006 Pong message not received
3007 Message queue limit reached
4000 Request is not properly formatted
4001 Authentication type not found
4002 Authentication details not found
4003 Unsupported authentication type