Introduction

Welcome to Levidge trader and developer documentation. These documents outline exchange functionality, market details, and APIs.

APIs are separated into two categories: trading and feed. Trading APIs require authentication and provide access to placing orders and other account information. Feed APIs provide market data and are public.

General

Market overview and general information.

Matching Engine

Levidge operates a continuous first-come, first-serve order book. Orders are executed in price-time priority as received by the matching engine.

Example

User A places a Buy order for 1 BTC at 100 USD. User B then wishes to sell 1 BTC at 80 USD. Because User A’s order was first to the trading engine, they will have price priority and the trade will occur at 100 USD.

Fees

Trading Fees

Levidge operates a maker-taker model. Orders which provide liquidity are charged different fees from orders taking liquidity. The fee is assessed as a percentage of the match amount (price * size). Maker and taker fees are calculated hourly based on the user’s 30d USD-equivalent trading volume:

Crypto and Perpetual Contracts

Contract Tier Maker Taker
Crypto 1 0.15 % 0.30 %
Crypto 2 0.10 % 0.20 %
Crypto 3 0 % 0.15 %

Other Perpetual Contracts

Contract Tier Maker Taker
Other 1 0.25 % 0.50 %
Other 2 0.15 % 0.35 %
Other 3 0 % 0.25 %

Perpetual Swap Funding Rate

Levidge charges a perpetual swap funding rate, calculated from the contract premium over an index price converted to BTC. Perpetual swap fees are paid to the counterparty contract holders.

HOW TAKER FEES ARE CALCULATED

Your taker fee is based upon total USD trading volume across all Order Books over the trailing 30 day period. For example, a purchase of 1 BTC for $10,000 on the BTC-USD book will count as $10,000 towards your 30 day USD volume.

HOW VOLUMES ARE CALCULATED ON NON-USD BOOKS

Transactions made on non-USD books are converted to USD based on the most recent fill price on the corresponding USD book. For example, a purchase of 1 ETH for 0.1 BTC on the ETH-BTC book will count as the most recent fill price of 1 ETH on the ETH-USD Order Book.

Deposit/Withdraw Fees

Levidge does not charge any additional deposit fees, and only charges network transaction fees to withdraw

Client Libraries

Client libraries can help you integrate with our API quickly.

Official

Unofficial

API

The REST API has endpoints for account and order management as well as public market data.

REST API Endpoint URL

https://levidge.com/api/

There is also a FIX API for order management.

Requests

All requests and responses are application/json content type and follow typical HTTP response status codes for success and failure.

Errors

{
    "error": "Invalid userId"
}

Unless otherwise stated, errors to bad requests will respond with HTTP 4xx or status codes. The body will also contain a message parameter indicating the cause. Your language’s http library should be configured to provide message bodies for non-2xx requests so that you can read the message field from the body.

Common error codes

Status CodeReason
400Bad Request – Invalid request format
401Unauthorized – Invalid API Key
403Forbidden – You do not have access to the requested resource
404Not Found
500Internal Server Error – We had a problem with our server

Success

A successful response is indicated by HTTP status code 200 and may contain an optional body. If the response has a body it will be documented under each resource below.

Rate Limits

When a rate limit is exceeded, a status of 429 Too Many Requests will be returned.

REST API

Public endpoints

We throttle public endpoints by IP: 3 requests per second, up to 6 requests per second in bursts.

Private endpoints

We throttle private endpoints by user ID: 5 requests per second, up to 10 requests per second in bursts.

Financial Information eXchange API

The FIX API throttles the number of incoming messages to 50 commands per second.

Private

Private endpoints are available for order management, and account management. Every private request must be signed using the described authentication scheme.

Authentication

Generating an API Key

Before being able to sign any requests, you must create an API key via the Levidge website. Upon creating a key you will have 4 pieces of information which you must remember:

  • Username
  • Password
  • RequestToken
  • RequestSecret

The RequestToken and RequestSecret will be randomly generated and provided by Levidge.

API Key Permissions

A separate paid of RequestToken, and RequestSecret will be generated for withdrawal requests

  • View - Allows a key read permissions. This includes all GET endpoints.
  • Transfer - Allows a key to transfer currency on behalf of an account, including deposits and withdraws. Enable with caution - API key transfers WILL BYPASS two-factor authentication.
  • Trade - Allows a key to enter orders, as well as retrieve trade data. This includes POST /orders and several GET endpoints.

Please refer to documentation below to see what API key permissions are required for a specific route.

Creating a Request

All REST requests must contain the following headers using HTTP POST:

  • requestToken The API RequestToken
  • signature hex(HMAC_SHA384(base64(payload), key=RequestSecret))

All request bodies should have content type application/json and be valid JSON.

Signing a Message


import CryptoJS from 'crypto-js';
import hmacSHA384 from 'crypto-js/hmac-sha384';

const paramsString = JSON.stringify(params);
    const signature = hmacSHA384(
      paramsString,
      this.state.requestSecret
    ).toString();

    Utils.postData('/order/', params, this.state.requestToken, signature)
      .then(data => {
        console.log(data);
      })

      .catch(error => {
        alert(error.message);
      });
  };

To sign the payload, decode it to base64, and generate the HMAC SHA using the private key

Selecting a Timestamp

The CB-ACCESS-TIMESTAMP header MUST be number of seconds since Unix Epoch in UTC. Decimal values are allowed.

Your timestamp must be within 30 seconds of the api service time or your request will be considered expired and rejected. We recommend using the time endpoint to query for the API server time if you believe there many be time skew between your server and the API servers.

