NAV
curl javascript python

Change Log

Introduction

Welcome to CoinFLEX US's application programming interface (API). CoinFLEX US's APIs provide clients programmatic access to control aspects of their accounts and to place orders on CoinFLEX US's trading platform. CoinFLEX US supports the following types of APIs:

Using these interfaces it is possible to place both authenticated and unauthenticated API commands for public and prvate commands respectively.

To get started please register for a TEST account at https://stg.coinflex.us/user-console/register

API Key Management

An API key is required to make an authenticated API command. API keys (public and corresponding secret key) can be generated via the CoinFLEX US GUI within a clients account.

By default, API Keys are read-only and can only read basic account information, such as positions, orders, and trades. They cannot be used to trade such as placing, modifying or cancelling orders.

If you wish to execute orders with your API Key, clients must select the Can Trade permission upon API key creation.

API keys are also only bound to a single sub-account, defined upon creation. This means that an API key will only ever interact and return account information for a single sub-account.

Historical Data

CoinFLEX US's historical L2 order book data (depth data), can be found at https://docs.tardis.dev/historical-data-details/coinflexus (third party API), which includes historical market data details - instruments, data coverage and data collection specifics for all of our instruments since 2020-07-14.

Rate Limit

CoinFLEX US's APIs allows our clients to access and control their accounts or view our market data using custom-written software. To protect the performance of the system, we impose certain limits:

Type Limit
Rest API 100 per second
Rest API 2500 per 5 mins
Initialising Websocket Connection 200 per minute
Websocket API (Auth) 50 per second
Websocket API (No Auth) 1 per second

Websocket API

Subscription request format

{
  "op": "<value>",
  "tag": "<value>",
  "args": ["<value1>", "<value2>",.....]
}

Subscription success response format

{
  "event": "<opValue>",
  "success": True,
  "tag": "<value>",
  "channel": "<argsValue>",
  "timestamp": "1592491945368"
}

Subscription failure response format

{
  "event": "<opValue>",
  "success": False,
  "tag": "<value>",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "timestamp": "1592498745368"
}

Command request format

{
  "op": "<value>",
  "tag": "<value>",
  "data": {"<key1>": "<value1>",.....}
}

Command success response format

{
  "event": "<opValue>",
  "success": True
  "tag": "<value>",
  "timestamp": "1592498745368",
  "data": {"<key1>": "<value1>",.....}
}

Command failure response format

{
  "event": "<opValue>",
  "success": False,
  "message": "<errorMessage>",
  "code": "<codeCode>",
  "timestamp": "1592498745368",
  "data": {"<key1>": "<value1>",.....}
}

TEST site

LIVE site

CoinFLEX US's application programming interface (API) provides our clients programmatic access to control aspects of their accounts and to place orders on the CoinFLEX US trading platform. The API is accessible via WebSocket connection to the URIs listed above. Commands, replies, and notifications all traverse the WebSocket in text frames with JSON-formatted payloads.

Websocket commands can be sent in either of the following two formats:

For subscription based requests

{"op": "<value>", "args": ["<value1>", "<value2>",.....]}

op: can either be:

args: the value(s) will be the instrument ID(s) or asset ID(s), for example:

All other commands

{"op": "<command>", "data": {"<key1>":"<value1>",.....}}

op: can be:

data: JSON string of the request object containing the required parameters

Further information regarding the error codes and corresponding error messages from a failed subscription or order command request can be found in a later section of this documentation Error Codes.

WebSocket adapter

coinflex-us-ws is a websocket wrapper to easily connect to CoinFLEX US's websockets.

Authentication

Request format

{
  "op": "login",
  "tag": "<value>",
  "data": {
            "apiKey": "<string>",
            "timestamp": "<string>",
            "signature": "<string>"
          }
}
import websockets
import asyncio
import time
import hmac
import base64
import hashlib
import json

api_key = 'API-KEY'
api_secret = 'API-SECRET'
ts = str(int(time.time() * 1000))
sig_payload = (ts+'GET/auth/self/verify').encode('utf-8')
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), sig_payload, hashlib.sha256).digest()).decode('utf-8')

msg_auth = \
{
  "op": "login",
  "tag": 1,
  "data": {
           "apiKey": api_key,
           "timestamp": ts,
           "signature": signature
          }
}

async def subscribe():
    async with websockets.connect('wss://stgapi.coinflex.us/v1/websocket') as ws:
        await ws.send(json.dumps(msg_auth))
        while ws.open:
            resp = await ws.recv()
            print(resp)

asyncio.get_event_loop().run_until_complete(subscribe())
const CryptoJS = require("crypto-js");
const WebSocket = require('ws');

var apiKey = "API-KEY";
var secretKey = "API-SECRET";
const ts = '' + Date.now();

var sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(ts +'GET/auth/self/verify', secretKey));
var msg = JSON.stringify({  
                            "op": "login",
                            "tag": 1,
                            "data": {
                              "apiKey": apiKey,
                              "timestamp": ts,
                              "signature": sign
                            }
                          });

var ws = new WebSocket('wss://stgapi.coinflex.us/v1/websocket');

ws.onmessage = function (e) {
  console.log('websocket message from server : ', e.data);
};

ws.onopen = function () {
    ws.send(msg);
};

Success response format

{
  "event": "login",
  "success": true,
  "tag": "<value>",
  "timestamp": "1592491803978"
}
{
  "event": "login",
  "success": true,
  "tag": "1",
  "timestamp": "1592491808328"
}
{
  "event": "login",
  "success": true,
  "tag": "1",
  "timestamp": "1592491808329"
}

Failure response format

{
  "event": "login",
  "success": false,
  "code": "<errorCode>",
  "message": "<errorMessage>",
  "tag": "1",
  "timestamp": "1592492069732"
}
{
  "event": "login",
  "success": false,
  "code": "<errorCode>",
  "message": "<errorMessage>",
  "tag": "1",
  "timestamp": "1592492031972"
}
{
  "event": "login",
  "success": false,
  "code": "<errorCode>",
  "message": "<errorMessage>",
  "tag": "1",
  "timestamp": "1592492031982"
}

The Websocket API consists of public and private methods. The public methods do not require authentication. The private methods requires an authenticated websocket connection.

To autenticate a websocket connection a "login" message must be sent containing the clients signature.

The signature is constructed using a HMAC SHA256 operation to get a hash value, which in turn requires the clients API Secret as the key and a constructed message string as the value for the HMAC operation. This hash value is then encoded as a BASE-64 value which becomes the signature used for authentication.

API keys (public and corresponding secret key) can be generated via the GUI within the clients account.

The message string used in the HMAC SHA256 operation is constructed in the following way:

The signature can therefore be summarised by the following:

Request Parameters

Parameter Type Required Description
op STRING Yes 'login'
tag INTEGER or STRING No If given it will be echoed in the reply
data DICTIONARY object Yes
apiKey STRING Yes Clients public API key, visible in the GUI when created
timestamp STRING Yes Current millisecond timestamp
signature STRING Yes Base64(HmacSHA256(current_ms_timestamp + 'GET/auth/self/verify', API-Secret))

Session Keep Alive

To maintain an active WebSocket connection it is imperative to either be subscribed to a channel that pushes data at least once per minute (Depth or Balance) or send a ping to the server once per minute.

Order Commands

Place Limit Order

Request format

{
  "op": "placeorder",
  "tag": 123,
  "data": {
            "timestamp": 1638237934061,
            "recvWindow": 500,
            "clientOrderId": 1,
            "marketCode": "BTC-flexUSD",
            "side": "BUY",
            "orderType": "LIMIT",
            "quantity": 1.5,
            "timeInForce": "GTC",
            "price": 9431.48
          }
}
import websockets
import asyncio
import time
import hmac
import base64
import hashlib
import json

api_key = ''
api_secret = ''
ts = str(int(time.time() * 1000))
sig_payload = (ts+'GET/auth/self/verify').encode('utf-8')
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), sig_payload, hashlib.sha256).digest()).decode('utf-8')

auth = \
{
  "op": "login",
  "tag": 1,
  "data": {
           "apiKey": api_key,
           "timestamp": ts,
           "signature": signature
          }
}
place_order = \
{
  "op": "placeorder",
  "tag": 123,
  "data": {
            "timestamp": 1638237934061,
            "recvWindow": 500,
            "clientOrderId": 1,
            "marketCode": "BTC-flexUSD",
            "side": "BUY",
            "orderType": "LIMIT",
            "quantity": 1.5,
            "timeInForce": "GTC",
            "price": 9431.48
          }
}

url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            if 'nonce' in data:
                    await ws.send(json.dumps(auth))
            elif 'event' in data and data['event'] == 'login':
                if data['success'] == True:
                    await ws.send(json.dumps(place_order))
            elif 'event' in data and data['event'] == 'placeorder':
                continue

asyncio.get_event_loop().run_until_complete(subscribe())

Success response format


{
  "event": "placeorder",
  "submitted": True,
  "tag": "123",
  "timestamp": "1592491945248",
  "data": {
            "clientOrderId": "1",
            "marketCode": "BTC-flexUSD",
            "side": "BUY",
            "orderType": "LIMIT",
            "quantity": "1.5",
            "timeInForce": "GTC",
            "price": "9431.48",
            "orderId": "1000000700008",
            "source": 0
          }
}

Failure response format

{
  "event": "placeorder",
  "submitted": False,
  "tag": "123",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "timestamp": "1592491945248",
  "data": {
            "clientOrderId": "1",
            "marketCode": "BTC-flexUSD",
            "side": "BUY",
            "orderType": "LIMIT",
            "quantity": "1.5",
            "timeInForce": "GTC",
            "price": "9431.48",
            "source": 0
          }
}

Requires an authenticated websocket connection. Please also subscribe to the User Order Channel to receive push notifications for all message updates in relation to an account or sub-account (e.g. OrderOpened, OrderMatched etc......).

Request Parameters

Parameter Type Required Description
op STRING Yes placeorder
tag INTEGER or STRING No If given it will be echoed in the reply
data DICTIONARY object Yes
clientOrderId ULONG No Client assigned ID to help manage and identify orders with max value 9223372036854775807
marketCode STRING Yes Market code e.g. BTC-flexUSD
orderType STRING Yes LIMIT
price FLOAT No Price
quantity FLOAT Yes Quantity (denominated by contractValCurrency)
side STRING Yes BUY or SELL
timeInForce ENUM No
  • GTC (Good-till-Cancel) - Default
  • IOC (Immediate or Cancel, i.e. Taker-only)
  • FOK (Fill or Kill, for full size)
  • MAKER_ONLY (i.e. Post-only)
  • MAKER_ONLY_REPRICE (Reprices order to the best maker only price if the specified price were to lead to a taker trade)
timestamp LONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.
recvWindow LONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.

Place Market Order

Request format

