Current API version: 0.8 (last modified on 9 Aug 2018).

Introduction

Market data API

Sample

Endpoint

Market Data Request

Depth of market

Stream

Subscribe message sample

Snapshot

Sample

Increment

Sample

Last trades

Stream

Subscribe message sample

Snapshot

Sample

Increment

Sample

Candles

Stream

Subscribe message sample

Snapshot

Sample

Increment

Sample

Static data

Symbols

Endpoint

Response

Example

Trading API

Flow

Endpoint

Authentication

Code snippets

Logging in

Logon message

Sample

Logon message response

Sample

Requesting the active orders snapshot

Order Mass Status Request

Sample

Order Mass Status Response

Sample

Balance updates

Samples

Snapshot

Update

Sending orders

New order single

Sample

Cancelling orders

Order Cancel Request

Sample

Order Cancel Reject

Sample

Execution reports

Order status matrices

Execution report

Sample

Transfers API

Endpoint

Authentication

Requesting account list

Retrieving deposit address

Obtaining and renewal of deposit address

Retrieving balance information

Retrieving list of trusted addresses

Creating withdrawal requests

Retrieving list of active withdrawal requests

Withdrawal request statuses

Retrieving list of active deposits

Deposit statuses

Introduction

There are two dedicated websocket endpoints for trading and market data.

Both APIs use messages and flows are based on FIX 5.0 SP2+, with slight changes.

For example, the message MarketDataSnapshotFullRefresh

Field name

Field tag

MsgType

35

Repeating group MdFullGrp

NoMDEntries

268

FirstPx

1025

is serialized as follows:

{ “35”: “W”, “268”: [ { “1025”: “3.20” }, { “1025”: “3.22” } ] }

Market data API

All market data feeds work with concept of streams:

  1. Send Market Data Request with the name of the stream.
  2. API responds with Market Data Snapshot Full Refresh message containing the snapshot of the data for the requested stream, e.g. current state of the order book.
  3. API sends Market Data Incremental Refresh messages that containing updates.
  4. Send Market Data Request to unsubscribe from the stream.

Once connected, the market data API sends the initial Logon message:

Field

Tag

Type / possible values

Description

MsgType

35

M

A (Logon)

SendingTime

52

M

Long — Unix timestamp in nanoseconds

CstmApplVerID

1129

M

String

Current API version

Sample

{

"1129":"1.0",

"35":"A",

"52":1520433521222952779

}

Endpoint

/api/ws/market-data

Market Data Request

Field

Tag

Type / possible values

Description

MsgType

35

M

V (Market Data Request)

MDStreamID

1500

M

String

SubscriptionRequestType

263

M

int

1 SnapshotAndUpdates (to subscribe)

2 DisablePreviousSnapshot (to unsubscribe)

ThrottleType

1612

O

int

1 InboundRate

Use these 3 fields to enable throttling. Time interval is defined in milliseconds. If the fields are not present, throttling is disabled.

Throttling is now supported only for the depth of market channel.

ThrottleTimeInterval

1614

O

int

500

5000

ThrottleTimeUnit

1615

O

int

3 Milliseconds

Depth of market

Stream

MDStreamID: “DOM:<symbol>:<aggregation>”

<aggregation>: only “aggregated” is supported now. Later “orderlog” and “bbo” will be added.

Subscribe message sample

{

"35":"V",

"263":1,

"1500":"DOM:BTC/USDT:aggregated",

“1612”: 1,

“1614”: 500,

“1615”: 3

}

Snapshot

Field

Tag

Type / possible values

Description

MsgType

35

M

W (Market Data Snapshot Full Refresh)

MDStreamID

1500

M

String

LastUpdateTime

779

M

Long — Unix timestamp in nanoseconds

Symbol

55

M

String

MDBookType

1021

M

int

2 Price Depth

MDFullGrps

268

O

Array of MDEntry

Will be omitted in case of empty book.

MDEntry

MDEntryType

269

M

String

0 Bid

1 Offer

MDEntryPx

270

M

Decimal

Price level.

MDEntrySize

271

M

Decimal

Total volume at the given price level.

NumberOfOrders