Accounts

Logon



    {"login":"test","password":"123456"}
    

Logon

HTTP Request

POST /logon

API Key Permissions

This endpoint requires either the “view” or “trade” permission.

Logon Input Fields

FieldTypeDescription
idintUser ID
loginStringthe user login
passwordStringthe user password
codeint*required for 2fa users, otherwise ignored

Logon Output Fields

FieldTypeDescription
idintUser ID
requestTokenStringthe user requestToken
requestSecretStringthe user requestSecret

Get User Profile

{
    "id": 10250474,
    "login": "traderabc",
    "password": "pwd123",
    "firstname": "John",
    "middlename": "Lee",
    "lastname": "Doe",
    "email": "johndoe555@gmail.com"
}

Get the user's profile information

HTTP request

POST /getUserProfile

API Key Permissions

This endpoint requires either the “view” or “trade” permission.

Input Fields

FieldTypeDescription
userIdintUser ID

Output Fields

FieldTypeDescription
idintUser ID
loginString
passwordString
firstnameString
middlenameString
lastnameString
emailString
typeString
statusString
createDateString
referralCodeString
referredByCodeString
phoneString
companyString
countryString
cityString
stateString
zipString
address1String
address2String
address3String
registeredIPString
lastIPString
firmIdint
feeTierint
birthdateString
taxidString
linkedinString
facebookString
skypeString
photoUrlString

Orders

Place a New Order

{
"userId": 1045725,
"instrumentId": 5,
"side": 1,
"ordType": 2,
"symbol": "SPY/USD",
"quantity": 125,
"quantity_scale": 2,
"price": 245,
"price_scale": 2
}

Response



Data fields use enums defined in the FIX 4.4 standard

You can place two types of orders: limit and market. Orders can only be placed if your account has sufficient funds. Once an order is placed, your account funds will be put on hold for the duration of the order. How much and which funds are put on hold depends on the order type and parameters specified. See the Holds details below.

HTTP Request

POST /order

API Key Permissions

This endpoint requires the “trade” permission.

Parameters

These parameters are common to all order types. Depending on the order type, additional parameters will be required (see below).

FieldTypeDescription
userIdintUser ID
instrumentIdint
symbolString
clOrdIdString
sideint1 = Buy, 2 = Sell
ordTypeint1 = Market, 2 = Limit, 3 = Stop, 4 = Stop limit
priceint
price_scaleint
quantityint
quantity_scaleint
stopPxint(not required unless stop order)
stopPx_scaleint(not required unless stop order)
timeInForceint(not required, defaults to 1 = Good Till Cancel (GTC))

Cancel Order

{
"origOrderId": 954751144,
"userId": 1045725,
"instrumentId": 5,
"side": 1,
"ordType": 2,
"symbol": "SPY/USD",
"quantity": 125,
"quantity_scale": 2,
"price": 245,
"price_scale": 2
}

Response



Cancel a previously placed order.

Data fields use enums defined in the FIX 4.4 standard

You can place two types of orders: limit and market. Orders can only be placed if your account has sufficient funds. Once an order is placed, your account funds will be put on hold for the duration of the order. How much and which funds are put on hold depends on the order type and parameters specified. See the Holds details below.

HTTP Request

POST /cancelOrder

API Key Permissions

This endpoint requires the “trade” permission.

Parameters

These parameters are common to all order types. Depending on the order type, additional parameters will be required (see below).

FieldTypeDescription
origOrderIdintoriginal order Id
userIdintUser ID
instrumentIdint
symbolString
clOrdIdString
sideint1 = Buy, 2 = Sell
ordTypeint1 = Market, 2 = Limit, 3 = Stop, 4 = Stop limit
priceint
price_scaleint
quantityint
quantity_scaleint
stopPxint(not required unless stop order)
stopPx_scaleint(not required unless stop order)
timeInForceint(not required, defaults to 1 = Good Till Cancel (GTC))

Cancel Reject

If the order could not be canceled (already filled or previously canceled, etc), then an error response will indicate the reason in the message field.

Cancel Replace

With best effort, cancel an order and replace it.

{
"origOrderId": 954751144,
"userId": 1045725,
"instrumentId": 5,
"side": 1,
"ordType": 2,
"symbol": "SPY/USD",
"quantity": 125,
"quantity_scale": 2,
"price": 245,
"price_scale": 2,
"quantity2": 125,
"quantity2_scale": 2,
"price2": 245,
"price2_scale": 2
}

Response



Cancel a previously placed order.

Data fields use enums defined in the FIX 4.4 standard

You can place two types of orders: limit and market. Orders can only be placed if your account has sufficient funds. Once an order is placed, your account funds will be put on hold for the duration of the order. How much and which funds are put on hold depends on the order type and parameters specified. See the Holds details below.

HTTP Request

POST /cancelOrder

API Key Permissions

This endpoint requires the “trade” permission.

Parameters

These parameters are common to all order types. Depending on the order type, additional parameters will be required (see below).

FieldTypeDescription
origOrderIdintoriginal order Id
userIdintUser ID
instrumentIdint
symbolString
clOrdIdString
sideint1 = Buy, 2 = Sell
ordTypeint1 = Market, 2 = Limit, 3 = Stop, 4 = Stop limit
priceint
price_scaleint
quantityint
quantity_scaleint
price2int
price2_scaleint
quantity2int
quantity2_scaleint
stopPxint(not required unless stop order)
stopPx_scaleint(not required unless stop order)
timeInForceint(not required, defaults to 1 = Good Till Cancel (GTC))

