SDM API Reference

Build trading integrations on Secure Digital Markets.

Use SDM WebSocket, REST, and FIX APIs to connect market data, order execution, RFQ, trade, balance, and instrument workflows for institutional digital asset trading.

REST sandboxtrade-sandbox.sdm.co
WebSocket sandboxwss://trade-sandbox.sdm.co/ws/v1
Source versionsTrading v1.4.0 / FIX v2.50

Environments and API keys

Welcome to the SDM API. The websocket API provides the user with access to real-time market data subscription, orders execution and balance information. The REST API provides historical market data.

If you do not have an API key and a signature assigned, you will need to obtain them first. You can do so by using the following method. Email SDM support staff at: tech@sdm.co. You will need separate API Keys for connecting to the sandbox and production environments.

Your websocket endpoint is trade-sandbox.sdm.co in sandbox, and trade.sdm.co in production.

EnvironmentWebSocketREST
Sandboxwss://trade-sandbox.sdm.co/ws/v1https://trade-sandbox.sdm.co
Productionwss://trade.sdm.co/ws/v1https://trade.sdm.co

WebSocket and REST authentication

Websocket connections must be authenticated by signing the request and sending the signature in HTTP headers.

REST requests must be authenticated by signing the request and sending the signature in HTTP headers.

REST Endpoints are available for OHLCV data.

The signature is a base64 encoded sha256 HMAC using the API secret of the following:

Websocket authentication headers

HeaderDescription
ApiKeyYour SDM API key
ApiTimestampAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
ApiSignbase64-encoded signature

REST authentication headers

HeaderDescription
ApiKeyYour API key
ApiTimestampAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
ApiSignbase64-encoded signature
WebSocket signature payload
text
GET\n<ApiTimestamp>\n<host>\n<path>
WebSocket signature payload example
text
GET\n2019-02-13T05:17:32.000000Z\ntrade-sandbox.sdm.co\n/ws/v1
WebSocket Python 2/3 example
py
# to install websocket lib:
# $ pip install websocket-client
from websocket import create_connection
import datetime
import hmac
import hashlib
import base64

api_key = "<apikey>"
api_secret = "<apisecret>"
utc_now = datetime.datetime.utcnow()
utc_datetime = utc_now.strftime("%Y-%m-%dT%H:%M:%S.000000Z")
host = "<websocket host>"  # trade-sandbox.sdm.co, for example
path = "/ws/v1"
params = "\n".join([
"GET",
utc_datetime,
host,
path,
])
hash = hmac.new(
api_secret.encode('ascii'), params.encode('ascii'), hashlib.sha256)
hash.hexdigest()
signature = base64.urlsafe_b64encode(hash.digest()).decode()
header = {
"ApiKey": api_key,
"ApiSign": signature,
"ApiTimestamp": utc_datetime,
}
ws = create_connection("wss://" + host + path, header=header)

while True:
    print(ws.recv())
REST signature payload
text
GET\n<ApiTimestamp>\n<host>\n<path>[\nquery][\nbody]

query and body should only be included if they are not empty.

REST signature payload example
text
GET\n2019-02-13T05:17:32.000000Z\ntrade-sandbox.sdm.co\n/v1/symbols/BTC-USD/ohlcv/1D
REST Python 2/3 example
py
# to install requests lib:
# $ pip install requests
import requests
import datetime
import hmac
import hashlib
import base64

api_key = "<apikey>"
api_secret = "<apisecret>"
utc_now = datetime.datetime.utcnow()
utc_datetime = utc_now.strftime("%Y-%m-%dT%H:%M:%S.000000Z")
host = "<host>"  # trade-sandbox.sdm.co, for example
path = "/v1"
query = ""
body = ""
params = [
"GET",
utc_datetime,
host,
path,
]
endpoint = "https://" + host + path

if query:
    endpoint += "?" + query
    params.append(query)
if body:
    params.append(body)

payload = "\n".join(params)
hashvalue = hmac.new(
api_secret.encode('ascii'), payload.encode('ascii'), hashlib.sha256)
hashvalue.hexdigest()
signature = base64.urlsafe_b64encode(hashvalue.digest()).decode()
headers = {
"ApiKey": api_key,
"ApiSign": signature,
"ApiTimestamp": utc_datetime,
}

print(requests.get(url=endpoint, headers=headers))

WebSocket protocol

Timestamps: In all API requests, the user has the option to provide a timestamp (ts) in an ISO-8601 UTC string format with microsecond resolution. While optional, we recommend taking advantage of this field, as it will both enable our system to monitor client-server latency and allow certain security features. All system responses are tied to a specific client request. The user should provide a unique reqid (Request ID) on each request, and the system will echo this reqid on the corresponding responses.

The server sends a hello message on a successful connection

After a client connects, the server will send an unsolicited hello message.

Clients issue requests to subscribe to data and execute actions like placing orders. A request should be a JSON message with the following keys:

The server responds to requests with one or more response messages that reference the request by echoing back the reqid field.

There is no limit to how many concurrent websocket connections you're allowed, though this may change in the future. If you expect to have more than ~10 active connections, please contact tech@sdm.co.

Unsolicited hello message
json
{
  "type": "hello",
  "ts": "2019-10-16T10:41:23.168807Z",
  "session_id": "1109RQ13KXR00"
}

Hello fields

ParameterTypeRequiredDescription
typestringYAlways "hello".
tsnumberYAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
session_idstringYA session ID that uniquely identifies this websocket session.
General request
json
{
  "reqid": 1,
  "type": "subscribe",
  "streams": [
    {
      "name": "MessageType",
      "Arg1": 1
    }
  ],
  "ts": "2019-02-13T05:17:32.000000Z"
}

General request fields

ParameterTypeRequiredDescription
reqidnumberYA number that identifies this request and will be included on responses to this request.
typestringYThe type of message sent. This document describes all valid message types.
tsnumberNAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z

reqid cannot be equal to 0.

General response
json
{
  "reqid": 1,
  "seq": 1,
  "type": "MessageType",
  "action": "Update",
  "data": [
    {
      "Key": "Value"
    }
  ],
  "ts": "2019-02-13T05:17:32.000000Z"
}

General response fields

KeyTypeRequiredDescription
reqidnumberYA number that relates this response to a request.
seqnumberYThe sequence number for this response per request. seq begins at 1 on the first message with this reqid and increments by one for each message sent on this reqid.
typestringYThe type of message sent. This document describes all valid message types.
tagstringNAn optional tag from the stream request.
tsnumberYAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z.
initialboolNIf this is initial data for a request, the initial flag will be set.
actionstringN"Update" or "Remove"
total_countnumberNThe total number of records for this stream.

If a request requires responses with different types, then multiple responses may have the initial flag set for different types.

seq is for debug purposes only, the client is not required to do any sequencing.

action is either Update or Remove and tells the client if the given entity should be removed or added/updated. The key for a given entity depends on the message type.

In all messages below the described types are encoded as below:

Encoded types

TypeEncoding
datetimeAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
decimalA string encoded decimal; eg "4.327" represents the decimal 4.327

Subscription lifecycle and commands

Send a subscription request to begin a stream of data.

Commands can be submitted via the websocket API.

This is the general structure for sending a command to the websocket API. The type field is the command name, specified as one of the options listed below. The data required for each command is described below. There could be an error response to the command, otherwise any published response data should be consumed via the associated subscription above.

If you request a stream that is paged, the data on the stream will be delivered with a next field populated. If given this field, request the next set of data with the below structure. Response continues as with the original stream.

Subscribe or amend request

KeyTypeRequiredDescription
reqidintYRequest ID - will be echoed back in the response structure
typestringY"subscribe" for initializing a subscription
tagstringYOptional user generated tag to attach to stream data
streamsobject[]YStreams to subscribe to
→ namestringYSubscription name
→ <Subscription Parameters>-------Any required or optional parameters described for the subscription names below

Amends a subscription request by Request ID. Response structure remains the same, just the content of the data will change per the amendment.

Amend an Existing Stream: Request structure

KeyTypeRequiredDescription
reqidintYRequest ID - will be echoed back in the response structure
typestringY"subscribe" for initializing a subscription
tagstringYOptional user generated tag to attach to stream data
streamsobject[]YStreams to subscribe to
→ namestringYSubscription name
→ <Subscription Parameters>-------Any required or optional parameters described for the subscription names below

Stream update

KeyTypeRequiredDescription
reqidintYEchoed back request ID
typestringYEchoed back subscription name to define the type of the data
seqintYIncrementing sequence number of messages for request ID starting with 1
initialbooleanYFlag to indicate if this message is the initial state of the stream
tsdatetimeYTimestamp of message publication
dataobject[]YList of response data structured per subscription type below
nextstringNIf paging, tag for next page of data

Page request

KeyTypeRequiredDescription
reqidintYThe request ID to continue the page, must match the original request ID
typestringY"page" for continuing the paged stream
dataobject[]YStream request data to continue
→ namestringYSubscription name to continue the page
→ afterstringYDelivered next value from the paged stream payload

Cancels an existing stream by Request ID. No response, unless there is an error. Stream will just stop.

Cancel an Existing Stream: Request structure

KeyTypeRequiredDescription
reqidintYRequest ID to cancel
typestringY"cancel" for cancelling the subscription

Command envelope

KeyTypeRequiredDescription
typestringYThe type of the command to send
dataobject[]YAny requisite data that needs to be submitted along with the command

Security stream

SDM maintains a security master which contains up-to-date information about the securities supported over API that are available to trade. The user should use the below streams when subscribing to the Security Master data.

Request for stream of available securities for trading. On initial request, a snapshot of all available securities is provided. All subsequent messages are deltas to the securities snapshot.

WebSocketsubscribeSecurity
Security subscription
json
{
  "reqid": 2,
  "type": "subscribe",
  "streams": [
    {
      "name": "Security"
    }
  ]
}
Security response
json
{
  "reqid": 2,
  "type": "Security",
  "ts": "2021-09-14T22:11:47.512168Z",
  "initial": true,
  "seqNum": 1,
  "data": [
    {
      "Timestamp": "2021-09-14T22:11:47.512168Z",
      "UpdateAction": "Update",
      "SecurityID": 2,
      "Symbol": "ETH-USD",
      "MinPriceIncrement": "0.01",
      "MinSizeIncrement": "0.00000001",
      "MinAmtIncrement": "0.01",
      "MinimumSize": "0.00000001",
      "MaximumSize": "10000000",
      "QuoteCurrency": "USD",
      "BaseCurrency": "ETH",
      "DefaultPriceIncrement": "0.01",
      "DefaultSizeIncrement": "0.0001",
      "PriceDisplaySpec": "M.m",
      "SizeDisplaySpec": "M.m",
      "NormalSize": "2",
      "ProductType": "Spot",
      "PositionCurrency": "ETH",
      "SettlementCurrency": "USD",
      "NotionalMultiplier": "1",
      "SizeBuckets": [
        {
          "Size": "0"
        }
      ],
      "DisplaySymbol": "ETH-USD",
      "Description": "Ethereum/U.S. Dollar"
    }
  ]
}