346

M

int

Sample

{

"1021":2,

"1500":"DOM:BTC/USDT:aggregated",

"268":

[

{

"269":"0",

"270":"43.2",

"271":"20.444",

"346":2

},

{

"269":"0",

"270":"6000",

"271":"1",

"346":1

}

],

"35":"W",

"55":"BTC/USDT",

"779":1520415867338061271

}

Increment

Note that depth of market increments are throttled and sent once in 100 ms.

Field

Tag

Type / possible values

Description

MsgType

35

M

X (Market Data Incremental Refresh)

MDStreamID

1500

M

String

LastUpdateTime

779

M

Long — Unix timestamp in nanoseconds

MDBookType

1021

M

2 Price Depth

MDIncGrps

268

M

Array of MDEntry

MDEntry

MDUpdateAction

279

M

0 New

1 Change

2 Delete

Symbol

55

M

String

MDEntryType

269

M

0 Bid

1 Offer

MDEntryPx

270

M

Decimal

Price level.

MDEntrySize

271

C

Decimal

New total volume at the given price level.

Conditionally required when MDUpdateAction <> Delete.

NumberOfOrders

346

C

int

New number of orders at the given price level.

Conditionally required when MDUpdateAction <> Delete.

Sample

TODO

Last trades

Stream

MDStreamID: “trades:<symbol>”

Subscribe message sample

{

"35":"V",

"263":1,

"1500":

"trades:BTC/USDT"

}

Snapshot

Field

Tag

Type / possible values

Description

MsgType

35

M

W (Market Data Snapshot Full Refresh)

MDStreamID

1500

M

String

LastUpdateTime

779

M

Long — Unix timestamp in nanoseconds

Symbol

55

M

String

MDFullGrps

268

O

Array of MDEntry

Contains last 50 trades. Omitted if there are no trades.

MDEntry

MDEntryType

269

M

String

2 Trade

MDEntryPx

270

M

Decimal

Trade price.

MDEntrySize

271

M

Decimal

Trade volume.

AggressorSide

1501

M

int

1 Buy

2 Sell

Non-standard FIX tag.

The side of the trade.

Sample

{

"1500":"trades:BTC/USDT",

"268":

[

{

"1003":"8ed851f8-996a-45f6-a235-a5432953154e",

"1501":2,

"269":"2",

"270":"10494",

"271":"0.151",

"279":"0",

"60":1520425569334963219

},

{

"1003":"9ab4c9c8-f585-440c-a0d7-42460d679999",

"1501":2,

"269":"2",

"270":"10494",

"271":"1.779",

"279":"0",

"60":1520425629340376980

}

],

"35":"W",

"779":1520430075750254187

}

Increment

Field

Tag

Type / possible values

Description

MsgType

35

M

X (Market Data Incremental Refresh)

MDStreamID

1500

M

String

LastUpdateTime

779

M

Long — Unix timestamp in nanoseconds

MDIncGrps

268

M

Array of MDEntry

MDEntry

MDEntryType

269

M

String

2 Trade

MDEntryPx

270

M

Decimal

Trade price.

MDEntrySize

271

M

Decimal

Trade volume.

AggressorSide

1501

M

int

1 Buy

2 Sell

Non-standard FIX tag.

The side of the trade.

Sample

TODO

Candles

Stream

MDStreamID: “candles:<symbol>:<timeframe>”

Supported timeframes: 1m, 5m, 15m, 30m, 1h, 3h, 6h, 12h, 1d.

Subscribe message sample

{

"35":"V",

"263":1,

"1500":"candles:BTC/USDT:1m"

}

Snapshot

Field

Tag

Type / possible values

Description

MsgType

35

M

W (Market Data Snapshot Full Refresh)

MDStreamID

1500

M

String

LastUpdateTime

779

M

Long — Unix timestamp in nanoseconds

Symbol

55

M

String

MDFullGrps

268

O

Array of MDEntry

Contains last 100 candles. Omitted if no data.

MDEntry

FirstPx

1025

M

Decimal

HighPx

332

M

Decimal

LowPx

333

M

Decimal

LastPx

31

M

Decimal

BuyVolume