Cancel Reject

If the order could not be canceled (already filled or previously canceled, etc), then an error response will indicate the reason in the message field.

Get Orders List

Return a list of orders, ordered by id descending

{
"userId": 1045725,
"limit": 2
}

Response

{
"origOrderId": 954751144,
"userId": 1045725,
"instrumentId": 5,
"side": 1,
"ordType": 2,
"symbol": "SPY/USD",
"quantity": 125,
"quantity_scale": 2,
"price": 245,
"price_scale": 2
}

Data fields use enums defined in the FIX 4.4 standard

All types or orders are returned with their statuses

HTTP Request

POST /getOrders

API Key Permissions

This endpoint requires the “trade” permission.

Input Parameters

These parameters are common to all order types.

FieldTypeDescription
userIdintuser Id
orderIdintoptional filter
limitintoptional filter

Output Parameters

These parameters are common to all order types. Depending on the order type, additional parameters will be required (see below).

FieldTypeDescription
origOrderIdintoriginal order Id
userIdintUser ID
instrumentIdint
symbolString
clOrdIdString
sideint1 = Buy, 2 = Sell
ordTypeint1 = Market, 2 = Limit, 3 = Stop, 4 = Stop limit
priceint
price_scaleint
quantityint
quantity_scaleint
stopPxint(not required unless stop order)
stopPx_scaleint(not required unless stop order)
timeInForceint(not required, defaults to 1 = Good Till Cancel (GTC))
execTypeString
ordStatusint
execIdint
leavesQtyint
leavesQty_scaleint
cumQtyint
cumQty_scaleint
lastPxint
lastPx_scaleint
lastQtyint
lastQty_scaleint

Get Order

Return an order with its status

{
"orderId": 954751144,
"userId": 1045725
}

Response

{
"origOrderId": 954751144,
"userId": 1045725,
"instrumentId": 5,
"side": 1,
"ordType": 2,
"symbol": "SPY/USD",
"quantity": 125,
"quantity_scale": 2,
"price": 245,
"price_scale": 2
}

Data fields use enums defined in the FIX 4.4 standard

All types or orders are returned with their statuses

HTTP Request

POST /getOrder

API Key Permissions

This endpoint requires the “trade” permission.

Input Parameters

These parameters are common to all order types.

FieldTypeDescription
userIdintuser Id
orderIdintrequired

Output Parameters

These parameters are common to all order types. Depending on the order type, additional parameters will be required (see below).

FieldTypeDescription
origOrderIdintoriginal order Id
userIdintUser ID
instrumentIdint
symbolString
clOrdIdString
sideint1 = Buy, 2 = Sell
ordTypeint1 = Market, 2 = Limit, 3 = Stop, 4 = Stop limit
priceint
price_scaleint
quantityint
quantity_scaleint
stopPxint(not required unless stop order)
stopPx_scaleint(not required unless stop order)
timeInForceint(not required, defaults to 1 = Good Till Cancel (GTC))
execTypeString
ordStatusint
execIdint
leavesQtyint
leavesQty_scaleint
cumQtyint
cumQty_scaleint
lastPxint
lastPx_scaleint
lastQtyint
lastQty_scaleint

Positions

List Positions

Return list of all postitions / balances

{
"userId": 1045725
}

Response

{
"origOrderId": 954751144,
"userId": 1045725,
"instrumentId": 5,
"side": 1,
"ordType": 2,
"symbol": "SPY/USD",
"quantity": 125,
"quantity_scale": 2,
"price": 245,
"price_scale": 2
}

Data fields use enums defined in the FIX 4.4 standard

All types or orders are returned with their statuses

HTTP Request

POST /getPositions

API Key Permissions

This endpoint requires the “trade” permission.

Input Parameters

These parameters are common to all order types.

FieldTypeDescription
userIdintuser Id

Output Parameters

If the position is a coin instrumentId will be returned. If the position is a contract the pairId will be returned

FieldTypeDescription
symbolString
userIdintUser ID
instrumentIdinteither coindId or pairId
quantityint
quantity_scaleint
availableQuantityint

Deposits

Get Deposit Addresses

Return list of addresses for each coin

{
"userId": 1045725,
"instrumentId": 5
}

Response

{
"origOrderId": 954751144,
"userId": 1045725,
"instrumentId": 5,
"side": 1,
"ordType": 2,
"symbol": "SPY/USD",
"quantity": 125,
"quantity_scale": 2,
"price": 245,
"price_scale": 2
}

HTTP Request

POST /getDepositAddresses

API Key Permissions

This endpoint requires the “trade” permission.

Input Parameters

These parameters are common to all order types.

FieldTypeDescription
userIdintuser Id
instrumentIdintoptional filter

Output Parameters

FieldTypeDescription
symbolString
userIdintUser ID
instrumentIdintcoindId
addressString
statusint

Withdrawals

List Withdraw Requests

Return list of withdrawals

{
"userId": 1045725,
"instrumentId": 5
}

Response

{
"origOrderId": 954751144,
"userId": 1045725,
"instrumentId": 5,
"side": 1,
"ordType": 2,
"symbol": "SPY/USD",
"quantity": 125,
"quantity_scale": 2,
"price": 245,
"price_scale": 2
}

HTTP Request

POST /getWithdrawRequests

API Key Permissions

This endpoint requires the “trade” permission.

Input Parameters

These parameters are common to all order types.

FieldTypeDescription
userIdintuser Id
instrumentIdintoptional filter