{
  "op": "placeorder",
  "tag": 123,
  "data": {
            "timestamp": 1638237934061,
            "recvWindow": 500,
            "clientOrderId": 1,
            "marketCode": "ETH-flexUSD",
            "side": "SELL",
            "orderType": "MARKET",
            "quantity": 5
          }
}
import websockets
import asyncio
import time
import hmac
import base64
import hashlib
import json

api_key = '' 
api_secret = ''
ts = str(int(time.time() * 1000))
sig_payload = (ts+'GET/auth/self/verify').encode('utf-8')
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), sig_payload, hashlib.sha256).digest()).decode('utf-8')

auth = \
{
  "op": "login",
  "tag": 1,
  "data": {
           "apiKey": api_key,
           "timestamp": ts,
           "signature": signature
          }
}
place_order = \
{
  "op": "placeorder",
  "tag": 123,
  "data": {
            "timestamp": 1638237934061,
            "recvWindow": 500,
            "clientOrderId": 1,
            "marketCode": "ETH-flexUSD",
            "side": "SELL",
            "orderType": "MARKET",
            "quantity": 5
          }
}


url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)

            if 'nonce' in data:
                    await ws.send(json.dumps(auth))
            elif 'event' in data and data['event'] == 'login':
                if data['success'] == True:
                    await ws.send(json.dumps(place_order))
            elif 'event' in data and data['event'] == 'placeorder':
                continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "placeorder",
  "submitted": True,
  "tag": "123",
  "timestamp": "1592491945248",
  "data": {
            "clientOrderId": "1",
            "marketCode": "ETH-flexUSD",
            "side": "SELL",
            "orderType": "MARKET",
            "quantity": "5",
            "orderId": "1000001700008",
            "source": 0
          }
}

Failure response format

{
  "event": "placeorder",
  "submitted": False,
  "tag": "123",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "timestamp": "1592491503359",
  "data": {
            "clientOrderId": "1",
            "marketCode": "ETH-flexUSD",
            "side": "SELL",
            "orderType": "MARKET",
            "quantity": "5",
            "source": 0
          }
}

Requires an authenticated websocket connection. Please also subscribe to the User Order Channel to receive push notifications for all message updates in relation to an account or sub-account (e.g. OrderOpened, OrderMatched etc......).

Request Parameters

Parameter Type Required Description
op STRING Yes placeorder
tag INTEGER or STRING No If given it will be echoed in the reply
data DICTIONARY object Yes
clientOrderId ULONG No Client assigned ID to help manage and identify orders with max value 9223372036854775807
marketCode STRING Yes Market code e.g. BTC-flexUSD
orderType STRING Yes MARKET
quantity FLOAT Yes Quantity (denominated by contractValCurrency)
side STRING Yes BUY or SELL
timestamp LONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.
recvWindow LONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.

Place Stop Limit Order

Request format

{
  "op": "placeorder",
  "tag": 123,
  "data": {
            "timestamp": 1638237934061,
            "recvWindow": 500,
            "clientOrderId": 1,
            "marketCode": "ETH-flexUSD",
            "side": "BUY",
            "orderType": "STOP_LIMIT",
            "quantity": 10,
            "timeInForce": "MAKER_ONLY_REPRICE",
            "stopPrice": 100,
            "limitPrice": 120
         }
}
import websockets
import asyncio
import time
import hmac
import base64
import hashlib
import json

api_key = ''
api_secret = ''
ts = str(int(time.time() * 1000))
sig_payload = (ts+'GET/auth/self/verify').encode('utf-8')
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), sig_payload, hashlib.sha256).digest()).decode('utf-8')

auth = \
{
  "op": "login",
  "tag": 1,
  "data": {
           "apiKey": api_key,
           "timestamp": ts,
           "signature": signature
          }
}
place_order = \
{
  "op": "placeorder",
  "tag": 123,
  "data": {
            "timestamp": 1638237934061,
            "recvWindow": 500,
            "clientOrderId": 1,
            "marketCode": "ETH-flexUSD",
            "side": "BUY",
            "orderType": "STOP_LIMIT",
            "quantity": 10,
            "timeInForce": "MAKER_ONLY_REPRICE",
            "stopPrice": 100,
            "limitPrice": 120
         }
}


url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)

            if 'nonce' in data:
                    await ws.send(json.dumps(auth))
            elif 'event' in data and data['event'] == 'login':
                if data['success'] == True:
                    await ws.send(json.dumps(place_order))
            elif 'event' in data and data['event'] == 'placeorder':
                continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "placeorder",
  "submitted": True,
  "tag": "123",
  "timestamp": "1607639739098",
  "data": {
            "clientOrderId": "1",
            "marketCode": "ETH-flexUSD",
            "side": "BUY",
            "orderType": "STOP_LIMIT",
            "quantity": "10",
            "timeInForce": "MAKER_ONLY_REPRICE",
            "stopPrice": "100",
            "limitPrice": "120",
            "orderId": "1000002700008",
            "source": 0
          }
}

Failure response format

{
  "event": "placeorder",
  "submitted": False,
  "tag": "123",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "timestamp": "1592491503359",
  "data": {
            "clientOrderId": "1",
            "marketCode": "ETH-flexUSD",
            "side": "BUY",
            "orderType": "STOP_LIMIT",
            "quantity": "10",
            "timeInForce": "MAKER_ONLY_REPRICE",
            "stopPrice": "100",
            "limitPrice": "120",
            "source": 0
          }
}

Requires an authenticated websocket connection. Please also subscribe to the User Order Channel to receive push notifications for all message updates in relation to an account or sub-account (e.g. OrderOpened, OrderMatched etc......).

Request Parameters

Parameters Type Required Description
op STRING Yes placeorder
tag INTEGER or STRING No If given it will be echoed in the reply
data DICTIONARY object Yes
clientOrderId ULONG No Client assigned ID to help manage and identify orders with max value 9223372036854775807
marketCode STRING Yes Market code e.g. ETH-flexUSD
orderType STRING Yes STOP_LIMIT for stop-limit orders (stop-market orders not supported)
quantity FLOAT Yes Quantity (denominated by contractValCurrency)
side STRING Yes BUY or SELL
limitPrice FLOAT Yes Limit price for the stop-limit order.

For BUY the limit price must be greater or equal to the stop price.

For SELL the limit price must be less or equal to the stop price.

stopPrice FLOAT Yes Stop price for the stop-limit order.

Triggered by the best bid price for the SELL stop-limit order.

Triggered by the best ask price for the BUY stop-limit order.

timeInForce ENUM No
  • GTC (Good-till-Cancel) - Default
  • IOC (Immediate or Cancel, i.e. Taker-only)
  • FOK (Fill or Kill, for full size)
  • MAKER_ONLY (i.e. Post-only)
  • MAKER_ONLY_REPRICE (Reprices order to the best maker only price if the specified price were to lead to a taker trade)
timestamp LONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.
recvWindow LONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.

Place Batch Orders

Request format

{
  "op": "placeorders",
  "tag": 123,
  "dataArray": [{
                  "timestamp": 1638237934061,
                  "recvWindow": 500,
                  "clientOrderId": 1,
                  "marketCode": "ETH-flexUSD",
                  "side": "BUY",
                  "orderType": "LIMIT",
                  "quantity": 10,
                  "timeInForce": "MAKER_ONLY",
                  "price": 100
                }, 
                {
                  "timestamp": 1638237934061,
                  "recvWindow": 500,
                  "clientOrderId": 2,
                  "marketCode": "BTC-flexUSD",
                  "side": "SELL",
                  "orderType": "MARKET",
                  "quantity": 0.2
                }]
}
import websockets
import asyncio
import time
import hmac
import base64
import hashlib
import json

api_key = ''
api_secret = ''
ts = str(int(time.time() * 1000))
sig_payload = (ts+'GET/auth/self/verify').encode('utf-8')
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), sig_payload, hashlib.sha256).digest()).decode('utf-8')

auth = \
{
  "op": "login",
  "tag": 1,
  "data": {
           "apiKey": api_key,
           "timestamp": ts,
           "signature": signature
          }
}
place_batch_order =\
{
  "op": "placeorders",
  "tag": 123,
  "dataArray": [{
                  "timestamp": 1638237934061,
                  "recvWindow": 500,
                  "clientOrderId": 1,
                  "marketCode": "ETH-flexUSD",
                  "side": "BUY",
                  "orderType": "LIMIT",
                  "quantity": 10,
                  "timeInForce": "MAKER_ONLY",
                  "price": 100
                },
                {
                  "timestamp": 1638237934061,
                  "recvWindow": 500,
                  "clientOrderId": 2,
                  "marketCode": "BTC-USD",
                  "side": "SELL",
                  "orderType": "MARKET",
                  "quantity": 0.2
                }]
}

url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)
            if 'nonce' in data:
                    await ws.send(json.dumps(auth))
            elif 'event' in data and data['event'] == 'login':
                if data['success'] == True:
                    await ws.send(json.dumps(place_batch_order))
            elif 'event' in data and data['event'] == 'placeorder':
                continue

asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "placeorder",
  "submitted": True,
  "tag": "123",
  "timestamp": "1607639739098",
  "data": {
            "clientOrderId": "1",
            "marketCode": "ETH-flexUSD",
            "side": "BUY",
            "orderType": "LIMIT",
            "quantity": "10",
            "timeInForce": "MAKER_ONLY",
            "price": "100",
            "orderId": "1000003700008",
            "source": 0
          }
}

AND

{
  "event": "placeorder",
  "submitted": True,
  "tag": "123",
  "timestamp": "1607639739136",
  "data": {
            "clientOrderId": "2",
            "marketCode": "BTC-USD",
            "side": "SELL",
            "orderType": "MARKET",
            "quantity": "0.2",
            "orderId": "1000004700009",
            "source": 0
          }
}

Failure response format

{
  "event": "placeorder",
  "submitted": False,
  "tag": "123",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "timestamp": "1592491503359",
  "data": {
            "clientOrderId": "1",
            "marketCode": "ETH-flexUSD",
            "side": "BUY",
            "orderType": "LIMIT",
            "quantity": "10",
            "timeInForce": "MAKER_ONLY",
            "price": "100",
            "source": 0
          }
}

AND

{
  "event": "placeorder",
  "submitted": False,
  "tag": "123",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "timestamp": "1592491503457",
  "data": {
            "clientOrderId": "2",
            "marketCode": "BTC-USD",
            "side": "SELL",
            "orderType": "MARKET",
            "quantity": "0.2",
            "source": 0
          }
}

Requires an authenticated websocket connection. Please also subscribe to the User Order Channel to receive push notifications for all message updates in relation to an account or sub-account (e.g. OrderOpened, OrderMatched etc......).

All existing single order placement methods are supported:-

The websocket reply from the exchange will repond to each order in the batch separately, one order at a time, and has the same message format as the reponse for the single order placement method.

Request Parameters

