Overview
Welcome to the SFOX API!
SFOX offers a REST API, as well as a websocket feed, to access market data, manage your account, and create/cancel orders.
REST Endpoints
Endpoint | Description |
---|---|
Production | https://api.sfox.com |
OHLCV | https://chartdata.sfox.com |
Sandbox | Contact support |
Authentication
To authorize, use this code:
# With shell, you can just pass the correct header with each request
$ curl -u "<api token>:" api_endpoint_here
import requests
auth = requests.auth.HTTPBasicAuth("<api_token>", "")
requests.get("api_endpoint_here", auth=auth)
Make sure to replace <api_key> with your API key, and don’t forget the colon in the shell example
SFOX uses API keys to grant access. You can create a new SFOX API key at our developer portal.
The API key should be included in all API requests to the server in the Authorization
header that looks like the following:
Authorization: Bearer <api_key>
Account Management
Get Account Balance
$ curl "https://api.sfox.com/v1/user/balance" \
-u "<api_key>:"
requests.get("https://api.sfox.com/v1/user/balance", auth=requests.auth.HTTPBasicAuth("<api_key>", "")).json()
The above command returns JSON structured like this:
[
{
"currency":"btc",
"balance":0.627,
"available":0
},
{
"currency":"usd",
"balance":0.25161318,
"available":0.23161321
}
]
Use this endpoint to access your account balance. It returns an array of objects, each of which has details for a single asset.
You will get Balance and Available balance. Balance is your total balance for this asset. Available, on the other hand, is what is available to you to trade and/or withdraw. The difference is amount that is reserved either in an open trade or pending a withdrawal request.
HTTP Request
GET /v1/user/balance
Response Body
Key | Description |
---|---|
currency | |
balance | Amount of the currency in an account (available + held) |
available | Amount of the currency available for trading |
held | Amount of the currency “on hold” |
WalletTypeId | ignore |
Get Transaction History
curl "https://api.sfox.com/v1/account/transactions?from=0=250&to=1565114130000" \
-u "<api_key>:"
requests.get(
"https://api.sfox.com/v1/account/transactions",
auth=requests.auth.HTTPBasicAuth("<api_key>", ""),
params={"from": 0, "to": 1565114130000}
).json()
The above command returns JSON structured like this:
[
{
'id': 12224191,
'order_id': '67662454',
'client_order_id': '',
'day': '2018-07-29T21:30:10.000Z',
'action': 'Buy',
'currency': 'usd',
'memo': '',
'amount': -438.34854806,
'net_proceeds': -438.34854806,
'price': 465.19547184,
'fees': 1.53,
'status': 'done',
'hold_expires': '',
'tx_hash': '',
'algo_name': 'Smart',
'algo_id': '200',
'account_balance': 3929.90349381,
'AccountTransferFee': None
}
]
Use this endpoint to access your transaction history, including trades and transfers. It returns an array of objects, each of which has details for each individual transaction.
HTTP Request
GET /v1/account/transactions
Query Parameters
Parameter | Default | Description |
---|---|---|
from | 0 | Starting timestamp (in millis) |
to | utcnow | Ending timestamp (in millis) |
type | Withdraw: ‘Withdraw’, Deposit: ‘Deposit’, Charge: ‘Charge’, Buy: ‘Buy’, Sell: ‘Sell’, Unknown: ‘Unknown’, |
Response Body
This endpoint returns an array of objects, each of which has the details of the transaction:
Key | Example | Description |
---|---|---|
id | Transaction ID | |
order_id | Order ID, if applicable | |
client_order_id | The order ID that the client specified when placing an order | |
day | 2019-07-31T17:26:30.000Z | The timestamp of the transaction, in ISO8601 format |
action | Deposit | The action, this can be one of “Deposit”, “Withdraw”, “Buy”, “Sell” |
currency | btc | The base currency |
memo | ||
amount | 0.00262916 | Amount of the transaction of the currency |
net_proceeds | Net amount after fees | |
price | Price per unit of the base currency |
|
fees | Amount of fees paid in the transaction | |
status | ||
hold_expires | ||
tx_hash | ||
algo_name | ||
algo_id | ||
account_balance | ||
AccountTransferFee | ||
Description | ||
wallet_display_id |
Request an ACH transfer
SFOX allows users to transfer funds using ACH. First, set up your bank account by navigating to Deposit/Withdraw. Once your account is connected, use this call to initiate the transfer request.
curl "https://api.sfox.com/v1/user/bank/deposit" \
-H "Authorization: <api_key>" \
-d "amount=1"
requests.post(
"https://api.sfox.com/v1/user/bank/deposit",
auth=requests.auth.HTTPBasicAuth("<api_key>", ""),
json={"amount": 1}
).json()
The above command returns JSON structured like this:
{
"tx_status": 0000,
"success": true
}
HTTP Request
POST /v1/user/bank/deposit
Form/JSON Parameters
Parameter | Description |
---|---|
amount | The amount you wish to deposit from your bank account |
Deposit
List Available Crypto Addresses
List the available crypto asset addresses for deposits to your account.
curl "https://api.sfox.com/v1/user/deposit/address/{currency}" \
-H "Authorization: <api_key>"
requests.get(
"https://api.sfox.com/v1/user/deposit/address/{currency}",
auth=requests.auth.HTTPBasicAuth("<api_key>", ""),
).json()
The above command returns JSON structured list like this:
[
{
"address": "<address>",
"currency": "<currency>"
},
{
"address": "<address>",
"currency": "<currency>"
}
]
HTTP Request
GET /v1/user/deposit/address/{currency}
Response Body
This returns a list of available addresses to deposit crypto assets
key | description |
---|---|
address | Crypto address to use for deposits |
currency | Crypto asset |
Create a Deposit Address
Generate a new deposit address for the crypto asset of your choosing
Create a new address
curl "https://api.sfox.com/v1/user/deposit/address/{currency}" \
-H "Authorization: <api_key>" \
-X POST
requests.post(
"https://api.sfox.com/v1/user/deposit/address/{currency}",
auth=requests.auth.HTTPBasicAuth("<api_key>", ""),
).json()
HTTP Request
POST /v1/user/deposit/address/{currency}
Form Parameters
Parameter | Description |
---|---|
currency | Currency of choice: btc, bch, eth, ltc, bsv, etc |
Response Body
Key | Description |
---|---|
address | Created crypto address |
currency | Crypto asset |
Withdraw
Initiate a withdrawal from your SFOX account.
curl "https://api.sfox.com/v1/user/withdraw" \
-H "Authorization: <api_key>" \
-d "amount=1" \
-d "address=" \
-d "currency=usd"
requests.post(
"https://api.sfox.com/v1/user/withdraw",
auth=requests.auth.HTTPBasicAuth("<api_key>", ""),
json={
"amount": 1,
"address": "<address if crypto>",
"currency": "<currency>"
}
).json()
The above command returns JSON structured like this:
{
"success": true
}
HTTP Request
POST /v1/user/withdraw
Form/JSON Parameters
Parameter | Description |
---|---|
amount | The amount you wish to withdraw |
currency | Currency is one of: usd, btc, eth |
address | If the “currency” is a crypto asset, this field has to be a valid mainnet address. Otherwise leave it out or empty |
Post-Trade Settlement
$ curl "https://api.sfox.com/v1/post-trade-settlement" \
-u "<api_key>:"
requests.get("https://api.sfox.com/v1/post-trade-settlement", auth=requests.
auth.HTTPBasicAuth("<api_key>", "")).json()
The above command returns JSON structured like this:
{ "exposure":"1000378.13", "available_exposure":1999489.96, "exposure_limit":2000000.00, "equity": 100221.12, "equity_for_withdrawals":8000.42 }
Business Accounts Only
If your account has post-trade settlement enabled, use this endpoint to access your account post-trade settlement data. It returns an object, which has details for each datapoint.
HTTP Request
GET v1/post-trade-settlement
Response Body
Key | Description |
---|---|
exposure | The current USD value of the amount of credit used |
available_exposure | The USD value of credit available |
exposure_limit | The maximum value in USD of credit that may be borrowed |
equity | The portion of the portfolio owned by you |
equity_for_withdrawals | The amount of equity that is available for withdrawals |
Fetching Whitelist Withdrawal Addresses
$ curl -X GET \
-H 'Authorization: Bearer < API_TOKEN >' \
'https://api.sfox.com/v1/whitelisted-addresses'
Custody Accounts Only
HTTP Request
GET /v1/whitelisted-addresses
Creating Whitelist Withdrawal Addresses
$ curl -X POST \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer < API_TOKEN >' \
--data '{ "alias": "Satoshis Fund",
"currency_symbol": "btc",
"address": "1NLqQmwkGxxQmzS9uwtCGXxbxrcNW4FpYp"}' \
'https://api.sfox.com/v1/whitelisted-addresses'
Custody Accounts Only
HTTP Request
POST /v1/whitelisted-addresses
Custody Approval Rules
Fetching Account Approval Rules
$ curl -X GET \
-H 'Authorization: Bearer < API_TOKEN >' \
'https://api.sfox.com/v1/approval-rules'
{
"data": [
{
"id": 3,
"available_approver_count": 2,
"date_added": "2021-03-17T16:19:47.000Z",
"required_approvals": 2,
"rule_type": "WITHDRAW",
"status": "Pending Approval",
"threshold": 20
}
]
}
HTTP Request
GET /v1/approval-rules
Creating Approval Rules
$ curl -X PATCH \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer < API_TOKEN >' \
--data '{ "rule_type": "WITHDRAW" , "required_approvals": 2 , "threshold": 100 }' \
'https://api.sfox.com/v1/approval-rules'
HTTP Request
POST /v1/approval-rules
Expected Request Body:
{"rule_type"
Supported rule types: "WITHDRAW"
, "ADD_ALTER_COLL"
, or "ALTER_SAFE"
Editing Approval Rules
$ curl -X PATCH \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer < API_TOKEN >' \
--data '{ "required_approvals": 3 , "threshold": 500 }' \
'https://api.sfox.com/v1/approval-rules/1'
HTTP Request
PATCH /v1/approval-rules/:rule-id
Expected Request Body:
{"required_approvals": number, "threshold": number }
Fetching Approval Requests
# Fetches all approvals, both complete and pending
$ curl -X GET \
-H Authorization: Bearer < API_TOKEN >' \
'https://api.sfox.com/v1/approvals'
{
"data": [
{
"approval_id": 1,
"requested_by_username": "example@email.com",
"requested_by_uaid": "6ea3fb9e-7797-11eb-aa51-0242ac120002",
"date_added": "2021-03-03T20:28:41.000Z",
"status": "Pending",
"approval_type": "WITHDRAW",
"required_approvals": 2,
"received_approvals": 0,
"action_details": {
"atx_currency_code": "btc",
"atx_amount": 5,
"atx_dest_address": "0x1232131223",
"threshold": 1
},
"approval_responses": {
"ua_display_id": "3fb9e6ea-7797-11eb-aa51-200020242ac1",
"username": "collaborator@email.com",
"approved": true
}
]
}
HTTP Request
GET /v1/approvals
Optional query params:
pending=true|false
By default this route will return all approvals completed and pending. If you supply a query parameter of `pending=true`
only pending approvals will be returned.
Responding to Pending Approvals
$ curl -X POST \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer < API_TOKEN >' \
--data '{ "approve": true}' \
'https://api.sfox.com/v1/approvals/1'
HTTP Request
POST /v1/approvals/:id
Expected Request Body:
`{"approve": true | false }`
Orders
Place an Order
You can place eight types of orders, specified by an Algorithm ID. 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.
curl "https://api.sfox.com/v1/orders/buy" \
-u "<api_key>:" \
-d "quantity=1" \
-d "currency_pair=btcusd"
requests.post(
"https://api.sfox.com/v1/orders/buy",
auth=requests.auth.HTTPBasicAuth("<api_key>", ""),
json={
"quantity": 1,
"currency_pair": "<currency_pair>"
}
).json()
The above command returns the same JSON object as the Order Status API, and it is structured like this:
{
"id": 666,
"quantity": 1,
"price": 10,
"o_action": "Buy",
"pair": "btcusd",
"type": "Limit",
"vwap": 0,
"filled": 0,
"status": "Started"
}
HTTP Request
POST /v1/orders/buy
or POST /v1/orders/sell
Common Parameters
These parameters are common to all order creation requests. See Special Parameters for exceptions.
Parameter | Required? | Default | Description |
---|---|---|---|
quantity | Y | The quantity to trade. The minimum quantity is 0.001 for crypto-denominated pairs, and price*quantity must be greater than $5 for USD-denominated pairs. Not required for market orders. | |
currency_pair | Y | The pair or product to trade in the format: <base currency><quote currency> (i.e. btcusd, ethbtc, usdtusd) | |
price | Y | The limit price (Precision: 8 decimal places for crypto, 2 decimal places for fiat). Not required for market orders. Note: the executed price will always be better than or equal to this price; if the market conditions do not allow it, the order will not execute. | |
algorithm_id | N | 200 | Specifies the algorithm you wish to use to execute the order. |
routing_type | Y | How SFOX will route your order. For more info, see Routing Types. | |
client_order_id | N | An optional field that can hold a user-specified ID. |
Special Parameters
Some of SFOX’s algorithms require different parameters that define execution.
Parameter | Algorithms | Default | Description |
---|---|---|---|
amount | Market, IOC, Stop Trailing Stop | The amount (quote currency) to spend when buying. Note: required for buy orders using the applicable algorithms – in this case, quantity is not required and is ignored.. | |
interval | TWAP | 900 | The frequency at which TWAP trades are executed (in seconds). |
total_time | TWAP | The maximum time a TWAP order will stay active (in seconds). Must be >= 15 minutes and the interval. | |
routing_option | [Hare, Gorilla] | Fast | Specify how SFOX will trade your order – choose BestPrice or Fast . |
stop_amount OR stop_percent | Trailing Stop | Set the amount (in USD) or percentage (i.e. 0.1 = 10%) that the trigger price of a trailing stop order will trail the price of an asset | |
max_slippage | Market, Stop, Trailing Stop | A risk management parameter that will limit the slippage of an order in basis points (i.e. setting max_slippage to 5 = 0.05%) |
Cancel an Order
This endpoint will start cancelling the order specified.
curl "https://api.sfox.com/v1/orders/<order_id>" \
-u "<api_key>:" \
-X DELETE
requests.delete(
"https://api.sfox.com/v1/orders/<order_id>",
auth=requests.auth.HTTPBasicAuth("<api_key>", "")
).json()
The above command does not return anything. To determine the cancellation status of an order, you will need to poll the Order Status endpoint.
HTTP Request
DELETE /v1/orders/<order_id>
Amend an Order
Use this endpoint to make the following adjustments to the quantity or amount, price, and stop amount or stop percent parameters of an order without canceling the order.
curl "https://api.sfox.com/v1/orders/" \
-u "<api_key>:" \
-d "quantity=2" \
-X PATCH
requests.patch(
"https://api.sfox.com/v1/orders/",
auth=requests.auth.HTTPBasicAuth("<api_key>", "")
).json()
The above command returns an array of Order Status JSON objects structured like this:
{
"id": 123,
"quantity": 2,
"price": 10,
"o_action": "Buy",
"pair": "btcusd",
"type": "Limit",
"vwap": 0,
"filled": 0,
"status": "Started"
}
HTTP Request
PATCH v1/orders/<order_id>
Allowed Modifications
Parameter | Allowable Modifications | Example |
---|---|---|
quantity/amount | Increase the quantity or amount of an order Amount may only be increased for Stop and Trailing Stop buy orders |
Buy $100 of BTC instead of $50 |
price | Buy Orders: Increase limit price Sell Orders: Decreaselimit pricePrice cannot be modified for Trailing Stop orders |
Limit buy at $100 instead of $99
Smart sell at $99 instead of $100 |
stop_amount/stop_percent | Any modification is allowed | Trailing stop sell trail amount = $5 instead of $100 |
Response Body
Successfully amending an order will return the updated order details
Order Status
Get the status and details of an order.
curl "https://api.sfox.com/v1/orders/<order_id>" \
-u "<api_key>:"
requests.post(
"https://api.sfox.com/v1/orders/<order_id>",
auth=requests.auth.HTTPBasicAuth("<api_key>", "")
).json()
The above command returns a JSON object structured like this:
{
"id": 666,
"quantity": 1,
"price": 10,
"o_action": "Buy",
"pair": "btcusd",
"type": "Limit",
"vwap": 0,
"filled": 0,
"status": "Started"
}
HTTP Request
GET /v1/orders/<order_id>
Possible “status” values
Value | Description |
---|---|
Started | The order is open on the marketplace waiting for fills |
Cancel pending | The order is in the process of being cancelled |
Canceled | The order was successfully canceled |
Filled | The order was filled |
Done | The order was completed successfully |
Get Open Orders
Get a list of your current open orders.
curl "https://api.sfox.com/v1/orders" \
-u "<api_key>:"
requests.get(
"https://api.sfox.com/v1/orders",
auth=requests.auth.HTTPBasicAuth("<api_key>", "")
).json()
The above command returns an array of Order Status JSON objects structured like this:
[
{
"id": 666,
"quantity": 1,
"price": 10,
"o_action": "Buy",
"pair": "btcusd",
"type": "Limit",
"vwap": 0,
"filled": 0,
"status": "Started"
},
{
"id": 667,
"quantity": 1,
"price": 10,
"o_action": "Sell",
"pair": "btcusd",
"type": "Limit",
"vwap": 0,
"filled": 0,
"status": "Started"
}
]
HTTP Request
GET /v1/orders
Possible “status” values
Value | Description |
---|---|
Started | The order is open on the marketplace waiting for fills |
Cancel pending | The order is in the process of being cancelled |
Canceled | The order was successfully canceled |
Filled | The order was filled |
Done | The order was completed successfully |
Get Done Trades
Get a list of your completed trades.
curl "https://api.sfox.com/v1/orders/done" \
-u "<api_key>:"
requests.get(
"https://api.sfox.com/v1/orders/done",
auth=requests.auth.HTTPBasicAuth("<api_key>", "")
).json()
The above command returns an array of Order Status JSON objects structured like this:
[
{
"id": 666,
"quantity": 1,
"price": 10,
"o_action": "Buy",
"pair": "btcusd",
"type": "Limit",
"vwap": 0,
"filled": 0,
"status": "Done"
},
{
"id": 667,
"quantity": 1,
"price": 10,
"o_action": "Sell",
"pair": "btcusd",
"type": "Limit",
"vwap": 0,
"filled": 0,
"status": "Done"
}
]
HTTP Request
GET /v1/orders/done
List Asset Pairs
Get a list of the asset pairs that are currently active for your account.
curl "https://api.sfox.com/v1/markets/currency-pairs" \
-u "<api_key>:"
requests.get(
"https://api.sfox.com/v1/markets/currency-pairs",
auth=requests.auth.HTTPBasicAuth("<api_key>", "")
).json()
Response
{
"bchbtc": {
"formatted_symbol": "BCH/BTC",
"symbol": "bchbtc"
},
"bchusd": {
"formatted_symbol": "BCH/USD",
"symbol": "bchusd"
},
"btcusd": {
"formatted_symbol": "BTC/USD",
"symbol": "btcusd"
}
}
HTTP Request
GET /v1/markets/currency-pairs
Algorithms & Routing Types
Algorithms
SFOX offers a wide range of trading algorithms, as well as two routing types, to optimize your order’s execution. For more details, see SFOX Algorithms.
ID | Name | Description |
---|---|---|
100 | Market | Optimally-routed market order (taker-only) |
150 | Instant | Instantly-settled market order |
160 | Simple | Instantly-settled market order |
200 | Smart Routing | Smart Order Routing–an order to buy or sell an asset at a specific price or better |
201 | Limit | Smart-routed limit order–an order to buy or sell an asset at a specific price or better |
301 | Gorilla | Hidden, smart-routed order, optimized for larger order sizes (maker-only) |
302 | Tortoise | Optimizes order placement on the best-priced liquidity providers (maker-only)API only |
303 | Hare | Smart-routed maker-only order, optimizing order placement at the top of the orderbook for better prices and zero slippage |
304 | Stop | An order to buy or sell an asset once the price of the asset reaches a specified price. When the trigger price is reached, a stop order becomes a market order (taker-only) |
305 | Polar Bear | Hidden, optimally-routed less-aggressive order (taker-only) |
306 | Sniper | Hidden, optimally-routed agressive order (taker-only) |
307 | TWAP | Optimally-routed order for executing portions of an order over a specified period of time and number of intervals at or better than the specified limit price (taker-only) |
308 | Trailing Stop | Trailing stop sell sets the stop price at a fixed amount or percentage below the market price. As the market price rises, the stop price rises by the trail amount/percentage. If the price falls, the stop price doesn’t change, and a market order is submitted when the stop price is hit. “Buy” trailing stop orders are the mirror image of sell trailing stop orders) |
309 | Immediate-or-Cancel (IOC) | An immediate-or-cancel order (IOC) is an order to buy or sell an asset that attempts to execute immediately at or better than the limit price and then cancels any unfilled portion of the order |
Routing Types
The routing type defines how SFOX prioritizes different sources of liquidity when executing your order. SFOX always attempts to execute your order at the best available price.
Routing Type | Description |
---|---|
NetPrice | Routes orders to the best venues for execution by considering both the quoted prices and the fees charged by the trading venues. Orders can be routed to additional OTC trading venues and receive a 10bps discount on the SFOX fee. For more details, see here. |
Market Data
Smart Routing Order Estimate
$ curl "https://api.sfox.com/v1/offer/buy?amount=1"
requests.get("https://api.sfox.com/v1/offer/buy", params={"amount": 1}).json()
The result of the calls is something like this:
{
"quantity":1,
"vwap":383.00,
"price":383.21,
"fees":0.95,
"total":382.26
}
Get an estimated execution price for the specified quantity of a given asset using SFOX’s Smart Order Routing, as well as related information. Only use this as an estimate – execution is not guaranteed.
HTTP Request
Buy:
GET /v1/offer/buy?amount=1
Sell:
GET /v1/offer/sell?amount=1
Query Parameters
Parameter | Required | Default | Description |
---|---|---|---|
amount | Y | The amount you will be trading (base currency). | |
pair | N | btcusd | The pair you will be trading. |
Response Body
Key | Description |
---|---|
quantity | Quantity to buy or sell |
vwap | “Volume Weighted Average Price”, the price the user can expect to receive if the order is executed. Even though the price is $383.21 in this example, you will most likely pay $383 for the entire order. These prices are not guaranteed as the market is always moving. |
price | Limit price the user must specify when placing the order to achieve the VWAP price at execution |
fees | Expected fee for executing this order |
total | Total cost of the order |
Candlestick / OHLCV Historical Data
Use this endpoint to access historical, aggregated Open-High-Low-Close-Volume data from all supported liquidity providers and currency pairs
curl "https://chartdata.sfox.com/candlesticks?endTime=1592951280&pair=btcusd&period=60&startTime=1592939280"
requests.get("https://chartdata.sfox.com/candlesticks?endTime=1592951280&pair=btcusd&period=60&startTime=1592939280").json()
The result is an array of OHLCV datapoints:
[
{
"open_price":"9654",
"high_price":"9662.37",
"low_price":"9653.66",
"close_price":"9655.73",
"volume":"6.31945755",
"start_time":1592939280,
"pair":"btcusd",
"candle_period":60,
"vwap":"9655.70504211",
"trades":53
},
{
"open_price":"9655.72",
"high_price":"9663.381",
"low_price":"9653.8",
"close_price":"9653.9",
"volume":"19.78230049",
"start_time":1592939340,
"pair":"btcusd",
"candle_period":60,
"vwap":"9654.19237263",
"trades":56
},
...
]
HTTP Request
GET https://chartdata.sfox.com/candlesticks
Query Parameters
Parameter | Required | Default | Description |
---|---|---|---|
pair | N | btcusd | The pair you want data for |
startTime | N | The unix timestamp of the first datapoint returned | |
endTime | N | The unix timestamp of the last datapoint you want returned | |
period | N | The duration of each datapoint or candle in seconds (i.e. period = 60 would return 1-minute candles) |
Response Body
Key | Description |
---|---|
open_price | The price at the start of that period |
high_price | The highest price reached during that period |
low_price | The lowest price reached during that period |
close_price | The price at the end of that period |
volume | Total volume of the asset traded during that period |
start_time | The unix timestamp of the beginning of the period |
end_time | The unix timestamp of the end of the period |
pair | The trading pair of the data |
candle_period | The duration of each datapoint in seconds |
vwap | The volume-weighted average price of the period |
trades | The total number of trades executed across all liquidity providers during that period |
Orderbook
Get the blended L2 orderbook data of our connected exchanges, including the top bids and asks and the location of those bids and asks.
curl "https://api.sfox.com/v1/markets/orderbook/<asset_pair>"
requests.get("https://api.sfox.com/v1/markets/orderbook/<asset_pair>").json()
The result of the calls is an array of bids and asks:
{
"bids": [
[
9458.12,
1e-08,
"gemini"
],
[
9456,
1,
"itbit"
],
[
9453,
0.73553115,
"itbit"
],
// truncated
"asks": [
[
9455.55,
2.03782954,
"market1"
],
[
9455.56,
0.9908,
"market1"
],
[
9455.59,
0.60321264,
"market1"
],
// truncated
"market_making": {
"bids": [
[
9447.34,
2,
"bitstamp"
],
[
9452.01,
0.60321264,
"market1"
],
[
9452.31,
0.47488688,
"bittrex"
],
[
9456,
1,
"itbit"
],
[
9458.12,
1e-08,
"gemini"
]
],
"asks": [
[
9458.13,
2.07196048,
"gemini"
],
[
9457.75,
0.14748797,
"itbit"
],
[
9456,
0.1686167,
"bittrex"
],
[
9455.68,
0.742406,
"bitstamp"
],
[
9455.55,
2.03782954,
"market1"
]
]
},
"timestamps": {
"gemini": [
1572903458537,
1572903458538
],
"bitstamp": [
1572903458199,
1572903458199
],
"itbit": [
1572903458414,
1572903458416
],
"bittrex": [
1572903458517,
1572903458517
],
"market1": [
1572903458071,
1572903458071
]
},
"lastupdated": 1572903458756,
"pair": "btcusd",
"currency": "usd",
"lastpublished": 1572903458798
}
HTTP Request
The default pair is btcusd
GET /v1/markets/orderbook
However if you want to specify a pair:
GET /v1/markets/orderbook/ethusd
Response Body
Key | Description |
---|---|
pair | The trading pair |
currency | The quote currency |
asks | List of asks, size, and exchange |
bids | List of the bids, size, and exchange |
market_making | List of the best bid and ask on each exchange |
timestamps | A list of exchanges and the latest timestamps of the orderbook |
lastupdated | Last update of the blended orderbook |
lastpublished | Last time an orderbook update was published |
Websocket Feeds
Connecting
import asyncio
import websockets
async def main(uri):
async with websockets.connect(uri) as ws:
# don't forget to subscribe (see below)
async for msg in ws:
print(msg)
asyncio.run(main("wss://ws.sfox.com/ws"))
const WebSocket = require('ws');
const ws = new WebSocket('wss://ws.sfox.com/ws');
// don't forget to subscribe (see below)
ws.on('message', function(data) {
// Do something with data
console.log(data);
});
Connecting to the SFOX websocket feed gives you access to real-time market data from all supported exchanges.
Endpoint | Description |
---|---|
Production | wss://ws.sfox.com/ws |
Sandbox | Contact support |
Authentication
Authentication Message
var unsubscribe = {
"type": "authenticate",
"apiKey":"<your_api_key>",
}
ws.send(JSON.stringify(unsubscribe));
Success Response
{
"type":"success",
"sequence":1,
"timestamp":1611363288098046336
}
Private websocket feeds require authentication. These commands should be JSON with the following properties
Property | Type | Command |
---|---|---|
type | string | “authenticate” |
apiKey | string | “<your_api_key>” |
Subscribing & Unsubscribing
Subscribing
subscribe_msg = {
"type": "subscribe",
"feeds": ["ticker.sfox.btcusd"],
}
await ws.send(json.dumps(subscribe_msg))
var subscribeMsg = {
type: "subscribe",
feeds: ["ticker.sfox.btcusd"]
}
ws.send(JSON.stringify(subscribeMsg));
Response:
{
"type":"success",
"sequence":1,
"timestamp":1534443719605160397
}
{
"sequence": 2,
"recipient": "ticker.sfox.btcusd",
"timestamp": 1534443725944639261,
"payload": {
"amount": 0.0989,
"exchange": "coinbase",
"high": 6491.8,
"last": 6399.99,
"low": 6200,
"open": 6269.01,
"pair": "btcusd",
"route": "Smart",
"source": "ticker-info",
"timestamp": "2018-08-16T18:22:05.909Z",
"volume": 38541.16966647,
"vwap": 6358.123642949931
}
}
Unsubscribing
var unsubscribe = {
"type": "unsubscribe",
"feeds": ["ticker.sfox.btcusd"]
}
ws.send(JSON.stringify(unsubscribe));
Response:
{
"type":"success",
"sequence":30,
"timestamp":1534440639383033506
}
Once connected to the SFOX websocket you can subscribe to various public feeds without authenticating by using the subscribe
or unsubscribe
command. These commands should be JSON with the following properties.
Property | Type | Description |
---|---|---|
type | string | Command you are sending to the websocket (subscribe or unsubscribe ) |
feeds | []string | List of the feeds that should be subscribed/unsubscribed to |
Message Format
Messages that are sent to the various feeds will be JSON objects with the following similar format.
Property | Type | Description |
---|---|---|
sequence | int | The sequence number that the message was sent in. |
recipient | string | The feed that the message was sent to |
timestamp | int | The timestamp (in microseconds) |
payload | json | The payload parameter will be a JSON message that contains then data |
Supported Channels
Public Websocket Channels
Public websocket channels do NOT require authentication. The following public channels offer real-time data from SFOX’s global liquidity network
Channels
Channel | Example | Description |
---|---|---|
Orderbooks | Net Price orderbook.net.ethbtcNormal orderbook.sfox.btcusd |
Orderbook channels are of the form orderbook.type.pair. Channels with type sfox will stream the normal, consolidated SFOX orderbook, while type net channels will stream the fee-adjusted orderbook used for the NetPrice routing type. |
Trades | trades.sfox. i.e. trades.sfox.btcusd | Real-time tick data feed of all trades executed on SFOX’s supported exchanges |
Ticker | ticker.sfox. i.e. ticker.sfox.ltcbtc | Receive aggregated 24-hour OHLCV data from all supported exchanges and the last price before each update every 10 seconds. Subscriptions to the ticker feed will receive realtime trades that occur on any of the exchanges that are active on the SFOX platform. |
Private Websocket Channels
Private websocket channels require authentication. The following private channels offer real-time account updates.
Channels
Channel | Example | Description |
---|---|---|
Balances | private.user.balances | Real-time account balance updates |
Open Orders | private.user.open-orders | Real-time updates to open orders including order status changes, fills, and more |
Post-Trade Settlement | private.user.post-trade-settlement | Real-time post-trade settlement data updates |
Channel Descriptions
Orderbooks
Orderbook channels are of the form orderbook.type.pair
. Channels with type sfox
will stream the normal, consolidated SFOX orderbook, while type net
channels will stream the fee-adjusted orderbook used for the NetPrice
routing type.
E.g. orderbook.sfox.btcusd
or orderbook.net.ethbtc
Trades
Trade channels are of the form trades.sfox.pair
.
E.g. trades.sfox.btcusd
Ticker
Ticker channels are of the form ticker.sfox.pair
.
E.g. ticker.sfox.ltcbtc
Channel Descriptions
Ticker
Receive aggregated 24-hour OHLCV data from all supported exchanges and the last price before each update every 10 seconds. Subscriptions to the ticker feed will receive realtime trades that occur on any of the exchanges that are active on the SFOX platform.
Ticker Example
import asyncio
import json
import websockets
async def main(uri):
async with websockets.connect(uri) as ws:
await ws.send(json.dumps({
"type": "subscribe",
"feeds": [
"ticker.sfox.btcusd",
],
}))
async for msg in ws:
print(msg)
asyncio.run(main("wss://ws.sfox.com/ws"))
const WebSocket = require("ws");
const ws = new WebSocket("wss://ws.sfox.com/ws");
ws.on("message", function(data) {
console.log(data);
});
ws.on("open", function() {
ws.send(JSON.stringify({
type: "subscribe",
feeds: [
"ticker.sfox.btcusd"
],
}));
});
Ticker example message
{
"sequence": 2,
"recipient": "ticker.sfox.btcusd",
"timestamp": 1534440861543042409,
"payload": {
"amount": 0.0092443,
"exchange": "bitstamp",
"high": 6491.8,
"last": 6442.5,
"low": 6200,
"open": 6269.01,
"pair": "btcusd",
"route": "Smart",
"source": "ticker-info",
"timestamp": "2018-08-16T17:34:21.000Z",
"volume": 36810.02514349,
"vwap": 6355.319029430
}
}
Payload Description
Key | Description |
---|---|
amount | Last trade quantity |
exchange | Location of trade |
last | Last trade price (tick) |
high | 24 hour high price |
low | 24 hour low price |
open | 24 hour open price |
pair | Crypto asset traded |
route | disregard |
source | Data source |
timestamp | Time of trade |
volume | 24 hour volume |
vwap | 24 hour volume-weighted average price |
Orderbook
Receive real-time L2 orderbook data
Orderbook Example
import asyncio
import json
import websockets
async def main(uri):
async with websockets.connect(uri) as ws:
await ws.send(json.dumps({
"type": "subscribe",
"feeds": [
"orderbook.sfox.ethbtc",
],
}))
async for msg in ws:
print(msg)
asyncio.run(main("wss://ws.sfox.com/ws"))
const WebSocket = require("ws");
const ws = new WebSocket("wss://ws.sfox.com/ws");
ws.on("message", function(data) {
console.log(data);
});
ws.on("open", function() {
ws.send(JSON.stringify({
type: "subscribe",
feeds: [
"orderbook.sfox.ethbtc"
],
}));
});
Orderbook Response
{
"sequence": 2,
"recipient": "orderbook.sfox.ethbtc",
"timestamp": 1534440609281315077,
"payload": {
"bids": [
[
0.0454916,
1.519,
"market2"
],
[
0.04549109,
1.182,
"market2"
],
[
0.04549086,
0.21094215,
"market2"
]
// truncated
],
"asks": [
[
0.04564,
34.1074,
"gemini"
],
[
0.04559969,
4.8245942,
"bitstamp"
],
[
0.04556277,
0.507,
"market2"
]
// truncated
],
"timestamps": {
"gemini": [
1572882771172,
1572882771176
],
"bitstamp": [
1572882771112,
1572882771112
],
"itbit": [
1572882770106,
1572882770422
],
"bittrex": [
1572882769065,
1572882769115
],
"market1": [
1572882770515,
1572882770515
]
},
"lastupdated": 1534440609168,
"lastpublished": 1534440609168,
"pair": "ethbtc",
"currency": "btc"
}
}
Trades
Real-time tick data feed of all trades executed on SFOX’s supported exchanges
Trades Example
import asyncio
import json
import websockets
async def main(uri):
async with websockets.connect(uri) as ws:
await ws.send(json.dumps({
"type": "subscribe",
"feeds": [
"trades.sfox.btcusd",
],
}))
async for msg in ws:
print(msg)
asyncio.run(main("wss://ws.sfox.com/ws"))
const WebSocket = require("ws");
const ws = new WebSocket("wss://ws.sfox.com/ws");
ws.on("message", function(data) {
console.log(data);
});
ws.on("open", function() {
ws.send(JSON.stringify({
type: "subscribe",
feeds: [
"trades.sfox.btcusd"
],
}));
});
Trades Response
{
"sequence": 2,
"recipient": "trades.sfox.btcusd",
"timestamp": 1572883322244910600,
"payload": {
"buyOrderId": "4307737868",
"exchange": "bitstamp",
"exchange_id": 1,
"id": "99960684",
"pair": "btcusd",
"price": "9300",
"quantity": "390419",
"sellOrderId": "4307754886",
"side": "sell",
"timestamp": "2019-11-04T16:02:02.000"
}
}
Payload Description
Key | Description |
---|---|
buyOrderId | Order ID of the buy |
exchange | Location of the trade |
exchange_id | ID of the trade location |
pair | Crypto asset traded |
price | Price of the trade |
quantity | Quantity traded |
sellOrderId | Order ID of the sale |
side | Which side was the taker |
timestamp | Time of the trade |
Balances Example:
{
"sequence": 6,
"recipient": "private.user.balances",
"timestamp": 1611365208455005384,
"payload": [{
"currency": "btc",
"balance": 0,
"available": 0,
"held": 0
}, {
"currency": "usd",
"balance": 3320.55527573,
"available": 3320.55527573,
"held": 0
}, {
"currency": "ltc",
"balance": 9.22257079,
"available": 9.22257079,
"held": 0
}, {
"currency": "eth",
"balance": 8.80064155,
"available": 8.80064155,
"held": 0
}, {
"currency": "bch",
"balance": 0,
"available": 0,
"held": 0
}, {
"currency": "rvn",
"balance": 0,
"available": 0,
"held": 0
}, {
"currency": "bsv",
"balance": 0.59201937,
"available": 0.59201937,
"held": 0
}, {
"currency": "etc",
"balance": 32.59913691,
"available": 32.59913691,
"held": 0
}]
}
Balances
Real-time feed for all balances by currency belonging to the user authenticated API key. The initial snapshot will provide a list of all current balances by currency and then any updates to the balances list will be sent.
Payload Description
Key | Description |
---|---|
currency | Currency of which the following balances applies |
balance | Total balance of this currency |
available | Portion of the balance that is available for trading or withdrawals |
held | Potion of the balance that is currently on hold and unavailable for trading or withdrawals (i.e. an ACH deposit that has yet to settle) |
Post-Trade Settlement Example:
{
"sequence": 5,
"recipient": "private.user.post-trade-settlement",
"timestamp": 1603998101753588121,
"payload": {
"enabled": true,
"equity": 999999999999.99999999,
"equity_available": 999999999999.99999999,
"exposure": 0,
"exposure_available": 100000,
"exposure_limit": 100000,
}
}
Post-Trade Settlement
Real-time post-trade settlement data. Feed to show all of the account’s Post-Trade Settlement data belonging to the user authenticated API key. Initial snapshot will provide a list of all post trade settlement data and then any updates to the data list will be sent.
Payload Description
available_exposureUSD value of available creditexposure_limitMaximum USD value that may be borrowed
Key | Description |
---|---|
enabled | Boolean whether post-trade settlement is enabled on your account |
equity | Current USD value of your account equity (portion of the portfolio owned by you) |
equity_for_withdawals | Current USD value of the portion of equity that may be withdrawn from the platform |
exposure | Current USD value of the amount borrowed |
Enterprise
Streaming Quotes
Authentication message:
{
"type": "authenticate",
"apiKey": "<your_api_key>",
}
Subscribe message:
{
"type": "subscribe",
"feeds": ["private.orderbook.compact.btcusd"],
}
Unsubscribe message:
{
"type": "unsubscribe",
"feeds": ["private.orderbook.compact.btcusd"],
}
For Enterprise clients, SFOX offers a customizable compact orderbook of real-time executable quotes. Execution is not guaranteed.
Connecting
Streaming Quotes are accessible from the SFOX websocket feed.
Endpoint | Description |
---|---|
Production | wss://ws.sfox.com/ws |
Sandbox | Contact Support |
Authenticating and Subscribing
Once connected to the SFOX websocket, you must authenticate with your API key before subscribing to private feeds.
Authentication
Property | type | Command |
---|---|---|
type | string | “authenticate” |
apiKey | string | “your-api-key” |
Subscribing/Unsubscribing
Property | type | Command |
---|---|---|
type | string | “subscribe” or “unsubscribe” |
feeds | []string | “your-api-key” |
Errors
HTTP Status Codes
The SFOX API communicates error codes through HTTP status codes. The following are the error codes currently in use:
Error Code | Meaning |
---|---|
400 | Bad Request — Your request was malformed in some way |
401 | Unauthorized — Your API key is wrong |
403 | Forbidden — The API key is not authorized for this endpoint |
404 | Not Found — The specified endpoint could not be found |
405 | Method Not Allowed — You tried to access a endpoint with an invalid method |
406 | Not Acceptable — You requested a format that isn’t json |
429 | Too Many Requests — You have exceeded your request limit |
500 | Internal Server Error — We had a problem with our server. Try again later. |
503 | Service Unavailable — We’re temporarially offline for maintanance. Please try again later. |
FIX
Fix API
For information on how to implement the FIX protocol please contact support@sfox.com.
Field | Value | Description |
---|---|---|
HeartBtInt | <=30 | Heart beat interval |
BeginString | FIX.4.4 | Only FIX 4.4 is supported |
SenderCompID | Anything | You can provide your own sender comp id and have any number of FIX sessions |
TargetCompID | SFOX | |
ResetOnLogon | Y |
Endpoints
Environment | Value | Description |
---|---|---|
Production | fix.sfox.com:5001 | SSL Required |
Staging | fix.staging.sfox.com:5001 | SSL Required |
Supported Tags
Logon – A
Tag | Name | Required | Description |
---|---|---|---|
554 | Password | SSL Required | Your API Key (generate one here) |
NewOrderSingle – D
21HandlInst (semi-custom)N2 (NetPriceRoutingType: 1 = Rest API default (empty), 2 = NetPrice, 3 = Enterprise
Tag | Name | Required | Default | Description |
---|---|---|---|---|
11 | ClOrdID | Y | Client provided order ID, must be unique per-account | |
55 | Symbol | Y | Trading pair (see: List Asset Pairs) | |
54 | Side | Y | 1 = Buy, 2 = Sell | |
40 | OrdType | Y | 1 = Market, 2 = Limit, 3 = Stop, or one of our Algoritm IDs | |
44 | Price | Y (except market orders) | Limit Price | |
38 | OrderQty | Y | For limit orders, this is the quantity to trade in the base currency. For Market Sell orders, this is the amount in the base currency. | |
152 | CashOrderQty | Y (OrdType = 1 AND Side = 1 or OrdType = 3 (stop) AND Side = 1 (buy)) | For market buy orders, this is the amount to spend in the quote currency | |
59 | TimeInForce | N | 1 (GTC) | The lifetime of the order, immediate or cancel (3) and good till cancel (1) |
Tag | Name | Algorithm | Required | Default | Description |
---|---|---|---|---|---|
20000 | StopAmount | Trailing Stop (308) | N | The fixed amount to trail the market price by | |
20001 | StopPercent | Trailing Stop (308) | N | The percentage to trail the market price by (given as a decimal: 10% = 0.1) | |
20010 | Interval | TWAP (307) | Y | The frequency at which TWAP trades are executed (in seconds) | |
20011 | TotalTime | TWAP (307) | Y | The maximimum time a TWAP order will stay active (in seconds). Must be >= 15 minutes (900 seconds) and the interval (tag 20010) | |
20020 | RoutingOption | Gorilla (301), Hare (303) | Y | How SFOX will trade your order, BestPrice or Fast |
OrderStatusRequest – H
Tag | Name | Required | Description |
---|---|---|---|
11 | ClOrdID | Y | Original ClOrdID when creating the order |
790 | OrdStatusReqID | N | Optionally provided value that will be echoed in the response |
OrderCancelRequest – F
Tag | Name | Required | Description |
---|---|---|---|
11 | ClOrdID | Y | Unique ID of the cancel request |
41 | OrigClOrdID | Y | Original ClOrdID provided when creating the order |
ExecutionReport – 8
Tag | Name | Description |
---|---|---|
37 | OrderID | SFOX Assigned Order ID, when rejected this will be 0. |
17 | ExecID | SFOX Assigned Trade ID, when rejected this will be 0. |
11 | ClOrdID | Client provided order ID |
31 | LastPx | Last fill price |
32 | LastQty | Last fill quantity |
60 | TransactTime | |
55 | Symbol | Trading pair |
54 | Side | 1 = Buy, 2 = Sell |
40 | OrdType | 1 = Market, 2 = Limit |
44 | Price | Client provided limit price, only if OrdType = 2 |
150 | ExecType | Execution type: 0 = New, 4 = Canceled, 8 = Rejected, F = Trade, I = Order Status Request |
39 | OrdStatus | Current status of the order: 0 = New, 1 = Partially Filled, 2 = Filled, 3 = Done, 4 = Canceled, 8 = Rejected |
151 | LeavesQty | Amount remaining of the order |
14 | CumQty | Amount filled so far of the order |
799 | AvgPx | VWAP |
OrderCancelReject – 9
Tag | Name | Description |
---|---|---|
37 | OrderID | SFOX Order ID, unless the order is unknown (CxlRejReason = Unknown Order) |
11 | ClOrdID | Client provided order ID of the cancel request |
41 | OrigClOrdID | Client provided order ID of the original order (echoed back from the request) |
39 | OrdStatus | CExisting status of the order that could not be canceled |
Market Data Request – V
Tag | Name | Required | Description |
---|---|---|---|
262 | MDReqID | Y | Market data request id, this will be included in all Market Data Snapshot Full Refresh updates. |
146 | NoRelatedSym | Y | Number of symbols in this request |
-> 55 | Symbol | Y | Pair to subscribe to |
264 | MarketDepth | Y | Depth of the orderbook |
20030 | custom | N | Which marketdata feed: "" – default/standard, "net" – net price, "compact" – compact/enterprise |
Market Data Snapshot Full Refresh – W
Tag | Name | Description |
---|---|---|
262 | MDReqID | Market data request id that this is refresh was created by |
55 | Symbol | Pair |
268 | NoMDEntries | Market data request id that this is refresh was created by |
-> 269 | MDEntryType | 0 – Bid, 1 – Ask/Offer |
-> 270 | MDEntryPx | Price |
-> 271 | MDEntrySize | Size/Quantity |
-> 275 | MDMkt | Market of the entry, not applicable to the compacted feed |