Output Parameters

FieldTypeDescription
symbolString
userIdintUser ID
instrumentIdintcoindId
quantityint
quantity_scaleint
addressString
statusint

Send Withdraw Request

Request to send coins to an external address

{
"userId": 1045725,
"instrumentId": 5,
"address": "atd42iv4u62wrs743g64wsf8f",
"quantity": 125,
"quantity_scale": 2
}

Response

{
"origOrderId": 954751144,
"userId": 1045725,
"instrumentId": 5,
"side": 1,
"ordType": 2,
"symbol": "SPY/USD",
"quantity": 125,
"quantity_scale": 2,
"price": 245,
"price_scale": 2
}

HTTP Request

POST /sendWithdrawRequest

API Key Permissions

This endpoint requires the “trade” permission.

Input Parameters

These parameters are common to all order types.

FieldTypeDescription
userIdintuser Id
instrumentIdint
quantityint
quantity_scaleint
addressString

Output Parameters

FieldTypeDescription
symbolString
userIdintUser ID
instrumentIdintcoindId
quantityint
quantity_scaleint
addressString
statusint

Risk

Get Risk

Return real-time risk metrics

{
"userId": 1045725
}

Response

{
"userId": 1045725,
"usdValue": 56542.25,
"usdPositionValue": 56542.25,
"usdOpenOrdersValue": 56542.25,
"usdOpenOrdersRequiredValue": 56542.25,
"usdMarginValue": 56542.25,
"usdMarginRequiredValue": 56542.25,
"usdMarginMaintValue": 56542.25,
"leverageRatio": 56542.25,
"usdUnrealized": 56542.25,
"usdPositionValue": 56542.25,
"usdPositionValue": 56542.25,
"riskUpdateDate": "2018-12-12 4:44:20"
}

Data fields use enums defined in the FIX 4.4 standard

HTTP Request

POST /getRisk

API Key Permissions

This endpoint requires the “trade” permission.

Input Parameters

These parameters are common to all order types.

FieldTypeDescription
userIdintuser Id

Output Parameters

If the position is a coin instrumentId will be returned. If the position is a contract the pairId will be returned

FieldTypeDescription
userIdintUser ID
usdValuedouble
usdPositionValuedouble
usdOpenOrdersValuedouble
usdOpenOrdersRequiredValuedouble
usdMarginValuedouble
usdMarginRequiredValuedouble
usdMarginMaintValuedouble
leverageRatiodouble
usdUnrealizeddouble
riskUpdateDateStringTimestamp these risk metrics were calculated

Reports

Create a new report

Request

{
    "type": "fills",
    "start_date": "2014-11-01T00:00:00.000Z",
    "end_date": "2014-11-30T23:59:59.000Z"
}

Response

{
    "id": "0428b97b-bec1-429e-a94c-59232926778d",
    "type": "fills",
    "status": "pending",
    "created_at": "2015-01-06T10:34:47.000Z",
    "completed_at": undefined,
    "expires_at": "2015-01-13T10:35:47.000Z",
    "file_url": undefined,
    "params": {
        "start_date": "2014-11-01T00:00:00.000Z",
        "end_date": "2014-11-30T23:59:59.000Z"
    }
}

Reports provide batches of historic information about your account in various human and machine readable forms.

HTTP request

POST /reports

API Key Permissions

This endpoint requires either the “view” or “trade” permission.

Parameters

ParamDescription
typefills or account
start_dateStarting date for the report (inclusive)
end_dateEnding date for the report (inclusive)
product_idID of the product to generate a fills report for. E.g. BTC-USD. Required if type is fills
account_idID of the account to generate an account report for. Required if type is account
formatpdf or csv (defualt is pdf)
emailEmail address to send the report to (optional)

The report will be generated when resources are available. Report status can be queried via the /reports/:report_id endpoint. The file_url field will be available once the report has successfully been created and is available for download.

Expired reports

Reports are only available for download for a few days after being created. Once a report expires, the report is no longer available for download and is deleted.

Get report status

Response (creating report)

{
    "id": "0428b97b-bec1-429e-a94c-59232926778d",
    "type": "fills",
    "status": "creating",
    "created_at": "2015-01-06T10:34:47.000Z",
    "completed_at": undefined,
    "expires_at": "2015-01-13T10:35:47.000Z",
    "file_url": undefined,
    "params": {
        "start_date": "2014-11-01T00:00:00.000Z",
        "end_date": "2014-11-30T23:59:59.000Z"
    }
}

Response (finished report)

{
    "id": "0428b97b-bec1-429e-a94c-59232926778d",
    "type": "fills",
    "status": "ready",
    "created_at": "2015-01-06T10:34:47.000Z",
    "completed_at": "2015-01-06T10:35:47.000Z",
    "expires_at": "2015-01-13T10:35:47.000Z",
    "file_url": "https://example.com/0428b97b.../fills.pdf",
    "params": {
        "start_date": "2014-11-01T00:00:00.000Z",
        "end_date": "2014-11-30T23:59:59.000Z"
    }
}

HTTP request

GET /reports/:report_id

Once a report request has been accepted for processing, the status is available by polling the report resource endpoint.

The final report will be uploaded and available at file_url once the status indicates ready

API Key Permissions

This endpoint requires either the “view” or “trade” permission.

Status

StatusDescription
pendingThe report request has been accepted and is awaiting processing
creatingThe report is being created
readyThe report is ready for download from file_url

User Account

Trailing Volume