Parameters Type Required Description
op STRING Yes placeorders
tag INTEGER or STRING No If given it will be echoed in the reply
dataArray LIST of dictionaries Yes A list of orders with each order in JSON format, the same format/parameters as the request for placing a single order. The max number of orders is still limited by the message length validation so by default up to 20 orders can be placed in a batch, assuming that each order JSON has 200 characters.
timestamp LONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.
recvWindow LONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.

Cancel Order

Request format

{
  "op": "cancelorder",
  "tag": 456,
  "data": {
            "marketCode": "BTC-flexUSD",
            "orderId": 12
          }
}
import websockets
import asyncio
import time
import hmac
import base64
import hashlib
import json

api_key = ''
api_secret = ''
ts = str(int(time.time() * 1000))
sig_payload = (ts+'GET/auth/self/verify').encode('utf-8')
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), sig_payload, hashlib.sha256).digest()).decode('utf-8')

auth = \
{
  "op": "login",
  "tag": 1,
  "data": {
           "apiKey": api_key,
           "timestamp": ts,
           "signature": signature
          }
}
cancel_order = \
{
  "op": "cancelorder",
  "tag": 456,
  "data": {
            "marketCode": "BTC-flexUSD",
            "orderId": 12
          }
}

url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)

            if 'nonce' in data:
                    await ws.send(json.dumps(auth))
            elif 'event' in data and data['event'] == 'login':
                if data['success'] == True:
                    await ws.send(json.dumps(cancel_order))
            elif 'event' in data and data['event'] == 'cancelorder':
                continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "cancelorder",
  "submitted": True,
  "tag": "456",
  "timestamp": "1592491173964",
  "data": {
            "marketCode": "BTC-flexUSD",
            "clientOrderId": "1",
            "orderId": "12"
          }
}

Failure response format

{
  "event": "cancelorder",
  "submitted": False,
  "tag": "456",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "timestamp": "1592491173964",
  "data": {
            "marketCode": "BTC-flexUSD",
            "orderId": "12"
          }
}

Requires an authenticated websocket connection. Please also subscribe to the User Order Channel to receive push notifications for all message updates in relation to an account or sub-account (e.g. OrderClosed etc......).

This command can also be actioned via the trading GUI using the Cancel button next to an open order in the Open Orders blotter for both Spot and Derivative markets.

Request Parameters

Parameters Type Required Description
op STRING Yes cancelorder
tag INTEGER or STRING No If given it will be echoed in the reply
data DICTIONARY object Yes
marketCode STRING Yes Market code e.g. BTC-flexUSD
orderId INTEGER Yes Unique order ID from the exchange

Cancel Batch Orders

Request format

{
  "op": "cancelorders",
  "tag": 456,
  "dataArray": [{
                  "marketCode": "BTC-flexUSD",
                  "orderId": 12
                },
                {
                  "marketCode": "BCH-USD",
                  "orderId": 34
                }]
}
import websockets
import asyncio
import time
import hmac
import base64
import hashlib
import json

api_key = ''
api_secret = ''
ts = str(int(time.time() * 1000))
sig_payload = (ts+'GET/auth/self/verify').encode('utf-8')
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), sig_payload, hashlib.sha256).digest()).decode('utf-8')

auth = \
{
  "op": "login",
  "tag": 1,
  "data": {
           "apiKey": api_key,
           "timestamp": ts,
           "signature": signature
          }
}
cancel_batch_order = \
{
  "op": "cancelorders",
  "tag": 456,
  "dataArray": [{
                  "marketCode": "BTC-flexUSD",
                  "orderId": 12
                },
                {
                  "marketCode": "BCH-USD",
                  "orderId": 34
                }]
}

url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)

            if 'nonce' in data:
                    await ws.send(json.dumps(auth))
            elif 'event' in data and data['event'] == 'login':
                if data['success'] == True:
                    await ws.send(json.dumps(cancel_batch_order))
            elif 'event' in data and data['event'] == 'cancelorder':
                continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "cancelorder",
  "submitted": True,
  "tag": "456",
  "timestamp": "1592491173964",
  "data": {
            "marketCode": "BTC-flexUSD",
            "clientOrderId": "1",
            "orderId": "12"
          }
}

AND

{
  "event": "cancelorder",
  "submitted": True,
  "tag": "456",
  "timestamp": "1592491173978",
  "data": {
            "marketCode": "BCH-USD",
            "orderId": "34"
          }
}

Failure response format

{
  "event": "cancelorder",
  "submitted": False,
  "tag": "456",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "timestamp": "1592491173964",
  "data": {
            "marketCode": "BTC-flexUSD",
            "orderId": "12"
          }
}

AND

{
  "event": "cancelorder",
  "submitted": False,
  "tag": "456",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "timestamp": "1592491173989",
  "data": {
            "marketCode": "BCH-USD",
            "orderId": "12"
          }
}

Requires an authenticated websocket connection. Please also subscribe to the User Order Channel to receive push notifications for all message updates in relation to an account or sub-account (e.g. OrderClosed etc......).

Request Parameters

Parameters Type Required Description
op STRING Yes cancelorders
tag INTEGER or STRING No If given it will be echoed in the reply
dataArray LIST of dictionaries A list of orders with each order in JSON format, the same format/parameters as the request for cancelling a single order. The max number of orders is still limited by the message length validation so by default up to 20 orders can be placed in a batch, assuming that each order JSON has 200 characters.

Subscriptions - Private

All subscriptions to private account channels requires an authenticated websocket connection.

Multiple subscriptions to different channels both public and private can be made within a single subscription command:

{"op": "subscribe", "args": ["<value1>", "<value2>",.....]}

Balance Channel

Request format

{
  "op": "subscribe",
  "args": ["balance:all"],
  "tag": 101
}

OR

{
  "op": "subscribe", 
  "args": ["balance:USD", "balance:FLEX", ........], 
  "tag": 101
}
import websockets
import asyncio
import time
import hmac
import base64
import hashlib
import json

api_key = ''
api_secret = ''
ts = str(int(time.time() * 1000))
sig_payload = (ts+'GET/auth/self/verify').encode('utf-8')
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), sig_payload, hashlib.sha256).digest()).decode('utf-8')

auth = \
{
  "op": "login",
  "tag": 1,
  "data": {
           "apiKey": api_key,
           "timestamp": ts,
           "signature": signature
          }
}
balance = \
{
  "op": "subscribe",
  "args": ["balance:all"],
  "tag": 101
}
url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)
            if 'nonce' in data:
                    await ws.send(json.dumps(auth))
            elif 'event' in data and data['event'] == 'login':
                if data['success'] == True:
                    await ws.send(json.dumps(balance))
            elif 'event' in data and data['event'] == 'balance':
                 continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "success": True, 
  "tag": "101", 
  "event": "subscribe", 
  "channel": "<args value>", 
  "timestamp": "1607985371401"
}

Balance channel format

{
  "table": "balance",
  "accountId": "<Your account ID>",
  "timestamp": "1599693365059",
  "tradeType": "LINEAR",
  "data": [ {
              "total": "10000",
              "reserved": "1000",
              "instrumentId": "USD",
              "available": "9000",
              "quantityLastUpdated": "1599694369431"
            },
            {
              "total": "100000",
              "reserved": "0",
              "instrumentId": "FLEX",
              "available": "100000",
              "quantityLastUpdated": "1599694343242"
            }, 
            ........
          ]
}

Channel Update Frequency : 250ms

The websocket will reply with the shown success response format for each balance asset channel which has been successfully subscribed to.

If a subscription has been made to balance:all, the data array in the message from this balance channel will contain a JSON list. Each JSON will contain balance details for each spot asset. Otherwise the data array will contain a single JSON corresponding to one spot asset per asset channel subscription.

Request Parameters

Parameters Type Required Description
op STRING Yes subscribe
args LIST Yes balance:all or a list of individual assets balance:<assetId>
tag INTEGER or STRING No If given it will be echoed in the reply

Channel Update Fields

Fields Type Description
table STRING balance
accountId STRING Account identifier
timestamp STRING Current millisecond timestamp
tradeType STRING LINEAR
data LIST of dictionaries
total STRING Total spot asset balance
reserved STRING Reserved asset balance for working spot and repo orders
instrumentId STRING Base asset ID e.g. BTC
available STRING Remaining available asset balance (total - reserved)
quantityLastUpdated STRING Millisecond timestamp

Order Channel

Request format

{
  "op": "subscribe", 
  "args": ["order:all"], 
  "tag": 102
}

OR

{
  "op": "subscribe", 
  "args": ["order:FLEX-USD", "order:ETH-flexUSD", .....], 
  "tag": 102
}
import websockets
import asyncio
import time
import hmac
import base64
import hashlib
import json

api_key = ''
api_secret = ''
ts = str(int(time.time() * 1000))
sig_payload = (ts+'GET/auth/self/verify').encode('utf-8')
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), sig_payload, hashlib.sha256).digest()).decode('utf-8')

auth = \
{
  "op": "login",
  "tag": 1,
  "data": {
           "apiKey": api_key,
           "timestamp": ts,
           "signature": signature
          }
}
order = \
{
  "op": "subscribe", 
  "args": ["order:all"], 
  "tag": 102
}

url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)
            if 'nonce' in data:
                    await ws.send(json.dumps(auth))
            elif 'event' in data and data['event'] == 'login':
                if data['success'] == True:
                    await ws.send(json.dumps(order))
            elif 'event' in data and data['event'] == 'order':
                 continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "success": True, 
  "tag": "102", 
  "event": "subscribe", 
  "channel": "<args value>", 
  "timestamp": "1607985371401"
}

Channel Update Frequency : real-time, on order update

The websocket will reply with the shown success response format for EACH order channel which has been successfully subscribed to.

Request Parameters

Parameters Type Required Description
op STRING Yes subscribe
args LIST Yes order:all or a list of individual markets order:<marketCode>
tag INTEGER or STRING No If given it will be echoed in the reply

OrderOpened

OrderOpened message format - LIMIT order

{
  "table": "order",
  "data": [ {
              "notice": "OrderOpened",
              "accountId": "<Your account ID>",
              "clientOrderId": "16",
              "orderId" : "123",
              "price": "9600",
              "quantity": "2" ,
              "side": "BUY",
              "status": "OPEN",
              "marketCode": "BTC-flexUSD",
              "timeInForce": "MAKER_ONLY",
              "timestamp": "1594943491077"
              "orderType": "LIMIT",
              "isTriggered": "False"
            } ]
}

OrderOpened message format - STOP LIMIT order

{
  "table": "order",
  "data": [ {
              "notice": "OrderOpened",
              "accountId": "<Your account ID>",
              "clientOrderId": "17",
              "orderId": "2245",
              "quantity": "2",
              "side": "BUY",
              "status": "OPEN",
              "marketCode": "USDT-flexUSD",
              "timeInForce": "IOC",
              "timestamp": "1594943491077",
              "stopPrice": "9280",
              "limitPrice": "9300",
              "orderType": "STOP_LIMIT",
              "isTriggered": "True"
            } ]
}