330

M

Decimal

SellVolume

331

M

Decimal

TransactTime

60

M

Long — Unix timestamp in nanoseconds

Candle open timestamp.

Sample

{

"1500":"candles:BTC/USDT:1m",

"268":

[

{

"1025":"10502",

"31":"10502",

"330":"0",

"331":"0",

"332":"10502",

"333":"10502",

"60":1520403420000000000

},

{

"1025":"10502",

"31":"10502",

"330":"0",

"331":"0.225",

"332":"10502",

"333":"10502",

"60":1520403480000000000

}

],

"35":"W",

"779":1520430420000000000

}

Increment

Field

Tag

Type / possible values

Description

MsgType

35

M

X (Market Data Incremental Refresh)

MDStreamID

1500

M

String

LastUpdateTime

779

M

Long — Unix timestamp in nanoseconds

Symbol

55

M

String

MDIncGrps

268

M

Array of MDEntry

Contains last 100 candles.

MDEntry

FirstPx

1025

M

Decimal

HighPx

332

M

Decimal

LowPx

333

M

Decimal

LastPx

31

M

Decimal

BuyVolume

330

M

Decimal

SellVolume

331

M

Decimal

TransactTime

60

M

Long — Unix timestamp in nanoseconds

Candle open timestamp.

Sample

{

"1500":"candles:BTC/USDT:1m",

"268":

[

{

"1025":"10494",

"31":"10494",

"330":"0",

"331":"0",

"332":"10494",

"333":"10494",

"60":1520433480000000000

}

],

"35":"X",

"779":1520433480000000000

}


Static data

Information about symbols can be obtained with the Market Data Rest API.

Symbols

Endpoint

GET /api/market-data/symbols

Response

Field

Tag

Type / possible values

Description

Symbols

555

M

Array of SymbolInfo

SymbolInfo

Currency

15

M

String

Base currency

QuoteCurrencyName

1524

M

string

Quote currency

SecurityID

48

M

String

Internal ID of the instrument

Symbol

55

M

String

Symbol name

MinPriceIncrement

969

M

int

Pip scale: 1 means 1 decimal point in the price (7843.3), 2 means 2 points (342.44), -1 means the point value is 10 and so on.

LimitOrderMaxDistance

970

O

decimal

Maximal distance from the mid price ((Bid + Ask) / 2) for limit orders. 0.3 means orders can be placed within the range of 70% and 130% of the current mid price. 0 or null value means there is no restrictions.

MinOrderQty

1146

M

decimal

Minimal quantity of an order

OrderQtyStep

1147

M

decimal

Quantity step

Example

{

555”: [

{

15”: "BTC",

48”: "100",

55”: "BTC/USDT",

969”: 1,

970”: "0.5",

1146”: "0.001",

1147”: "0.001",

1524”: "USDT"

},

        ]

}

Trading API

Flow

  1. Send Logon message with the list of desired accounts.
  2. API will respond with Logon message and start sending execution reports and balance information related to all the requested accounts in real-time.
  3. Send OrderMassStatusRequest to get the snapshot of open orders.
  4. Send NewOrderSingle to submit a new order.
  5. Send Order Cancel Request to cancel an existing order.

Endpoint

/api/ws/trading

Authentication

To connect to the Trading API you need keys. A key consists of two fields: API Key (ID of the key) and API Secret (the private key for the ECSDA algorithm, curve NIST P256, format RFC 5915). XENA keeps only the respective public key to verify auth signatures. One key may give access to several accounts.

To authorize, one you need to send following information in the Logon message:

r, s = ECDSA(SHA256(Auth payload))

Auth signature = HEX([r bytes, s bytes])

Learn how to obtain keys for API.

Code snippets

Examples of signature generation:

Logging in

Logon message

The first message to be sent after the websocket is opened is Logon:

Field

Tag

Type / possible values

Description

MsgType

35

M

A (Logon)

Accounts

1

M

Array of int

List of accounts to trade on

Username

553

M

String

API Key

SendingTime

52

M

Long — Unix timestamp in nanoseconds

Nonce

RawData

96

M

String

“AUTH<nonce>”