[
    {
        "product_id": "BTC-USD",
        "exchange_volume": "11800.00000000",
        "volume": "100.00000000",
        "recorded_at": "1973-11-29T00:05:01.123456Z"
    },
    {
        "product_id": "LTC-USD",
        "exchange_volume": "51010.04100000",
        "volume": "2010.04100000",
        "recorded_at": "1973-11-29T00:05:02.123456Z"
    }
]

HTTP request

GET /users/self/trailing-volume

API Key Permissions

This endpoint requires either the “view” or “trade” permission.

This request will return your 30-day trailing volume for all products. This is a cached value that’s calculated every day at midnight UTC.

Public Market Data

Get Instruments

The Market Data API is an unauthenticated set of endpoints for retrieving market data. These endpoints provide snapshots of market data.


          {"instruments":[[1,"USD",2,2],[2,"ETH",2,6],[3,"BTC",2,6],[6,"BTCTEST",2,6],[7,"ETHTEST",2,6],[10,"LTC",2,6],[24,"LMM",2,6]]}
          

Get a list of available currency pairs for trading.

HTTP Request

GET /getInstruments

Details

getInstruments Input Fields

FieldTypeDescription

getInstruments Output Fields (comma deliminated)

FieldTypeDescription
instrumentIdintinstrument ID
symbolStringthe symbol
price_scaleintscale of the price
quantity_scaleintscale of the quantity

Pairs

Get Pairs


          {"instrumentPairs":[[4,"ETH/USD",2,1,2,6],[5,"BTC/USD",3,1,2,6],[11,"GOLD/USD[F]",3,1,2,6],[12,"BTC/USD[F]",3,1,2,6],[13,"SILVER/USD[F]",3,1,2,6],[14,"SPY/USD[F]",3,1,2,6],[15,"ETH/BTC",2,3,6,6],[16,"LTC/BTC",10,3,6,6],[17,"QQQ/USD[F]",3,1,2,6],[18,"AAPL/USD[F]",3,1,2,6],[19,"GOOG/USD[F]",3,1,2,6],[20,"FB/USD[F]",3,1,2,6],[21,"USO/USD[F]",3,1,2,6],[22,"EWJ/USD[F]",3,1,2,6],[23,"MCHI/USD[F]",3,1,2,6],[25,"LMM/USD",24,1,2,6],[26,"LMM/BTC",24,3,2,6],[27,"LMM/ETH",24,2,2,6]]}
          

Get a list of available currency pairs for trading.

HTTP Request

GET /getInstrumentPairs

Details

getInstrumentPairs Input Fields

FieldTypeDescription

getInstrumentPairs Output Fields (comma deliminated)

FieldTypeDescription
instrumentIdintinstrument ID
symbolStringthe symbol
price_scaleintscale of the price
quantity_scaleintscale of the quantity

Get Order Book Snap

Example Response for /getOrderBook?pairId=5

{"bids":[[373217,500000,1544056823375],[373191,100000,1544056823375],[372449,200000,1544056823375],[322200,1000000,1544056823375]], "asks":[[373318,500000,1544056823375],[373426,500000,1544056823375],[373441,100000,1544056823375]]}

Get open orders for a product. The amount of detail shown can be customized with the optional limit parameter.

HTTP Request

GET /getOrderBook?pairId=<pairId>

Details

Polling is discouraged in favor of connecting via the websocket stream and listening for match messages.

Order book data is returned as an array or order levels

[price,quantity,timestamp]

Price and quantity are integer numbers. To convert them to double, use the price_scale and quantity_scale defined in getInstrumentPairs

Get Trade History

Example Response for /getTradeHistory?pairId=5

{"trades":[[366309,200000,"20181206-15:04:18.278",9636],[365489,500000,"20181206-15:04:18.162",9635],[366406,500000,"20181206-15:04:18.143",9634],[366067,100000,"20181206-15:04:13.660",9633],[366329,200000,"20181206-15:04:11.726",9632],[366198,500000,"20181206-15:04:11.462",9631],[366174,500000,"20181206-15:04:11.426",9630],[366274,100000,"20181206-15:04:10.040",9629],[366461,500000,"20181206-15:04:06.168",9628],[366474,100000,"20181206-15:04:01.879",9627],[366666,200000,"20181206-15:04:01.877",9626],[366739,100000,"20181206-15:04:00.418",9625],[365872,500000,"20181206-15:03:59.309",9624],[366789,500000,"20181206-15:03:59.121",9623],[366792,500000,"20181206-15:03:54.032",9622],[367084,500000,"20181206-15:03:53.359",9621],[367224,500000,"20181206-15:03:51.088",9620],[367388,300000,"20181206-15:03:49.111",9619]]}

Most recent trades for the specified pair

HTTP request

GET /api/getTradeHistory?pairId=<pairId>

Real-time updates

Polling is discouraged in favor of connecting via the websocket stream and listening for match messages.

[price,quantity,timestamp,seqNumber]

Price and quantity are integer numbers. To convert them to double, use the price_scale and quantity_scale defined in getInstrumentPairs

Get Chart Data

Example Response for /getChart?pairId=5&timespan=2