Channel Update Fields

Fields Type Description
table STRING order
data LIST of dictionary
notice STRING OrderOpened
accountId STRING Account identifier
clientOrderId STRING Client assigned ID to help manage and identify orders with max value 9223372036854775807
orderId STRING Unique order ID from the exchange
price STRING Limit price submitted (only applicable for LIMIT order types)
quantity STRING Quantity submitted
side STRING BUY or SELL
status STRING Order status
marketCode STRING Market code e.g. FLEX-USD
timeInForce STRING Client submitted time in force, GTC by default
timestamp STRING Current millisecond timestamp
orderType STRING LIMIT or STOP_LIMIT
stopPrice STRING Stop price submitted (only applicable for STOP LIMIT order types)
limitPrice STRING Limit price submitted (only applicable for STOP LIMIT order types)
isTriggered STRING False or True

OrderClosed

OrderClosed message format - LIMIT order

{
  "table": "order",
  "data": [ {
              "notice": "OrderClosed",
              "accountId": "<Your account ID>",
              "clientOrderId": "16",
              "orderId": "73",
              "price": "9600",
              "quantity": "2",
              "side": "BUY",
              "status": "<Canceled status>",
              "marketCode": "BTC-flexUSD",
              "timeInForce": "<Time in force>",
              "timestamp": "1594943491077",
              "remainQuantity": "1.5",
              "orderType": "LIMIT",
              "isTriggered": "False" 
            } ]
}

OrderClosed message format - STOP LIMIT order

{
  "table": "order",
  "data": [ {
              "notice": "OrderClosed",
              "accountId": "<Your account ID>",
              "clientOrderId": "16",
              "orderId": "13",
              "quantity": "2",
              "side": "BUY",
              "status": "CANCELED_BY_USER",
              "marketCode": "BTC-flexUSD",
              "timeInForce": "<Time in force>",
              "timestamp": "1594943491077",
              "remainQuantity": "1.5",
              "stopPrice": "9100",
              "limitPrice": "9120",
              "orderType": "STOP_LIMIT",
              "isTriggered": "True" 
            } ]
}

There are multiple scenarios in which an order is closed as described by the status field in the OrderClosed message. In summary orders can be closed by:-

Channel Update Fields

Fields Type Description
table STRING order
data LIST of dictionary
notice STRING OrderClosed
accountId STRING Account identifier
clientOrderId STRING Client assigned ID to help manage and identify orders with max value 9223372036854775807
orderId STRING Unique order ID from the exchange
price STRING Limit price of closed order (only applicable for LIMIT order types)
quantity STRING Original order quantity of closed order
side STRING BUY or SELL
status STRING
  • CANCELED_BY_USER
  • CANCELED_BY_MAKER_ONLY
  • CANCELED_BY_FOK
  • CANCELED_ALL_BY_IOC
  • CANCELED_PARTIAL_BY_IOC
  • CANCELED_BY_AMEND
marketCode STRING Market code e.g. BTC-flexUSD
timeInForce STRING Time in force of closed order
timestamp STRING Current millisecond timestamp
remainQuantity STRING Remaining order quantity of closed order
stopPrice STRING Stop price of closed stop order (only applicable for STOP LIMIT order types)
limitPrice STRING Limit price of closed stop order (only applicable for STOP LIMIT order types)
ordertype STRING LIMIT or STOP_LIMIT
isTriggered STRING False or True

OrderClosed Failure

OrderClosed failure message format

{
  "event": "CANCEL", 
  "submitted": False, 
  "message": "Order request was rejected : REJECT_CANCEL_ORDER_ID_NOT_FOUND", 
  "code": "100004", 
  "timestamp": "0", 
  "data": {
            "clientOrderId": 3,
            "orderId": 3330802124194931673, 
            "displayQuantity": 0.0, 
            "lastMatchPrice": 0.0, 
            "lastMatchQuantity": 0.0, 
            "lastMatchedOrderId": 0, 
            "lastMatchedOrderId2": 0, 
            "matchedId": 0, 
            "matchedType": "MAKER", 
            "remainQuantity": 0.0, 
            "side": "BUY", 
            "status": "REJECT_CANCEL_ORDER_ID_NOT_FOUND", 
            "timeCondition": "GTC", 
            "marketCode": "BTC-flexUSD", 
            "timestampEpochMs": 1615377638518, 
            "orderType": "LIMIT",
            "price": 0.0, 
            "quantity": 0.0, 
            "isTriggered": False
          }
}

This order message can occur if:-

Channel Update Fields

Fields Type Description
event STRING
submitted BOOL
message STRING
code STRING
timestamp STRING
data LIST of dictionary
clientOrderId STRING Client assigned ID to help manage and identify orders with max value 9223372036854775807
orderId STRING Unique order ID from the exchange
displayQuantity DECIMAL
lastMatchPrice DECIMAL
lastMatchQuantity DECIMAL
lastMatchedOrderId DECIMAL
lastMatchedOrderId2 DECIMAL
matchedId DECIMAL
matchedType STRING
remainQuantity DECIMAL
side STRING
status STRING
timeCondition STRING
marketCode STRING
timestampEpochMs LONG
orderType STRING
price DECIMAL
quantity DECIMAL
isTriggered BOOL

OrderMatched

OrderMatched message format

{
  "table": "order",
  "data": [ {
              "notice": "OrderMatched",
              "accountId": "<Your account ID>",
              "clientOrderId": "16",
              "orderId": "567531657",
              "price": "9300",
              "quantity": "20",
              "side": "BUY",
              "status": "<Matched status>",
              "marketCode": "BTC-flexUSD",
              "timeInForce": "GTC",
              "timestamp": "1592490254168",
              "matchId": "11568123",
              "matchPrice": "9300",
              "matchQuantity": "20",
              "orderMatchType": "MAKER",
              "remainQuantity": "0",
              "orderType": "<Order type>", 
              "stopPrice": "9000",
              "limitPrice": "9050", 
              "fees": "3.7",
              "feeInstrumentId": "FLEX",   
              "isTriggered": "False"
        }
    ]
}

Channel Update Fields

Fields Type Required
table STRING order
data LIST of dictionary
notice STRING OrderMatched
accountId STRING Account identifier
clientOrderId STRING Client assigned ID to help manage and identify orders with max value 9223372036854775807
orderId STRING Unique order ID from the exchange
price STRING Limit price submitted (only applicable for LIMIT order types)
stopPrice STRING Stop price submitted (only applicable for STOP LIMIT order types)
limitPrice STRING Limit price submitted (only applicable for STOP LIMIT order types)
quantity STRING Order quantity submitted
side STRING BUY or SELL
status STRING FILLED or PARTIAL_FILL
marketCode STRING Market code i.e. BTC-flexUSD
timeInForce STRING Client submitted time in force (only applicable for LIMIT and STOP LIMIT order types)
timestamp STRING Millisecond timestamp of order match
matchID STRING Exchange match ID
matchPrice STRING Match price of order from this match ID
matchQuantity STRING Match quantity of order from this match ID
orderMatchType STRING MAKER or TAKER
remainQuantity STRING Remaining order quantity
orderType STRING
  • LIMIT
  • MARKET
  • STOP_LIMIT
fees STRING Amount of fees paid from this match ID
feeInstrumentId STRING Instrument ID of fees paid from this match ID
isTriggered STRING False (or True for STOP LIMIT order types)

Subscriptions - Public

All subscriptions to public channels do not require an authenticated websocket connection.

Multiple subscriptions to different channels both public and private can be made within a single subscription command:

{"op": "subscribe", "args": ["<value1>", "<value2>",.....]}

Orderbook Depth

Request format

{
  "op": "subscribe",
  "tag": 103,
  "args": ["depth:BTC-flexUSD"]
}
import websockets
import asyncio
import json

orderbook_depth = \
{
  "op": "subscribe",
  "tag": 103,
  "args": ["depth:BTC-flexUSD"]
}

url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)
            if 'nonce' in data:
                await ws.send(json.dumps(orderbook_depth))
            elif 'success' in data and data['success'] == 'True':
                continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "subscribe", 
  "channel": "depth:BTC-flexUSD",
  "success": True, 
  "tag": "103", 
  "timestamp": "1607985371601"
}

Orderbook depth channel format

{
  "table": "depth",
  "data": [ {
      "instrumentId": "BTC-flexUSD",
      "seqNum": 1608898592006137237,
      "timestamp": "1609350022785",
      "checksum": 1139901235, 
      "asks": [ [5556.82, 11, 0, 0],    //price, quantity, 0, 0
                [5556.84, 98.13, 0, 0],
                [5556.92, 1.582, 0, 0],
                [5557.6, 4.291, 0, 0],
                [5557.85, 2.54, 0, 0]
              ],
      "bids": [ [5556.81, 1.92, 0, 0],  //price, quantity, 0, 0
                [5556.8, 2.1, 0, 0],
                [5556.79, 1.9, 0, 0],
                [5556.19, 100, 0, 0],
                [5556.08, 2.972, 0, 0]
              ]
          } ]
}

Channel Update Frequency: 50ms

This orderbook depth channel sends a snapshot of the entire orderbook every 50ms.

Request Parameters

Parameters Type Required Description
op STRING Yes subscribe
tag INTEGER or STRING No If given it will be echoed in the reply
args LIST Yes List of individual markets <depth>:<marketCode> e.g: [depthL10:BTC-flexUSD], the depth can be depthL5 depthL10 depthL25 depth(includes all)

Channel Update Fields

Fields Type Description
table STRING depth
data LIST of dictionary
instrumentId STRING Instrument ID
seqNum INTEGER Sequence number of the order book snapshot
timestamp STRING Millisecond timestamp
asks LIST of floats Sell side depth;
  1. price
  2. quantity
  3. 0
  4. 0
bids LIST of floats Buy side depth;
  1. price
  2. quantity
  3. 0
  4. 0

Trade

Request format

{
  "op": "subscribe",
  "tag": 1,
  "args": ["trade:BTC-flexUSD"]
}
import websockets
import asyncio
import json

trade = \
{
  "op": "subscribe",
  "tag": 1,
  "args": ["trade:BTC-flexUSD"]
}

url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)
            if 'nonce' in data:
                await ws.send(json.dumps(trade))
            elif 'success' in data and data['success'] == 'True':
                continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "subscribe", 
  "channel": ["trade:BTC-flexUSD"], 
  "success": True, 
  "tag": "1", 
  "timestamp": "1594299886880"
}

Trade channel format

{
  "table": "trade",
  "data": [ {
              "side": "buy",
              "tradeId": "2778148208082945",
              "price": "5556.91",
              "quantity": "5",
              "marketCode": "BTC-flexUSD",
              "timestamp": "1594299886890"
            } ]
}

Channel Update Frequency: real-time, with every order matched event

This trade channel sends public trade information whenever an order is matched on the orderbook.

Request Parameters