Subscription parameters

KeyTypeRequiredDescription
Symbols[]stringNOptional list of symbols to filter the subscription on

Response fields

KeyTypeRequiredDescription
TimestampdatetimeYTimestamp of message publication
UpdateActionstringYUpdate or Remove where the latter indicates the Security is no longer available
SecurityIDstringYSystem ID for Security - for information only
SymbolstringYSymbol for security
MinPriceIncrementdecimalYMinimum Price Increment for Security
MinSizeIncrementdecimalYMinimum Size Increment for Security. This increment is used to validate orders and RFQS expressed in base currency of the security.
MinAmtIncrementdecimalNMinimum Amount Increment for Security. This increment is used to validate orders and RFQS expressed in quote currency of the security.
MinimumSizedecimalYMinimum Size for an Order on this Security
MaximumSizedecimalNMaximum Size for an Order on this Security
QuoteCurrencystringYCurrency in which the Security is quoted
BaseCurrencystringYBase currency for the Security
EndTimedatetimeNDate this security was Disabled
DefaultPriceIncrementdecimalYDefault price increment used in all Market Data and Orders
DefaultSizeIncrementdecimalYDefault size increment used in all Market Data and Orders
PriceDisplaySpecstringYString specification describing the price display
NormalSizedecimalNNormal size of Security
ProductTypestringNProduct type of Security
PositionCurrencystringYCurrency in which any position on this Security is tracked
SettlementCurrencystringNCurrency in which any settlement on thes Security is negotiated
NotionalMultiplierdecimalNNotional Multiplier of Security
ExpirationdecimalNExpiration of Security
SizeBuckets[]decimalYDefault array of Size Buckets for Market Data Snapshot Streams
DisplaySymbolstringYDisplay symbol for Security
DescriptionstringYDescription of Security

Currency stream

Request for stream of available currencies used within trading. On initial request, a snapshot of all available currencies is provided. All subsequent messages are deltas to the currency snapshot.

WebSocketsubscribeCurrency
Currency subscription
json
{
  "reqid": 3,
  "type": "subscribe",
  "streams": [
    {
      "name": "Currency"
    }
  ]
}
Currency response
json
{
  "reqid": 3,
  "type": "Currency",
  "ts": "2021-09-14T22:11:47.512168Z",
  "initial": true,
  "seqNum": 1,
  "data": [
    {
      "Timestamp": "2020-09-30T17:56:08.552227Z",
      "UpdateAction": "Update",
      "CurrencyID": 2,
      "Symbol": "USD",
      "MinIncrement": "0.01",
      "DefaultIncrement": "0.01",
      "Description": "U.S. Dollar"
    },
    {
      "Timestamp": "2020-05-13T13:24:58.983054Z",
      "UpdateAction": "Update",
      "CurrencyID": 17,
      "Symbol": "ETH",
      "MinIncrement": "0.00000001",
      "DefaultIncrement": "0.0001",
      "Description": "Ethereum"
    }
  ]
}

Subscription parameters

KeyTypeRequiredDescription
Symbols[]stringNOptional list of currency symbols to filter the subscription on

Response fields

KeyTypeRequiredDescription
TimestampdatetimeYTimestamp of message publication
CurrencyIDstringYSystem ID for Currency - for information only
SymbolstringYSymbol for currency
MinIncrementdecimalYMinimum increment for Currency
DefaultIncrementdecimalYDefault increment used in all Market Data and Orders
DescriptionstringYDescription of Security

MarketDataSnapshot stream

This section outlines how to subscribe to market data via the SDM API.

Request stream of MarketDataSnapshot messages. To stream security pricing.

WebSocketsubscribeMarketDataSnapshot
Market data subscription
json
{
  "reqid": 5,
  "type": "subscribe",
  "streams": [
    {
      "name": "MarketDataSnapshot",
      "Symbol": "BTC-USD"
    }
  ]
}
Market data response
json
{
  "reqid": 5,
  "type": "MarketDataSnapshot",
  "ts": "2021-09-14T22:20:49.862930Z",
  "initial": true,
  "seqNum": 1,
  "data": [
    {
      "Timestamp": "2021-09-14T22:20:49.860957Z",
      "Symbol": "BTC-USD",
      "Status": "Online",
      "Bids": [
        {
          "Price": "46817.27965000",
          "Size": "1.00000000"
        },
        {
          "Price": "46816.08025000",
          "Size": "2.00000000"
        }
      ],
      "Offers": [
        {
          "Price": "46868.59755873",
          "Size": "1.00000000"
        },
        {
          "Price": "46870.33345500",
          "Size": "2.00000000"
        }
      ]
    }
  ]
}

Subscription parameters

KeyTypeRequiredDescription
SymbolstringYSecurity to request
ThrottlestringNAn optional throttle duration for updates, defaults to configured MinMarketDataThrottle. A throttle is specified by a time duration + units. For example: "300ms", "500us". Valid time units are "ns", "us", "ms", "s".
PriceIncrementdecimalNPrice increment for levels to enable price bucketing
DepthdecimalNMaximum number of bid / offer levels to stream prices for
SizeBuckets[]decimalNA list of sizes to return price levels for; defaults to configured Security SizeBuckets

Response fields

KeyTypeRequiredDescription
TimestampdatetimeYTimestamp of update
SymbolstringYSecurity for update
StatusstringYStatus of update; Online or Offline
Bidsobject[]YFull list of Bids
→ PricedecimalYLimit price of the level.
→ SizedecimalYSize on this level.
Offersobject[]YFull list of Offers
→ PricedecimalYLimit price of the level.
→ SizedecimalYSize on this level.

CurrencyConversion stream

Request for stream of currency conversion rates.

WebSocketsubscribeCurrencyConversion
Conversion subscription
json
{
  "reqid": 4,
  "type": "subscribe",
  "streams": [
    {
      "name": "CurrencyConversion",
      "EquivalentCurrency": "USD",
      "Currencies": [
        "BTC",
        "ETH",
        "BCH-USD"
      ],
      "Throttle": "15s",
      "Tolerance": "0.0002"
    }
  ]
}
Conversion response
json
{
  "reqid": 4,
  "type": "CurrencyConversion",
  "ts": "2021-09-14T22:16:18.604996Z",
  "initial": true,
  "seqNum": 1,
  "data": [
    {
      "Timestamp": "2021-09-14T22:16:18.604674Z",
      "EquivalentCurrency": "USD",
      "Currency": "ETH",
      "Rate": "3368.16",
      "Status": "Online",
      "ConversionPath": "(ETH-USD)"
    },
    {
      "Timestamp": "2021-09-14T22:16:18.604674Z",
      "EquivalentCurrency": "USD",
      "Currency": "BTC",
      "Rate": "46841.35",
      "Status": "Online",
      "ConversionPath": "(BTC-USD)"
    },
    {
      "Timestamp": "2021-09-14T22:16:18.604674Z",
      "EquivalentCurrency": "USD",
      "Currency": "BCH-USD",
      "Rate": "639.530000000000",
      "Status": "Online",
      "ConversionPath": "(BCH-USD)"
    }
  ]
}

Subscription parameters

KeyTypeRequiredDescription
EquivalentCurrencystringYQuote currency to base the conversion rates on
Currencies[]stringNList of currencies and securities to generate conversion rates for; defaults to all available currencies
ThrottlestringNOptional throttle interval for conversion rate updates. Minimal / default value: 10s
TolerancedecimalNOptional param to indicate what conversation rate percent change should trigger sending out an update. Minimal / default value: 0.0001 which means 1 bps

Response fields

KeyTypeRequiredDescription
TimestampdatetimeYTimestamp of message publication
EquivalentCurrencystringYCurrency symbol for equivalent currency
CurrencystringYCurrency symbol for base currency on conversion
RatedecimalYCurrency conversion rate

Order workflow and supported strategies

This section outlines how to send orders using the SDM API. To send orders, first subscribe to the ExecutionReport stream. All order responses and updates are sent as ExecutionReport 's'. Send requests with the NewOrderSingle, OrderCancelRequest, OrderCancelReplaceRequest, and OrderControlRequest messages.

To generate a ClOrdID, we recommend using a UUID4 or another globally unique identifier. ClOrdID must be unique daily and among any open order and must be less than 36 characters.

The orders API roughly follows the same semantics as the FIX Protocol, though with some notable differences, see Order State Change Matrices for more details.

A typical trading strategy would do the following:

  1. Subscribe to MarketDataSnapshot for the relevant securities
  2. Subscribe to ExecutionReport with StartDate of the Timestamp of the last ExecutionReport processed to recover order state.
  3. Subscribe to Trade with StartDate of the Timestamp of the last Trade processed to recover any missed trades.
  4. Maintain a map of (OrderID , last received ExecutionReport ) for open orders.
  5. Maintain a set of ClOrdID for each pending request.
  6. To submit an order, first generate a new ClOrdID (see instructions below). Send a NewOrderSingle specifying the ClOrdID , Side , Price , OrderQty , Strategy , etc. for that request.
  7. The response for the request will be received on the ExecutionReport stream with the ClOrdID being the ClOrdID specified on the NewOrderSingle . If the order is accepted (ExecType=PendingNew ), then add this order to the set of open orders.
  8. To cancel or modify the open order, generate a new ClOrdID and send an OrderCancelRequest or OrderCancelReplaceRequest specifying the the ClOrdID , OrigClOrdID from the previous successful request, and remaining parameters.
  9. Fills will be received as ExecutionReport with ExecType=Trade .

A schedule-based algorithm that divides an order into suborders (clips) and submits them at equal, user defined intervals.

SteadyPace parameters

ParameterTypeRequiredDescription
ClipSizeQtyYA quantity (subset of the total order size) to send on each execution of the schedule.
ClipIntervalstringYTime interval between individual clips specified as an interval string.
StartTimestringNTime at which this order will activate and begin sending orders. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
EndTimestringNOptional expire time for the order. An ISO-8601 UTC string of the form 2019-02- 13T05:17:32.000000Z
VariancedecimalNOptional degree of randomization for clip sizes.

An interval or duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as 300ms or 2h45m. Valid time units are ns, us (or µs), ms, s, m, h. A variance of 0.1 (implying a variance of 10%) for a clip size of 1.0 would result in clips ranging between 0.9 and 1.1.

StopLimit parameters

ParameterTypeRequiredDescription
TriggerPricePriceYThe price that must be met to trigger execution of the order with the configured limit price.
EndTimestringNOptional expire time for the order. An ISO-8601 UTC string of the form 2019-02- 13T05:17:32.000000Z