Password

554

M

String

Signature

Sample

{

"1":[1,2],

"35":"A",

“553”: “”,

“52”: …,

“96”: “”,

“554”: “”

}

Logon message response

Field

Tag

Type / possible values

Description

MsgType

35

M

A (Logon)

Accounts

1

M

Array of int

List of accounts

SendingTime

52

M

Long — Unix timestamp in nanoseconds

SessionStatus

1409

M

String

0 (SessionActive)

5 (InvalidUsernameOrPassword)

6 (AccountLocked)

RejectText

1328

O

String

Reason for logon failure

Sample

{

"1":[1,2],

"1409":"0",

"35":"A",

"52":1520415869093505337

}

Requesting the active orders snapshot

Order Mass Status Request

Field

Tag

Type / possible values

Description

MsgType

35

M

AF (OrderMassStatusRequest)

Account

1

M

int

Sample

{

"1":1,

"35":"AF"

}

Order Mass Status Response

Field

Tag

Type / possible values

Description

MsgType

35

M

U8 (Order Mass Status Response)

Account

1

M

int

Orders

1268

M

Array of Execution Reports

Active orders (New, Partially filled)                

Fills

1269

M

Array of Execution Reports

30 last history orders (Filled, Partially filled)

Sample

TODO

Balance updates

After authorizing, API will send snapshot of account balance and all changes of the balance.

Each balance object may contain information about the client’s position in the currency of the balance. Position information is calculated in two base currencies — BTC and USDT.

Field

Tag

Type / possible values

Description

MsgType

35

M

XAR (Account Status Report Snapshot)

XAF (Account Status Report Incremental Refresh)

Account

1

int

LastUpdateTime

779

Long — Unix timestamp in nanoseconds

Repeating group Balance (1800)

Currency

15

M

String

AvailableBalance

1801

M

decimal

Available = Settled - Locked

LockedBalance

1802

M

decimal

Balance locked in orders

SettledBalance

1803

M

decimal

Balance of the account

Repeating group PositionInfo (1804), inside the Balance group, optional field

Currency

15

M

string

Position calculation currency

AvgPx

6

M

decimal

Position open price

PositionId

2618

M

int

PositionOpenDate

1805

M

Long — Unix timestamp in nanoseconds

RealizedPL

1806

M

decimal

Samples

Snapshot

{

"1":15,

"1800": [

{

"15":"BTC",

"1801":"7.5",

"1802":"0",

"1803": "7.5",

"1804": [

{

"15":"USDT",

"1618":130722517,

"1805":1526656273317908000,

"1806":"0",

"6":"7350"

},

{

"15":"BTC",

"1618":130722517,

"1805":1526656273317908000,

"1806":

"0",

"6":"1"

}],

"779":1526656379897959000}]

}],

"35":"XAR",

"779":1523018132051736000

}

Update

{

"1":15,

"1800": [

{

"15":"BTC",

"1801":"7.5",

"1802":"0",

"1803": "7.5"

}],

"35":"XAF",

"779":1523018132051736000

}

Sending orders

New order single

Field

Tag

Type / possible values

Description

MsgType

35

M

D (NewOrderSingle)

ClOrdId

11

M

String, 20 symbols max

ClOrdId must be unique within 24 hours moving frame.

Symbol

55

M

String

Side

54

M

int

1 Buy

2 Sell

SettlType

63

M

String

1 Cash (TOD / T+0)

TransactTime

60

M

Long — Unix timestamp in nanoseconds

OrderQty

38

M

Decimal

OrdType

40

M

string

1 Market

2 Limit

3 Stop

Price

44

C

Decimal

Mandatory for limit orders. Will be omitted for market orders.

Account

1

M

int

TimeInForce

59

O

int

1 Good Till Cancel (default value)

3 Immediate Or Cancel

4 Fill Or Kill

Sample

{

"1":1,

"11":"akBZL9xeQ",

"35":"D",

"38":"1",

"40":”2”,

"44":"10493.5",

"54":1,

"55":"BTC/USDT",

"60":1520424185040000000,

"63":"1"

}

Cancelling orders

Order Cancel Request

Field