Parameters Type Required Description
op STRING Yes subscribe
tag INTEGER or STRING No If given it will be echoed in the reply
args LIST Yes list of individual markets trade:<marketCode>

Channel Update Fields

Fields Type Description
table STRING trade
data LIST of dictionary
tradeId STRING Transaction Id
price STRING Matched price
quantity STRING Matched quantity
side STRING Matched side
timestamp STRING Matched timestamp
marketCode STRING Market code

Ticker

Request format

{
  "op": "subscribe", 
  "tag": 1,
  "args": ["ticker:all"]
}

OR

{
  "op": "subscribe", 
  "tag": 1,
  "args": ["ticker:FLEX-USD", ........]
}
import websockets
import asyncio
import json

ticker = \
{
  "op": "subscribe",
  "tag": 1,
  "args": ["ticker:all"]
}

url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)
            if 'nonce' in data:
                await ws.send(json.dumps(ticker))
            elif 'success' in data and data['success'] == 'True':
                continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "subscribe", 
  "channel": "<args value>",
  "success": True,
  "tag": "1",
  "timestamp": "1594299886890"
}

Channel update format

{
    "table": "ticker",
    "data": [
        {
            "last": "0",
            "open24h": "2.80500000",
            "high24h": "3.39600000",
            "low24h": "2.53300000",
            "volume24h": "0",
            "currencyVolume24h": "0",
            "openInterest": "0",
            "marketCode": "1INCH-USD",
            "timestamp": "1622020931049",
            "lastQty": "0",
            "markPrice": "3.304",
            "lastMarkPrice": "3.304"
        },
        {
            "last": "0",
            "open24h": "2.80600000",
            "high24h": "3.39600000",
            "low24h": "2.53300000",
            "volume24h": "0",
            "currencyVolume24h": "0",
            "openInterest": "0",
            "marketCode": "1INCH-flexUSD",
            "timestamp": "1622020931046",
            "lastQty": "0",
            "markPrice": "3.304",
            "lastMarkPrice": "3.304"
        },
        ...
    ]
}

Channel Update Frequency: 500 ms

The ticker channel pushes live price and volume information about the contract.

The websocket will reply with the shown success response format for each ticker channel which has been successfully subscribed to.

The data array in the message from this ticker channel will contain a single JSON corresponding to one ticker subscription.

If you subcribe "ticker:all", you would get one whole message containing all markets.

Request Parameters

Parameters Type Required Description
op STRING Yes subscribe
tag INTEGER or STRING No If given it will be echoed in the reply
args LIST Yes ticker:all or a list of individual markets ticker:<marketCode>

Channel Update Fields

Fields Type Description
table STRING ticker
data LIST of dictionary
marketCode STRING Market code
last STRING Last traded price
markPrice STRING Mark price
open24h STRING 24 hour rolling opening price
volume24h STRING 24 hour rolling trading volume in counter currency
currencyVolume24h STRING 24 hour rolling trading volume in base currency
high24h STRING 24 hour highest price
low24h STRING 24 hour lowest price
openInterest STRING Open interest
lastQty STRING Last traded price amount
timestamp STRING Millisecond timestamp

Candles

Request format

{
  "op": "subscribe", 
  "tag": 1,
  "args": ["candles60s:BTC-flexUSD"]
}
import websockets
import asyncio
import json

candles = \
{
  "op": "subscribe",
  "tag": 1,
  "args": ["candles60s:BTC-flexUSD"]
}

url= 'wss://stgapi.coinflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)
            if 'nonce' in data:
                await ws.send(json.dumps(candles))
            elif 'success' in data and data['success'] == 'True':
                continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "subscribe", 
  "channel": ["candles60s:BTC-flexUSD"], 
  "success": True, 
  "tag": "1", 
  "timestamp": "1594313762698"
}

Channel update format

{
  "table": "candle60s",
  "data": [ {
              "marketCode": "BTC-flexUSD",
              "candle": [
                "1594313762698", //timestamp
                "9633.1",        //open
                "9693.9",        //high
                "9238.1",        //low
                "9630.2",        //close
                "45247",         //volume in counter currency
                "5.3"            //volume in base currency
              ]
          } ]
}

Channel Update Frequency: 500ms

Granularity: 60s, 180s, 300s, 900s, 1800s, 3600s, 7200s, 14400s, 21600s, 43200s, 86400s

The candles channel pushes candlestick data for the current candle.

Request Parameters

Parameters Type Required Description
op STRING Yes subscribe
tag INTEGER or STRING No If given it will be echoed in the reply
args LIST Yes list of individual candle granularity and market candles<granularity>:<marketCode>

Channel Update Fields

Fields Type Description
table STRING candles<granularity>
data LIST of dictionary
marketCode STRING Market code
candle LIST of strings
  1. timestamp
  2. open
  3. high
  4. low
  5. close
  6. volume in counter currency
  7. volume in base currency

Market

Request format

{
  "op": "subscribe", 
  "tag": 1,
  "args": ["market:all"]
}

OR

{
  "op": "subscribe", 
  "tag": 1,
  "args": ["market:FLEX-USD", ........]
}
import websockets
import asyncio
import json

market = \
{
  "op": "subscribe",
  "tag": 1,
  "args": ["market:all"]
}

url= 'wss://stgapi.comflex.us/v1/websocket'
async def subscribe():
    async with websockets.connect(url) as ws:
        while True:
            if not ws.open:
                print("websocket disconnected")
                ws = await websockets.connect(url)
            response = await ws.recv()
            data = json.loads(response)
            print(data)
            if 'nonce' in data:
                await ws.send(json.dumps(market))
            elif 'success' in data and data['success'] == 'True':
                continue
asyncio.get_event_loop().run_until_complete(subscribe())

Success response format

{
  "event": "subscribe", 
  "channel": "<args value>",
  "success": True,
  "tag": "1",
  "timestamp": "1594299886890"
}

Channel update format

{
    "table":"market",
    "data": [
        {
            "marketCode":"USDC-flexUSD",
            "name":"USDC/flexUSD",
            "referencePair":"USDC/flexUSD",
            "base":"USDC",
            "counter":"flexUSD",
            "type":"SPOT",
            "tickSize":"0.0001",
            "minSize":"0.01",
            "listedAt":"1645430673095",
            "upperPriceBound":"1.0800",
            "lowerPriceBound":"0.9200",
            "markPrice":"1.000000000",
            "lastUpdatedAt":"1645430673204"
        }
    ]
}

Channel Update Frequency: 1s

The market channel pushes live information about the market such as the current market price and the lower & upper sanity bounds as well as reference data related to the market.

The websocket will reply with the shown success response format for each market which has been successfully subscribed to.

If a subscription has been made to market:all, the data array in the message from this channel will contain a JSON list of all markets. Each JSON will contain information for each market seperately. Otherwise the data array will contain a single JSON corresponding to one market per market channel subscription.

Request Parameters

Parameters Type Required Description
op STRING Yes subscribe
tag INTEGER or STRING No If given it will be echoed in the reply
args LIST Yes market:all or a list of individual markets market:<marketCode>

Channel Update Fields

Fields Type Description
table STRING market
data LIST of dictionaries
marketCode STRING
name STRING
referencePair STRING
base STRING
counter STRING
type STRING
tickSize STRING Tick size
minSize STRING Minimum size
listedAt STRING Millisecond timestamp
upperPriceBound STRING Upper sanity price bound
lowerPriceBound STRING Lower sanity price bound
marketPrice STRING Mark price
marketId STRING
lastUpdatedAt STRING Millisecond timestamp
qtyIncrement STRING Quantity increment
contractValCurrency STRING
marginCurrency STRING

Other Responses

By subscribing to an authenticated websocket there may be instances when a REST method will also generate a websocket reponse in addition to the REST reply. There are also some GUI commands which will generate a websocket reponse.

Cancel All Open Orders

Success response format

{
  "event": "CANCEL",
  "submitted": True,
  "timestamp": "1612476498953"
}

Documentation for the REST method for cancelling all open orders for an account can be found here Cancel All Orders.

Documentation for the REST method for cancelling all open orders by market for an account can be found here Cancel All Orders By Market.

In both these instances a successful action will generate the shown repsonse in an authenticated websocket.

This action can also be executed via the trading GUI using the Cancel All button on the Open Orders blotter for both Spot and Derivative markets.

Error Codes

Failure response format

{
  "event": "<opValue>",
  "message": "<errorMessage>",
  "code": "<errorCode>",
  "success": False
}

Both subscription and order command requests sent via websocket can be rejected and the failure response will return an error code and a corresponding error message explaining the reason for the rejection.

Code Error Message
05001 Your operation authority is invalid
20000 Signature is invalid
20001 Operation failed, please contact system administrator
20002 Unexpected error, please check if your request data complies with the specification.
20003 Unrecognized operation
20005 Already logged in
20006 Quantity must be greater than zero
20007 You are accessing server too rapidly
20008 clientOrderId must be greater than zero if provided
20009 JSON data format is invalid
20010 Either clientOrderId or orderId is required
20011 marketCode is required
20012 side is required
20013 orderType is required
20014 clientOrderId is not long type
20015 marketCode is invalid
20016 side is invalid
20017 orderType is invalid
20018 timeInForce is invalid
20019 orderId is invalid
20020 stopPrice or limitPrice is invalid
20021 price is invalid
20022 price is required for LIMIT order
20023 timestamp is required
20024 timestamp exceeds the threshold
20025 API key is invalid
20026 Token is invalid or expired
20027 The length of the message exceeds the maximum length
20028 price or stopPrice or limitPrice must be greater than zero
20029 stopPrice must be less than limitPrice for Buy Stop Order
20030 limitPrice must be less than stopPrice for Sell Stop Order
100005 Open order not found with id
100006 Open order does not match to the given account
200050 The market is not active
710002 FAILED sanity bound check as price (.....) < lower bound (.....)
710003 FAILED sanity bound check as price (.....) > upper bound (.....)
710004 FAILED net position check as position (.....) > threshold (.....)
710005 FAILED margin check as collateral (.....) < var (.....)
710006 FAILED balance check as balance (.....) < value (.....)

REST API

TEST

LIVE site

For clients who do not wish to take advantage of CoinFLEX US's native WebSocket API, CoinFLEX US offers a RESTful API that implements much of the same functionality.

Error Codes

Code Description
429 Rate limit reached
10001 General networking failure
20001 Invalid parameter
30001 Missing parameter
40001 Alert from the server
50001 Unknown server error

Rate Limits

Each IP is limited to:

Certain endpoints have extra IP restrictions:

Affected APIs:

Authentication

Request

{
    "Content-Type": "application/json",
    "AccessKey": "<string>",
    "Timestamp": "<string>",
    "Signature": "<string>",
    "Nonce": "<string>"
}
import requests
import hmac
import base64
import hashlib
import datetime
import json


# rest_url = 'https://api.coinflex.us'
# rest_path = 'api.coinflex.us'