This strategy will only place the order once the specified stop price has been met. For a Buy StopLimit order, the stop price must be above the current market price. For a Sell StopLimit order, the stop price must be below the current market price.

Order stream

Request stream of Order updates.

An Order update having a data field containing an array that has a similar structure to ExecutionReport

WebSocketsubscribeOrder
Order subscription
json
{
  "reqid": 7,
  "type": "subscribe",
  "streams": [
    {
      "name": "Order"
    }
  ]
}
Order response
json
{
  "reqid": 7,
  "type": "Order",
  "ts": "2021-09-14T22:26:44.518538Z",
  "initial": false,
  "seqNum": 3,
  "data": [
    {
      "Timestamp": "2021-09-14T22:26:44.505519Z",
      "Symbol": "BTC-USD",
      "OrderID": "b35b1c3b-a304-4224-919f-9db1319de188",
      "ClOrdID": "d7635e40-15aa-11ec-b0a2-2554a9e1e7a4",
      "SubmitTime": "2021-09-14T22:26:44.457050Z",
      "ExecID": "c73fcf77-aaa1-46e7-9260-f625d6416646",
      "Side": "Buy",
      "ExecType": "New",
      "OrdStatus": "New",
      "OrderQty": "0.10000000",
      "OrdType": "Market",
      "Currency": "BTC",
      "LeavesQty": "0.10000000",
      "CumQty": "0",
      "AvgPx": "0",
      "TimeInForce": "FillOrKill",
      "LastPx": "0",
      "LastQty": "0",
      "LastAmt": "0",
      "LastFee": "0",
      "CumAmt": "0",
      "DecisionStatus": "Active",
      "AmountCurrency": "USD",
      "CustomerUser": "tom@company.com",
      "Parameters": {
        "ErrorAction": "Pause"
      }
    }
  ]
}

Subscription parameters

KeyTypeRequiredDescription
StartDatestringNIf provided, the subscription will return orders that were submitted after this time. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
EndDatestringNIf provided, the subscription will return orders that were submitted before this time. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
SymbolstringNIf provided, Symbol of the security to get the orders for
Statusesstring[]NIf provided, comma-separated Statuses of orders to include e.g. New,Filled
OrderIDstringNIf provided, filter by OrderID
RFQIDstringNIf provided, filter by RFQID

ExecutionReport stream

Request stream of Execution Reports.

WebSocketsubscribeExecutionReport
Execution report subscription
json
{
  "reqid": 6,
  "type": "subscribe",
  "streams": [
    {
      "name": "ExecutionReport"
    }
  ]
}
Execution report response
json
{
  "reqid": 6,
  "type": "ExecutionReport",
  "ts": "2021-09-14T22:23:11.920903Z",
  "initial": false,
  "seqNum": 2,
  "data": [
    {
      "Timestamp": "2021-09-14T22:23:11.903074Z",
      "Symbol": "BTC-USD",
      "OrderID": "1b6b882b-e2fc-4774-ad2d-9db4df536f29",
      "ClOrdID": "58b9adb0-15aa-11ec-b0a2-2554a9e1e7a4",
      "SubmitTime": "2021-09-14T22:23:11.903074Z",
      "ExecID": "4b423f54-4a54-4679-9ee7-1f5f417ec5f5",
      "Side": "Buy",
      "TransactTime": "2021-09-14T22:23:11.883000Z",
      "ExecType": "PendingNew",
      "OrdStatus": "PendingNew",
      "OrderQty": "0.20000000",
      "OrdType": "Market",
      "Currency": "BTC",
      "LeavesQty": "0.20000000",
      "CumQty": "0",
      "AvgPx": "0",
      "TimeInForce": "FillOrKill",
      "LastPx": "0",
      "LastQty": "0",
      "LastAmt": "0",
      "LastFee": "0",
      "CumAmt": "0",
      "AmountCurrency": "USD",
      "CustomerUser": "tom@company.com",
      "Parameters": {
        "ErrorAction": "Pause"
      }
    }
  ]
}

Subscription parameters

KeyTypeRequiredDescription
StartDatestringNIf provided, the subscription will return execution reports that were published at or after this time. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
EndDatestringNIf provided, the subscription will return execution reports that were published before this time. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
SymbolstringNIf provided, Symbol of the security to get the executions for
Statusesstring[]NIf provided, comma-separated statuses of orders to include e.g. New,Filled
OrderIDstringNIf provided, filter by OrderID
RFQIDstringNIf provided, filter by RFQID

Response fields

KeyTypeRequiredDescription
TimestampdatetimeYTimestamp of the message
SymbolstringYSymbol of the order security
OrderIDstringYServer assigned Order ID, will be a UUID
ClOrdIDstringYClient assigned Order ID for the last request
OrigClOrdIDstringYOriginal client assigned
SubmitTimedatetimeYTime of original order submission
ExecIDstringYServer assigned ID of this update, will be a UUID
SidestringY"Buy" or "Sell"
TransactTimedatetimeNAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
ExecTypestringYDescribes the specific execution (e.g. Pending Cancel) while OrdStatus will always identify the current order status (e.g. Partially Filled). Valid values: New, Trade, Canceled, Replaced, PendingCancel, Stopped, Rejected, PendingNew, Restated, PendingReplace, CancelRejected, ReplaceRejected, PendingResume, Resumed, PendingPause, Paused, Triggered, Started
OrdStatusstringYIdentifies current status of order. Valid values: New, PartiallyFilled, Filled, Canceled, PendingCancel, Rejected, PendingNew, PendingReplace.
OrderQtydecimalYOrder quantity
OrdTypestringYOrder type. Valid values: Market, Limit, or RFQ
PricedecimalNOrder limit price, required when OrdType=Limit
CurrencystringYCurrency of Quantity
LeavesQtydecimalYQuantity open for further execution. If the OrdStatus is Canceled or Rejected (in which case the order is no longer active) then LeavesQty could be 0, otherwise LeavesQty = OrderQty – CumQty
CumQtydecimalYTotal quantity filled. Always in Currency units (BTC of a BTC-USD order)
AvgPxdecimalNAverage filled price of the order. Only valid if CumQty > 0. Does not include fees
TimeInForcestringYSpecifies how long the order remains in effect. Valid values: GoodTillCancel, FillAndKill, or FillOrKill
LastPxdecimalNLast price, specified when ExecType=Trade
LastQtydecimalNLast qty, specified when ExecType=Trade
LastAmtdecimalNLast amount, specified when ExecType=Trade
LastFeedecimalNLast fee, specified when ExecType=Trade
LastFeeCurencystringNLast fee currency, specified when ExecType=Trade. Note this may be different from the cumulative fee
CumAmtdecimalNTotal amount filled. Always in Amount currency (USD of a BTC-USD order)
FeeCurencystringNCumulative fee currency
OrdRejReasonstringNOrder reject reason, specified when ExecType=Rejected. Valid values: UnknownSymbol, OrderExceedsLimit, TooLateToEnter, UnknownOrder, DuplicateOrder, StaleRequest, InternalError, BrokerOption, RateLimit, ForceCancel, ImmediateOrderDidNotCross, PostOnlyOrderWouldCross, InvalidStrategy, QuoteRequestTimeout, QuoteExpired
CxlRejReasonstringNCancel reject reason, specified when ExecType=CancelRejected or ExecType=ReplaceRejected. Valid values: UnknownOrder, Broker, OrderAlreadyInPendingCancelOrPendingReplaceStatus, DuplicateClOrdID, TooLateToCancel, StaleRequest, RateLimit, InvalidStrategy, Other
QuoteIDstringNServer assigned QuoteID for RFQ Orders
AmountCurrencystringYCurrency of Amount
SessionIDstringYSessionID that submitted this order
CancelSessionIDstringNIf specified, the order will be cancelled when this session is closed
StrategystringNName of the Order Strategy to use
RFQIDstringNServer assigned RFQID for RFQ Orders
AllowedSlippagedecimalNAllowedSlippage in absolute value (ie. 0.001 = 10 bps) if specified on order
TextstringNHuman readable error message
CustomerUserstringNThe customer user associated with this execution report.

NewOrderSingle command

Command used to submit a new order either against any provided liquidity or an open RFQ. Results of this command will be visible in the Order , ExecutionReport and Trade streams which will track the lifecycle of the order.

WebSocketsendNewOrderSingle
Submit NewOrderSingle
json
{
  "reqid": 12,
  "type": "NewOrderSingle",
  "data": [
    {
      "Symbol": "BTC-USD",
      "ClOrdID": "4d489920-15da-11ec-b5e7-7f4881f01b7d",
      "Side": "Buy",
      "TransactTime": "2021-09-15T04:06:28.530000Z",
      "OrderQty": "0.5",
      "OrdType": "Limit",
      "Price": "43000",
      "Currency": "BTC",
      "TimeInForce": "GoodTillCancel",
      "Strategy": "Limit",
      "Parameters": {
        "ErrorAction": "Pause"
      }
    }
  ]
}

Command data

