FIX API
Introduction
FIX is a robust, reliable, and time-proven way for market participants to exchange requests to buy/sell certain assets, market data streaming, control settlement process, and many other things.
For more information and supporting materials on the FIX protocol, please refer to the FPL website, http://www.fixprotocol.org
Axon Trade uses a slightly modified specification of FIX 4.4 in order to facilitate both market data streaming and trading activities. Below are the links on ready-to-use dictionaries for popular FIX engines:
Axon Trade provides two types of sessions - trading and market data with their own set of messages. Each session requires authentication, and, depending on the configuration might enforce SSL usage.
We offer a demo environment that can be used during the integration stage and code samples for several FIX engines and programming languages: https://bitbucket.org/axon-trade/axon_demos/src/master/
Maintenance
Our goal is to provide the best possible service to our customers and it's impossible without constant changes and improvements on our end.
In order to create predictability, we chose a small ten minutes window that should be enough for us to deploy new changes and install security patches.
Both market data and trading sessions are subject to scheduled restarts and might not be available for up to 10 minutes each day.
Below are the maintenance schedules for all current locations:
Datacenter | Start Time | End Time |
---|---|---|
LD4 | 02:00 UTC | 02:10 UTC |
NY4 | 08:00 UTC | 08:10 UTC |
TY8 | 09:00 UTC | 09:10 UTC |
Market Data Session
Market Data session uses to transmit books updates from the Axon Trade servers back to the client.
In order to optimize bandwidth, books updates are delivered in a form of incremental changes between books states.
The correct workflow includes receiving the initial book(s) state followed by applying incoming changes. These changes are self-explanatory:
- NEW: add a new level in the book
- UPDATE: change size available on a particular price level
- DELETE: remove price level from the book
Workflow
Messages Structure
The Feed server is using a slightly modified FIX 4.4. specification(see Market Data Incremental Refresh).
Header
Example:
Field Name
Example
BeginString
8=FIX4.4
BodyLength
9=502
MsgType
35=A
SenderCompID
49=COMPANY_NAME
TargetCompID
56=AXON-MD-NY4-1
MsgSeqNum
34=1000123
SendingTime
52=2018-08-02T03:30:30.658
Tag | Field Name | Required | Comments |
---|---|---|---|
8 | BeginString | Y | Identifies the beginning of the message and represents the Transmission Protocol version. Supported values:
|
9 | BodyLength | Y | Message length (number of bytes) forward to the CheckSum tag. |
35 | MsgType | Y | Defines message type e.g. Logon(A) |
49 | SenderCompID | Y | Assigned value used to identify sender of a message |
56 | TargetCompID | Y | Assigned value used to identify receiving firm Supported values:
|
34 | MsgSeqNum | Y | Integer message sequence number |
52 | SendingTime | Y | Time of message transmission (always expressed in UTC (Universal Time Coordinated, also known as "GMT") |
Footer
Example:
Field Name
Example
CheckSum
10=250
Tag | Field Name | Required | Comments |
---|---|---|---|
10 | CheckSum | Y | Three bytes, simple checksum |
Messages
Logon
Example:
Field Name
Example
EncryptMethod
89=0
HeartBtInt
108=5
ResetSeqNumFlag
141=Y
Username
553=account_1
Password
554=StR0nG_P
MsgType: A
Direction: IN/OUT
Description: Logon should be sent as a very first message to establish FIX session and pass authentication process. In the case of successful authentication, server will respond with corresponding Logon message.
Tag | Field Name | Required | Comments |
---|---|---|---|
98 | EncryptMethod | Y | Supported Values:
|
108 | HeartBtInt | Y | 108=5 |
141 | ResetSeqNumFlag | N | Indicates both sides of a FIX session should reset sequence numbers |
553 | Username | Y | Session Username Required for Outgoing message |
554 | Password | Y | Session Password Required for Outgoing message |
Logout
Example:
Field Name
Example
Text
58=Incorrect Username or Password
MsgType: 5
Direction: IN/OUT
Description: Logout message is used as a confirmation.
Tag | Field Name | Required | Comments |
---|---|---|---|
58 | Text | N | Disconnection reason in human-readable format Please note, that this field might be absent |
SecurityListRequest
Example:
FieldName
Example
SecurityReqID
320=REQ_1
SecurityListRequestType
559=0
SecurityExchange
207=HUOBI
MsgType: x
Direction: OUT
Description: this message is used to receive a list of all tradable instruments on a particular exchange.
Tag | FieldName | Required | Comments |
---|---|---|---|
320 | SecurityReqID | Y | Unique request ID |
559 | SecurityListRequestType | Y | Type of request being performed by a counterparty. Supported values:
|
207 | SecurityExchange | Y | Exchange name to extract a list of all instruments |
SecurityList
Example:
FieldName
Example
SecurityReqID
320=REQ_1
SecurityResponseID
SecurityRequestResult
560=0
TotNoRelatedSym
393=51
LastFragment
893=false
Text
58=Exchange ABC not found
NoRelatedSym
146=1
Symbol
55=ETH/BTC
SecurityExchange
207=HUOBI
Price Precision
5001=8
Size Precision
5002=4
MsgType: y
Direction: IN
Description: this message is used to return a list of Securities that matched criteria, specified in SecurityListRequest. Taking into account, that such lists could be big enough, all instruments will be streamed one by one(one instrument per SecurityList message).
Combination of TotNoRelatedSym(393) and LastFragment(893) tags can be used to identify the end of a transmission.
Tag | FieldName | Required | Comments | |
---|---|---|---|---|
320 | SecurityReqID | Y | ID from the initiating SecurityListRequest | |
322 | SecurityResponseID | Y | ||
560 | SecurityRequestResult | Y | Supported Values:
|
|
393 | TotNoRelatedSym | N | This field contains information about a number of instruments that matched initial search criteria. |
|
893 | LastFragment | N | Boolean field that indicates is given message is last in particular transmission or not | |
58 | Text | C | Optional field that will held human-readable information about the error(if occurred) | |
146 | NoRelatedSym | C | In case of successful request - always 1 | |
↦ | 55 | Symbol | C | |
↦ | 207 | SecurityExchange | C | |
↦ | 5001 | Price Precision | C | Integer value that represents a number of decimal points in prices for given Symbol/Exchange |
↦ | 5002 | Size Precision | C | Integer value that represents a number of deciman points in size for given Symbol/Exchange |
MarketDataRequest
Example:
Field Name
Example
MDReqID
262=1001_1
SubscriptionRequestType
263=1
MarketDepth
264=0
MDUpdateType
265=1
NoMDEntryTypes
267=1
MDEntryType
269=0
NoRelatedSym
141=1
Symbol
55=ETH/BTC
SecurityExchange
207=HUOBI
MsgType: V
Direction: OUT
Description: given command used to initiate subscription on real-time market data for symbol(s) on the particular exchange(s). In case of a successful request, the server will respond with a book snapshot followed by incremental updates for this book.
MDEntryTypes should always contain two types - BID(0) and OFFER(1).
Caller might subscribe on several instruments from several exchanges using a single MarketDataRequest message.
Please note that subscription requests will be processed using "all or nothing" principles. This means that the whole message will be rejected for complex requests containing at least one error in a subscription.
Tag | Field Name | Required | Comments | |
---|---|---|---|---|
262 | MDReqID | Y | Unique ID | |
263 | SubscriptionRequestType | Y | Supported Values:
|
|
264 | MarketDepth | Y | The field used to specify the number of bids/asks to receive. Supported Values:
|
|
265 | MDUpdateType | Y | Supported values:
|
|
267 | NoMDEntryTypes | Y | You can choose one or several values | |
↦ | 269 | MDEntryType | Y | Supported Values:
|
146 | NoRelatedSym | Y | It is possible to subscribe to several symbols using a single MarketDataRequest message |
|
↦ | 55 | Symbol | Y | Symbol name |
↦ | 207 | SecurityExchange | Y | Name of the exchange to receive market data |
MarketDataRequestReject
Example:
Field Name
Example
MDReqID
262=100_112
MDReqRejReason
281=0
Text
58=ABC/TEST
MsgType: Y
Direction: IN
Description: in case of logically incorrect MarketDataRequest message, subscription for the particular symbol will be rejected and server will provide additional information about the cause.
If initial MarketDataRequest messages contained several instruments that caused errors, then the server will respond with the only one MarketDataRequestReject messages under the same MDReqID and contains a description of the first error.
Tag | Field Name | Required | Comments |
---|---|---|---|
262 | MDReqID | Y | Unique MDReqID provided in MarketDataRequest message that has been failed. |
281 | MDReqRejReason | Y |
|
58 | Text | Y | Error description in a human-readable format |
MarketDataSnapshotFullRefresh
Example:
Field Name
Example
MDReqID
262=100_1
Symbol
55=ETH/BTC
SecurityExchange
207=HUOBI
RptSeq
83=2685
NoMDEntries
268=1
MDEntryType
269=0
MDEntryPx
270=0.035089
MDEntrySize
271=3.014
MDEntryDate
272=20180601
MDEntryTime
273=03:30:30.657
MsgType: W
Direction: IN
Description: this message contains book snapshot for the particular instrument. A number of levels could be controlled by MarketDepth parameter submitted as part of MarketDataRequest message.
Tag | Field Name | Required | Comments | |
---|---|---|---|---|
262 | MDReqID | Y | MDReqID associated with the previous request | |
55 | Symbol | Y | Symbol name | |
207 | SecurityExchange | Y | Exchange name | |
83 | RptSeq | Y | Sequence number of events | |
268 | NoMDEntries | Y | ||
↦ | 269 | MDEntryType | Y | Supported Values:
|
↦ | 270 | MDEntryPx | Y | Price |
↦ | 271 | MDEntrySize | Y | Entry size |
↦ | 272 | MDEntryDate | Y | Date when the given entry has been added or modified last time ISO 8601 format is used, UTC timezone |
↦ | 273 | MDEntryTime | Y | Time when the given entry has been added or modified, UTC timezone |
MarketDataIncrementalRefresh
Example:
Field Name
Example
MDReqID
262=100_1
Symbol
55=ETH/BTC
SecurityExchange
207=HUOBI
NoMDEntries
268=1
MDUpdateAction
279=1
MDEntryType
269=0
MDEntryPx
270=0.035089
MDEntrySize
271=3.214
MDEntryDate
272=20180601
MDEntryTime
273=03:30:32.506
AggressorSide
2446=0
RptSeq
83=587
MsgType: X
Direction: IN
Description: given message is used to transmit sequential updates for the particular order book. It might contain any number of NEW, UPDATE, DELETE and TRADE events that reflect the most recent book’s changes.
Valid processing order: DELETE → UPDATE → NEW.
Server always stream explicit DELETE events.
Please note, that standard FIX 4.4 MarketDataIncrementalRefresh message has been changed by moving Symbol(55) and Security Exchange(207) fields out of NoMDEntires(268) group.
Tag | Field Name | Required | Comments | |
---|---|---|---|---|
262 | MDReqID | Y | MDReqID associated with the previous request | |
55 | Symbol | Y | Symbol Name | |
207 | SecurityExchange | Y | Exchange Name | |
268 | NoMDEntries | Y | ||
↦ | 279 | MDUpdateAction | Y | Supported Values:
|
↦ | 269 | 9 MDEntryType | Y | Supported Values:
|
↦ | 270 | MDEntryPx | Y | Price |
↦ | 271 | MDEntrySize | N | Entry size. This field might be absent in case of DELETE event |
↦ | 272 | MDEntryDate | Y | Date when the given entry has been added or modified last time ISO 8601 format is used, UTC timezone |
↦ | 273 | MDEntryTime | Y | Time when the given entry has been added or modified, UTC timezone |
↦ | 2446 | AggressorSide | N | Indicates which side is the aggressor of the trade (MDEntryType = TRADE). Supported Values:
|
↦ | 83 | RptSeq | Y | MD Entry sequence number per instrument update |
Trading Session
Trading sessions are used to send orders to different liquidity providers and to receive confirmations.
FIX session is a two-way asynchronous communication channel that does not require any polling/constant refreshes. Any changes in the order's status will be automatically pushed back to the client.
By default, a trading session works as a single entry point for all organization's accounts and exchanges which helps significantly reduce integration complexity. When more complex scenarios are needed, embedded ACL rules allow configuring who can send where.
Organizational structure
Organization | An organization is an entity, that represents the entire client's company inside the Axon Trade. |
Account | An account is an entity that holds links to exchanges. Organizations can have multiple accounts. |
Login | This entity is used to perform trading operations. |
Order states diagram
Once the server received client’s order, it will respond with ExecutionReport message with two possible statuses(OrdStatus field):
- PENDING NEW – order has been accepted for execution
- REJECTED – order did not pass initial validation
- PENDING NEW can be followed with several possible state changes:
- NEW – order has been accepted by specified exchange
- after this point, itis possible to receive ExecutionReports in PARTIALLY FILLED/FILLED statuses or CANCELED(in case the order being canceled by corresponding Order Cancel Request message or by TimeInForce modifier)
- CANCELED – order has been rejected by the exchange
Dictionaries
Security Type
Type | Value | Description |
---|---|---|
Foreign Exchange Contract | FOR | All fiat to fiat pairs |
Digital Assets Spot Contract | CRYPROSPOT | All crypto to crypto or crypto to fiat spot contracts |
Perpetual Swap Contract | PERPSWAP | Perpetual swap contracts such as BTC-PERPETUAL |
Futures Contracts | FUT | Futures contracts |
Order Types
Order Type | Comments |
---|---|
Market(1) | When sending market orders, Price or StopPx is not required to be set |
Limit(2) | When sending limit orders, Price(44) field is required to be set |
Order Sides
Only 2 sides are supported:
- Buy(1)
- Sell(2)
Time in Force
Type | Comments |
---|---|
Day(0) | If order becomes pending, it will be canceled at the end of the trading session |
Good Till Cancel(1) | |
Immediate Or Cancel(3) | Limit order will be executed at an exact price or better immediately, else will be canceled |
Fill Or Kill(4) | Order will be filled for the quantity specified in OrderQt, else will be canceled |
Messages
Logon
MsgType: A
Direction: IN/OUT
Description: Logon should be sent as a very first message to establish FIX session and pass authentication process. In the case of successful authentication, server will respond with corresponding Logon message.
Tag | Field Name | Required | Comments | Example |
---|---|---|---|---|
98 | EncrypMethod | Y | Always set to None(0) | 98=0 |
108 | HeartBtInt | Y | Heartbeat interval, always 30s | 108=30 |
553 | Username | Y | 553=1001 | |
554 | Password | Y | 554=Rr68twd6mw |
Logout
MsgType: 5
Direction: IN/OUT
Description: Logout message is used as a confirmation.
Tag | Field Name | Required | Comments |
---|---|---|---|
58 | Text | N | Disconnection reason in human-readable format Please note, that this field might be absent |
NewOrderSingle
Example:
Field Name
Example
Account
1=1001
ClOrdID
11=1234
12=ORD_1234
OrderQty
39=0.125
OrdType
40=1
Price
44=0.033528
StopPx
99=0.033612
Side
54=1
Symbol
55=ETH/BTC
TimeInForce
59=0
TransactionTime
60=20180912-12:05:15.105
ExDestination
100=OKEX
SecurityType
167=FOR
ExecInst
18=6
MsgType: D
Direction: OUT
Description: The message is used by institutions wishing to electronically submit securities and forex orders to a broker for execution.
Tag | Field Name | Required | Comments |
---|---|---|---|
1 | Account | Y | Login ID, associated with given session |
11 | ClOrdID | Y | Client assigned order ID Maximum length - 50 characters |
38 | OrderQty | Y | Initial Order size |
40 | OrdType | Y | Type of order Supported values:
|
44 | Price | C | Conditional field, indicating an expected fill price. Required for:
|
99 | StopPx | C | Conditional field, required for Stop order type |
54 | Side | Y | Order side used Supported Values:
|
55 | Symbol | Y | Symbol name |
59 | TimeInForce | Y | Control orders lifetime behavior. Supported Values:
|
60 | TransactionTime | Y | Timestamp in UTC timezone when the order was created with included milliseconds |
100 | ExDestination | Y | ECN or Venue name where the order will be sent/executed |
167 | SecurityType | Y | Type of security to trade. Supported values:
|
18 | ExecInst | N | Instructions for orders handling during execution. Supported values:
|
Order Cancel Request
Example:
Field Name
Example
Account
1=1001
ClOrdID
11=1234
OrderID
37=312351044
OrigClOrdID
41=1233
Side
51=1
Symbol
55=ETH/USD
TransactionTime
60=20180912-12:05:15.105
MsgType: F
Direction: OUT
Description: Order Cancel/Request is used to cancel the order in its entirety. Only orders in NEW or PARTIALLY_FILLED statuses can be canceled. If you need to cancel only a part of the non-filled amount (leaves quantity), please refer to Order Cancel/Replace Request.
Tag | Field Name | Required | Comments |
---|---|---|---|
1 | Account | Y | Trader ID that owns order that has to be canceled |
11 | ClOrdID | Y |
Client order ID for cancel operation Maximum length - 50 characters |
37 | OrderID | Y | OrderID which should be canceled |
41 | OrigClOrdID | Y |
Client order ID of order which should be canceled Maximum length - 50 characters |
54 | Side | Y | Order side of order, identified by OrigClOrdID/OrderID |
55 | Symbol | Y | Symbol, association with working order |
60 | TransactionTime | Y |
Timestamp in UTC timezone when an order was created with included milliseconds *it is possible to send a timestamp down to the one-second resolution, but this approach is not recommended. |
Order Cancel/Replace Request
Example:
Field Name
Example
Account
1=1001
ClOrdID
11=1234
OrderID
37=312351044
OrigClOrdID
41=1233
Side
51=1
Symbol
55=ETH/USD
Price
44=1400.50
OrderQty
38=1.12
TransactionTime
60=20180912-12:05:15.105
MsgType: G
Direction: OUT
Description: Order Cancel/Replace Request command is used to update previously placed orders. Requests for modification are accepted only for orders in NEW or PARTIALLY FILLED status. It is possible to change an order price and/size. A size of an order can be changed both ways - it is possible to increase it (LeavesQty will grow), or decrease it (LeavesQty will be reduced).
Tag | Field Name | Required | Comments |
---|---|---|---|
1 | Account | Y | Trader ID that owns order that has to be canceled |
11 | ClOrdID | Y | Client-assigned ID for replacement operation Maximum length - 50 characters |
37 | OrderID | Y | OrderID which should be canceled |
41 | OrigClOrdID | Y | Client order ID of order that should be canceled Maximum length - 50 characters |
54 | Side | Y | Order side of order, identified by OrigClOrdID/OrderID |
55 | Symbol | Y | Symbol, association with working order |
44 | Price | N | New price for the order |
38 | OrderQty | Y |
New size for the order. OrderQty has to be submitted even if only Price has to be changed. |
60 | TransactionTime | Y |
Timestamp in UTC timezone when an order was created with included milliseconds. *it is possible to send a timestamp down to the one-second resolution, but this approach is not recommended. |
Order Cancel/Reject
Example:
Field Name
Example
Account
1=1001
ClOrdID
11=CCL_001
OrigClOrdID
41=TRD_00231
OrderID
37=1123423
CxlRejReason
102=0
CxlRejResponseTo
434=1
Text
58=Can't cancel filled order
TransactionTime
60=20180912-12:15:15.105
MsgType: F
Direction: IN
Description: This message will be sent by the server in response to Order Cancel/Request if the operation failed for some reason.
Tag | Field Name | Required | Comments |
---|---|---|---|
1 | Account | Y | |
11 | ClOrdID | C | ID of client order which was used to perform cancel operation Maximum length - 50 characters |
41 | OrigClOrdID | C | ID of canceling client order Maximum length - 50 characters |
37 | OrderID | C | ID of working order on Axon Trade side. Usually transmitted as OrderID within ExecutionReport message |
102 | CxlRejReason | Y | Supported Values:
|
434 | CxlRejResp onseTo |
Y | Supported Values:
|
58 | Text | C | Textual comments about rejection reason |
60 | TransactionTime | Y | Timestamp in UTC timezone when Order can rejected |
ExecutionReport
Example:
Field Name
Example
Account
1=1001
ClOrdID
11=1234
12=ORD_1234
OrderID
37=312351043
SecondaryOrderID
198=ea4063b0-4b66-11ea-b77f2e728ce88125
ExecID
17=4000123541
MassStatusReqId
584=ord_req_1223
TotNumReports
911=14
LastRptRequested
913=Y
OrdType
40=1
Price
44=0.033953
Side
54=1
Symbol
55=ETH/BTC
OrdStatus
39=2
ExecType
150=F
AvgPx
6=0.033959
LastPx
31=0.033951
LastQty
32=0.100
CumQty
14=0.200
LeavesQty
151=0.300
Text
58=Account not found.
TimeInForce
59=0
TransactionTime
60=20180912-12:05:15.105
ExDestination
100=OKEX
OrdRejReason
103=11
SecurityType
167=CRYPTOSPOT
Commission
12=0.001
CommisionType
13=3
CommissionCurrency
479=USD
ExecInst
18=6
MsgType: 8
Direction: IN
Description: Used to send order status information to a FIX client, such as confirmations, fills, and unsolicited changes
Tag | Field Name | Required | Comments |
---|---|---|---|
1 | Account | Y | Login ID, associated with a given session |
11 | ClOrdID | Y | Client-assigned order ID |
37 | OrderID | Y | Order ID on Axon Trade side |
198 | SecondaryOrderID | C | Order ID, assigned by target exchange |
17 | ExecID | Y | Order execution ID This field will be set to zero("0") when processing MassOrderStatusRequest message (ExecType=ORDER STATUS(I)) |
584 | MassStatusReqId | N | Request ID, associated with MassOrdertStatusRequest message |
911 | TotNumReports | N | A conditional field that will appear in the response to Order Mass Status Request(AF) message. Contains a total number of all orders that meet search criteria |
912 | LastRptRequested | N | A conditional field that appears only for reports with ExecType=ORDER STATUS. Indicates that this is the very last message in the batch |
40 | OrdType | Y | Order Type (Market, Limit) |
44 | Price | Y | Conditional field, indicating expected fill price for Limit orders |
54 | Side | Y | Order side used Supported Values:
|
55 | Symbol | Y | Symbol name |
39 | OrdStatus | Y | Reports current order status Supported values:
|
150 | ExecType | Y | Reports current execution status: Supported values:
|
6 | AvgPx | Y | Average price of all executed parts(in case of partial fills) |
31 | LastPx | C | Price of last executed part. If order fully filled at once, LastPx will be same as AvgPx |
32 | LastQty | C | Last executed size. |
14 | CumQty | Y | Total executed quantity for a given order (sum of all fills) |
151 | LeavesQty | Y | Indicates quantity of order still not-executed yet live. |
58 | Text | C | May contain optional text information related to order status. E.g. textual explanation of rejection |
59 | TimeInForce | Y | Control order lifetime behavior. Supported Values:
|
60 | TransactionTime | Y | Time of the most recent Order's update,timestamp in UTC timezone. |
100 | ExDestination | Y | ECN or Venue name where the order was sent/executed |
103 | OrdRejReason | C | If a case of a rejection, this field will help identify the source of error
|
167 | SecurityType | Y | Type of security. Supported values:
|
12 | Commission | C | Commission charged for the last execution or for the entire chain of executions(as a response for OrderMassStatusRequest). Only orders in status PARTIALLY_FILLED(1) or FILLED(2) have this tag set. |
13 | CommisionType | C | Supported values:
|
479 | CommissionCurrency | C | Currency used to charge given commission Only orders in status PARTIALLY_FILLED(1) or FILLED(2) have this tag set. |
18 | ExecInst | N | Instructions for orders handling during execution. Supported values:
|
OrderMassStatusRequest
Example:
Field Name
Example
MassStatusReqId
584=request_123
MassStatusReqType
585=1
NoPartyIDs
453=1
PartyID
448=HUOBI
PartyRole
452=22
MsgType: AF
Direction: OUT
Description: This message is used when counterparty needs to obtain a list of list(working) orders that match certain criteria.
A response will be provided through a series of ExecutionReports that contains ExecType=Status and echoed back MassStatusReqId (584) field.
Tag | Field Name | Required | Comments | |
---|---|---|---|---|
584 | MassStatusReqId | Y | Unique ID, associated with a given request | |
585 | MassStatusReqType | Y | Specify the scope of a mass status request. Supported Values:
|
|
453 | NoPartyIDs | C | Mandatory, when MassStatusReqType=8 and holds a list of actual trading Logins. Additionally, can be used to narrow request scope by specifying exchanges. If no exchange-related information is provided, the server will respond with a list that includes open orders from all exchanges. |
|
↦ | 448 | PartyID | Exchange name Login ID |
|
↦ | 452 | PartyRole | Supported values:
|
RequestForPositions
Example:
Field Name
Example
PosReqId
710=req_1
PosReqType
724=0
SubscriptionRequestType
263=1
Account
1=1001
AccountType
581=1
ClearingBusinessDay
715=20191107
NoPartyIDs
453=1
PartyID
HUOBI
PartyRole
452=22
TransactTime
60=20191107-12:05:15.105
MsgType: AN
Direction: OUT
Description: This message is used to request a list of positions associated with a given exchange and trading login. This information is available in the form of a snapshot or incremental updates send by the server once the position size changed.
Tag | Field Name | Required | Comments | |
---|---|---|---|---|
710 | PosReqId | Y | Unique ID, associated with a given request | |
724 | PosReqType | Y | Used to narrow the scope of information transmitted. Supported values:
|
|
263 | SubscriptionRequestType | Y | Used to subscribe or unsubscribe from reports. Supported values:
|
|
1 | Account | Y | Organization ID | |
581 | AccountType | Y | Type of account associated with a position request Supported values:
|
|
715 | ClearingBusinessDay | Y | The Clearing Business Date referred to by this request | |
453 | NoPartyIDs | Y | ||
↦ | 448 | PartyID | Y | Counterparty name e.g. name of the target exchange Login ID |
↦ | 452 | PartyRole | Y | Supported values:
|
60 | TransactTime | Y | Time, when this request was initiated |
Examples
Your Organization ID is 1001 and it manages four trading accounts – 1234, 2000, 2101, 4442.
You want to get a snapshot of all positions your organization has under the management. In this case, NoPartyIDs group will look as following:
Entry # | Tag | Name | Value |
---|---|---|---|
0 | 448 | PartyID | 1001 |
0 | 452 | PartyRole | 6 |
This request(if executed successfully) should returns positions for logins 1234, 2000, 2101, and 4442.
If you are looking for positions that belong to certain logins(e.g. 1234 and 4442) then NoPartyIDs group will be as following:
Entry # | Tag | Name | Value |
---|---|---|---|
0 | 448 | PartyID | 1234 |
0 | 452 | PartyRole | 11 |
1 | 448 | PartyID | 4442 |
1 | 452 | PartyRole | 11 |
RequestForPositionsAck
Example:
Field Name
Example
PosMaintRptId
721=123456021
PosReqId
710=req_1
TotalNumPosReports
727=246
PosReqResult
728=0
PosReqStatus
729=0
NoPartyIDs
453=2
PartyID
448=AXON
PartyRole
452=11
Account
1=1001
AccountType
581=1
SecurityExchange
207=OKEX
Text
58=Not authorized to request positions for given Account
MsgType: AO
Direction: IN
Description: This message will be sent as a confirmation to Request for Positions. It contains basic information such is request status and a number of positions returned with the following snapshot.
Tag | Field Name | Required | Comments | |
---|---|---|---|---|
721 | PosMaintRptId | Y | Unique identifier for this position report | |
710 | PosReqId | N | Request ID, copied from the parent message | |
727 | TotalNumPosReports | N | Number of positions returned | |
728 | PosReqResult | Y | Indicates the request status. Supported values:
|
|
729 | PosReqStatus | Y | Status of request for positions. Supported values:
|
|
453 | NoPartyIDs | Y | ||
↦ | 448 | PartyID | ||
↦ | 452 | PartyRole | Supported values:
|
|
1 | Account | Y | Organization ID | |
581 | AccountType | Y | Type of account associated with a position request Supported values:
|
|
207 | SecurityExchange | N | Name of the trading venue to get a list of the positions | |
58 | Text | N | Human-readable error message |
PositionReport
Example:
Field Name
Example
PosMaintRptID
721=1002312
PosReqID
710=req_12
PosReqResult
728=0
ClearingBusinessDate
715=20191107
NoPartyIDs
453=2
PartyID
448=12
PartyRole
1=1001
Account
1=2342
AccountType
581=1
Symbol
55=ETH
SecurityType
167=FUT
NoPositions
702=1
PosType
703=ETR
LongQty
703=500.123000
MsgType: AP
Direction: IN
Description: This message is providing you with all your balances.
Tag | Field Name | Required | Comments | |
---|---|---|---|---|
721 | PosMaintRptID | Y | Unique identifier for this position report | |
710 | PosReqID | N | This field will be set when returning positions snapshot and will be omitted for any sequential updates |
|
728 | PosReqResult | Y | Always 0(Valid Request) | |
715 | ClearingBusinessDate | Y | Always today | |
453 | NoPartyIDs | Y | For a regular report, NoParties group contains 2 entries:
|
|
↦ | 448 | PartyID | ||
↦ | 452 | PartyRole | N | Supported values:
|
1 | Account | Y | Organization ID | |
581 | AccountType | Y | Type of account associated with a position request Supported values:
|
|
55 | Symbol | Y | Human readable asset name | |
167 | SecurityType | Y | Supported values:
|
|
702 | NoPositions | Y | ||
↦ | 703 | PosType | Supported Values:
|
|
↦ | 704 | LongQty | Either LongQty or ShortQty is available as part of this group. ShortQty is not available for SPOT markets. |
|
↦ | 705 | ShortQty |
TradingSessionStatusRequest
Example:
Field Name
Example
TradSesReqID
335=session_request_1
SubscriptionRequestType
263=1
MsgType: g
Direction: OUT
Description: This message requests the current status and subscribes to status updates of all outgoing connections belonging to the acting client. In case of a successful request, the server will respond with TradingSessionStatuses messages.
Tag
|
Field Name
|
Required
|
Comments
|
---|---|---|---|
335 | TradSesReqID | Y | Unique ID associated with the given request |
263 | SubscriptionRequestType | Y |
Supported Values:
|
TradingSessionStatus
Example:
Field Name
Example
TradSesReqID
335=session_request_1
TradingSessionID
336=DERIBIT
TradingSessionSubId
625=1
UnsolicitedIndicator
325=Y
TradSesStatus
340=2
Text
58=AUTH ERROR
MsgType: h
Direction: IN
Description: This message sends by the server in response to TradingSessionRequest(to transmit snapshot) or when one of the client's outgoing connections changed its status for various reasons e.g. because of the network error.
Tag
|
Field Name
|
Required
|
Comments
|
---|---|---|---|
335 | TradSesReqID | Y | Unique identifier for the Status Request, copied from the original TradingSessionStatusRequest message |
336 | TradingSessionID | Y | Name of the trading destination that changed its status |
625 | TradingSessionSubId | Y | Account ID, associated with Exchange from TradingSessionID. TradingSessionSubId uses to clearly identify which trading session changed its status as long the Organization might have multiple accounts and multiple outgoing connections to the same destination. |
325 | UnsolicitedIndicator | Y |
Supported Values:
|
340 | TradSesStatus | Y |
Supported Values:
|
58 | Text | N |
Might contain additional information in case of the error |
Naming Convention
Axon Trade uses the following rules to keep symbol names coherent across a variety of services
Type | Format | Security Type (167) | Base Asset | Quote Asset | Example |
---|---|---|---|---|---|
Crypto Spot | CCY1/CCY2 | CRYPTOSPOT | BTC | USD | BTC/USD |
FX | CCY1/CCY2 | CRYPTOSPOT | EUR | USD | EUR/USD |
Perpetual Swaps | security_type:base-asset:quote-asset | PERPSWAP | BTC-PERP | BTC USDT |
PERP:BTC-PERP:BTC PERP:ETH-PERP:USDT |
Futures Contracts | security_type:base-asset:quote-asset | FUT | MAR22 | BTC | FUT:MAR22:BTC |
Options | security_type:base-asset:quote-asset | OPT | JUL21P40000 | USDT | OPT:JUL21P40000:USDT |
Management API
Introduction
Axon Trade OEMS provides easy to use REST API to automate certain aspects of integration such as Accounts and Exchanges management and so on.
URL schema represents resources linkage where Accounts are linked to parent Organization, and Exchanges are linked to Accounts. Exchanges themselves have their own resources that could be managed through the REST API.
Authentication
Each request to the management REST API should contain an authentication token. The token has to be provided within Api-Key-Token
header.
In order to obtain the token, the organization administrator has to manually generate it using the Client's Portal.
Accounts
Axon Trade OEMS designed as a multitenant application where a single Organization can carry underlying Accounts which, in their turn, carry Logins.
An Organization is an entity, designed to represent the end client. Some resources such as market data subscriptions or the number of messages sent are properties of the Organization.
An Account is a form of entity, that holds such valuable resources as links to exchanges. Therefore, all balances are associated with an Account.
A Login is an entity that uses to initiate operations under orders - open, cancel, update.
Each Account has only one Login, Organization might have multiple Accounts.
Get all Accounts
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts",
{
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.get("https://service.url/rest/organizations/1/accounts", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
[
{
"id":1,
"name":"Office A",
"organization_id":1,
"status":1
},
{
"id":2,
"name":"Office X",
"organization_id":1,
"status":1
}
]
This endpoint returns the list of all accounts, registered under your organization.
Method and path
GET /rest/organizations/{ORGANIZATION}/accounts/statuses?statusId=1
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
STATUS | Status ID |
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
Response Codes
Code | Description |
---|---|
200 | Request was successfully executed |
401 | Incorrect/stale token provided |
403 | Forbidden |
Get Account by ID
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1",
{
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.get("https://service.url/rest/organizations/1/accounts/1", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
{
"id":1,
"name":"Office A",
"organization_id":1,
"status":1
}
Endpoint to extract Account by it's ID.
Method and path
GET /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
Response Codes
Code | Description |
---|---|
200 | Request was successfully executed |
401 | Invalid token provided |
403 | Forbidden |
404 | Organization or Account with provided ID is not found |
Add Account
Body example:
{
"name": "FX UAT Account",
"status": 1,
"organization_id": 1
}
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
body: {
name: "FX UAT Account",
status: 1,
organization_id: 1
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.post("https://service.url/rest/organizations/1/accounts/", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'}, data={
"name": "FX UAT Account",
"status": 1,
"organization_id": 1
})
data = request.json()
Response:
{
"id": 75,
"name": "FX UAT Account",
"organization_id": 1,
"login": {
"id": 28,
"name": "FX UAT Account",
"account_id": 1,
"balance": 100.0
}
}
Endpoint to add a new account into your organization. Server also will create a Login entry that can be used to perform trading operations.
Method and path
POST /rest/organizations/{ORGANIZATION}/accounts
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
Response Codes
Code | Description |
---|---|
200 | Request was successfully executed |
401 | Invalid token provided |
500 | An error occured while processing the creation |
Add properties for account
Body example:
{
"key":"data_center_id",
"value":"1"
}
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1/properties",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
body: {
key: "data_center_id",
value: "1"
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.post("https://service.url/rest/organizations/1/accounts/1/properties", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'}, data={
"key":"data_center_id",
"value":"1"
})
data = request.json()
Response:
{
"message":"2 new record(s) added, 0 record(s) updated"
}
Endpoint to add a properties for account.
Method and path
POST /rest/organizations/{ORGANIZATION}/accounts/ACCOUNT/properties
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
Response Codes
Code | Description |
---|---|
200 | Request was successfully executed |
401 | Invalid token provided |
500 | An error occured while processing the creation |
Update Account information
Body example:
{
"name": "Account 2 New Name"
}
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1",
{
method: "PUT",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
body: {
id: 1,
name: "Account 2 New Name",
organization_id: 1
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.post("https://service.url/rest/organizations/1/accounts/1", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'}, data={"name": "Account 2 New Name"})
data = request.json()
Response:
{
"id": 1,
"name": "Account 2 New Name",
"organization_id": 1,
"status": 1
}
Endpoint to update certain fields on a given Account. The only field that could be altered right now is the Account's name.
Method and path
POST /rest/organizations/{ORGANIZATION}/accounts
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
Response Codes
Code | Description |
---|---|
200 | Request was successfully executed |
401 | Invalid token provided |
404 | Account with given ID is not found |
500 | An error occured while processing the updating |
Delete account
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.post("https://service.url/rest/organizations/1/accounts/1", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
{
"id": 1,
"name": "Account 2",
"organization_id": 1,
"description": "some description",
"status": 1
}
Endpoint to delete Account.
Method and path
POST /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
Response Codes
Code | Description |
---|---|
200 | Request was successfully executed |
401 | Invalid token provided |
404 | Account with given ID is not found |
500 | An error occured while processing the deleting |
Exchanges
This set of calls allows you to control links between Account and Exchange as a trading destination. According to the Axon Trade workflow, each Account can have an unlimited number of linked exchanges but their types should be different. E.g. Account 'Trading Desk #1' can't have two Binance accounts. If your workflow requires two or more exchanges of similar type, it is possible to create another Account and link new Exchange credentials to it.
Get all exchanges
Request:
let response = await fetch("https://service.url/rest/exchanges", {
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
});
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.get("https://service.url/rest/exchanges", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
[
{
"id": 10,
"name": "GEMINI",
"full_name": "Gemini exchange"
},
{
"id": 12,
"name": "BITFINEX",
"full_name": "BitFinex exchange"
},
{
"id": 20,
"name": "BITMART",
"full_name": "BitMart exchange"
}
]
This method to get exchanges list. Success request will return full formed exchange objects.
Method and path
GET /rest/exchanges
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
Response Codes
Code | Description |
---|---|
200 | Request was successfully executed |
401 | Invalid token provided |
500 | Internal server error - exchanges can't be received because of certain reasons |
Get configured exchanges
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/exchanges?ACCOUNT_ID={ACCOUNT}",
{
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.get("https://service.url/rest/organizations/1/exchanges?ACCOUNT_ID={ACCOUNT}", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
[
{
"id":481,
"name":"CEX.IO",
"description":"CEX PROD",
"status":1
},
{
"id":667,
"name":"OKEX",
"description":" ",
"status":0
}
]
This method returns a list of exchanges where given account can trade.
Method and path
GET /rest/organizations/{ORGANIZATION}/exchanges?ACCOUNT_ID={ACCOUNT}
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT_ID | Account ID |
Response Codes
Code | Description |
---|---|
200 | Exchanges (a.k.a connectors) was successfully received |
401 | Invalid token provided |
500 | Internal server error - exchanges can't be received because of certain reasons |
Add exchange to Account
Body example:
{
"route_id": 3,
"name":"Binance",
"description":"Binance | Futures | Coins description for new exchange",
"params":[
{
"key":"api_key",
"value":"111-222-333"
},
{
"key":"private_key",
"value":"4442131212"
}
]
}
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1/exchanges/add",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
body: {
route_id: 3,
name: "Binance",
description: "Binance | Futures | Coins description for new exchange",
params:[
{
key: "api_key",
value: "111-222-333"
},
{
key: "private_key",
value: "4442131212"
}
]
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.get("https://service.url/rest/organizations/1/accounts/1/exchanges/add", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'}, {
"route_id": 3,
"name":"Binance",
"description":"Binance | Futures | Coins description for new exchange",
"params":[
{
"key":"api_key",
"value":"111-222-333"
},
{
"key":"private_key",
"value":"4442131212"
}
]
})
data = request.json()
Response:
{
"id": 757,
"name": "Binance",
"exchange": {
"id": 9,
"name": "BINANCE"
}
}
This method is provided to enable trading on a particular exchange. It required to provide credentials(such as Private Key, Api Key, SenderCompId and so on)
Method and path
POST /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}/exchanges/add
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
Response Codes
Code | Description |
---|---|
200 | Operation is accomplished successfully |
201 | Connector created but something went wrong: |
400 | Incomplete or incorrect data has been passed |
401 | Invalid token provided |
404 | Organization ID, Account ID, Router ID did not find |
409 | Account already has registered routing destination to target exchange or failed to create connector |
Update credentials on Exchange
Body example:
{
"private_key": "da281ca8-7a43-11ec-90d6-0242ac120003",
"api_key": "66442f2c-c7ef-404b-b01c-30f2eb8ca318"
}
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1/exchanges/1/edit",
{
method: "PUT",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
body: {
params:[
{
type: 2,
key: "api_key",
value: "333-222-333"
},
{
type: 2,
key: "private_key",
value: "skdjfslkdjfsldkj"
}
]
}
,
}
);
if (response.ok) {
let json = await response.text();
}
import requests
request = requests.get("https://service.url/rest/organizations/1/accounts/1/exchanges/1", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'}, {
"params":[
{
"type":2,
"key":"api_key",
"value":"333-222-333"
},
{
"type":2,
"key":"private_key",
"value":"skdjfslkdjfsldkj"
}
]
}
)
data = request.json()
Response:
{
"message": "Exchange ID: 757 settings has been updated"
}
Endpoint allows to update/change credential information on Account/Exchange record. Some Exchanges have key expiry mechanisms so keys have to be updated from time to time.
Method and path
POST /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}/exchanges/{EXCHANGE}
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
EXCHANGE | ID of configured exchange |
Response Codes
Code | Description |
---|---|
200 | Operation is accomplished successfully |
401 | Invalid token provided |
404 | Organization ID, Account ID, or Exchange ID is not found |
Unlink Exchange from Account
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1/exchanges/1/delete",
{
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.delete("https://service.url/rest/organizations/1/accounts/1/exchanges/1/delete", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
{
"message": "Exchange ID: 757 has been removed"
}
Endpoint will remove the link between Exchange and the given Account.
All credentials will be deleted from our internal database.
If Account has open orders on this Exchange, they will remain open.
Trading history will still be stored and available for you.
Method and path
DELETE /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}/exchanges/{EXCHANGE}
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
EXCHANGE | ID of an exchange |
Response Codes
Code | Description |
---|---|
200 | Operation is accomplished successfully |
202 | Exchange(a.k.a connector) deleted but user data not deleted |
401 | Invalid token provided |
404 | Organization ID, Account ID, Exchange ID did not find |
409 | Exchange is not deleted |
Get connectivity statuses for all exchanges
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1/exchanges/status",
{
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.get("https://service.url/rest/organizations/1/accounts/1/exchanges/status", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
[
{
"id": 95,
"status": 0,
}
]
Endpoint to extract connectivity statuses for all exchanges for given Account. A successful result will contain an array of objects, each of which represents status for a single exchange's link.
A link to exchange has several states such as DISCONNECTED or CONNECTED. Having a link in CONNECTED state doesn't mean that it's possible to trade. Once a connection is established, our system tries to synchronize its internal state(orders, positions, trading history) with what is currently available on the exchange.
Method and path
GET /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}/exchanges/status
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
Response Codes
Code | Description |
---|---|
200 | Operation is accomplished successfully |
401 | Invalid token provided |
404 | Organization ID, Account ID is not found |
Start link to Exchange
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1/exchanges/1/start",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.post("https://service.url/rest/organizations/1/accounts/1/exchanges/1/start", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
{
"message":"Request to start connector has been sent"
}
Endpoint to start link to a selected Exchange. Newly created links are always in DISCONNECTED status so this method has to be called in order to establish the connection and initiate all synchronization procedures.
Method and path
GET /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}/exchanges/{EXCHANGE}/start
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
EXCHANGE | ID of an exchange |
Response Codes
Code | Description |
---|---|
200 | Operation is accomplished successfully |
401 | Invalid token provided |
404 | Organization ID, Account ID, Exchange ID is not found |
Stop Exchange's link
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1/exchanges/1/stop",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.post("https://service.url/rest/organizations/1/accounts/1/exchanges/1/stop", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
{
"message": "Request to stop connector has been sent"
}
Endpoint to terminate a link to Exchange. It will not delete the connectivity itself, the method simply close the outgoing connection whatever protocol is used(WebSocket, FIX etc) endpoint to terminate a link to Exchange. It will not delete the connectivity itself, the method simply close the outgoing connection whatever protocol is used(WebSocket, FIX etc)
Method and path
POST /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}/exchanges/{EXCHANGE}/stop
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
EXCHANGE | ID of an exchange |
Response Codes
Code | Description |
---|---|
200 | Operation is accomplished successfully |
401 | Invalid token provided |
404 | Organization ID, Account ID, Exchange ID is not found |
Get extended positions
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1/exchanges/1/extended_positions",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.post("https://service.url/rest/organizations/1/accounts/1/exchanges/1/extended_positions", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
[
{
"asset": {
"id": 1043569,
"name": "PERP:XRP-PERP:USDT"
},
"size": "0.1", // size > 0 -> side = buy, size < 0 -> side = sell
"avg_price": "141.6",
"mark_price": "154.354",
"liquidation_price": "0.00",
"leverage": "1.7",
"unreleased_pnl": "1.2754"
}
]
Method to get extended positions for given account and exchange.
Method and path
POST /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}/exchanges/{EXCHANGE}/extended_positions
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
EXCHANGE | ID of an exchange |
Response Codes
Code | Description |
---|---|
200 | Request was processed correctly |
401 | Invalid token provided |
403 | Forbidden |
404 | Organization ID, Account ID, Exchange ID is not found |
500 | An error occurred during get transactions for organization |
Get balances
Request:
let response = await fetch(
"https://service.url/rest/organizations/1/accounts/1/exchanges/1/balances",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.post("https://service.url/rest/organizations/1/accounts/1/exchanges/1/balances", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
{
"asset": {
"id": 1033342,
"name": "USDT"
},
"available": "42.39",
"locked": "9.83",
"available_value": "42.38",
"locked_value": "9.83"
}
Method to get balances for given account and exchange.
Method and path
POST /rest/organizations/{ORGANIZATION}/accounts/{ACCOUNT}/exchanges/{EXCHANGE}/balances
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ORGANIZATION | Organization ID |
ACCOUNT | Account ID |
EXCHANGE | ID of an exchange |
Response Codes
Code | Description |
---|---|
200 | Request was processed correctly |
401 | Invalid token provided |
403 | Forbidden |
404 | Organization ID, Account ID, Exchange ID is not found |
500 | An error occurred during get transactions for organization |
Routing destinations
Routes or routing destinations is the concept that helps to separate actual Exchange(e.g. Binance or FTX) from factual connectivity(link) established between Axon Trade servers and the exchange itself. Some exchanges, such as FTX or Gemini, might have more, than one route, for example, WebSockets and/or FIX.
Get routing destinations
Request:
let response = await fetch(
"https://service.url/rest/routes?router_id={ROUTER}",
{
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.get("https://service.url/rest/routes/?router_id={ROUTER}", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
[
{
"id":37,
"name":"BITMEX",
"exchange":{
"id":16,
"name":"BITMEX"
}
},
{
"id":68,
"name":"LIQUID",
"exchange":{
"id":66,
"name":"LIQUID"
}
}
]
Endpoint to return a list of all supported by server routing destinations.
It is possible when a single Exchange might have several routes. This happens, when we provide alternative implementations.
Method and path
GET /rest/routes?router_id={ROUTER}
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ROUTER | Router ID |
Response Codes
Code | Description |
---|---|
200 | Operation is accomplished successfully |
401 | Invalid token provided |
404 | Organization ID is not found |
Get route description
Request:
let response = await fetch(
"https://service.url/rest/routes/{ROUTE}",
{
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.get("https://service.url/rest/routes/1", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
{
"id":59,
"name":"Binance|Spot",
"settings":[
{
"key":"api_key",
"value":null
},
{
"key":"private_key",
"value":null
}
]
}
Endpoint to extract detailed information about the route from the server.
The most important information here is located inside the parameters array. These are the required parameters, for example, API Key or Private Key, that have to be provided in order to establish a real connection to the exchange of your interest.
Method and path
GET /rest/routes/
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
URL Parameters
Parameter | Description |
---|---|
ROUTE | Routing Destination ID |
Response Codes
Code | Description |
---|---|
200 | Operation is accomplished successfully |
401 | Invalid token provided |
404 | Organization ID or Route ID is not found |
Datacenters
Get Datacenters
Request:
let response = await fetch(
"https://service.url/rest/datacenter",
{
headers: {
"Content-Type": "application/json",
"Api-Key-Token": "sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw",
},
}
);
if (response.ok) {
let json = await response.json();
}
import requests
request = requests.get("https://service.url/rest/datacenter", {'Api-Key-Token': 'sHBXSvuk3fF2MKigsUI1AAAA1AAAgABYXJ0aHVyLnJhZGNoZW5rbw', 'Content-Type': 'application/json'})
data = request.json()
Response:
[
{
"id":1,
"name":"NewYork",
"description":"description",
"location":"NY"
},
{
"id":5,
"name":"London",
"description":"London DC",
"location":"LD"
}
]
Endpoint to return a list of to get the list of datacenters.
Method and path
GET /rest/datacenter
Headers
Name | Value |
---|---|
Content-Type | application/json |
Api-Key-Token | your API token |
Response Codes
Code | Description |
---|---|
200 | Operation is accomplished successfully |
401 | Invalid token provided |
500 | An error occurred during get all datacenters |
Constants
Exchange connection statuses
Status ID | Meaning |
---|---|
0 | DISCONNECTED |
1 | DISCONNECTING |
2 | CONNECTING |
3 | CONNECTED |
4 | AWAIT SUBSCRIBE |
5 | AUTH REQUIRED |
6 | AUTH FAILED |
Extended Statuses
Status ID | Meaning |
---|---|
2000 | Sync open orders |
2001 | Orders synchronization failed |
2002 | Sync trading history |
2003 | Trading history synchronization failed |
2004 | Sync positions |
2005 | Positions synchronization failed |
2006 | Ready to Trade |
2007 | Trading Disabled |
UAT Environment
Introduction
Our demo environment provides the ability to finish the integration without putting real money at risk. To start the process, you'll need to create new or use existing credentials for one of the supported exchanges.
Important: do not use production credentials with a demo environment.
Exchange | URL | Comments |
---|---|---|
Deribit | https://test.deribit.com/ | |
Coinbase Pro | https://public.sandbox.pro.coinbase.com/ | |
OKX | https://www.okx.com/learn/how-to-practice-trading-crypto-on-okx-with-demo-trading | |
ByBit | https://testnet.bybit.com/ | |
BitMEX | https://testnet.bitmex.com/ |
Available instruments
Exchange | Internal exchange name | Symbol | Native Name |
---|---|---|---|
Deribit | DERIBIT | PERP:BTC-PERP:BTC | BTC-PERPETUAL |
PERP:ETH-PERP:ETH | ETH-PERPETUAL | ||
PERP:BTC-PERP:USDC | BTC_USDC-PERPETUAL | ||
Coinbase Pro | COINBASE | BTC/USD | BTC-USD |
ETH/USD | ETH-USD | ||
LTC/USD | LTC-USD | ||
OKX | OKEX | BTC/USDT | BTC-USDT |
ETH/USDT | ETH-USDT | ||
LTC/USDT | LTC-USDT | ||
PERP:BTC-PERP:BTC | BTC-USD-SWAP | ||
PERP:ETH-PERP:ETH | ETH-USD-SWAP | ||
PERP:LTC-PERP:LTC | LTC-USD-SWAP | ||
ByBit | BYBIT | PERP:BTC-PERP:BTC | BTCUSD |
PERP:BTC-PERP:USDT | BTCUSDT | ||
BTC/USDT | BTCUSDT | ||
BTC/USDC | BTCUSDC | ||
ETH/BTC | ETHBTC | ||
PERP:ETH-PERP:ETH | ETHUSD | ||
PERP:ETH-PERP:USDT | ETHUSDT | ||
ETH/USDT | ETHUSDT | ||
ETH/USDC | ETHUSDC | ||
BitMEX | BITMEX | PERP:BTC-PERP:BTC | XBTUSD |
PERP:BTC-PERP:USDT | XBTUSDT | ||
PERP:ETH-PERP:BTC | ETHUSD | ||
PERP:ETH-PERP:USDT | ETHUSDT |