rest_url = 'https://stgapi.coinflex.us'
rest_path = 'stgapi.coinflex.us'

api_key = "API-KEY"
api_secret = "API-SECRET"

ts = datetime.datetime.utcnow().isoformat()
nonce = 123
method = "API-METHOD"

# Optional and can be omitted depending on the REST method being called 
body = json.dumps({'key1': 'value1', 'key2': 'value2'})

if body:
    path = method + '?' + body
else:
    path = method

msg_string = '{}\n{}\n{}\n{}\n{}\n{}'.format(ts, nonce, 'GET', rest_path, method, body)
sig = base64.b64encode(hmac.new(api_secret.encode('utf-8'), msg_string.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8')

header = {'Content-Type': 'application/json', 'AccessKey': api_key,
          'Timestamp': ts, 'Signature': sig, 'Nonce': str(nonce)}

resp = requests.get(rest_url + path, headers=header)
# When calling an endpoint that uses body
# resp = requests.post(rest_url + method, data=body, headers=header)
print(resp.json())

Public market data methods do not require authentication, however private methods require a Signature to be sent in the header of the request. These private REST methods use HMAC SHA256 signatures.

The HMAC SHA256 signature is a keyed HMAC SHA256 operation using a client's API Secret as the key and a message string as the value for the HMAC operation.

The message string is constructed as follows:-

msgString = f'{Timestamp}\n{Nonce}\n{Verb}\n{URL}\n{Path}\n{Body}'

Component Required Example Description
Timestamp Yes 2020-04-30T15:20:30 YYYY-MM-DDThh:mm:ss
Nonce Yes 123 User generated
Verb Yes GET Uppercase
Path Yes stg.coinflex.us
Method Yes /v1/positions Available REST methods
Body No marketCode=BTC-USD-SWAP-LIN Optional and dependent on the REST method being called

The constructed message string should look like:-

2020-04-30T15:20:30\n 123\n GET\n stg.coinflex.us\n /v1/positions\n marketCode=BTC-USD-SWAP-LIN

Note the newline characters after each component in the message string. If Body is omitted it's treated as an empty string.

Finally, you must use the HMAC SHA256 operation to get the hash value using the API Secret as the key, and the constructed message string as the value for the HMAC operation. Then encode this hash value with BASE-64. This output becomes the signature for the specified authenticated REST API method.

The signature must then be included in the header of the REST API call like so:

header = {'Content-Type': 'application/json', 'AccessKey': API-KEY, 'Timestamp': TIME-STAMP, 'Signature': SIGNATURE, 'Nonce': NONCE}

Account & Wallet - Private

GET /v1/accounts

Get account information

Request

GET /v1/accounts

Successful response format

{
    "success": true,
    "data": [
        {
            "accountId": "21213",
            "name": "main",
            "accountType": "LINEAR",
            "balances": [
                {
                    "asset": "BTC",
                    "total": "2.823",
                    "available": "2.823",
                    "reserved": "0",
                    "lastUpdatedAt": "1593627415234"
                },
                {
                    "asset": "FLEX",
                    "total": "1585.890",
                    "available": "325.890",
                    "reserved": "1260",
                    "lastUpdatedAt": "1593627415123"
                }
            ],
            "notionalBalance": "2314221",
            "feeTier": "6",
            "createdAt": "1611665624601"
        }
    ]
}
Response Field Type Description
accountId STRING Account ID
name STRING Account name
accountType STRING Account type
balances LIST of dictionaries
asset STRING Asset name
total STRING Total balance
available STRING Available balance
reserved STRING Reserved balance
lastUpdatedAt STRING Timestamp of updated at
notionalBalance STRING Total dollar value of the account
feeTier STRING Fee tier
createdAt STRING Timestamp indicating when the account was created

GET /v1/wallets

Get wallet history.

Request

GET /v1/wallets?type={type}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
          "accountId": "21213",
          "walletHistory": [
              {
                  "asset": "USD",
                  "type": "deposit",
                  "amount": "10",
                  "createdAt": "162131535213"
              }
          ]
        }
    ]
}
Request Parameter Type Required Description
type STRING NO Type of the history, e.g. DEPOSIT WITHDRAWAL, return all if not provided
limit ULONG NO Default 200, max 500
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other.
Response Field Type Description
accountId STRING Account ID
asset STRING Asset name
type STRING Type of the history
amount STRING Amount
createdAt STRING Millisecond timestamp of created at

GET /v1/balances

Get balances of accounts.

Request

GET /v1/balances?asset={asset}

Successful response format

{
    "success": true,
    "data": [
        {
            "accountId": "21213",
            "name": "main",
            "balances": [
                {
                    "asset": "BTC",
                    "total": "4468.823",
                    "available": "4468.823",
                    "reserved": "0",
                    "lastUpdatedAt": "1593627415234"
                },
                {
                    "asset": "FLEX",
                    "total": "1585.890",
                    "available": "325.890",
                    "reserved": "1260",
                    "lastUpdatedAt": "1593627415123"
                }
            ]
        }
    ]
}
Request Parameter Type Required Description
asset STRING NO Asset name
Response Field Type Description
accountId STRING Account ID
name STRING Account name
asset STRING Asset name
total STRING Total balance
available STRING Available balance
reserved STRING Reserved balance
lastUpdatedAt STRING Millisecond timestamp of last updated at

GET /v1/trades

Get historical trades sorted by time in descending order (most recent trades first).

Request

GET /v1/trades?marketCode={marketCode}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
            "orderId": "160067484555913076",
            "clientOrderId": "123",
            "matchId": "160067484555913077",
            "marketCode": "FLEX-USD",
            "side": "SELL",
            "matchedQuantity": "0.1",
            "matchPrice": "0.065",
            "total": "0.0065",
            "orderMatchType": "TAKER",
            "feeAsset": "FLEX",
            "fee": "0.0096",
            "source": "1",
            "matchedAt": "1595514663626"
        }
    ]
}
Request Parameter Type Required Description
marketCode STRING NO Market code
limit ULONG NO Default 200, max 500
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other
endTime ULONG NO Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other
Response Field Type Description
orderId STRING Order ID which generated by the server
clientOrderId STRING Client assigned ID to help manage and identify orders with max value 9223372036854775807
matchId STRING Match ID
marketCode STRING Market code
side STRING Side of the match
matchQuantity STRING Match quantity
matchPrice STRING Match price
total STRING Total cost
orderMatchType STRING Order match type, available values: TAKER,MAKER
feeAsset STRING Asset name of the fees
fees STRING Fees
matchedAt STRING Millisecond timestamp of the trade

Deposits & Withdrawals - Private

GET /v1/deposit-addresses

Deposit addresses

Request

GET /v1/deposit-addresses?asset={asset}&network={network}

Successful response format

{
    "success": true,
    "data": {
        "address":"0xD25bCD2DBb6114d3BB29CE946a6356B49911358e"
    }
}
Request Parameter Type Required Description
asset STRING YES
network STRING YES
Response Field Type Description
address STRING Deposit address
memo STRING Memo (tag) if applicable

GET /v1/deposit

Get deposit histories sorted by time in descending order (most recent deposits first).

Request

GET /v1/deposit?asset={asset}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
            "asset": "flexUSD",
            "network": "SLP",
            "address": "simpleledger:qzlg6uvceehgzgtz6phmvy8gtdqyt6vf35fxqwx3p7",
            "quantity": "1000.0",
            "status": "COMPLETED",
            "txId": "38c09755bff75d33304a3cb6ee839fcb78bbb38b6e3e16586f20852cdec4886d",
            "assetType": "CRYPTO",
            "creditedAt": "1617940800000"
        },
        {
            "asset": "USD",
            "quantity": "2.0",
            "status": "COMPLETED",
            "assetType": "FIAT",
            "creditedAt": "1651117830000"
        }
    ]
}
Request Parameter Type Required Description
asset STRING NO Default all assets
limit ULONG NO Default 50, max 200
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other
endTime ULONG NO Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other
Response Field Type Description
asset STRING
network STRING
address STRING Deposit address
memo STRING Memo (tag) if applicable
quantity STRING
status STRING
txId STRING
assetType STRING Available values: CRYPTO, FIAT
creditedAt STRING Millisecond timestamp

GET /v1/withdrawal-addresses

Withdrawal addresses

Request

GET /v1/withdrawal-addresses?asset={asset}?network={network}

Successful response format

{
    "success": true,
    "data": [
        {
            "asset": "FLEX",
            "network": "ERC20",
            "address": "0x047a13c759D9c3254B4548Fc7e784fBeB1B273g39",
            "label": "farming",
            "whitelisted": true
        }
    ]
}

Provides a list of all saved withdrawal addresses along with their respected labels, network, and whitelist status

Request Parameter Type Required Description
asset STRING NO Default all assets
network STRING NO Default all networks
Response Field Type Description
asset STRING
network STRING
address STRING
memo STRING Memo (tag) if applicable
label STRING Withdrawal address label
whitelisted BOOL

GET /v1/withdrawal

Get withdrawal histories sorted by time in descending order (most recent withdrawals first).

Request

GET /v1/withdrawal?id={id}&asset={asset}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
            "id": "651573911056351237",
            "asset": "flexUSD",
            "network": "SLP",
            "address": "simpleledger:qzlg6uvceehgzgtz6phmvy8gtdqyt6vf35fxqwx3p7",
            "quantity": "1000.0",
            "fee": "0.000000000",
            "status": "COMPLETED",
            "txId": "38c09755bff75d33304a3cb6ee839fcb78bbb38b6e3e16586f20852cdec4886d",
            "assetType": "CRYPTO",
            "requestedAt": "1617940800000",
            "completedAt": "16003243243242"
        },
        {
            "id": "751474625867710465",
            "asset": "USD",
            "quantity": "25",
            "fee": "0.0",
            "status": "COMPLETED",
            "txId": "55cc39a6a599e3b055c7238375d96402",
            "assetType": "FIAT",
            "requestedAt": "1649402256000",
            "completedAt": "1649402502000"
        }
    ]
}
Request Parameter Type Required Description
id STRING NO
asset STRING NO Default all assets
limit ULONG NO Default 50, max 200
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other. This filter applies to "requestedAt"
endTime ULONG NO Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other. This filter applies to "requestedAt"
Response Field Type Description
id STRING
asset STRING
network STRING
address STRING
memo STRING Memo (tag) if applicable
quantity STRING
fee STRING
id STRING
status STRING COMPLETED, PROCESSING, PENDING, ON HOLD, CANCELED, or FAILED
txId STRING
assetType STRING Available values: CRYPTO, FIAT
requestedAt STRING Millisecond timestamp
completedAt STRING Millisecond timestamp

POST /v1/withdrawal

Withdrawal request

Request

POST /v1/withdrawal
{
    "asset": "flexUSD",
    "network": "SLP",
    "address": "simpleledger:qzlg6uvceehgzgtz6phmvy8gtdqyt6vf35fxqwx3p7",
    "quantity": "100",
    "externalFee": true,
    "tfaType": "GOOGLE",
    "code": "743249"
}