{"chart":[[1544112300000,361446,361500,359286,360130,8,417],[1544112000000,363074,363074,359435,361055,18,416],[1544111700000,363790,364335,362300,363185,33,415],[1544111400000,362860,364258,361143,363789,63,414],[1544111100000,360807,364890,360542,363054,29,413],[1544110800000,361501,361501,359710,360746,34,412],[1544110500000,361135,362134,357187,361608,50,411],[1544110200000,360414,360414,358312,360027,25,410],[1544109900000,359116,361838,357769,360474,47,409],[1544109600000,361132,361977,358621,359430,61,408],[1544109300000,362963,365340,360316,360316,35,407],[1544109000000,365543,366009,361300,362989,34,406],[1544108700000,366159,366247,364199,364679,32,405],[1544108400000,367693,369459,364712,366219,41,404],[1544108100000,368979,370778,367027,367737,53,403],[1544107800000,357505,370673,355075,367584,70,402],[1544107500000,359257,360819,355142,356737,55,401],[1544107200000,361928,362205,358492,358875,44,400],[1544106900000,363513,364069,358780,361546,70,399],[1544106600000,367300,367654,363701,363701,26,398]]}

Returns an array of chart data points in OHLC format

HTTP request

GET /getChart?pairId=<pairId>×pan=<timespan>

[<timestamp>,<open>,<high>,<low>,<close>,<volume>,<seqNumber>]

timespan enum values

ONE_MINUTE=1

FIVE_MINUTE=2

FIFTEEN_MINUTE=3

ONE_HOUR=4

SIX_HOUR=5

ONE_DAY=6

ONE_WEEK=7

Websocket Feed

The websocket feed provides real-time market data updates for orders and trades.

wss://levidge.com

Overview

Real-time market data updates provide the fastest insight into order flow and trades. This however means that you are responsible for reading the message stream and using the message relevant for your needs which can include building real-time order books or tracking real-time trades.

The websocket feed is publicly available, but connections to it are rate-limited to 1 per 4 seconds per IP.

Protocol overview

The websocket feed uses a bidirectional protocol, which encodes all messages as JSON objects. All messages have a type attribute that can be used to handle the message appropriately.

Please note that new message types can be added at any point in time. Clients are expected to ignore messages they do not support.

Error messages: Most failure cases will cause an error message (a message with the type "error") to be emitted. This can be helpful for implementing a client or debugging issues.

Subscribe


			{"login":"trader123","password":"pwd","userId":53234}
          

To begin receiving feed messages, you must first send a subscribe message to the server indicating which channels and products to receive. This message is mandatory — you will be disconnected if no subscribe has been received within 5 seconds.

Once a subscribe message is received the server will respond with a subscriptions message that lists all channels you are subscribed to.

Subsequent subscribe messages will add to the list of subscriptions. In case you already subscribed to a channel without being authenticated you will remain in the unauthenticated channel.

If you want to unsubscribe from channel/product pairs, send an unsubscribe param with the value 1. The structure is equivalent to subscribe messages.

Authentication

Authentication is required for private data channels

Channels

The Orderbook Channel


          {"bids":[[373217,500000,1544056823375],[373191,100000,1544056823375],[372449,200000,1544056823375],[322200,1000000,1544056823375]], "asks":[[373318,500000,1544056823375],[373426,500000,1544056823375],[373441,100000,1544056823375]]}
          

Get realtime snapshot of orderbook

Public Websocket Request

WS /orderbook

Details

orderbook Input Fields

FieldTypeDescription
pairIdintpair ID

orderbook Output Fields (comma deliminated)

[price,quantity,timestamp]

Price and quantity are integer numbers. To convert them to double, use the price_scale and quantity_scale defined in getInstrumentPairs

The Trade History Channel


	{"trades":[[366309,200000,"20181206-15:04:18.278",9636],[365489,500000,"20181206-15:04:18.162",9635],[366406,500000,"20181206-15:04:18.143",9634],[366067,100000,"20181206-15:04:13.660",9633],[366329,200000,"20181206-15:04:11.726",9632],[366198,500000,"20181206-15:04:11.462",9631],[366174,500000,"20181206-15:04:11.426",9630],[366274,100000,"20181206-15:04:10.040",9629],[366461,500000,"20181206-15:04:06.168",9628],[366474,100000,"20181206-15:04:01.879",9627],[366666,200000,"20181206-15:04:01.877",9626],[366739,100000,"20181206-15:04:00.418",9625],[365872,500000,"20181206-15:03:59.309",9624],[366789,500000,"20181206-15:03:59.121",9623],[366792,500000,"20181206-15:03:54.032",9622],[367084,500000,"20181206-15:03:53.359",9621],[367224,500000,"20181206-15:03:51.088",9620],[367388,300000,"20181206-15:03:49.111",9619]]}
          

Get realtime trade history

Public Websocket Request

WS /tradehistory

Details

tradehistory Input Fields

FieldTypeDescription
pairIdintpair ID

orderbook Output Fields (comma deliminated)

[price,quantity,timestamp,seqNumber]

Price and quantity are integer numbers. To convert them to double, use the price_scale and quantity_scale defined in getInstrumentPairs

The User Orders Channel


			{"orderId":1025401,"clOrdId":"1234","instrumentId":5,"side":2,"userId":123456}
          

Get user order updates streamed through a websocket channel

This private channel must be subscribed to by authenticating

Example: {"login":"trader123","password":"pwd","userId":53234}

Private Websocket Request

WS /userorders

Details

user orders Input Fields

FieldTypeDescription
loginStringuser login
passwordStringuser password
userIdint

Data fields use enums defined in the FIX 4.4 standard

user orders output Fields

