The Fenix Pipeline API provides REST and websockets endpoints to facilitate retrieving data from the Fenix Pipeline.
The following should be considered when using the SDK:
- The Fenix Pipeline API requires an authentication token. Tokens are currently only available to select beta customers.
Two headers are required on every request:
- API version
- authorization token
All requests to the API require a version specification. This can be passed in a header named x-api-version
. If the values passed is currently supported, the request will continue. A curl
example would be:
$ curl -X GET -H "x-api-version: beta" https://api.fenixblockchain.com/exchanges
Requests that fail the version check will return the following error:
- 412 (precondition failed): the version passed is not currently supported by the API
If using query parameters for the version, use the api-version
parameter:
$ curl -X GET -H https://api.fenixblockchain.com/exchanges?api-version=beta
All requests to the API require an authentication token. This can be passed in a header named authorization
with a value of bearer <TOKEN VALUE>
. A curl
example would be:
$ curl -X GET -H "authorization: bearer abc:12345" https://api.fenixblockchain.com/exchanges
Requests that fail authentication will return an error from the following list:
- 401 (unauthorized): the server could not find the
authorization
header or the bearer-type was notbearer
- 403 (forbidden): the
authorization
header was found but the token value was improperly formed or contained invalid credentials
If using query parameters for the authentication token, use the auth-token
parameter:
$ curl -X GET -H https://api.fenixblockchain.com/exchanges?auth-token=abc:12345
Note: DO NOT USE THIS QUERY PARAMETER IN THE BROWSER. This method is vulnerable to accidental reveal to any browser extension that monitors the URLs you visit. This is a convenience only for languages that do not support headers in web requests (JavaScript WebSocket, for instance). This behavior will change in the next version of the API to support single-use, time limited authentication tokens that can be passed safely as query parameters without concern.
The REST API contains the following endpoints:
/
: basic API details/exchanges
: a list of exchanges currently active in the Fenix Pipeline/exchanges/<name>
: details for a specific exchange/markets
: a list of markets currently active in the Fenix Pipeline
Note: In many examples below, responses are trimmed for clarity. Trimmed data is replaced by ...
on a line by itself.
The /
endpoint does not return data.
The /exchanges
endpoint returns a list of exchanges being actively collected by Fenix:
Request: GET > /exchanges
Response (trimmed):
[
{
"name": "bibox",
"display_name": "bibox",
"enabled": true
},
{
"name": "binance",
"display_name": "binance",
"enabled": true
},
...
]
The /exchanges/<exchange_name>
endpoint returns more details about that exchange:
Request: GET > /exchanges/binance
Response (trimmed):
{
"name": "binance",
"display_name": "binance",
"enabled": true,
"markets": [
"ada-bnb",
"ada-btc",
"ada-eth",
...
"btc-busd",
"btc-pax",
"btc-tusd",
"btc-usdc",
"btc-usds",
"btc-usdt",
...
"eth-btc",
"eth-pax",
"eth-tusd",
"eth-usdc",
"eth-usdt",
...
]
}
The /markets
endpoint returns a list of markets being actively collected on at least one exchange and which exchange(s) are collecting it:
Request: GET > /markets
Response (trimmed):
[
{
"name": "ada-bnb",
"exchanges": [
"binance"
]
},
...
{
"name": "btc-busd",
"exchanges": [
"binance"
]
},
...
{
"name": "btc-eur",
"exchanges": [
"bitstamp",
"coinbase",
"livecoin"
]
},
...
{
"name": "btc-usd",
"exchanges": [
"bitstamp",
"bittrex",
"coinbase",
"hitbtc",
"livecoin",
"yobit"
]
},
...
{
"name": "btc-usdt",
"exchanges": [
"bibox",
"binance",
"bittrex",
"huobi",
"kucoin",
"livecoin",
"poloniex"
]
},
...
]
The websockets data feeds are available at https://api.fenixblockchain.com/ws
. All messages to the socket and all responses and data from the socket are described below.
Once connected, you can send a subscribe
request to subscribe to a given channel.
{"request": "subscribe", "channel": "<channel>"}
You can get trade data in three basic subscription types. Each of these types is selectable from the SubscriptionTypes
enum:
trades/exchange/<name>
: all trades on any market within a certain exchangetrades/market/<name>
: all trades from any exchange associated with a specific market (such asbtc-usdt
)trades/all
: every received trade regardless of market and regardless of exchange
To subscribe to all trades:
{"request": "subscribe", "channel": "trades/all"}
Note: the trades/all
subscription will contain a very large number of trades; ensure your code is performant and your network connection is sufficient to avoid losing data in the stream.
To subscribe to all trades within a given market (in this example, BTC-USDT):
{"request": "subscribe", "channel": "trades/market/btc-usdt"}
To subscribe to all trades coming from a given exchange (in this example, Binance):
{"request": "subscribe", "channel": "trades/exchange/binance"}
After sending a subscription request, a message will be sent back confirming the channel has been successfully subscribed:
{"type": "subscribed", "message": "trades/exchange/binance" }
You should then begin receiving trade data from that exchange in the stream (the format of this data is described later).
If you send an invalid channel reference:
{"request": "subscribe", "channel": "trades/market/btc-%"}
... you will receive an error:
{"type": "error", "message": "trades/market/btc-% invalid"}
Unsubscribing from channels is exactly like subscribing but sending unsubscribe
request:
{"request": "unsubscribe", "channel": "trades/exchange/binance"}
After sending an unsubscribe request, a message will be sent back confirming the channel has been successfully unsubscribed:
{"type": "unsubscribed", "message": "trades/exchange/binance" }
If you send a reference to a channel you are not subscribed to:
{"request": "unsubscribe", "channel": "trades/market/btc-eudt"}
... you will receive an error:
{"type": "error", "message": "trades/market/btc-eudt not subscribed" }
Apart from subscribe
, unsubscribe
, and error
messages described above, the messages received from the API will depend on the type of object being transferred. Currently only trade
entities are supported; other types will be added in the future.
Trade data will be received as a json package with a key type
containing the value data
and a channel starting with trades:
:
{
"type": "data",
"message": {
"channel": "trades:btc-usdt:binance",
"data": {
"exchange": "kucoin",
"market": "btc-usdt",
"euid": "12345",
"direction": "sell",
"price": 8145.35,
"quantity": 0.003646,
"timestamp": 1570588205.321,
},
},
}
Schema notes:
exchange
: the exchange where the trade was effectedmarket
: the market the trade encompasseseuid
: the unique ID as reported by the exchange for that trade- the combination of
exchange
,market
, andeuid
is globally unique amongst all trades in the API
- the combination of
direction
:buy
orsell
price
: the price per unit of the tradequantity
: the quantity tradedtimestamp
: a timestamp in seconds since the epoch with millisecond resolution
Close the connection by sending a close
request:
{"request": "close"}
Note: the close
request is not required; you can alternately just close the socket.
If the server needs to terminate the connection, it will make a best-effort to send a termination message:
{"type": "!", "message": "closing connection"}
Note: it is not guaranteed that this message will be successfully sent prior to a connection being terminated.
Note that subscriptions may include overlapping data. For instance, if you subscribe to all trades on the btc-usdt
market and also all trades on the binance
exchange, trades that take place on Binance related to the BTC-USDT market may appear twice in the output stream. This will change in a future version of the API so that each trade will only ever appear once.
Duplicates can be recognized by comparing the unique combination of exchange
, market
, and euid
; these three properties together form a natural key for each record.