Successful response format

{
    "success": true,
    "data": {
        "id": "651573911056351237",
        "asset": "flexUSD",
        "network": "SLP",
        "address": "simpleledger:qzlg6uvceehgzgtz6phmvy8gtdqyt6vf35fxqwx3p7",
        "quantity": "1000.0",
        "externalFee": true,
        "fee": "0",
        "status": "PENDING",
        "requestedAt": "1617940800000"
    }
}

Withdrawals may only be initiated by API keys that are linked to the main account and have withdrawals enabled. If the wrong 2fa code is provided the endpoint will block for 10 seconds.

Request Parameter Type Required Description
asset STRING YES
network STRING YES
address STRING YES
memo STRING NO Memo is required for chains that support memo tags
quantity STRING YES
externalFee BOOL YES If false, then the fee is taken from the quantity
tfaType STRING NO GOOGLE, or AUTHY_SECRET, or YUBIKEY
code STRING NO 2fa code if required by the account
Response Field Type Description
id STRING
asset STRING
network STRING
address STRING
memo STRING
quantity STRING
externalFee BOOL If false, then the fee is taken from the quantity
fee STRING
status STRING
requestedAt STRING Millisecond timestamp

GET /v1/withdrawal-fee

Withdrawal fee estimate

Request

GET /v1/withdrawal-fee?asset={asset}&network={network}&address={address}&memo={memo}&quantity={quantity}&externalFee={externalFee}

Successful response format

{
    "success": true,
    "data": {
        "asset": "flexUSD",
        "network": "SLP",
        "address": "simpleledger:qzlg6uvceehgzgtz6phmvy8gtdqyt6vf35fxqwx3p7",
        "quantity": "1000.0",
        "externalFee": true,
        "estimatedFee": "0"
    }
}
Request Parameter Type Required Description
asset STRING YES
network STRING YES
address STRING YES
memo STRING NO Required only for 2 part addresses (tag or memo)
quantity STRING YES
externalFee BOOL NO Default false. If false, then the fee is taken from the quantity
Response Field Type Description
asset STRING
network STRING
address STRING
memo STRING Memo (tag) if applicable
quantity STRING
externalFee BOOL If false, then the fee is taken from the quantity
estimatedFee STRING

Flex Assets - Private

POST /v1/flexasset/mint

Mint

Request

POST /v1/flexasset/mint
{
    "asset": "flexUSD",
    "quantity": "100"
}

Successful response format

{
    "success": true,
    "data": {
        "asset": "flexUSD",
        "quantity": "100"
    }
}
Request Parameter Type Required Description
asset STRING YES Asset name, available assets: flexUSD
quantity STRING YES Quantity to mint , minimum quantity required: 10 flexUSD
Response Field Type Description
asset STRING
quantity STRING

POST /v1/flexasset/redeem

Redeem

Request

POST /v1/flexasset/redeem
{
    "asset": "flexUSD",
    "quantity": "100",
    "type": "NORMAL"
}

Successful response format

{
    "success": true,
    "data": {
        "asset": "flexUSD",
        "quantity": "100",
        "type": "NORMAL",
        "redemptionAt": "1617940800000"
    }
}
Request Parameter Type Required Description
asset STRING YES Asset name, available assets: flexUSD
quantity STRING YES Quantity to redeem, minimum quantity required: 10 flexUSD
type STRING YES NORMAL queues a redemption until the following interest payment and incurs no fee
Response Field Type Description
asset STRING
quantity STRING
type STRING Available types: NORMAL
redemptionAt STRING Millisecond timestamp indicating when redemption will take place

GET /v1/flexasset/mint

Get historical flexasset mints sorted by time in descending order (most recent mints first).

Request

GET /v1/flexasset/mint?asset={asset}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
          "asset": "flexUSD",
          "quantity": "1000.0",
          "mintedAt": "16003243243242"
        }
    ]
}
Request Parameter Type Required Description
asset STRING NO Asset name, available assets: flexUSD
limit ULONG NO Default 50, max 200
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other
endTime ULONG NO Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other
Response Field Type Description
asset STRING
quantity STRING
mintedAt STRING

GET /v1/flexasset/redeem

Get historical flexasset redemptions sorted by time in descending order (most recent redemptions first).

Request

GET /v1/flexasset/redeem?asset={asset}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
          "asset": "flexUSD",
          "quantity": "1000.0",
          "requestedAt": "16003243243242",
          "redeemedAt": "16003243243242"
        }
    ]
}
Request Parameter Type Required Description
asset STRING NO Asset name, available assets: flexUSD
limit ULONG NO Default 50, max 200
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other. Here startTime and endTime refer to the "requestedAt" timestamp
endTime ULONG NO Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other. Here startTime and endTime refer to the "requestedAt" timestamp
Response Field Type Description
asset STRING
quantity STRING
requestedAt STRING Millisecond timestamp indicating when redemption was requested
redeemedAt STRING Millisecond timestamp indicating when the flexAssets were redeemed (if applicable)

GET /v1/flexasset/earned

Get historical flexasset interest payments sorted by time in descending order (most recent payments first).

Request

GET /v1/flexasset/earned?asset={asset}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
            "asset": "flexUSD",
            "apr": "25",
            "rate": "0.00022831",
            "amount": "2.28310502",
            "paidAt": "1635822660847"
        }
    ]
}
Request Parameter Type Required Description
asset STRING NO Asset name, available assets: flexUSD
limit ULONG NO Default 50, max 200
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other
endTime ULONG NO Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other
Response Field Type Description
asset STRING Asset name
apr STRING Annualized APR (%) = rate * 3 * 365 * 100
rate STRING Period interest rate
amount STRING
paidAt STRING

Orders - Private

POST /v1/orders/place

Place order.

Request

POST /v1/orders/place
{
    "recvWindow": 3000,
    "timestamp": 1637100050453,
    "responseType":"FULL",
    "orders": [
        {
            "clientOrderId": 1612249737434,
            "marketCode": "USDC-flexUSD",
            "side": "BUY",
            "quantity": "0.01",
            "timeInForce": "GTC",
            "orderType": "LIMIT",
            "price": "0.9998"
        }
    ]
}

Successful response format

{
    "success": true,
    "data": [
        {
            "notice": "OrderOpened",
            "accountId": "100356",
            "orderId": "1000000705002",
            "submitted": true,
            "clientOrderId": "1612249737434",
            "marketCode": "USDC-flexUSD",
            "status": "OPEN",
            "side": "BUY",
            "price": "0.9998",
            "isTriggered": false,
            "quantity": "0.01",
            "orderType": "LIMIT",
            "timeInForce": "GTC",
            "createdAt": "1650959751803"
        }
    ]
}
Request Parameters Type Required Description
recvWindow ULONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.
timestamp ULONG YES In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.
responseType STRING YES FULL or ACK
orders LIST YES A list of orders
clientOrderId ULONG NO Client assigned ID to help manage and identify orders with max value 9223372036854775807
marketCode STRING YES Market code
side STRING YES Side of the order, BUY or SELL
quantity STRING YES Quantity submitted
timeInForce STRING NO Default GTC
orderType STRING YES Type of the order, LIMIT or MARKET or STOP
price STRING NO Price submitted
stopPrice STRING NO Stop price for the stop order
Response Parameters Type Description
notice STRING OrderClosed or OrderMatched or OrderOpend
accountId STRING Account ID
orderId STRING Order ID which generated by the server
submitted BOOL Whether the request is submitted or not submitted
clientOrderId STRING Client assigned ID to help manage and identify orders with max value 9223372036854775807
marketCode STRING Market code
status STRING Order status
side STRING SELL or BUY
price STRING Price submitted
stopPrice STRING Stop price for the stop order
isTriggered STRING false (or true for STOP order types)
quantity STRING Quantity submitted
remainQuantity STRING Remainning quantity
matchId STRING Exchange match ID
matchPrice STRING Matched price
matchQuantity STRING Matched quantity
feeInstrumentId STRING Instrument ID of fees paid from this match ID
fees STRING Amount of fees paid from this match ID
orderType STRING MARKET or LIMIT or STOP
timeInForce STRING Time in force
createdAt STRING Millisecond timestamp of created at
lastModifiedAt STRING Millisecond timestamp of last modified at
lastMatchedAt STRING Millisecond timestamp of last matched at

GET /v1/orders

Get order history.

Request

GET /v1/orders?marketCode={marketCode}&orderId={orderId}&clientOrderId={clientOrderId}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
            "orderId": "1000000700000",
            "clientOrderId": "1612249737434",
            "marketCode": "USDC-flexUSD",
            "status": "CLOSED",
            "side": "BUY",
            "price": "0.9998",
            "quantity": "0.01",
            "remainQuantity": "0.01",
            "matchedQuantity": "0",
            "orderType": "LIMIT",
            "timeInForce": "GTC",
            "createdAt": "1650959840448",
            "closedAt": "1650959970325"
        }
    ]
}
Request Parameter Type Required Description
marketCode STRING NO Market code
clientOrderId ULONG NO Client assigned ID to help manage and identify orders with max value 9223372036854775807
orderId STRING Order ID which generated by the server
limit ULONG NO Default 50, max 200
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other
endTime ULONG NO Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other
Response Field Type Description
orderId STRING Order ID which generated by the server
clientOrderId STRING Client assigned ID to help manage and identify orders with max value 9223372036854775807
marketCode STRING Market code
status STRING Status of the order, available values: CLOSED OPEN PARTIALLY_FILLED FILLED
side STRING Side of the order, BUY or SELL
price STRING Price submitted
stopPrice STRING Stop price for the stop order
isTriggered BOOL Available values: true false, true is for stop orders
quantity STRING Quantity submitted
remainQuantity STRING Remainning quantity
matchedQuantity STRING Matched quantity
avgFillPrice STRING Average of filled price
fees LIST of dictionaries Overall fees with instrument ID, if FLEX is no enough to pay the fee then USD will be paid
orderType STRING Type of the order, LIMIT or STOP
timeInForce STRING Time in force
createdAt STRING Millisecond timestamp of created at
lastModifiedAt STRING Millisecond timestamp of last modified at
lastMatchedAt STRING Millisecond timestamp of last matched at
closedAt STRING Millisecond timestamp of closed at

GET /v1/orders/working

Get working order history.

Request

GET /v1/orders/working?marketCode={marketCode}&orderId={orderId}&clientOrderId={clientOrderId}

Successful response format