FieldTypeDescription
orderIdint
clOrdIdStringclient order id
symbolString
instrumentIdint
sideint
userIdint
accountint(same as userId)
execTypeString
ordTypeint
ordStatusint
timeInForceString(not required)
execIdint(only for fills)
priceint
price_scaleint
quantityint
quantity_scaleint
stopPxint(not required unless stop order)
stopPx_scaleint(not required unless stop order)
leavesQtyintremaining quantity of order
leavesQty_scaleint
cumQtyint
cumQty_scaleint
lastPxint
lastPx_scaleint
lastQtyint
lastQty_scaleint

The User Risk Channel


			{"orderId":1025401,"clOrdId":"1234","instrumentId":5,"side":2,"userId":123456,"userId":53234}
          

Get user risk updates streamed through a websocket channel

This private channel must be subscribed to by authenticating

Example: {"login":"trader123","password":"pwd","userId":53234}

Private Websocket Request

WS /userrisk

Details

user risk Input Fields

FieldTypeDescription
loginStringuser login
passwordStringuser password
userIdint

user risk output Fields

FieldTypeDescription
userIdint
usdValuedouble
usdPositionValuedouble
usdOpenOrdersValuedouble
usdOpenOrdersRequiredValuedouble
usdMarginValuedouble
usdMarginValuedouble
usdMarginRequiredValuedouble
usdMarginMaintValuedouble
leverageRatiodouble
usdUnrealizeddouble
riskUpdateDateString

The User Position Channel


			{"userId":1025401,"instrumentId":5,"quantity":2,"quantity_scale":2,"availableQuantity":54}
          

Get user risk updates streamed through a websocket channel

This private channel must be subscribed to by authenticating

Example: {"login":"trader123","password":"pwd","userId":53234}

Private Websocket Request

WS /userrisk

Details

user position Input Fields

FieldTypeDescription
loginStringuser login
passwordStringuser password
userIdint

user position output Fields

FieldTypeDescription
userIdint
instrumentIdint
quantityint
quantity_scaleint
availableQuantityint
symbolString

FIX API

FIX (Financial Information eXchange) is a standard protocol which can be used to enter orders, submit cancel requests, and receive fills. Users of the FIX API will typically have existing software using FIX for order management. Users who are not familiar with FIX should first consider using the REST API.

FIX API Endpoint URL

tcp+ssl://fix.levidge.com:4198

Connectivity

Before logging onto a FIX session, clients must establish a secure connection to the FIX gateway (fix.levidge.com:4198). If your FIX implementation does not support establishing a TCP SSL connection natively, you will need to setup a local proxy such as stunnel to establish a secure connection to the FIX gateway. See the SSL Tunnels section for more details and examples.

Messages

The baseline specification for this API is FIX 4.2. There are additional tags from later versions of FIX, and custom tags in the high number range as allowed by the standard.

A standard header must be present at the start of every message in both directions.

TagNameDescription
8BeginStringMust be FIX.4.2
49SenderCompIDClient API key (on messages from the client)
56TargetCompIDMust be Levidge (on messages from the client)

Logon (A)

// create a new Logon message
var logon = new Msgs.Logon();
logon.SendingTime = new Date();
logon.HeartBtInt = 30;
logon.EncryptMethod = 0;
logon.passphrase = '...';

var presign = [
    logon.SendingTime,
    logon.MsgType,
    session.outgoing_seq_num,
    session.sender_comp_id,
    session.target_comp_id,
    passphrase
].join('\x01');

// add the presign string to the RawData field of the Logon message
logon.RawData = sign(presign, secret);

// send the logon message to the server
session.send(logon);

function sign(what, secret) {
    var key = Buffer(secret, 'base64');
    var hmac = crypto.createHmac('sha256', key);
    return hmac.update(what).digest('base64');
}

Sent by the client to initiate a session, and by the server as an acknowledgement. Only one session may exist per connection; sending a Logon message within an established session is an error.

TagNameDescription
98EncryptMethodMust be 0 (None)
108HeartBtIntMust be 30 (seconds)
554PasswordClient API passphrase
96RawDataClient message signature (see below)
8013CancelOrdersOnDisconnectY: Cancel all open orders for the current profile; S: Cancel open orders placed during session
9406DropCopyFlagIf set to Y, execution reports will be generated for all user orders (defaults to Y)

The Logon message sent by the client must be signed for security. The signing method is described in Signing a Message. The prehash string is the following fields joined by the FIX field separator (ASCII code 1):

SendingTime, MsgType, MsgSeqNum, SenderCompID, TargetCompID, Password.

There is no trailing separator. The RawData field should be a base64 encoding of the HMAC signature.

Logout (5)

Sent by either side to initiate session termination. The side which receives this message first should reply with the same message type to confirm session termination. Closing a connection without logging out of the session first is an error.

New Order Single (D)

Sent by the client to enter an order.

TagNameDescription
21HandlInstMust be 1 (Automated)
11ClOrdIDUUID selected by client to identify the order
55SymbolE.g. BTC-USD
54SideMust be 1 to buy or 2 to sell
44PriceLimit price (e.g. in USD) (Limit order only)
38OrderQtyOrder size in base units (e.g. BTC)
152CashOrderQtyOrder size in quote units (e.g. USD) (Market order only)
40OrdTypeMust be 1 for Market, 2 for Limit, 3 for Stop Market, or 4 for Stop Limit
99StopPxStop price for order
59TimeInForceMust be a valid TimeInForce value. See the table below (Limit order only)
7928SelfTradePreventionOptional, see the table below

SelfTradePrevention Values

ValueDescription
DDecrement and cancel (the default)
OCancel resting order
NCancel incoming order
BCancel both orders

If an order is decremented due to self-trade prevention, an Execution Report will be sent to the client with ExecType=D indicating unsolicited OrderQty reduction (i.e. partial cancel).

See the self-trade prevention documentation for more details about this field.

TimeInForce Values

ValueDescription
1Good Till Cancel
3Immediate or Cancel
4Fill or Kill
PPost-Only

The post-only flag (P) indicates that the order should only make liquidity. If any part of the order results in taking liquidity, the order will be rejected and no part of it will execute. Open Post-Only orders will be treated as Good Till Cancel.

See the time in force documentation for more details about these values.

Errors

If a trading error occurs (e.g. user has insufficient funds), an ExecutionReport with ExecType=8 is sent back, signifying that the order was rejected.

Order Cancel Request (F)

Sent by the client to cancel an order.

TagNameDescription
11ClOrdIDUUID selected by client for the order
37OrderIDOrderID from the ExecutionReport with OrdStatus=New (39=0)
41OrigClOrdIDClOrdID of the order to cancel (originally assigned by the client)
55SymbolSymbol of the order to cancel (must match Symbol of the Order)

ClOrdID

Use of the ClOrdID is not available after reconnecting or starting a new session. You should use the OrderID obtained via the ExecutionReport once available.

Order Status Request (H)

Sent by the client to obtain information about pending orders.

TagNameDescription
37OrderIDOrderID of order(s) to be sent back. Can be equal to * (wildcard) to send back all pending orders

Response

The response to an Order Status Request is a series of ExecutionReports with ExecType=I, each representing one open order belonging to the user. If the user has no open orders, a single ExecutionReport is sent back with OrderID=0.

Execution Report (8)

Sent by the server when an order is accepted, rejected, filled, or canceled. Also sent when the user sends an OrderStatusRequest.

TagNameDescription
11ClOrdIDOnly present on order acknowledgements, ExecType=New (150=0)
37OrderIDOrderID from the ExecutionReport with ExecType=New (150=0)
55SymbolSymbol of the original order
54SideMust be 1 to buy or 2 to sell
32LastSharesAmount filled (if ExecType=1). Also called LastQty as of FIX 4.3
44PricePrice of the fill if ExecType indicates a fill, otherwise the order price
38OrderQtyOrderQty as accepted (may be less than requested upon self-trade prevention)
152CashOrderQtyOrder size in quote units (e.g. USD) (Market order only)
60TransactTimeTime the event occurred
150ExecTypeMay be 1 (Partial fill) for fills, D for self-trade prevention, etc.
39OrdStatusOrder status as of the current message
103OrdRejReasonInsufficient funds=3, Post-only=8, Unknown error=0
136NoMiscFees1 (Order Status Request response only)
137MiscFeeAmtFee (Order Status Request response only)
139MiscFeeType4 (Exchange fees) (Order Status Request response only)
1003TradeIDProduct unique trade id
1057AggressorIndicatorY for taker orders, N for maker orders

ExecType Values

ExecTypeDescription
0New Order
1Fill
3Done
4Canceled
7Stopped
8Rejected
DOrder Changed
IOrder Status

Order Cancel Reject (9)

Sent by the server when an Order Cancel Request cannot be satisfied, e.g. because the order is already canceled or completely filled.

TagNameDescription
11ClOrdIDAs on the cancel request
37OrderIDAs on the cancel request
41OrigClOrdIDAs on the cancel request
39OrdStatus4 if too late to cancel
102CxlRejReason1 if the order is unknown
434CxlRejResponseTo1 (Order Cancel Request)

Reject (3)

Sent by either side upon receipt of a message which cannot be processed, e.g. due to missing fields or an unsupported message type.

TagNameDescription
45RefSeqNumMsgSeqNum of the rejected incoming message
371RefTagIDTag number of the field which caused the reject (optional)
372RefMsgTypeMsgType of the rejected incoming message
58TextHuman-readable description of the error (optional)
373SessionRejectReasonCode to identify reason for reject

SessionRejectReason Values

The following values can be sent by the server.

ValueDescription
1Required tag missing
5Value is incorrect (out of range) for this tag
6Incorrect data format for value
11Invalid MsgType (35)

Heartbeat (0)

Sent by both sides if no messages have been sent for HeartBtInt seconds as agreed during logon. May also be sent in response to a Test Request.

TagNameDescription
112TestReqIDCopied from the Test Request, if any

Test Request (1)

May be sent at any time by either side.

TagNameDescription
112TestReqIDFree text

SSL Tunnels

fix.levidge.com:4198 only accepts TCP connections secured by SSL. If your FIX client library cannot establish an SSL connection natively, you will need to run a local proxy that will establish a secure connection and allow unencrypted local connections.

Stunnel Configuration

This is an example configuration file for stunnel to listen on a port locally and proxy unencrypted TCP connections to the encrypted SSL connection. The service name (Levidge) and the accept port (4197) may be changed to any suitable values.

[Levidge]
client = yes
accept = 4197
connect = fix.levidge.com:4198
verify = 4
CAfile = /example/path/to/fix.levidge.com.pem

When stunnel is started with the above configuration file, it will run in the background. On Unix-like systems the option foreground = yes may be specified at the top of the file to avoid running in the background. For testing it may be easier to use foreground mode, or to specify the top-level output option as a file path where stunnel will write log messages.

If your system has OpenSSL installed, you can run this command to download the certificate:

openssl s_client -showcerts -connect fix.levidge.com:4198 < /dev/null | openssl x509 -outform PEM > fix.levidge.com.pem