KeyTypeRequiredDescription
TimestampdatetimeNTimestamp of the message
SymbolstringYSymbol of the security to submit an order on
ClOrdIDstringYUnique Client Order ID for this request, usually a UUID
SidestringYSide of the order, either Buy or Sell
OrderQtydecimalYOrder quantity in units of Currency
OrdTypestringYOrder type. Valid values: Market, Limit, or RFQ
PricedecimalNOrder limit price, required for Limit orders
TransactTimedatetimeNAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
CurrencystringNThe currency that the quantity is specified in. If not specified, defaults to the base currency for the symbol
QuoteIDstringNOptional QuoteID to trade on. Must be specified when OrdType=RFQ
RFQIDstringNOptional RFQID to trade on. Must be specified when OrdType=RFQ
TimeInForcestringYSpecifies how long the order remains in effect. Valid values: GoodTillCancel, FillAndKill, or FillOrKill
StrategystringNOptional order strategy to use. For algorithmic orders SteadyPace, `StopLimit' are supported
AllowedSlippagedecimalNOptional allowed price slippage for Limit order placed against RFQ
ParametersobjectNOptional order strategy parameters

OrderCancelRequest command

Command used to cancel an open order. Results of this command will be visible in the Order and ExecutionReport streams.

WebSocketsendOrderCancelRequest
Submit OrderCancelRequest
json
{
  "reqid": 13,
  "type": "OrderCancelRequest",
  "data": [
    {
      "ClOrdID": "c0be17e0-15da-11ec-b5e7-7f4881f01b7d",
      "OrderID": "16a55364-4248-4575-aa0b-dddd3f694ca3",
      "TransactTime": "2021-09-15T04:09:42.238000Z"
    }
  ]
}

Command data

KeyTypeRequiredDescription
TimestampdatetimeNTimestamp of the message
SymbolstringYSymbol of the security to submit an order on
ClOrdIDstringYUnique Client Order ID for this request, usually a UUID
OrigClOrdIDstringNClient Order ID of the order to cancel, one of OrderID, OrigClOrdID is required
OrderIDstringNOrder ID of the order to cancel, one of OrderID, OrigClOrdID is required
TransactTimedatetimeYAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z

OrderCancelReplaceRequest command

Command used to modify an open order. Results of this command will be visible in the Order and ExecutionReport streams.

WebSocketsendOrderCancelReplaceRequest
Submit OrderCancelReplaceRequest
json
{
  "reqid": 14,
  "type": "OrderCancelReplaceRequest",
  "data": [
    {
      "Price": "44000",
      "Symbol": "BTC-USD",
      "OrderID": "16a55364-4248-4575-aa0b-dddd3f694ca3",
      "ClOrdID": "b5e52570-15da-11ec-b5e7-7f4881f01b7d",
      "TransactTime": "2021-09-15T04:09:24.039000Z",
      "OrderQty": "0.5",
      "Parameters": {
        "ErrorAction": "Pause"
      }
    }
  ]
}

Command data

KeyTypeRequiredDescription
TimestampdatetimeNTimestamp of the message
SymbolstringYSymbol of the security to submit an order on
ClOrdIDstringYUnique Client Order ID for this request, usually a UUID
OrigClOrdIDstringNClient Order ID of the order to cancel, one of OrderID, OrigClOrdID is required
OrderIDstringNOrder ID of the order to cancel, one of OrderID, OrigClOrdID is required
OrderQtydecimalYOrder quantity in units of Currency
PricedecimalNOrder limit price, required for Limit orders
TransactTimedatetimeYAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
StrategystringNOptional order strategy to use. For algorithmic orders Pegged, TWAP, FullAmount, TimeSliced, and SteadyPace are supported
EndTimedatetimeNOptional expire time for the order. An ISO-8601 UTC string of the form 2019-02- 13T05:17:32.000000Z
ParametersobjectNOptional order strategy parameters

OrderControlRequest command

Command used to Pause or Resume an open order. Results of this command will be visible in the Order and ExecutionReport streams.

WebSocketsendOrderControlRequest
Submit OrderControlRequest
json
{
  "reqid": 17,
  "type": "OrderControlRequest",
  "data": [
    {
      "ClOrdID": "9eb07120-15da-11ec-b5e7-7f4881f01b7d",
      "OrderID": "16a55364-4248-4575-aa0b-dddd3f694ca3",
      "Action": "Pause"
    }
  ]
}

Command data

KeyTypeRequiredDescription
TimestampdatetimeNTimestamp of the message
ClOrdIDstringYUnique Client Order ID for this request, usually a UUID
OrigClOrdIDstringNClient Order ID of the order to submit the control request for, one of OrderID, OrigClOrdID is required
OrderIDstringNOrder ID of the order to submit the control request for, one of OrderID, OrigClOrdID is required
TransactTimedatetimeYAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
ActionstringYAction to apply on the order, either Pause or Resume

WebSocket order state change matrices

The orders API follows FIX 4.4 semantics closely. The main difference is that instead of sending separate OrderCancelReject messages, two extra ExecType are supported: CancelRejected and ReplaceRejected. The order state change matrices below are heavily inspired by the FIX documentation.

Filled order

TimeRequest (ClOrdID,OrigClOrdID)Response (ClOrdID,OrigClOrdID)ExecTypeOrdStatusOrderQtyCumQtyLeavesQtyLastQtyComment
1NewOrderSingle(A)10
2ExecutionReport(A)PendingNewPendingNew10010
3ExecutionReport(A)RejectedRejected10010If order is rejected
3ExecutionReport(A)NewNew10010
4ExecutionReport(A)TradePartiallyFilled10282
5ExecutionReport(A)TradePartiallyFilled10371
6ExecutionReport(A)TradeFilled101007

Orders with CumQty > 0 will receive an Execution Report that will have CumQty for the filled size of the order. Orders that are partially filled and canceled will receive an ExecutionReport with a terminal state (Canceled) and a CumQty > 0

Canceled order

TimeRequest (ClOrdID,OrigClOrdID)Response (ClOrdID,OrigClOrdID)ExecTypeOrdStatusOrderQtyCumQtyLeavesQtyLastQtyComment
1NewOrderSingle(A)10
2ExecutionReport(A)PendingNewPendingNew10010
3ExecutionReport(A)RejectedRejected10010If order is rejected
3ExecutionReport(A)NewNew10010
4OrderCancelRequest(B,A)
5ExecutionReport(B,A)CancelRejectedNew10010If cancel is rejected
5ExecutionReport(B,A)PendingCancelPendingCancel10010
6ExecutionReport(B,A)CancelRejectedNew10010If cancel is rejected
7ExecutionReport(B,A)CanceledCanceled1000

Replace to increase quantity

TimeRequest (ClOrdID,OrigClOrdID)Response (ClOrdID,OrigClOrdID)ExecTypeOrdStatusOrderQtyCumQtyLeavesQtyLastQtyComment
1NewOrderSingle(A)10
2ExecutionReport(A)PendingNewPendingNew10010
3ExecutionReport(A)NewNew10010
4OrderCancelReplaceRequest(B,A)11
5ExecutionReport(B,A)ReplaceRejectedNew10010If replace is rejected
5ExecutionReport(B,A)PendingReplacePendingReplace10010
6ExecutionReport(B,A)CancelRejectedNew10010If replace is rejected
7ExecutionReport(B,A)ReplacedNew1100
8ExecutionReport(B)TradePartiallyFilled111101

Replace during fill

TimeRequest (ClOrdID,OrigClOrdID)Response (ClOrdID,OrigClOrdID)ExecTypeOrdStatusOrderQtyCumQtyLeavesQtyLastQtyComment
1NewOrderSingle(A)10
2ExecutionReport(A)PendingNewPendingNew10010
3ExecutionReport(A)NewNew10010
4OrderCancelReplaceRequest(B,A)8
5ExecutionReport(A)TradePartiallyFilled10191Fill before replace is received
6ExecutionReport(B,A)PendingReplacePendingReplace1019
7ExecutionReport(A)TradePendingReplace10372Fill before replace is processed
8ExecutionReport(B,A)ReplacedNew835
9ExecutionReport(B)TradeFilled8805

Trade stream

Upon Subscription, the server will return all Trade for this client as long as the optional constraints are satisfied. Server will also send a Trade update when the order receives more fills or new fills arrive on a new order that came in as long as the optional constraints are satisfied.

Request stream of Trade messages.

WebSocketsubscribeTrade
Trade subscription
json
{
  "reqid": 8,
  "type": "subscribe",
  "streams": [
    {
      "name": "Trade",
      "StartDate": "2021-09-14T00:00:00.000000Z"
    }
  ]
}
Trade response
json
{
  "reqid": 8,
  "type": "Trade",
  "ts": "2021-09-14T22:29:32.255949Z",
  "initial": true,
  "seqNum": 1,
  "data": [
    {
      "Timestamp": "2021-09-14T22:23:11.989845Z",
      "Symbol": "BTC-USD",
      "OrderID": "1b6b882b-e2fc-4774-ad2d-9db4df536f29",
      "TradeID": "a0ec46f2-6d0e-451a-a4f1-2a0be7d32d26",
      "Side": "Buy",
      "TransactTime": "2021-09-14T22:23:11.964531Z",
      "ExecType": "Trade",
      "Currency": "BTC",
      "Price": "47085.090668824440",
      "Quantity": "0.20000000",
      "Amount": "9417.02",
      "Fee": "0",
      "CustomerUser": "tom@company.com",
      "TradeStatus": "Confirmed",
      "AggressorSide": "Buy",
      "AmountCurrency": "USD",
      "DealtCurrency": "BTC"
    },
    {
      "Timestamp": "2021-09-14T22:26:44.515692Z",
      "Symbol": "BTC-USD",
      "OrderID": "b35b1c3b-a304-4224-919f-9db1319de188",
      "TradeID": "17f9da19-d3bd-4ba2-b29a-1f31516458f2",
      "Side": "Buy",
      "TransactTime": "2021-09-14T22:26:44.485836Z",
      "ExecType": "Trade",
      "Currency": "BTC",
      "Price": "46945.3659525",
      "Quantity": "0.10000000",
      "Amount": "4694.54",
      "Fee": "0",
      "CustomerUser": "tom@company.com",
      "TradeStatus": "Confirmed",
      "AggressorSide": "Buy",
      "AmountCurrency": "USD",
      "DealtCurrency": "BTC"
    }
  ]
}

Subscription parameters

KeyTypeRequiredDescription
StartDatestringNIf provided, the subscription will return trades that were executed after this time. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
EndDatestringNIf provided, the subscription will return trades that were executed before this time. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
SymbolstringNIf provided, Symbol of the security to get the orders for
OrderIDstringNIf provided, filter by OrderID
RFQIDstringNIf provided, filter by RFQID

Response fields

KeyTypeRequiredDescription
TimestampdatetimeYTimestamp of the message
OrderIDstringYServer assigned Order ID, will be a UUID
TradeIDstringYServer assigned Trade ID, will be a UUID
SidestringY"Buy" or "Sell"
TransactTimedatetimeYAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
ExecTypestringYDescribes the specific execution (e.g. Pending Cancel) while OrdStatus will always identify the current order status (e.g. Partially Filled). Valid values: New, Trade, Canceled, Replaced, PendingCancel, Stopped, Rejected, PendingNew, Restated, PendingReplace, CancelRejected, ReplaceRejected, PendingResume, Resumed, PendingPause, Paused, Triggered, Started
CurrencystringYCurrency of Quantity
PricedecimalNOrder limit price, required when OrdType=Limit
QuantitydecimalYTrade quantity
AmountdecimalYTrade amount
FeedecimalYTrade fee
FeeCurencystringNCumulative fee currency
TradeStatusstringYStatus of the trade. Valid values: Pending, Confirmed, Canceled
QuoteIDstringNServer assigned QuoteID for RFQ Orders
AmountCurrencystringYCurrency of Amount
RFQIDstringNServer assigned RFQID for RFQ Orders
CustomerUserstringNThe customer user associated with this trade.

Quote stream and RFQ lifecycle

This section outlines how to request quotes from multiple dealers simultaneously and accept them using the SDM API. To send a quote request, first subscribe to the Quote stream, and the ExecutionReport stream as with orders. All quote responses are sent as Quote updates, and all order responses and updates are sent as ExecutionReport .

To request a quote, send a QuoteRequest message. The server responds with one or many Quote messages as the streaming prices update.

An in-progress Quote can be cancelled by sending a QuoteCancelRequest message. Quotes time out automatically after 3 minutes by default.

To accept a quote, send a NewOrderSingle (RFQ) message.

To generate a QuoteReqID, we recommend using a UUID4 or another globally unique identifier. QuoteReqID must be unique and with length less than or equal to 36 characters.

Request stream of Quotes.

A typical workflow to request and accept a quote would be:

  1. Subscribe to Quote .
  2. Subscribe to ExecutionReport .
  3. Subscribe to Trade with StartDate of the Timestamp of the last Trade processed to recover any missed trades.
  4. To request a quote, first generate a new QuoteReqID (see instructions below). Send a QuoteRequest specifying the QuoteReqID , OrderQty , Currency etc. for that request.
  5. Quote updates will be received that are able to be priced.
  6. To accept a quote that is received, send a NewOrderSingle referencing the RFQID and parameters depending on OrdType
  7. Fills will be received as ExecutionReport with ExecType=Trade .
  8. QuoteStatus will change to Filled when the Quote is successfully accepted.
QuoteRequest enters PendingNew, which becomes Rejected or Open when prices are available. Open enters PendingFill on a new order. An order rejection returns PendingFill to Open; a fill reaches Filled. User cancellation or EndTime takes Open to Canceled. Rejected, Filled, and Canceled lead to the terminal state.
Original QuoteStatus state diagram, Trading API page 36.
WebSocketsubscribeQuote
Quote subscription
json
{
  "reqid": 9,
  "type": "subscribe",
  "streams": [
    {
      "name": "Quote"
    }
  ]
}
Quote response
json
{
  "reqid": 9,
  "type": "Quote",
  "ts": "2021-09-14T22:31:27.214025Z",
  "initial": false,
  "seqNum": 3,
  "data": [
    {
      "Timestamp": "2021-09-14T22:31:27.204209Z",
      "Symbol": "BTC-USD",
      "Currency": "BTC",
      "RFQID": "8688ceab-ea67-416c-8ce1-9b63d6c0fe4e",
      "QuoteReqID": "7feb22f0-15ab-11ec-b0a2-2554a9e1e7a4",
      "QuoteStatus": "Open",
      "QuoteID": "20e240c5-9a82-4731-809e-91b3a2bf2f49",
      "SubmitTime": "2021-09-14T22:31:27.183751Z",
      "OrderQty": "0.30000000",
      "AmountCurrency": "USD",
      "EndTime": "2021-09-14T22:31:42.183751Z",
      "BidPx": "46836.27",
      "BidAmt": "14050.88",
      "OfferPx": "46879.47",
      "OfferAmt": "14063.85",
      "ValidUntilTime": "2021-09-14T22:31:28.204209Z",
      "CustomerUser": "tom@company.com"
    }
  ]
}

Subscription parameters

KeyTypeRequiredDescription
StartDatestringNIf provided, the subscription will return quotes for rfqs that were submitted after this time. An ISO- 8601 UTC string of the form 2019-02-13T05:17:32.000000Z
EndDatestringNIf provided, the subscription will return quotes for rfqs that were submitted before this time. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
SymbolstringNIf provided, Symbol of the security to get the orders for
RFQIDstringNIf provided, filter by RFQID

Response fields

KeyTypeRequiredDescription
TimestampdatetimeYTimestamp of the message
SymbolstringYSymbol of the order security
CurrencystringYCurrency of Quantity
RFQIDstringNServer assigned RFQID for RFQ Orders
QuoteReqIDstringYClient assigned Quote Req ID for the quote request
QuoteStatusstringYStatus of the quote, one of PendingNew, Open, PendingCancel, Canceled, PendingFill, Filled, Rejected
QuoteIDstringYServer assigned ID for this quote update
QuoteRequestRejectReasonstringYQuote request reject reason, specified when ExecType=Rejected. Valid values: UnknownSymbol, OrderExceedsLimit, TooLateToEnter, UnknownOrder, DuplicateOrder, StaleRequest, InternalError, BrokerOption, RateLimit, ForceCancel, ImmediateOrderDidNotCross, PostOnlyOrderWouldCross, InvalidStrategy, QuoteRequestTimeout, QuoteExpired
SubmitTimedatetimeYTime of original quote request submission
OrderQtydecimalYOrder quantity
AmountCurrencystringYCurrency of Amount
EndTimedatetimeYEnd time of RFQ; an ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
SidestringY"Buy" or "Sell"
TradedPxdecimalNThe price of the trade if the quote is filled. This will be an all-in price that includes fees
TradedQtydecimalNThe quantity of the trade if the quote is filled in units of Currency
TradedAmtdecimalNThe amount of the trade if the quote is filled in units of AmountCurrency
TradedSidestringNThe side of the trade if the quote is filled
BidPxdecimalNBid quote price
BidAmtdecimalNBid quote amount in units of AmountCurrency
OfferPxdecimalNOffer quote price
OfferAmtdecimalNOffer quote amount in units of AmountCurrency
ValidUntilTimedatetimeYThe expire time of the quote. An ISO-8601 UTC string of the form 2019-02- 13T05:17:32.000000Z
TextstringNHuman readable error message
CustomerUserstringNThe customer user associated with this quote.

QuoteRequest and QuoteCancelRequest commands

Command used to request a quote thereby opening a new RFQ. Results of this command will be visible in the Quote stream.

Command used to cancel an open RFQ. Results of this command will be visible in the Quote stream.

WebSocketsendQuoteRequest
Submit QuoteRequest
json
{
  "reqid": 15,
  "type": "QuoteRequest",
  "data": [
    {
      "QuoteReqID": "8e9540d0-15db-11ec-b5e7-7f4881f01b7d",
      "OrderQty": "0.75",
      "Currency": "BTC",
      "Symbol": "BTC-USD",
      "TransactTime": "2021-09-15T04:15:27.581000Z",
      "Parameters": {}
    }
  ]
}

QuoteRequest command data

KeyTypeRequiredDescription
TimestampdatetimeNTimestamp of the message
SymbolstringYSymbol of the security to submit an order on
CurrencystringYThe currency that the quantity is specified in.
QuoteReqIDstringYUnique ID for this request, usually a UUID
SidestringNOptional side for a one sided request, either "Buy" or "Sell". Leave blank for a two way quote
OrderQtydecimalYRequested quantity in units of Currency
TransactTimedatetimeNAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
WebSocketsendQuoteCancelRequest
Submit QuoteCancelRequest
json
{
  "reqid": 16,
  "type": "QuoteCancelRequest",
  "data": [
    {
      "QuoteReqID": "8e9540d0-15db-11ec-b5e7-7f4881f01b7d",
      "RFQID": "f47bfb99-4d1e-4179-b62c-a96e83cc93ba",
      "TransactTime": "2021-09-15T04:15:24.581000Z"
    }
  ]
}

QuoteCancelRequest command data

KeyTypeRequiredDescription
QuoteReqIDstringYQuoteReqID from the request to cancel
RFQIDstringYRFQID to cancel, required and must align with QuoteReqID
TransactTimedatetimeYAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z

Balance stream

Request for stream of Balance updates

WebSocketsubscribeBalance
Balance subscription
json
{
  "reqid": 11,
  "type": "subscribe",
  "streams": [
    {
      "name": "Balance",
      "EquivalentCurrency": "USD"
    }
  ]
}
Balance response
json
{
  "reqid": 11,
  "type": "Balance",
  "ts": "2021-09-16T16:17:06.892914Z",
  "initial": true,
  "seqNum": 1,
  "data": [
    {
      "Currency": "USD",
      "Amount": "-1928479.77953598",
      "AvailableAmount": "-1928479.77953598",
      "Equivalent": {
        "Currency": "USD",
        "Amount": "-1928479.78",
        "AvailableAmount": "-1928479.78"
      }
    },
    {
      "Currency": "BTC",
      "Amount": "40.15480673",
      "AvailableAmount": "40.15480673",
      "Equivalent": {
        "Currency": "USD",
        "Amount": "1930241.56",
        "AvailableAmount": "1930241.56"
      }
    },
    {
      "Currency": "ETH",
      "Amount": "11.00000000",
      "AvailableAmount": "11.00000000",
      "Equivalent": {
        "Currency": "USD",
        "Amount": "39753.78",
        "AvailableAmount": "39753.78"
      }
    },
    {
      "Currency": "BCH",
      "Amount": "23.68787010",
      "AvailableAmount": "23.68787010",
      "Equivalent": {
        "Currency": "USD",
        "Amount": "15066.67",
        "AvailableAmount": "15066.67"
      }
    },
    {
      "Currency": "ADA",
      "Amount": "10330.26832917",
      "AvailableAmount": "10330.26832917",
      "Equivalent": {
        "Currency": "USD",
        "Amount": "25340.27",
        "AvailableAmount": "25340.27"
      }
    }
  ]
}

Subscription parameters

KeyTypeRequiredDescription
Currenciesstring[]NOptional list of currencies to filter these balance updates by, default is all available currencies
EquivalentCurrencystringNIf provided, will provide converted equivalent amounts of each currency in the provided Equivalent Currency

Response fields

KeyTypeRequiredDescription
CurrencystringYCurrency of this balance update
AmountdecimalYCurrent balance amount in the specified currency
AvailableAmountdecimalYAmount available for trading right now
Equivalentobject[]NIf requested equivalent balance amount, will provide a Balance update in the specified equivalent currency
→ CurrencystringNRequested Equivalent Currency
→ AmountdecimalNAmount of this balance in the equivalent currency
→ AvailableAmountdecimalNEquivalent amount of amount available for trading right now

Exposure stream

Request for stream of Exposure updates

WebSocketsubscribeExposure
Exposure subscription
json
{
  "reqid": 11,
  "type": "subscribe",
  "streams": [
    {
      "name": "Exposure"
    }
  ]
}
Exposure response
json
{
  "reqid": 11,
  "type": "Exposure",
  "ts": "2021-09-16T16:17:06.892914Z",
  "initial": true,
  "seqNum": 1,
  "data": [
    {
      "ExposureCurrency": "USD",
      "Exposure": "1000000",
      "ExposureLimit": "5000000",
      "Status": "Online",
      "Timestamp": "2021-09-16T16:17:06.892914Z"
    }
  ]
}

Response fields

KeyTypeRequiredDescription
ExposureCurrencystringYThe currency all exposure values are expressed in
ExposuredecimalYCurrent credit utilization expressed in the ExposureCurrency
ExposureLimitdecimalYCredit limit expressed in the ExposureCurrency
StatusstatusYStatus of the exposure information. Possible values: Online, Offline
TimestampstatusYThe last time the credit was updated as an ISO-8601 UTC string of the form 2019-02- 13T05:17:32.000000Z.

BalanceTransaction stream

Request stream of Balance Transaction Updates

Subscription Parameters: None

WebSocketsubscribeBalanceTransaction
Balance transaction subscription
json
{
  "reqid": 9,
  "type": "subscribe",
  "streams": [
    {
      "name": "BalanceTransaction"
    }
  ]
}
Balance transaction response
json
{
  "reqid": 9,
  "type": "BalanceTransaction",
  "ts": "2023-02-10T16:49:18.300588Z",
  "initial": true,
  "seqNum": 1,
  "data": [
    {
      "Timestamp": "2023-02-10T16:50:12.562757Z",
      "ClReqID": "06b78113c1454174b9e403a1245d67ea",
      "TransactionID": "1D2FBR4J00R00",
      "Revision": 0,
      "TransactionType": "Withdrawal",
      "MarketAccount": "default",
      "Quantity": "1",
      "Currency": "ETH",
      "Status": "PendingApproval",
      "LastUpdateTime": "2023-02-10T16:50:12.556229Z"
    }
  ]
}

Response fields

KeyTypeRequiredDescription
TimestampdatetimeYTimestamp of the message
CurrencystringYCurrency of Quantity
ClReqIDstringYClient assigned Request ID
StatusstringYStatus of the quote, one of PendingApproval, PendingTransfer, Rejected, Completed
TransactionIDstringYServer assigned ID for this transaction
LastUpdateTimedatetimeYTime of most recent update to the Transaction
QuantitydecimalYTrnasaction quantity
MarketAccountstringYAccount to apply this transaction to
RevisionstringYRevision of this transaction

NewWithdrawRequest command

Command used to request a new withdrawal

WebSocketsendNewWithdrawRequest
Submit NewWithdrawRequest
json
{
  "reqid": 34,
  "type": "NewWithdrawRequest",
  "data": [
    {
      "Quantity": "1",
      "Currency": "ETH",
      "MarketAccount": "default",
      "RoutingInfo": {
        "WalletAddress": "XXYYZZ",
        "Memo": "",
        "DestinationTag": ""
      },
      "ClReqID": "06b78113c1454174b9e403a1245d67ea"
    }
  ]
}

Command data

KeyTypeRequiredDescription
CurrencystringYThe currency that the quantity is specified in.
ClReqIDstringYUnique ID for this request, usually a UUID
QuantitydecimalYRequested quantity in units of Currency
TransactTimedatetimeNAn ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z
RoutingInfoobjectNProvides routing info for the transaction such as WalletAddress

User stream

Request for updates for this customer user. No subscription parameters.

WebSocketsubscribeUser
User subscription
json
{
  "reqid": 10,
  "type": "subscribe",
  "streams": [
    {
      "name": "User"
    }
  ]
}
User response
json
{
  "reqid": 10,
  "type": "User",
  "ts": "2021-09-15T03:33:07.545223Z",
  "initial": true,
  "seqNum": 1,
  "data": [
    {
      "CustomerUserID": "174K1Q9GC0C00",
      "Email": "tom@company.com",
      "DisplayName": "Tom",
      "Config": [
        {
          "Timestamp": 1628004805337309202,
          "CustomerUserID": "174K1Q9GC0C00",
          "Key": "recentSymbols",
          "Value": "{\"BTC-USD\":[1626111502357],\"ADA-USD\":[1626732116743],\"BCH-USD\":[1628004751665]}"
        },
        {
          "Timestamp": 1628004805377207692,
          "CustomerUserID": "174K1Q9GC0C00",
          "Key": "symbol",
          "Value": "\"BTC-USD\""
        }
      ]
    }
  ]
}

Response fields

KeyTypeRequiredDescription
CustomerUserIDstringYServer assigned ID of this Customer User
EmailstringYEmail of Customer User
DisplayNamestringYFriendly name for customer user
Configobject[]YList of user config settings
→ TimestampdatetimeYTimestamp of config setting update
→ CustomerUserIDstringYCustomer User for this config setting
→ ModestringYSetting whether config is enabled, values Enabled or Disabled
→ KeystringYUser config key
→ ValuestringYUser config value

UserConfig command

Command used to update user config on behalf of session user. Results of this command will be visible in the User stream.

WebSocketsendUserConfig
Submit UserConfig
json
{
  "reqid": 18,
  "type": "UserConfig",
  "data": [
    {
      "Key": "symbol",
      "Value": "\"ETH-BTC\""
    }
  ]
}

Command data

KeyTypeRequiredDescription
TimestampdatetimeNTimestamp of the message
ModestringNOptional mode on config, either Enabled or Disabled
KeystringYKey of config
ValuestringNValue of config

OHLCV endpoint

The OHLCV API provides data on the specified symbols.

Get the open, high, low, close, and volume parameters for a given symbol and resolution

RESTGET/v1/symbols/<symbol>/ohlcv/<resolution>
Example request
text
GET /v1/symbols/BTC-USD/ohlcv/1h

Query parameters

NameTypeDescription
startDatestringIf provided, will return data starting at this time. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z.
endDatestringIf provided, will return data ending at this time. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z.
OHLCV response
json
{
  "type": "OHLCV",
  "ts": "2019-09-16T14:57:19.785823Z",
  "data": [{
      "Timestamp":"2023-02-27T10:52:00.000000Z",
      "Symbol":"BTC-USD",
      "Open":"23413.30000",
      "High":"23418.24",
      "Low":"23399.46",
      "Close":"23407.10000",
      "Volume":"0.49309984",
      "Ticks":74
        }
      ]
    }
  ]
}

Response fields

KeyTypeDescription
TimestampdatetimeThe start time for this interval
SymbolstringA unique symbol for this security.
VolumedecimalTotal base-currency volume traded (if any) for the symbol in the time interval.
OpendecimalFirst trade price (if any) for the symbol in the time interval.
ClosedecimalLast trade price (if any) for the symbol in the time interval.
HighdecimalHighest traded price (if any) for the symbol in the time interval.
LowdecimalLowest traded price (if any) for the symbol in the time interval.
TicksdecimalTotal number of ticks for the symbol in the time interval

FIX connectivity, configuration, and protocol

The FIX API provides the user with access to real-time market data subscription and orders execution. Additional data is available via the websocket API.

Connectivity is made to the Secure Digital API via the internet. The following will be provided to the client during onboarding: ● Hostname ● Port number

Secure Digital acts as an acceptor for all FIX sessions. FIX session information will be provided during onboarding: ● SenderCompID ● TargetCompID ● StartTime ● EndTime

Sessions can be configured with or without FIX session level message recovery. A typical setup includes 2 sessions: ● A FIX session for market data with recovery disabled. ● A FIX session for orders submission with recovery enabled.

Last updated: Feb 27, 2025

See the FIX.4.4 spec available at https://www.fixtrading.org/standards/fix-4-4/.

Onboarding values

ConnectivitySession configuration
HostnameSenderCompID
Port numberTargetCompID
StartTime
EndTime

After FIX Logon, the client should send a MarketDataRequest to subscribe to market data snapshots. On subscription, the client can choose to subscribe to aggregated prices as price or size levels. After subscription, Secure Digital will stream market data full snapshot updates as the market prices change. Market data delta updates will be supported in a future release.

The orders API supports order submission. All orders can be amended and canceled via the API. Specifying order strategy and algo parameters will be supported in a future release.

By default, all open orders submitted via the FIX session will be canceled on disconnect. Cancel on Disconnect does not affect other orders for the same user that were submitted on other sessions, or orders that were explicitly placed as CancelOnDisconnect=N, see New Order Single.

Sessions will receive a full drop copy for all execution reports associated with the session user. This includes orders submitted via the UI or other protocols (websocket, etc).

The API sends UTC timestamps with millisecond precision. For example: 20140515-19:49:56.659. The API accepts UTC timestamps with second, millisecond, or microsecond precision in the format YYYYddmm-HH:MM:SS.ffffff. For example, 20140515-19:49:56, 20140515-19:49:56.659, or 20140515-19:49:56.659441.

FIX standard header and trailer

Standard Header

TagField NameReq'dComments
8BeginStringYFIX.4.4. Must be the first field in the message
9BodyLengthYMust be the second field in the message
35MsgTypeYMust be the third field in the message
49SenderCompIDYProvided by Secure Digital during onboarding
56TargetCompIDYProvided by Secure Digital during onboarding
34MsgSeqNumY
43PossDupFlagNAlways required for retransmitted messages, whether prompted by the sending system or as the result of a resend request.
97PossResendNRequired when the message may be duplicate of another message sent under a different sequence number.
52SendingTimeY
122OrigSendingTimeNRequired for message re-sent as a result of a ResendRequest. If data is not available set to same value as SendingTime <52>

Standard Header

TagField NameReq'dComments
10CheckSumYThree byte, simple checksum. See the FIX spec for details

FIX Logon and signature

The signature is created by concatenating

  • SendingTime (52) as a string
  • ASCII 01 value
  • SeqNum (34) as a string
  • ASCII 01 value
  • SenderCompID (49)
  • ASCII 01 value
  • TargetCompID (56)

Logon fields

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = A
108HeartBtIntYNote same value used by both sides
141ResetSeqNumFlagNIndicates both sides of a FIX session should reset sequence numbers
96RawDataYContains signature (see below for creating a signature)
554PasswordYContains the API Key for the Customer user
<MessageTrailer>Y

This string is then signed using the HMAC SHA-256 Algorithm and the API Secret for the API Key. Sample Java code showing how this can be done programmatically. Note this sample relies on Apache Commons-Codec and QuickFIX for Java.

Java signing example
java
/**
 * Takes a Message, an apiKey and apiSecret and uses the HMAC-SHA256 algorithm to sign a FIX message by appending
 * the sending-time sequenceNumber, SenderCompID and TargetCompID with \u0001 separator and signing using the
 * secret, putting it into the RawBytes in Base64 encoding.
 */
private static void signLogon(
    final Message message,
    final SessionID sessionId,
    final String apiKey,
    final String apiSecret
) throws FieldNotFound {
    final var senderCompId = sessionId.getSenderCompID();
    final var targetCompId = sessionId.getTargetCompID();
    final var sendingTime = message.getString(SendingTime.FIELD);
    final var seqNum = message.getInt(MsgSeqNum.FIELD);
    final var sep = "\u0001";
    final var hmac = sign(
        apiSecret,
        sendingTime + sep + seqNum + sep + senderCompId + sep + targetCompId
    );

    message.setString(Password.FIELD, apiKey);
    message.setInt(RawDataLength.FIELD, hmac.length());
    message.setString(RawData.FIELD, hmac);
}

private static String sign(final String apiSecret, final String data) {
    final var mac = HmacUtils.getInitializedMac(
        HmacAlgorithms.HMAC_SHA_256,
        apiSecret.getBytes()
    );
    final var encodedBytes = mac.doFinal(data.getBytes());
    final var encoder = Base64.getUrlEncoder(); //URL Safe Base64
    return encoder.encodeToString(encodedBytes);
}

FIX session-level messages

Heartbeat (35=0)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = 0
112TestReqIDYRequired when the heartbeat is the result of a Test Request message
<MessageTrailer>Y

Test Request (35=1)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = 1
112TestReqIDY
<MessageTrailer>Y

Resend Request (35=2)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = 2
7BeginSeqNoY
16EndSeqNoY
<MessageTrailer>Y

Reject (35=3)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = 3
45RefSeqNumYMsgSeqNum of rejected message
371RefTagIDNThe tag number of the FIX field being referenced
372RefMsgTypeNThe MsgType of the FIX message being referenced
373SessionRejectReasonNCode to identify reason for a session-level Reject message
58TextNWhere possible, message to explain reason for rejection
<MessageTrailer>Y

Sequence Reset (35=4)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = 4
123GapFillFlagN
36NewSeqNoY
<MessageTrailer>Y

Logout (35=5)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = 5
58TextN
<MessageTrailer>Y

FIX market data messages

Market Data Request (35=V)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = V
262MDReqIDYMust be unique, or the ID of previous Market Data Request to disable if SubscriptionRequestType(263) = 2 (Disable previous Snapshot + Updates Request).
263SubscriptionRequestTypeY0 = Snapshot, 1 = Snapshot + Updates (Subscribe) 2 = Unsubscribe
264MarketDepthNDepth of market for Book Snapshot / Incremental updates 0 - full book depth 1 - top of book 2 and above - book depth (number of levels) Exactly one of tag 264 or tag 20020 must be specified.
1070MDQuoteTypeNType of liquidity to be included 0 - Indicative 1 - Tradeable (i.e., Firm)
20020NoSizeBucketsSegmentsNA list of sizes to return price levels for. Used to ask for prices of aggregated sizes. Exactly one of tag 264 or tag 20020 must be specified. Note: only supported with MDUpdateType(265) = 0 (Full refresh)
→20021SizeBucketYIdentifies a single size bucket
→55SymbolYThe symbol of the currency pair to subscribe to. For example, BTC-USD
<MessageTrailer>Y

Note : that exactly one of either Depth, or SizeBucket must be specified. For example, specifying both Depth and SizeBuckets will result in an error.

Market Data Request Reject (35=Y)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = Y
262MDReqIDYRefers to the MDReqID of the request
58TextN
<MessageTrailer>Y

Market Data Snapshot Full Refresh (35=W)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = W
262MDReqIDYRefers to the MDReqID of the request.
55SymbolYSymbol updated by the Market Data Entry.
268NoMDEntriesYNumber of entries following.
→269MDEntryTypeYType of market data entry. 0 = Bid 1 = Offer Required if NoMDEntries(268) > 0.
→270MDEntryPxYPrice of the Market Data Entry.
→271MDEntrySizeYQuantity represented by the Market Data Entry.
→272MDEntryDateYDate of Market Data Entry.
→273MDEntryTimeYTime of Market Data Entry.
<MessageTrailer>Y

FIX order messages

The NewOrderSingle message is used to submit a new order. Market and Limit orders are currently supported. Orders are routed using the default routing strategy. Specifying order strategy and algo parameters will be supported in a future release.

The OrderCancelRequest message is used to cancel an existing order.

The OrderCancelReplaceRequest message is used to amend the price, quantity, or markets for an existing order.

The ExecutionReport message is used to acknowledge/reject an order or changes to an order, and to relay order status and fill updates.

The OrderCancelReject message is used to reject invalid cancel or cancel/replace requests.

The NewOrderSingle message is used to submit a new order. Market and Limit orders are currently supported. Orders are routed using the default routing strategy. Specifying order strategy and algo parameters will be supported in a future release.

New Order Single (35=D)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = D
1AccountNThe specific account for this order. Required if multiple accounts are enabled
11ClOrdIDYUnique identifier for Order as assigned by the client. Must be <= 36 characters. UUIDs are recommended.
55SymbolYThe symbol of the currency pair to place an order on. For example, BTC-USD
54SideYSide of order 1 = Buy 2 = Sell
40OrdTypeYOrder type 1 = Market 2 = Limit A = LimitAllIn, requested price/size includes fees
38OrderQtyYSize of the order
15CurrencyNThe currency the quantity is specified in. If not specified, defaults to the base currency for the symbol.
44PriceNPrice of the order. Required for limit orders.
59TimeInForceYSpecifies how long the order remains in effect. 1 = Good Till Cancel (GTC) 3 = Immediate Or Cancel (IOC) 4 = Fill Or Kill (FOK)
60TransactTimeYBusiness timestamp for this request.
126ExpireTimeNOptional expiration time for the order. Only valid on orders with TimeInForce=1 (GTC). UTC Timestamp.
168EffectiveTimeNTime at which this order will activate and begin sending orders to the market. UTC Timestamp.
847TargetStrategyNAllows Specifying an Order Strategy Type See Order Strategies
957NoStrategyParamsNThe number of strategy parameter repeating groups
958StrategyParameterNameNThe name of the StrategyParameter being set
960StrategyParameterValueNThe value for the StrategyParameter being set
20030CancelOnDisconnectNWhether or not this order should be canceled when this session is disconnected, Y / N. Defaults to Y.
<MessageTrailer>Y

Order Cancel Request (35=F)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = F
11ClOrdIDYUnique ID of cancel request as assigned by the client. Must be <= 36 characters. UUIDs are recommended.
41OrigClOrdIDYClOrdID(11) of the previous non-rejected order.
55SymbolYThe symbol of the currency pair of the order. For example, BTC-USD
54SideYSide of order 1 = Buy 2 = Sell
60TransactTimeYBusiness timestamp for this request.
<MessageTrailer>Y

Order Cancel Replace Request (35=G)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = G
11ClOrdIDYUnique ID of cancel request as assigned by the client. Must be <= 36 characters. UUIDs are recommended.
41OrigClOrdIDYClOrdID(11) of the previous non-rejected order.
55SymbolYThe symbol of the currency pair of the order. For example, BTC-USD
54SideYSide of order 1 = Buy 2 = Sell
40OrdTypeYOrder type 1 = Market 2 = Limit A = LimitAllIn, requested price/size includes fees
38OrderQtyYSize of the order
44PriceNPrice of the order. Required for limit orders.
60TransactTimeYBusiness timestamp for this request.
<MessageTrailer>Y

Execution Report (35=8)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = 8
11ClOrdIDNClOrdID of the order.
41OrigClOrdIDNSet to the ClOrdID of the previous accepted order when responding to a Cancel or Cancel/Replace request
37OrderIDYUnique identifier of most recent order as assigned by Secure Digital.
55SymbolYThe symbol of the currency pair of the order. For example, BTC-USD
54SideYSide of order 1 = Buy 2 = Sell
38OrderQtyYSize of the order
44PriceNPrice of the order. Required for limit orders.
60TransactTimeNBusiness timestamp for this execution.
17ExecIDYUnique identifier of execution message as assigned by Secure Digital.
527SecondaryExecIDNUnique identifier of execution message as assigned by the exchange or liquidity provider. Only specified when ExecType=Trade.
150ExecTypeYDescribes the specific ExecutionRpt (e.g. Pending Cancel) while OrdStatus(39) will always identify the current order status (e.g. Partially Filled). 0 = New 3 = Done for day 4 = Canceled 5 = Replaced 6 = Pending Cancel (e.g. result of Order Cancel Request) 8 = Rejected A = Pending New E = Pending Replace (e.g. result of Order Cancel/Replace Request) F = Trade (partial fill or fill)
59TimeInForceYSpecifies how long the order remains in effect. 1 = Good Till Cancel (GTC) 3 = Immediate Or Cancel (IOC) 4 = Fill Or Kill (FOK)
40OrdTypeYOrder type 1 = Market 2 = Limit
39OrdStatusYDescribes the current state of the order, same scope as OrderQty, CumQty, LeavesQty, and AvgPx 0 = New 1 = Partially filled 2 = Filled 3 = Done for day 4 = Canceled 6 = Pending Cancel (i.e. result of Order Cancel Request) 8 = Rejected A = Pending New E = Pending Replace (i.e. result of Order Cancel/Replace Request)
151LeavesQtyYQuantity open for further execution. If the OrdStatus(39) is = 4 (Canceled), 3 (Done For Day), or 8 (Rejected) (in which case the order is no longer active) then LeavesQty(151) could be 0, otherwise LeavesQty(151) = OrderQty(38) - CumQty(14).
14CumQtyYCurrently executed quantity for chain of orders.
6AvgPxYCalculated average price of all fills on this order.
103OrdRejReasonNFor optional use with ExecType = 8 (Rejected) 0 = Broker / Exchange option 1 = Unknown symbol 2 = Exchange closed 3 = Order exceeds limit 5 = Unknown order 6 = Duplicate Order (e.g. dupe ClOrdID) 7 = Duplicate of a verbally communicated order 8 = Stale order
31LastPxNPrice of this (last) fill. Required if ExecType(150) = ExecType = F (Trade)
32LastQtyNQuantity bought/sold on this (last) fill. Required if ExecType(150) = F (Trade)
381GrossTradeAmtNLast amount traded (i.e. quantity * price) expressed in units of counter currency. Required if ExecType(150) = F (Trade)
4015CumAmtNTotal amount traded (i.e. quantity * price) expressed in units of counter currency.
4016CumFeeNTotal fee expressed in units of FeeCurrency.
4033LastFeeNLast fee expressed in units of FeeCurrency
4034LastFeeCurrencyNCurrency of the Fee
20030CancelOnDisconnectNWhether or not this order will be canceled when this session is disconnected, Y / N
20032DecisionStatusNThe current decision-status of the order. A = Active (default) P = Paused U = Pending Pause R = Pending Resume W = Waiting for StartTime T = Waiting for Trigger Paused / Staged orders can be edited and resumed from the Secure Digital UI. Pending statuses are intermediate states.
58TextN
<MessageTrailer>Y

Order Cancel Reject (35=9)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = 9
11ClOrdIDYClOrdID(11) which could not be canceled/replaced.
41OrigClOrdIDYClOrdID of the previous accepted order
37OrderIDYUnique identifier of most recent order as assigned by Secure Digital. If CxlRejReason="Unknown order", then will be "NONE".
60TransactTimeNBusiness timestamp for this reject.
39OrdStatusYIdentifies current status of order. 0 = New 1 = Partially filled 2 = Filled 4 = Canceled 6 = Pending Cancel (i.e. result of Order Cancel Request) 8 = Rejected A = Pending New E = Pending Replace (i.e. result of Order Cancel/Replace Request)
434CxlRejResponseToYIdentifies the type of request that a Cancel Reject is in response to. 1 = Order cancel request 2 = Order cancel/replace request
102CxlRejReasonNCode to identify reason for cancel rejection. 0 = Too late to cancel 1 = Unknown order 2 = Broker / Exchange Option 3 = Order already in Pending Cancel or Pending Replace status
58TextN
<MessageTrailer>Y

FIX Security List messages

The Security List message is used to return a list of securities that matches the criteria specified in the Security List Request.

Security List Request (35=x)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = x
320SecurityReqIDYUnique ID to identify this request
559SecurityListRequestTypeYIdentifies the type of Security List Request 4 = ALL_SECURITIES
<MessageTrailer>Y

Security List (35=y)

TagField NameReq'dComments
<MessageHeader>YMsgType <35> = y
320SecurityReqIDYUnique ID to identify this request
322SecurityResponseIDYIdentifier for the SecurityList message
560SecurityRequestResultYResult of the Security Request Identified by the SecurityReqID 0 = Valid Request 1 = invalid or Unsupported Request 2 = No instruments found that match the selection criteria 3 = Not authorized to retrieve instrument data 4 = Instrument data temporarily unavailable 5 = Request for instrument data not supported
393TotalNoRelatedSymNUsed to indicate the total number of securities being returned for this request. Used in the event that message fragmentation is required
893LastFragmentNIndicates whether this is the last fragment in a sequence of message fragments. Only required where message has been fragmented
146NoRelatedSym
Component Block <Instrument>Y if 560=0
→55SymbolYCommon “human understood” representation of the security
→48SecurityIDYInternal Secure Digital ID for Security - for information only
→561RoundLotYThe trading lot size of a security
→562MinTradeVolYMinimum Trading Volume for a security
→969MinPriceIncrementYThe smallest difference between quoted prices for this instrument
→1140MaxTradeVolYMaximum Size for an order on this security
<MessageTrailer>Y

FIX order strategies

Order routing strategies are specified for New Order Single Messages (35=D) using the TargetStrategy(847) tag and the NoStrategyParameters(950) repeating group to specify the required parameters for the strategy.

StopLimit parameters

Parameter NameTypeRequiredDescription
TriggerPricePriceYThe price that must be met to trigger execution of the order with the configured limit price.
TriggerSourceStringNOptional aggregation which will be used to construct the order's trigger reference rate.
EndTimeStringNOptional expiration time for the order. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z

This strategy will only place the order once the specified stop price has been met. For a Buy StopLimit order, the stop price must be _above_ the current market price. For a Sell StopLimit order, the stop price must be _below_ the current market price. To place a StopLimit order, you must send in TargetStrategy(847)=StopLimit

TakeProfitLimit parameters

Parameter NameTypeRequiredDescription
TriggerPricePriceYThe price that must be met to trigger execution of the order with the configured limit price.
TriggerSourceStringNOptional aggregation which will be used to construct the order's trigger reference rate.
EndTimeStringNOptional expiration time for the order. An ISO-8601 UTC string of the form 2019-02-13T05:17:32.000000Z

This strategy will only place the order once the specified take profit price has been met. For a Buy TakeProfitLimit order, the take profit price must be _below_ the current market price. For a Sell TakeProfitLimit order, the take profit price must be _above_ the current market price. To place a TakeProfitLimit order, you must send in TargetStrategy(847)=TakeProfitLimit

FIX order state change matrices

Filled order

TimeRequest (ClOrdID,OrigClOrdID)Response (ClOrdID,OrigClOrdID)ExecTypeOrdStatusOrderQtyCumQtyLeavesQtyLastQtyComment
1NewOrderSingle(A)10
2ExecutionReport(A)PendingNewPendingNew10010
3ExecutionReport(A)RejectedRejected10010If order is rejected
3ExecutionReport(A)NewNew10010
4ExecutionReport(A)TradePartiallyFilled10282
5ExecutionReport(A)TradePartiallyFilled10371
6ExecutionReport(A)TradeFilled101007

Canceled order

TimeRequest (ClOrdID,OrigClOrdID)Response (ClOrdID,OrigClOrdID)ExecTypeOrdStatusOrderQtyCumQtyLeavesQtyLastQtyComment
1NewOrderSingle(A)10
2ExecutionReport(A)PendingNewPendingNew10010
3ExecutionReport(A)RejectedRejected10010If order is rejected
3ExecutionReport(A)NewNew10010
4OrderCancelRequest(B,A)
5OrderCancelRejected(B,A)New10010If cancel is rejected
5ExecutionReport(B,A)PendingCancelPendingCancel10010
6OrderCancelRejected(B,A)New10010If cancel is rejected
7ExecutionReport(B,A)CanceledCanceled1000

Replace to increase quantity

TimeRequest (ClOrdID,OrigClOrdID)Response (ClOrdID,OrigClOrdID)ExecTypeOrdStatusOrderQtyCumQtyLeavesQtyLastQtyComment
1NewOrderSingle(A)10
2ExecutionReport(A)PendingNewPendingNew10010
3ExecutionReport(A)NewNew10010
4OrderCancel/ReplaceRequest(B,A)11
5OrderCancelRejected(B,A)New10010If replace is rejected
5ExecutionReport(B,A)PendingReplacePendingReplace10010
6OrderCancelRejected(B,A)New10010If replace is rejected
6ExecutionReport(B,A)ReplacedNew1100
7ExecutionReport(B)TradePartiallyFilled111101

Replace during fill

TimeRequest (ClOrdID,OrigClOrdID)Response (ClOrdID,OrigClOrdID)ExecTypeOrdStatusOrderQtyCumQtyLeavesQtyLastQtyComment
1NewOrderSingle(A)10
2ExecutionReport(A)PendingNewPendingNew10010
3ExecutionReport(A)NewNew10010
4OrderCancel/ReplaceRequest(B,A)8
5ExecutionReport(A)TradePartiallyFilled10191Fill before replace is received
6ExecutionReport(B,A)PendingReplacePendingReplace1019
7ExecutionReport(A)TradePendingReplace10372Fill before replace is processed
8ExecutionReport(B,A)ReplacedNew835
9ExecutionReport(B)TradeFilled8805

FIX example messages

Logon
text
8=FIX.4.4^A9=143^A35=A^A34=1^A49=CUSTOMER^A52=20220915-18:29:58.756^A56=Secure Digital^A95=44^A96=ZduZiNxyxS7_4UPDesOryd9KVEecg9LAqqTRR79Pp20=^A98=0^A108=300000^A141=Y^A554=Daniel^A10=248^A
Logon response
text
8=FIX.4.4^A9=78^A35=A^A34=1^A49=Secure Digital^A52=20220915-18:29:58.765^A56=CUSTOMER^A98=0^A108=300000^A141=Y^A10=255^A
SecurityList request
text
8=FIX.4.4^A9=88^A35=x^A34=3^A49=CUSTOMER^A52=20220930-13:28:16.451^A56=Secure Digital^A320=id-220929160342682-27^A559=4^A10=156^A
SecurityList response
text
8=FIX.4.4^A9=243^A35=y^A34=3^A49=Secure Digital^A52=20220930-13:28:16.514^A56=CUSTOMER^A146=2^A55=ETH-USD^A48=2^A561=0.00000001^A562=0.00000001^A969=0.00001^A1140=1000.00^A55=BTC-USD^A48=24^A561=0.00000001^A562=0^A969=0.01^A1140=1000.00^A320=id-220929160342682-27^A322=1BQM22QR01G00^A560=0^A10=153^A
NewOrderSingle
text
8=FIX.4.4^A9=147^A35=D^A34=2^A49=CUSTOMER^A52=20220915-18:30:01.335^A56=Secure Digital^A11=id-220912164936074-1152^A38=1^A40=2^A44=1630.123^A54=2^A55=ETH-USD^A59=1^A60=20220915-14:30:01^A10=228^A
ExecutionReport rejection
text
8=FIX.4.4^A9=366^A35=8^A34=2^A49=Secure Digital^A52=20220915-18:30:01.393^A56=CUSTOMER^A1=default^A6=0^A11=id-220912164936074-1152^A14=0^A17=ba22dbe1-cb33-4fcb-9613-921006afdebd^A37=94869628-b862-43e4-bd2d-be85e4295bd4^A38=1.00000000^A39=8^A40=2^A44=1630.123^A54=2^A55=ETH-USD^A58=Unable to submit market order - please try again later.^A59=1^A60=20220915-14:30:01.000^A103=0^A150=8^A151=1.00000000^A20030=N^A20032=A^A10=205^^A
MarketDataSnapshot request
text
8=FIX.4.4^A9=186^A35=V^A34=2^A49=CUSTOMER_MD^A52=20220930-13:28:06.146^A56=Secure Digital^A262=id-220929160342682-26^A263=1^A264=0^A265=0^A1070=1^A146=1^A55=ETH-USD^A267=2^A269=0^A269=1^A20020=4^A20021=1^A20021=2^A20021=5^A20021=10^A10=226^A
MarketDataSnapshot response
text
8=FIX.4.4^A9=608^A35=W^A34=2^A49=Secure Digital^A52=20220930-13:28:06.454^A56=CUSTOMER_MD^A55=ETH-USD^A262=id-220929160342682-26^A268=8^A269=0^A270=1320.43^A271=1.00000000^A272=20220930^A273=13:28:06.401^A269=0^A270=1320.43^A271=2.00000000^A272=20220930^A273=13:28:06.401^A269=0^A270=1320.43^A271=5.00000000^A272=20220930^A273=13:28:06.401^A269=0^A270=1320.43^A271=10.00000000^A272=20220930^A273=13:28:06.401^A269=1^A270=1323.42^A271=1.00000000^A272=20220930^A273=13:28:06.401^A269=1^A270=1323.42^A271=2.00000000^A272=20220930^A273=13:28:06.401^A269=1^A270=1323.42^A271=5.00000000^A272=20220930^A273=13:28:06.401^A269=1^A270=1323.42^A271=10.00000000^A272=20220930^A273=13:28:06.401^A10=247^A

SDM Trading API PDF

Original SDM Trading API PDF provided for reference.

SDM Trading API PDF

Open the original SDM Trading API document.

Open PDF
Original PDFView the complete document in PDF format.

Secure Digital FIX API PDF

Original Secure Digital FIX API PDF provided for reference.

Secure Digital FIX API PDF

Open the original Secure Digital FIX API document.

Open PDF
Original PDFView the complete document in PDF format.

Source changelog

Version notes from both source PDFs.

VersionChanges
Trading API v1.4.0Adds new REST API endpoint OHLCV
Trading API v1.3.0Adds new subscription BalanceTransaction Adds new command NewWithdrawRequest
Trading API v1.2.0Change TransactTime on QuoteRequest and <a href=#executionreport">ExecutionReport to be optional. Please note that this documentation change reflects existing behavior in the API. Change Currency on QuoteRequest to be required. Please note that this documentation change reflects existing behavior in the API. Add MinAmtIncrement field to Security.
Trading API v1.1.0Change MaximumSize for Security to be optional field.
FIX API v2.50V 2.50: Added description for Order Strategies