{
    "success": true,
    "data": [
        {
            "orderId": "1000000705002",
            "clientOrderId": "1612249737434",
            "marketCode": "USDC-flexUSD",
            "status": "OPEN",
            "side": "BUY",
            "price": "0.9998",
            "quantity": "0.01",
            "remainQuantity": "0.01",
            "matchedQuantity": "0.00",
            "orderType": "LIMIT",
            "timeInForce": "GTC",
            "createdAt": "1650959751718",
            "lastModifiedAt": "1650959751799"
        }
    ]
}
Request Parameter Type Required Description
marketCode STRING NO Market code
orderId STRING NO Order ID which generated by the server
clientOrderId ULONG NO Client assigned ID to help manage and identify orders with max value 9223372036854775807
Response Field Type Description
orderId STRING Order ID which generated by the server
clientOrderId STRING Client assigned ID to help manage and identify orders with max value 9223372036854775807
marketCode STRING Market code
status STRING Status of the working order, available values: OPEN PARTIALLY_FILLED
side STRING Side of the order, BUY or SELL
price STRING Price submitted
stopPrice STRING Stop price for the stop order
isTriggered BOOL Available values: true false, true is for stop orders
quantity STRING Quantity submitted
remainQuantity STRING Remainning quantity
matchedQuantity STRING Matched quantity
orderType STRING Type of the order, LIMIT or STOP
timeInForce STRING Time in force
createdAt STRING Millisecond timestamp of created at
lastModifiedAt STRING Millisecond timestamp of last modified at
lastMatchedAt STRING Millisecond timestamp of last matched at

DELETE /v1/orders/cancel

Cancel order by ID.

Request

DELETE /v1/orders/cancel
{
    "recvWindow": 3000,
    "timestamp": 1737100050453,
    "responseType": "FULL",
    "orders": [
        {
            "marketCode": "BTC-flexUSD",
            "clientOrderId": "1612249737434",
            "orderId": "1000000545000"
        }
    ]
}

Successful response format

{
    "success": true,
    "data": [
        {
            "notice": "OrderClosed",
            "accountId": "100020",
            "orderId": "1000000545000",
            "submitted": true,
            "clientOrderId": "1612249737434",
            "marketCode": "BTC-flexUSD",
            "status": "CANCELED_BY_USER",
            "side": "BUY",
            "price": "25000.0",
            "isTriggered": false,
            "quantity": "0.9",
            "remainQuantity": "0.9",
            "orderType": "LIMIT",
            "timeInForce": "GTC",
            "closedAt": "1648200825424"
        }
    ]
}
Request Parameters Type Required Description
recvWindow ULONG NO In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.
timestamp ULONG YES In milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used. If recvWindow is provided with no timestamp, then the request will not be rejected. If neither timestamp nor recvWindow are provided, then the request will not be rejected.
responseType STRING YES FULL or ACK
orders LIST YES A list of orders
marketCode STRING YES Market code
clientOrderId ULONG Either one of orderId or clientOrderId is required Client assigned ID to help manage and identify orders with max value 9223372036854775807
orderId STRING Either one of orderId or clientOrderId is required Order ID
Response Parameters Type Description
notice STRING OrderClosed or OrderMatched or OrderOpend
accountId STRING Account ID
orderId STRING Order ID which generated by the server
submitted BOOL Whether the request is submitted or not submitted
clientOrderId STRING Client assigned ID to help manage and identify orders with max value 9223372036854775807
marketCode STRING Market code
status STRING Order status
side STRING SELL or BUY
price STRING Price submitted
stopPrice STRING Stop price for the stop order
isTriggered STRING false (or true for STOP order types)
quantity STRING Quantity submitted
remainQuantity STRING Remainning quantity
orderType STRING MARKET or LIMIT or STOP
timeInForce STRING Time in force
closedAt STRING Millisecond timestamp of closed at

DELETE /v1/orders/cancel-all

Cancel all orders.

Request

DELETE /v1/orders/cancel-all
{
    "marketCode": "BTC-flexUSD"
}

Successful response format

{
    "success": true, 
    "data": {
        "notice": "Orders queued for cancelation"
    }
}
Request Parameters Type Required Description
marketCode STRING NO Market code, if it's null or not sent then cancel all orders for the account
Response Parameters Type Description
notice STRING Orders queued for cancelation or No working orders found

Market Data - Public

GET /v1/markets

Get a list of markets on CoinFlex US.

Request

GET /v1/markets?marketCode={marketCode}

Successful response format

{
    "success": true,
    "data": [
        {
            "marketCode": "BTC-USD",
            "name": "BTC/USD",
            "referencePair": "BTC/USD",
            "base": "BTC",
            "counter": "USD",
            "type": "SPOT",
            "tickSize": "0.1",
            "minSize": "0.001",
            "listedAt": "1593345600000",
            "upperPriceBound": "65950.5",
            "lowerPriceBound": "60877.3",
            "markPrice": "63413.9",
            "lastUpdatedAt": "1635848576163"
        }
    ]
}
Request Parameter Type Required Description
marketCode STRING NO Market code
Response Field Type Description
marketCode STRING Market Code
name STRING Name of the contract
referencePair STRING Reference pair
base STRING Base asset
counter STRING Counter asset
type STRING Type of the contract
tickSize STRING Tick size of the contract
minSize STRING Minimum quantity
listedAt STRING Listing date of the contract
upperPriceBound STRING Sanity bound
lowerPriceBound STRING Sanity bound
markPrice STRING Mark price
lastUpdatedAt STRING Millisecond timestamp of last updated time

GET /v1/assets

Get a list of assets supported on CoinFLEX US.

Request

GET /v1/assets?asset={asset}

Successful response format

{
    "success": true,
    "data": [
        {
            "asset": "USDC",
            "networkList": [
                {
                    "network": "ERC20",
                    "transactionPrecision": "6",
                    "isWithdrawalFeeChargedToUser": true,
                    "canDeposit": true,
                    "canWithdraw": true,
                    "minWithdrawal": "0.0001"
                }
            ]
        },
        {
            "asset": "BTC",
            "networkList": [
                {
                    "network": "BTC",
                    "transactionPrecision": "8",
                    "isWithdrawalFeeChargedToUser": true,
                    "canDeposit": true,
                    "canWithdraw": true,
                    "minWithdrawal": "0.0001"
                }
            ]
        }
    ]
}
Request Parameter Type Required Description
asset STRING NO Name of the asset
Response Field Type Description
asset STRING Asset name
networkList LIST List of dictionaries
network STRING Network for deposit and withdrawal
transactionPrecision STRING Precision for the transaction
isWithdrawalFeeChargedToUser BOOL Indicates the withdrawal fee is charged to user or not
canDeposit BOOL Indicates can deposit or not
canWithdraw BOOL Indicates can withdraw or not
minDeposit STRING Minimum deposit amount
minWithdrawal STRING Minimum withdrawal amount

GET /v1/tickers

Get tickers.

Request

GET /v1/tickers?marketCode={marketCode}

Successful response format

{
    "success": true,
    "data": [
        {
            "marketCode": "BTC-USD-SWAP-LIN",
            "markPrice": "41512.4",
            "open24h": "41915.3",
            "high24h": "42662.2",
            "low24h": "41167.0",
            "volume24h": "114341.4550",
            "currencyVolume24h": "2.733",
            "lastTradedPrice": "41802.5",
            "lastTradedQuantity": "0.001",
            "lastUpdatedAt": "1642585256002"
        }
    ]
}
Request Parameter Type Required Description
marketCode STRING NO Market code
Response Field Type Description
marketCode STRING Market code
markPrice STRING Mark price
open24h STRING 24 hour rolling opening price
high24h STRING 24 hour highest price
low24h STRING 24 hour lowest price
volume24h STRING Volume in 24 hours
currencyVolume24h STRING 24 hour rolling trading volume in counter currency
lastTradedPrice STRING Last traded price
lastTradedQuantity STRIN Last traded quantity
lastUpdatedAt STRING Millisecond timestamp of last updated time

GET /v1/candles

Get candles.

Request

GET /v1/candles?marketCode={marketCode}&timeframe={timeframe}&limit={limit}
&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true, 
    "timeframe": "3600s", 
    "data": [
        {
            "open": "35888.80000000", 
            "high": "35925.30000000", 
            "low": "35717.00000000", 
            "close": "35923.40000000", 
            "volume": "0",
            "currencyVolume": "0",
            "openedAt": "1642932000000"
        },
        {
            "open": "35805.50000000", 
            "high": "36141.50000000", 
            "low": "35784.90000000", 
            "close": "35886.60000000", 
            "volume": "0",
            "currencyVolume": "0",
            "openedAt": "1642928400000"
        }
    ]
}
Request Parameter Type Required Description
marketCode STRING YES Market code
timeframe STRING NO Available values: 60s,300s,900s,1800s,3600s,7200s,14400s,86400s, default is 3600s
limit ULONG NO Default 200, max 500
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other.
endTime ULONG NO Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other.
Response Field Type Description
timeframe STRING Available values: 60s,300s,900s,1800s,3600s,7200s,14400s,86400s
open STRING Opening price
high STRING Highest price
low STRING Lowest price
close STRING Closing price
volume STRING Trading volume in counter currency
currencyVolume STRING Trading volume in base currency
openedAt STRING Millisecond timestamp of the candle opened at

GET /v1/depth

Get depth.

Request

GET /v1/depth?marketCode={marketCode}&level={level}

Successful response format

{
    "success": true, 
    "level": "5", 
    "data": {
        "marketCode": "BTC-USD-SWAP-LIN", 
        "lastUpdatedAt": "1643016065958", 
        "asks": [
            [
                39400, 
                0.261
            ], 
            [
                41050.5, 
                0.002
            ], 
            [
                41051, 
                0.094
            ], 
            [
                41052.5, 
                0.002
            ], 
            [
                41054.5, 
                0.002
            ]
        ], 
        "bids": [
            [
                39382.5, 
                0.593
            ], 
            [
                39380.5, 
                0.009
            ], 
            [
                39378, 
                0.009
            ], 
            [
                39375.5, 
                0.009
            ], 
            [
                39373, 
                0.009
            ]
        ]
    }
}
Request Parameter Type Required Description
marketCode STRING YES Market code
level ULONG NO Default 5, max 100
Response Field Type Description
level ULONG Level
marketCode STRING Market code
lastUpdatedAt STRING Millisecond timestamp of the depth last updated at
asks LIST of floats Sell side depth: [price, quantity]
bids LIST of floats Buy side depth: [price, quantity]

GET /v1/exchange-trades

Get historical exchange trades sorted by time in descending order (most recent trades first).

Request

GET /v1/exchange-trades?marketCode={marketCode}&limit={limit}
&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
          "marketCode": "BTC-USD-SWAP-LIN",
          "matchPrice": "9600.000000000",
          "matchQuantity": "0.100000000",
          "side": "BUY",
          "matchedAt": "1595585860254"
        }
    ]
}
Request Parameter Type Required Description
marketCode STRING NO Market code
limit ULONG NO Default 300, max 300
startTime ULONG NO Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other.
endTime ULONG NO Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other.
Response Field Type Description
marketCode STRING Market code
matchPrice STRING
matchQuantity STRING
side STRING Aggressor (taker) side, available values: BUY SELL
matchedAt STRING Millisecond timestamp of matched at