Tag

Type / possible values

Description

MsgType

35

M

F (Order Cancel Request)

OrigClOrdID

41

C

String

One of the fields must be submitted.

OrderID

37

C

String / Guid

ClOrdID

11

M

String

ClOrdId must be unique within 24 hours moving frame.

Side

54

M

int

1 Buy

2 Sell

Symbol

55

M

String

TransactTime

60

M

Long — Unix timestamp in nanoseconds

Account

1

M

int

Sample

{

"1":1,

"11":"wOQYGqklK",

"35":"F",

"37":"3975158b-2c25-4d26-acfd-c78921408eb6",

"54":1,

"55":"BTC/USDT",

"60":1520424390152000000

}

Order Cancel Reject

Field

Tag

Type / possible values

Description

MsgType

35

M

9 (Order Cancel Reject)

OrderId

37

O

String / Guid

OrderId of the order being cancelled, if it has been found.

OrigClOrdId

41

O

String

ClOrdId of the order being cancelled, if it has been found, or if OrigClOrdId has been submitted in the request.

ClOrdId

11

M

String

OrdStatus

39

M

2 Filled

4 Cancelled

6 Pending Cancel

8 Rejected — if the order hasn’t been found by OrderId or ClOrdId

Current status of the order being cancelled.

CxlRejResponseTo

434

M

1 Order Cancel Request

CxlRejReason

102

M

0 TooLateToCancel

1 UnknownOrder

3 OrderAlreadyInPendingStatus

6 DuplicateClOrdID

99 Other

RejectText

1328

O

String

Reject reason.

TransactTime

60

M

Long — Unix timestamp in nanoseconds

Account

1

M

int

Sample

TODO

Execution reports

Order status matrices

Link

Execution report

Field

Tag

Type / possible values

Description

MsgType

35

M

8 (ExecutionReport)

OrderId

37

M

String / Guid

ClOrdId

11

M

String

OrigClOrdId

41

O

String

ClOrdId of the order being cancelled, if OrigClOrdId has been submitted in the request.

TradeId

1003

C

int

Conditionally required when ExecType = Trade

Symbol

55

M

String

ExecType

150

M

0 New

F Trade

4 Cancelled

According to order status matrices.

OrdStatus

39

M

0 New

1 Partially Filled

2 Filled

4 Cancelled

According to order status matrices.

Side

54

M

int

1 Buy

2 Sell

OrdType

40

M

int

1 Market

2 Limit

3 Stop

Price

44

C

Decimal

Conditionally required for limit orders.

OrderQty

38

M

Decimal

According to order status matrices.

LeavesQty

151

M

Decimal

According to order status matrices.

CumQty

14

M

Decimal

According to order status matrices.

LastQty

32

C

Decimal

According to order status matrices.

Conditionally required when ExecType is Trade.

LastPx

31

C

Decimal

Conditionally required when ExecType is Trade.

CalculatedCcyLastQty

1056

C

Decimal

Net payment of the fill, not including commission.

Conditionally required when ExecType is Trade.

NetMoney

118

C

Decimal

Gross amount of the fill, including commission.

Conditionally required when ExecType is Trade.

TransactTime

60

M

Long — Unix timestamp in nanoseconds

Timestamp of the event.

LastLiquidityInd

851

C

1 AddedLiquidity

2 RemovedLiquidity

Conditionally required when ExecType is Trade.

Commission

12

O

Decimal

CommCurrency

479

O

String

Account

1

M

Int

Currency

15

M

String

Pair base currency

SettlCurrency

120

M

String

Pair quote currency

SettlType

63

M

1 Cash (TOD / T+0)

Sample

{

"1":1,

"11":"9Naow8V5b",

"14":"0",

"150":"0",

"151":"1",

"17":"8ddc1450-5c26-4a6c-9e21-d7a46756bf8c",

"18":null,

"32":"0",

"35":"8",

"37":"a5012f7f-be4c-4f25-9418-1f99c7af5175",

"38":"1",

"39":"0",

"40":2,

"44":"6000",

"54":1,

"55":"BTC/USDT",

"60":1519897377377284246

}


Transfers API

