NAV Navbar

Note

Quick Start

  1. Apply for an account and get accountID, API_Key_ID and API_Secret_Key
  2. Use JWT to sign every request.
  3. Send new order through order.insertOrder
  4. Use Websocket client to get order status.

Make Request

HTTP:

POST /openApi/v1 HTTP/1.1
Host: api.apifiny.com
Content-Type: application/json
cache-control: no-cache
{
    "accountId": "ST-00000001"
}

Use HTTP POST to make request:

POST https://api.apifiny.com/openApi/v1?signature={signature}

The request end point is imbedded in the signature.

Signature

Signature:

// js
signature = JWT(payload={
    "accountId": "accountID",
    "secretKeyId": "API_Key_ID",
    "digest": hash256(RequestBody),
    "method": "module.methodName",
    "exp": 1535526941
}, key='API_Secret_Key', algorithm='HS256')
# python3
import hashlib
import jwt
import json

digest = hashlib.sha256(json.dumps(RequestBody).encode()).hexdigest()
signature = jwt.encode({
    'accountId': "accountID",
    'secretKeyId': "API_Key_ID",
    'digest': digest,
    'method': "module.methodName",
    'exp': 1535526941,
}, "API_Secret_Key", algorithm='HS256')

Please use JWT to generate Signature for each request , please refer to jwt.io on how to use JWT.

For every request, please use JWT and secretKey to generate Signature and use Signature in HTTP post parameter.

Payload in Signature includes following content:

Parameter Description
accountId Account ID
secretKeyId API Key ID
key API Key secret
digest hash value of the request body using sha256 hash
method api method
exp expiration time of signature

Standard response

The structure of response:

{
  "result": null,
  "error": {
    "code": 131114,
    "message": "account not found"
  }
}

After making API request, the server will send back a response in JSON format. The response include:

Parameter Description
result when request is successful, this key will include result of request. When request if not successful, its value is null.
error when request is not successful, the key will give the error message. Its value is null when request is successful.
code Error code. Please refer to error code explanation section.
message Error message.

Open API

Note:the response in following API is the result part of standard response.

Create New Order

Request:

{
  "accountId": "ST-0000001",
  "orderId": "000000121574697605570321",
  "orderInfo": {
    "symbol": "BTCUSD",
    "orderType": "LIMIT",
    "orderSide": "BUY",
    "limitPrice": "100",
    "quantity": "1.12"
  }
}

Response:

{
  "accountId": "ST-0000001",
  "orderId": "000000121574697605570321",
  "exchOrdId" : "",
  "symbol": "BTCUSD",
  "orderType": "LIMIT",
  "orderSide": "BUY",
  "limitPrice": 100,
  "quantity": 1.12,
  "filledAveragePrice": 0,
  "filledCumulativeQuantity": 0,
  "openQuantity": 1.12,
  "orderStatus": "PENDING_SUBMIT",
  "createdAt": 1537857271784,
  "updatedAt":  1537857271784,
  "cancelledUpdatedAt": null,
  "filledUpdatedAt": null
}

Make a new order a request:

Method:

method: order.insertOrder

Request:

Parameter Description
accountId Account ID
orderId Order ID
symbol symbol
orderType order type
orderSide order side
limitPrice limit price
quantity quantity

Order ID needs to be following format: account id plus 13 digit of timestamp + 3 digit of random number.

Response:

Parameter Description
accountId Account ID
orderId Order ID
exchOrdId Exchange Order Id -- reserved for future enhancement
symbol symbol
orderType order type
orderSide order side
limitPrice limit price
quantity quantity
filledAveragePrice average fill price
filledCumulativeQuantity accumulated fill quanity
openQuantity Open quantity to be filled
orderStatus Order Status
createdAt Order creation timestamp
updatedAt Order update timestamp
cancelledUpdatedAt if it is cancelled, cancellation timestamp
filledUpdatedAt Last filled timestamp

Order Type:

Order Side:

Order Status:

Order Status Explanation
PENDING_SUBMIT Order has been send but not confirmed
SUBMITTED and has been accepted and acknowledged or Partially filled.
FILLED Completely filled
CANCELLED Order is cancelled
REJECTED Order is rejected.

Cancel Order

Request:

{
  "accountId": "ST-0000001",
  "orderId": "000000121574697605570321"
}

Response:

{
  //Same as new order response
}

Request Cancel Order,cancelledUpdatedAt in Order will be updated.

Note:Order can only be cancelled when order status is not PENDING_SUBMIT,and cancelledUpdatedAt is null.

Method:

method: order.cancelOrder

Request:

Parameter Description
accountId Account ID
orderId Order ID

Response:

Same as new order response.

Query Single Order Info

Request:

{
  "accountId": "ST-0000001",
  "orderId": "000000121574697605570321"
}

Response:

{
  //Same as new order response
}

Method:

method: order.queryOrderInfo

Request:

Parameter Description
accountId Account ID
orderId Order ID

Response:

Same as new order response.

Query Multiple Order Info

Request:

{
  "accountId": "ST-0000001",
  "orderIdList": ["000000121574697605570321","000000121574697754664817"]
}

Response:

[
  {
     //Same as new order response
  }
  {
     //Same as new order response
  }
]

Method:

method: order.listOrderInfo

Request:

Parameter Description
accountId Account ID
orderIdList the total number of order id cannot exceed 500

Response:

Same as new order response.

Query All Open Order

Request:

{
  "accountId": "ST-0000001",
}

Response:

[
  {
     //Same as new order response
  }
  {
     //Same as new order response
  }
]

Method:

method: order.listOpenOrder

Request:

Parameter Description
accountId Account ID

Response:

Same as new order response.

Query All Completed Order

Request:

{
  "accountId": "ST-0000001",
  "startTime": 1537857271784,
  "endTime": 1537857271784,
  "limit": 100,
  "forward": null,
  "baseAsset": null,
  "quoteAsset": null,
  "orderSide": null,
  "orderStatus": null
}

Response:

[
  {
     //Same as new order response
  }
  {
     //Same as new order response
  }
]

Query all filled orders, cancelled orders, and rejected orders.

Method:

method: order.listCompletedOrder

Request:

Parameter Description
accountId Account ID
startTime start time
endTime end time
limit total number of orders, max is 500
forward true for forward, false for backward. (optional)
baseAsset base asset. for example, for BTCUSD,it is BTC. (optional)
quoteAsset quote asset,For BTCUSD,it is USD. (optional)
orderSide Order Side: BUY, SELL. (optional)
orderStatus Order Status: FILLED, CANCELLED. (optional)

Response:

Same as new order response.

Query Account Info

Request:

{
  "accountId": "ST-0000001",
}

Response:

{
  "accountId": "STA-0000001",
  "accountStatus": "OPENED",
  "createdAt": 1537857271784,
  "updatedAt": 1551956476878,
}

Method:

method: account.queryAccountInfo

Request:

Parameter Description
accountId Account ID

Response:

Parameter Description
accountId Account ID
accountStatus Account Status
orderCommissionRate Commission Rate
orderCommissionAdjust Commission adjust is allowed
createdAt creation time
updatedAt update time

Account Status:

Account Status Explanation
OPENED normal
RESTRICTED restricted. Cannot submit order, cancel order, but can query order.
SUSPENDED Suspended, all operation are not allowed.

Query Account Asset

Request:

{
  "accountId": "ST-0000001",
}

Response:

[
  {
    "accountId": "ST-0000001",
    "currency": "BTC",
    "available": 51.95,
    "frozen": 0,
    "amount": 51.95,
    "updatedAt": 1547208404061
  }
]

Method:

method: asset.listBalance

Request:

Parameter Description
accountId Account ID

Response:

Parameter Description
accountId Account ID
currency Symbol of asset
available Available quantity
frozen frozen value
amount amount
updatedAt update time

Query List Symbol

Response:

[
    {
      "symbol": "BTCUSD",
      "status": "TRADING",
      "nextStatus": null,
      "nextStatusAt": null,
      "baseAsset": "BTC",
      "baseAssetPrecision": 8,
      "quoteAsset": "USD",
      "quotePrecision": 8,
      "minPrice": 0.00000001,
      "maxPrice": 99999,
      "priceTickSize": 0.000001,
      "minQuantity": 0.01,
      "maxQuantity": 99999,
      "quantityStepSize": 0.01,
      "commissionRate": 0.01
    }
  ]

Method:

method: utils.listSymbol

Request: None

Response:

Parameter Description
symbol symbol
status symbol status
nextStatus next status
nextStatusAt next status time
baseAsset base asset
baseAssetPrecision base asset precision
quoteAsset quote asset,the right side of symbol
quotePrecision quote asset precision
minPrice min price
maxPrice max price
priceTickSize min price increament size
minQuantity min quantity
maxQuantity max quantity
quantityStepSize quantity step size
commissionRate commission rate

symbol status:

symbol status explanation
TRADING normal trading
HALT trading is halted

Query asset currency

Response:

[
  {
    "currency": "BTC",
    "currencyPrecision": 8,
    "withdrawMaxAmount": 1000,
    "withdrawMinAmount": 0.01,
    "withdrawMinFee": 0.0001,
    "status": "DEPOSIT_WITHDRAW",
    "nextStatus": null,
    "nextStatusAt": null
  }
]

Method:

method: utils.listCurrency

Parameters: None

Response:

Parameter Description
currency currency
currencyPrecision currency precision
withdrawMaxAmount max withdraw amount
withdrawMinAmount min withdraw ammount
withdrawMinFee min withdraw fee
status current status
nextStatus next status
nextStatusAt next status time

currency status:

status explanation
DEPOSIT_WITHDRAW deposit and withdraw are both allowed
NOT_DEPOSIT_WITHDRAW deposit is not allowed, withdraw is allowed
DEPOSIT_NOT_WITHDRAW deposit is allowed, but withdraw is not allowed
NOT_DEPOSIT_NOT_WITHDRAW deposit and withdraw are both not allowed

Query current timestamp of server

Response:

1552112542263

Method:

method: utils.currentTimeMillis

Parameter: None

Response: the server timestamp

Order Status Push Notice

Order status change notice obtained through HTTP and Websocket.

open API

Request:

{
  "accountId": "ST-0000001",
}

Response:

{
  {
   "logTimestamp" : 1552116459512,
   "payload" : {
     "accountId" : "ST-00000001",
     "orderId" : "000000121574697605570321",
     "symbol" : "BTCUSD",
     "orderType" : "LIMIT",
     "orderSide" : "BUY",
     "limitPrice" : 100.0,
     "quantity" : 1.12,
     "filledAveragePrice" : 0,
     "filledCumulativeQuantity" : 0,
     "openQuantity" : 0.001,
     "orderStatus" : "PENDING_SUBMIT",
     "createdAt" : 1537857271784,
     "updatedAt" : 1537857271784,
     "cancelledUpdatedAt" : null,
     "filledUpdatedAt" : null,
     "lastFilledQuantity" : null,
     "lastFilledPrice" : null,
     "lastFilledCreatedAt" : null
  },
  {
   "logTimestamp" : 1552116459536,
   "payload" : {
     "accountId" : "ST-00000001",
     "orderId" : "000000121574697605570321",
     "symbol" : "BTCUSD",
     "orderType" : "LIMIT",
     "orderSide" : "BUY",
     "limitPrice" : 100.0,
     "quantity" : 1.12,
     "filledAveragePrice" : 100.0,
     "filledCumulativeQuantity" : 1.12,
     "openQuantity" : 0,
     "orderStatus" : "FILLED",
     "createdAt" : 1537857271784,
     "updatedAt" : 1537857271784,
     "cancelledUpdatedAt" : null,
     "filledUpdatedAt" : 1552116459467,
     "lastFilledQuantity" : 1.12,
     "lastFilledPrice" : 100.0,
     "lastFilledCreatedAt" : 1537857271784
  }
}

Method:

method: order.streamDetail

Request:

Parameter Description
accountId Account ID
orderId Order ID

Response:

Parameter Description
lastFilledQuantity last filled quantity
lastFilledPrice last filled price
lastFilledCreatedAt last filled time

WebSocket API

Response:

{
  {
   "logTimestamp" : 1552116459536,
   "payload" : {
     "accountId" : "ST-00000001",
     "orderId" : "000000121574697605570321",
     "symbol" : "BTCUSD",
     "orderType" : "LIMIT",
     "orderSide" : "BUY",
     "limitPrice" : 100.0,
     "quantity" : 1.12,
     "filledAveragePrice" : 100.0,
     "filledCumulativeQuantity" : 1.12,
     "openQuantity" : 0,
     "orderStatus" : "FILLED",
     "createdAt" : 1552116459467,
     "updatedAt" : 1552116459467,
     "cancelledUpdatedAt" : null,
     "filledUpdatedAt" : 1552116459467,
     "lastFilledQuantity" : 1.12,
     "lastFilledPrice" : 100.0,
     "lastFilledCreatedAt" : 1552116459467
  }
}

Order update notice can be obtained through WebSocket :

Method:

ws[s]://api.apifiny.com/openApi/v1?signature={signature}&body={body}&p=webSocket

Note: Need to add one parameter in url:&p=webSocket

Method:

method: order.streamDetail

Market Data Specification(ExOne)

Market data is obtained through Websocket or RESTful interface.

Signature

Signature:

// js
signature = JWT(payload={
    "accessKey": "API_Key_ID"
}, key="API_Secret_Key", algorithm='HS256')
# python3
import jwt
signature = jwt.encode({'accessKey': "API_Key_ID"}, "API_Secret_Key", algorithm='HS256')
headers = {'signature': str(signature, encoding='utf-8')}

Request:

curl -X GET -H "signature: eyJhbI1NiJ9.eyJhY**************lY1TyJ9.RrWnyheQs" "https://api.apifiny.com/gx/orderbook/v1/BTCUSD/VENUE1"

Please use JWT to generate Signature and add parameter signature to each request header.

For every request, please use JWT and secretKey to generate Signature and use Signature in request header parameter.

Parameter Description
accessKey API Key ID
key API Key secret

Websocket Inteface

Request (subscription):

{
  "channel":"orderbook",
  "symbol":"BTCUSD",
  "action":"sub"
}

Request (unsubscribing):

{
  "channel":"orderbook",
  "symbol":"BTCUSD",
  "action":"unsub"
}

Response:

{
  "channel" : "orderbook",
  "symbol" : "BTCUSD",
  "orderbook" : {
    "symbol" : "BTCUSD",
    "updatedAt" : 1574713605000,
    "asks": [
        [10000.0, 0.004]
        // [price, size]
        // ……
    ],
    "bids": [
        [7000.0, 0.04],
        [6980.0, 0.0048]
    ]
 }

The websocket end point is

URL:

wss://api.apifiny.com/orderbook/v1

Request:

The request for subscription/unsubscribing must be in JSON format.

Parameter Description
channel channel is orderbook
symbol symbol
action subscription or unsubscribing

Response:

The response of websocket request is also in JSON format.

RESTful Interface

Response:

{
  "channel" : "orderbook",
  "symbol" : "BTCUSD",
  "orderbook" : {
    "symbol" : "BTCUSD",
    "updatedAt" : 1574713605000,
    "asks": [
        [10000.0, 0.004]
        // [price, size]
        // ……
    ],
    "bids": [
        [7000.0, 0.04],
        [6980.0, 0.0048]
    ]
 }

RESTFul interface endpoint is:

URL:

GET https://api.apifiny.com/orderbook/v1/{SYMBOL}

The {SYMBOL} is the pair to be subscribed. For example, ETHBTC.

Response:

Same as websocket response.

FIX Protocol Specification

FIX Protocol can be implemented using QuickFIX open source engine,please refer to :QuickFIX

The following language is supported :

Configuration for quickfix

quickfix configuration :

[default]
ConnectionType=initiator
SenderCompID=ST-00000001
TargetCompID=broker
SocketConnectHost=fix.api.apifiny.com
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ReconnectInterval=5
UseDataDictionary=Y
ResetSeqNumFlag=Y
ResetOnLogon=Y
ResetOnLogout=Y
ResetOnDisconnect=Y

[session]
BeginString=FIX.4.2
SocketConnectPort=443

There has an optional sample configuration for login using quickfix. Fix endpoint is: fix.api.apifiny.com:443

Below is an example using Python.

Logon

 def toAdmin(self, message, sessionID):
        if message.getHeader().getField(35) is "A":
            key = 'XXXX'
            signature = get_signature('new_gbbo_order', 'ST-00000015', 'STA-00000015','STA-00000015', key)
            message.setField(fix.RawDataLength(len(signature)))
            message.setField(fix.RawData(signature))
        ...

get_signature is as following:

def get_signature(method, account_id, secret_key_id, params, secret_key):
    now = datetime.datetime.now()
    expect_time = now + datetime.timedelta(seconds=30)
    params_json_string = json.dumps(params) if isinstance(params, dict) else params
    digest = hashlib.sha256(params_json_string.encode()).hexdigest()
    signature = jwt.encode({
        'accountId': account_id,
        'secretKeyId': secret_key_id,
        'digest': digest,
        'method': method,
        'exp': int(expect_time.timestamp()),
    }
        , secret_key)
    # print(str(signature, encoding='utf-8'))
    return str(signature, encoding='utf-8')

Add JWT encrypted token in toAdmin.

New Order

    msg = quickfix42.NewOrderSingle()
    msg.setField(fix.ClOrdID(order_id)) # generated order id:00000015+13digt time stamp + 3 digit random number
    msg.setField(fix.Symbol(symbol)) # symbol:BTCUSD
    msg.setField(fix.HandlInst('1'))
    msg.setField(fix.OrdType(fix.OrdType_LIMIT)) # OrdType:limit
    msg.setField(fix.TransactTime())
    msg.setField(fix.Side(side))
    msg.setField(fix.Price(price))
    msg.setField(fix.Account(account_id))
    msg.setField(fix.OrderQty(qty))
    msg.setField(fix.Text("new Order"))
    quickfix.Session.sendToTarget(msg, application.sessionID)

New Order message is following in :

Cancel Order

    msg = quickfix42.OrderCancelRequest()
    msg.setField(fix.OrigClOrdID(order_id))
    msg.setField(fix.ClOrdID(order_id))
    msg.setField(fix.Symbol(symbol))
    msg.setField(fix.TransactTime())
    msg.setField(fix.Side(side))
    msg.setField(fix.Account(account_id))
    msg.setField(fix.Text("Cancel Order"))

Cancel ordermessage:

Execution Report

Execution Report message Sent by the broker/gateway when an order is accepted, rejected, filled, or canceled.

Tag Name Description
11 ClOrdID Only present on order acknowledgements, ExecType=New (150=0)
37 OrderID OrderID from the ExecutionReport with ExecType=New (150=0)
17 ExecId Unique identifier of execution message
55 Symbol Symbol of the original order
54 Side Must be 1 to buy or 2 to sell
32 LastShares Amount filled (if ExecType=1). Also called LastQty as of FIX 4.3
44 Price Price of the fill if ExecType indicates a fill, otherwise the order price
38 OrderQty OrderQty as accepted
60 TransactTime Time the event occurred
150 ExecType May be 1 (Partial fill) for fills
39 OrdStatus Order status as of the current message

ExecType VALUES

ExecType Description
0 Ack
1 Fill
4 Canceled
8 Rejected

Query order status

    msg = quickfix42.OrderStatusRequest()
    msg.setField(fix.ClOrdID(order_id))
    msg.setField(fix.Symbol(symbol))
    msg.setField(fix.Side(side))
    msg.setField(fix.Account(account_id))

query order message is as following:

Others

HTTP Error code

Response Error code

The error code in the response is hex integer number。

Last number is A means client side error, B means server side error.

Please don't do frequent request when error happens. If it is client side error, please correct error and resubmit request. If it is server side error, it can retried but in low frequency, if it still has error, please contact customer support.

If too many error happens or frequent request, the IP will be banned.

Error Code Explanation
0x01001A general request error, please check if the parameters in request are correct.
0x01002B general server side error, retry or contact customer service
0x02002A Account doesn't exist, please verify account ID.
0x02005A Account status doesn't satisfy request, please verify account status.
0x05001A Order ID doesn't exist, please check order id.
0x05002B New order failure,retry or contact customer service
0x05003A Order doesn't exist, please change order ID
0x05004B cancel order error, need to contact customer service
0x05005A timeout for new order or other request, please wait and retry.
0x05006A too many open orders, cannot create new order, need to delete some orders and retry.
0x05007A cannot cancel order under current order status, need confirm order status and retry or abandon request
0x05008A timeout for cancel order operation, need wait and retry.
0x05011A the number of new order within 24 hours exceed limit, please contact customer service.
0x05014A the order is being cancelled, please verify order status
0x05015A order cannot be cancelled when in Pending_Submit status,please wait for status changed to submitted to cancel order.( if order status is still pending submit after 10 minutes, please contact customer service. )
0x06002A Not enough asset available. Please verify if there is enough asset in account.