Apiary Powered Documentation
Sign in with Apiary account.
Requests should be sent to https://otc.ftx.com/api/ for FTX or https://otc.ftx.us/api for FTXUS. Requests and responses use JSON.
See our sample client code here: https://github.com/ftexchange/ftx/blob/master/rest/otc_client.py
Requests should be sent with the following headers:
FTX-APIKEY
: Your API key
FTX-TIMESTAMP
: Number of milliseconds since Unix epoch
FTX-SIGNATURE
: SHA256 HMAC of the following four strings, using your API secret:
1528394229375
)GET
or POST
)/otc/quotes?limit=10
)We sign every API response using ECDSA signatures. In each payload, you will see fields called "signature" and "canonical". The signature is an ECDSA signature of the value in "canonical", which the same as the API response but with keys sorted
Our public key is:
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEZGMMvr3y0ZaDiuhJgVlYMsu4TGjXcpow
dHuHktZsgU5oNiFTeIYxGPzFFaDqimkzg1b1SZS5zE/iKv7wFZNPGg==
-----END PUBLIC KEY-----
Please do not send more than 10 requests per second. Sending requests more frequently will result in HTTP 429 errors.
We also limit the number of quote requests. Contact us please if you need higher limits.
3 (401): Unauthenticated
4 (400): MissingParameter
5 (400): InvalidParameter
6 (404): UnknownMarket
7 (404): OrderNotFound
8 (400): NotEnoughBalances
9 (400): OrderTooSmall
10 (400): OrderAlreadyClosed
11 (404): UnknownCoin
12 (400): InvalidAddress
13 (400): WithdrawalsNotSupported
14 (404): WithdrawalNotFound
15 (400): WithdrawalAlreadySent
16 (400): MarketDisabled
17 (403): NotAllowed
18 (429): RateLimitExceeded
19 (400): CoinLimitExceeded
20 (400): OrderTooLarge
21 (400): CannotWithdraw
Get the list of currency symbols and their corresponding metadata
true
Get metadata about all trading pairs.
true
true
hideZero | can set this to anything to drop 0 balances from response |
---|
true
Includes USD deposits
limit | default 100, max 200 |
---|---|
start_time | unix timestamp in seconds. Only fetch deposits on or after this time. Must include end_time. |
end_time | unix timestamp in seconds. Only fetch deposits on or before this time. Must include start_time. |
true
ticker |
---|
true
Includes USD withdrawals
limit | default 100, max 200 |
---|---|
start_time | unix timestamp in seconds. Only fetch deposits on or after this time. Must include end_time. |
end_time | unix timestamp in seconds. Only fetch deposits on or before this time. Must include start_time. |
true
true
Withdrawal must have status requested
true
Can only be done for coins with property canTransferFromFtx
. Query the /currencies endpoint for this information
true
OK
Can only be done for coins with property canTransferToFtx
. Query the /currencies endpoint for this information
true
OK
Request a quote. Quotes are generated asynchronously, so the response object will not contain a
price. Instead, a request needs to be made to /otc/quotes/{quote_id}
with the quote ID to retrieve the
price
Note that the counterparty is always FTX.
BTC
USDT
buy, sell, or twoWay
buy
either this or quoteCurrencySize
needs to be specified
1.23
either this or baseCurrencySize
needs to be specified
4908.8
if true, do not show the quote on the website. If accepted, expire other live quotes with matching apiOnly
false
if true, wait for the price to be generated before returning a response. Defaults to false.
true
List recent quotes
true
Retrieve a quote by ID.
quote_id |
---|
true
The URL parameter quote_id
is an integer or string, e.g. 12345. You can optionally prefix it with "rfq:", e.g. "rfq:12345"
true
settledImmediat | whether or not the quote was fully settled immediately by both parties |
---|---|
fullySettled | whether or not the quote has been fully settled by both parties |
before | max id to fetch (by default, we will fetch the most recent accepted quotes) |
limit |
true
quoteId | id of the quote to restrict returned defer costs payments to |
---|---|
before | max id to fetch (by default, we will fetch the most recent defer cost payments) |
limit |
true
quoteId | id of the quote to restrict returned defer costs payments to |
---|---|
before | max id to fetch (by default, we will fetch the most recent defer proceeds payments) |
limit |
true
quoteId | id of the quote to restrict returned defer costs payments to |
---|---|
before | max id to fetch (by default, we will fetch the most recent settlements) |
limit |
true
quoteId | id of the quote to restrict returned defer costs payments to |
---|---|
before | max id to fetch (by default, we will fetch the most recent counterparty settlements) |
limit |
true
true
List your most recent trades, even those from quotes that are unsettled
limit | number of fills to retrieve |
---|---|
start_time | unix timestamp in seconds, only show fills after this |
end_time | unix timestamp in seconds, only show fills before this |
true
List your most recent RFQ trades
limit | number of fills to retrieve. max 100, default 100 |
---|---|
startMs | unix timestamp in milliseconds, only show fills created after this |
endMs | unix timestamp in milliseconds, only show fills created before this |
true
List your most recent RFS orders, even those that were not filled
limit | number of fills to retrieve. max 100, default 100 |
---|---|
startMs | unix timestamp in seconds, only show fills created after this |
endMs | unix timestamp in seconds, only show fills created before this |
clientStreamIds | comma delimited client stream IDs |
clientOrderIds | comma delimited client order IDs |
filledOnly | set this field to anything to make the response only include filled orders |
true
true
Notes:
baseCurrencySize
or quoteCurrencySize
limitPrice
is set, you will receive a partial fill if quote price is worse than thisBody
baseCurrency
: BTC (string)quoteCurrency
: USD (string)side
: sell (string)intervalSeconds
: 3600 (number) - minimum number of seconds between twap fills. Must be 60 (1 minute) or greaterbaseCurrencySize
1.0 (number, nullable)quoteCurrencySize
100.0 (number, nullable) - must provide exactly one of base/quote currency sizelimitPrice
: 40000.0 (number, nullable)true
twapId
: 1 (number)true
twapId
: 1 (number)true
The FTX and FTXUS OTC portal now supports the ability to create a websocket connection and stream quotes for a (market, max size) pairs
For FTX OTC, connect to wss://otc.ftx.com/ws
For FTXUS OTC, connect to wss://otc.ftx.us/ws
See our sample client code here: https://github.com/ftexchange/ftx/blob/master/websocket/otc_client.py
Send a message with the following payload:
{
"op": "login",
"args": {
"api_key": "your-api-key",
"sign": "signature-using-api-secret",
"timestamp": 1647980276000
}
}
Upon successfully logging in you will receive the following message:
{
"type": "login",
"message": "logged in"
}
Our signature format for RFS is the SHA256 HMAC of the request timestamp (in milliseconds) signed with your api secret. You may use the same signing function as for RFQ authentication, with method, path and request data as empty strings
Send a message with the following payload:
{
"op": "subscribe",
"channel": "quotes",
"baseCurrency": "ETH",
"quoteCurrency": "USD",
"baseCurrencySize": 100.0
}
Optionally you can include a clientId
argument that will be passed back on each payload in the stream. This must be unique
Upon successfully subscribing, you will receive a message to confirm this:
{
"type": "subscribed",
"channel": "quotes",
"userId": 1,
"baseCurrency": "ETH",
"quoteCurrency": "USD",
"baseCurrencySize": 100.0,
"clientId": "uvm123"
}
You can unsubscribe to a stream by passing in the same payload you would use to subscribe, except with "op": "unsubscribe":
{
"op": "unsubscribe",
"channel": "quotes",
"baseCurrency": "ETH",
"quoteCurrency": "USD",
"baseCurrencySize": 100.0
}
The messages in the quote stream will be of the form:
{
"channel": "quotes",
"userId": 1,
"baseCurrency": "ETH",
"quoteCurrency": "USD",
"baseCurrencySize": 100.0,
"type": "update",
"clientId": "uvm123",
"data": {
"id": 3286,
"askPrice": 2875.91,
"bidPrice": 2872.9,
"expiresAt": 1647843528197,
"quotedAt": 1647843468197,
"clientId": "uvm123",
"baseCurrency": "ETH",
"quoteCurrency": "USD",
"baseCurrencySize": 100.0,
}
}
If you disconnect and then resubscribe, and the latest quote you had been sent before you disconnected is still alive, then you will receive that quote upon subscribing except the "type" of this payload will be "latest" rather than "update"
Send a message with the following payload:
{
"op": "trade",
"quoteId": 3286,
"side": "buy",
"price": 2875.91,
"baseCurrencySize": 10.0,
"clientOrderId": "abc123"
}
To sell instead of buy, set side to "sell"
The price you submit will be the worst possible price you are willing to receive
Sizes:
Client IDs are optional; they can be ascii strings up to 32 characters. If you do not pass this in, we will create it for you
You may also accept an RFS quote using the same API to accept an RFQ quote. To do this you prefix the RFS quote_id
with "rfs:"
, e.g. "rfs:1234". Then fill out the following JSON body. The response will be the same as you would expect when accepting an RFQ quote
side
: buy (string) - either "buy" or "sell", as all RFS quotes are two-sidedprice
: 1000.0 (number, optional) a limit price for the quotebaseCurrencySize
: 1.0 (number, optional) execute a fraction of the size, expressed in base currency termsquoteCurrencySize
: 100.0 (number, optional) execute a fraction of the size, expressed in qupte currency termsclientOrderId
: abc123
(string, optional)true
When a trade is executed, you will immediately receive a fill of the form:
{
"type": "fill",
"message": "sold 0.00023428 BTC @ 42,683.16 (received 9.9998107 USD)",
"data": {
"order": {
"id": 1255,
"streamingQuoteId": 4112,
"side": "sell",
"price": 42683.16,
"state": "filled",
"clientOrderId": "abc123"
"placedAt": "2022-03-22T21:23:05.138897"
},
"quote": {
"baseCurrency": "BTC",
"quoteCurrency": "USD",
"maxBaseCurrencySize": 10.0,
"id": 4112,
"askPrice": 42717.25,
"bidPrice": 42683.16,
"expiresAt": 1647984185885,
"quotedAt": 1647984185004,
"fillId": 41513991,
"unsettledCost": 0.0,
"unsettledProceeds": 0.0,
"clientId": "xvu123"
},
"fill": {
"id": 41513991,
"orderId": 291669965,
"market": "BTC-USD",
"baseCurrency": "BTC",
"quoteCurrency": "USD",
"side": "sell",
"price": 42683.16,
"size": 0.00023428,
"liquidity": "taker",
"fee": 0.0,
"feeCurrency": "BTC",
"time": "2022-03-22T21:23:05.173244+00:00"
}
},
"channel": "fills"
}
Shortly after receiving the fill, you may also receive cancelled (and subsequently updated) quotes for other streams
The payload for a cancelled quote is identical to a quote update, except the "type" is "cancel" and the "expiresAt" timestamp will be in the past