Transfers API allows automation of deposits and withdrawals to your account.

Endpoint

Transfers API is a REST API. All its methods are accessible by the following endpoint:

/api/transfers/...

Authentication

Authentication requires the same information as the Trading API. Instead of sending some initial message like Logon, each call to the REST Transfers API must contain 4 HTTP headers:

Nonce (UNIX nanoseconds timestamp) must be unique for each request and not older than 60 seconds.

Learn how to get keys for API.

Requesting account list

The method returns array of accounts to which the API Key has access with the scope “transfers”.

GET /accounts

Response:

[10832434,10834231]

Retrieving deposit address

GET /accounts/{accountId}/deposit-address/{currency}

Response:

{

"address":"mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9",

"uri":"bitcoin:mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9?message=Xena Exchange",

“allowsRenewal”: true

}

The method returns HTTP status code 404 (Not Found) if there is no active address for the requested account and currency.

“allowsRenewal” indicates whether the address may be renewed by the client or whether it is permanent.

Obtaining and renewal of deposit address

POST /accounts/{accountId}/deposit-address/{currency}

Response:

{

"address":"mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9",

"uri":"bitcoin:mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9?message=Xena Exchange",

“allowsRenewal”: true

}

Retrieving balance information

GET /accounts/{accountId}

Response:

{

"balances": [

{

"available":"9.999",

"onHold":"0",

"currency":"BTC"

},

...

]

}

Retrieving list of trusted addresses

It is possible to withdraw funds only through trusted addresses via the API. The method returns the list of such addresses for all currencies for the given account.

GET /accounts/{accountId}/trusted-addresses

Response:

{

        “trustedAddresses”: [

                {

                        “address”: “mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9”,

                        “blockchain”: “ETH”,

                        “currency”: “ETH”

},

...

]

}

Creating withdrawal requests

It is possible to withdraw funds only through trusted addresses via the API. Two factor authentication is skipped for requests created through the API.

POST /accounts/{accountId}/withdrawals

Body:

{

        “address”: “mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9”,

        “amount”: “10.2”,

        “сurrency”: ”ETH”,

        “id”: ”.....”        // mandatory external ID (string), used by the client to identify his request

}

Response:

{

        “withdrawalRequestId”: 47383243,

“status”: 1,

        “statusMessage”: “Pending confirmation”

}

In case of a bad request the response has the HTTP status code 400 and error description in its body:

{

        “error”: “Description of the error”,

        “fields”: [“...”, “...”] - optional

}

fields” array contains the names of the fields that have not passed the validation.

Retrieving list of active withdrawal requests

The method returns active requests and requests completed within last 24 hours.

GET /accounts/{accountId}/withdrawals

Response:

{

        “withdrawals”: [

                {

        “withdrawalRequestId”: 47383243,

        “externalId”: “...”,        // external ID submitted by the client when creating the request

        “status”: 1,

“statusMessage”: ”Pending confirmation”,

        “amount”: “10.2”,

        “currency”: “BTC”,

        “lastUpdated”: <UNIX nanoseconds>,

                “blockchain”: “Bitcoin”,

                “address”: “mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9”,

                “txId”: “0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98”

}

        ]

}

Withdrawal request statuses

Status

Status Message

1

New

2

Completed

3

Duplicate

4

Not enough money

5

Waiting for manual approval by XENA

100, 101, 102, 103

Request is being processed

Retrieving list of active deposits

Returns active deposits and deposits completed within last 24 hours.

GET /accounts/{accountId}/deposits

Response:

{

        “deposits”: [

                {

                        “currency”: “BTC”,

                        “amount”: “1.2”,

                        “status”: 1,

                        “statusMessage”: “Processing”,

“blockchain”: “Bitcoin”,

                        “txId”: “0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98”,

                        “address”: “mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9”,

                        “lastUpdated”: <UNIX nanoseconds>

                        “confirmations”: 2,

                        “requiredConfirmations”: 6

}

]

}

Deposit statuses

Status

Status Message

1

New

2

Completed


Managing API keys

To create new keys for API sign in to your XENA account and navigate to the API Keys section.

Each key gives access one or two scopes: