API reference
The API is shaped like Binance USD-M Futures: the same paths, the same parameter names, the same error codes. A client written against Binance should need a base URL and a key, and nothing else. Where we differ, it says so below.
Base URL —
getting a key
Create one under account → API keys. You choose the permissions when you create it, and you can restrict it to a list of addresses.
| permission | what it allows |
|---|---|
read | Your account, positions, orders, trades and income. Changes nothing. |
trade | Place and cancel orders, set leverage and margin type. |
transfer | Move money in and out of the account. |
The secret is shown once, at creation. We store a hash of it and cannot show it to you again; if you lose it, revoke the key and create another.
A key cannot create or revoke keys, change your password, or manage your sessions — those need the password behind a browser session. That is deliberate: otherwise a leaked read-only key becomes a trading key in two steps.
signing a request
Every authenticated request carries:
| where | name | what |
|---|---|---|
| header | X-MBX-APIKEY | The key. Not the secret. |
| parameter | timestamp | Milliseconds since the epoch. |
| parameter | recvWindow | Optional. Milliseconds. Default 5000, maximum 60000. |
| parameter | signature | Lowercase hex HMAC-SHA256, under the secret, of everything else. Sent last. |
Sign the bytes you send, in the order you send them. The
payload is the query string (or the form body) exactly as it goes on the
wire, with signature removed — not a re-encoding of a parsed
object. If you build the string, sign that same string, and send it
unchanged, you cannot get this wrong. If you sign a re-serialisation, a
different parameter order or a differently-escaped space will produce a
payload you never sent.
GET parameters go in the query string; POST and DELETE parameters go in the query string too.
curl -H "X-MBX-APIKEY: $KEY" \ "$BASE/fapi/v2/balance?timestamp=$TS&signature=$SIG" # where TS=$(date +%s000) SIG=$(printf 'timestamp=%s' "$TS" | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d' ' -f1)
import { createHmac } from 'node:crypto';
function signed(params, secret) {
const q = new URLSearchParams({ ...params, timestamp: Date.now() }).toString();
return `${q}&signature=${createHmac('sha256', secret).update(q).digest('hex')}`;
}
There is no /fapi/v1/time yet. Binance
publishes one and most client libraries call it at startup to measure
their clock offset. We do not serve it, so if your clock is more than
recvWindow out you will get -1021 on every
request. Check your clock first. Raising recvWindow works but
widens the window in which a captured request can be replayed.
endpoints
no credential
| endpoint | parameters | what |
|---|---|---|
GET /fapi/v1/exchangeInfo | — | The instrument catalogue: symbols, tick size, lot size, minimum notional, rate limits. Read it before you trade; the filters here are the ones that reject orders. |
GET /broker/v1/quote/{symbol} | — | Our current two-sided price. A sidecar, not a Binance path. 503 when we are not quoting that symbol, which is a real state and not an error to retry through. |
read
| endpoint | parameters | what |
|---|---|---|
GET /fapi/v2/account | — | Balances, margin and open positions in one response. |
GET /fapi/v2/balance | — | Balance per asset. |
GET /fapi/v2/positionRisk | symbol optional | Open positions with entry price, liquidation price and leverage. |
GET /fapi/v1/order | symbol required; orderId or origClientOrderId | One order. -2013 if it does not exist. |
GET /fapi/v1/openOrders | symbol optional | Orders still resting. An unlisted symbol is an error, not an empty list. |
GET /fapi/v1/allOrders | symbol required; orderId, startTime, endTime, limit optional | Order history. |
GET /fapi/v1/userTrades | symbol, startTime, endTime, limit optional | Your fills, with the commission charged on each. |
GET /fapi/v1/income | symbol, incomeType, startTime, endTime, limit optional | Everything that moved your balance other than a fill: funding, commission, realised P&L, transfers. |
trade
| endpoint | parameters | what |
|---|---|---|
POST /fapi/v1/order | symbol, side, type, quantity required; price, stopPrice, timeInForce, reduceOnly, newClientOrderId as the type needs them | Place an order. |
DELETE /fapi/v1/order | symbol required; orderId or origClientOrderId | Cancel one order. |
DELETE /fapi/v1/allOpenOrders | symbol required | Cancel every resting order on that symbol. Answers success even when nothing was open. |
POST /fapi/v1/leverage | symbol, leverage | Set leverage for that symbol. Sticky per symbol. -2019 if lowering it would leave you short of margin. |
POST /fapi/v1/marginType | symbol, marginType = ISOLATED | CROSSED | Set margin mode. -4047 if the symbol has an open position or order; -4046 if it is already that mode. |
Send newClientOrderId. Binance has no
request-id parameter, so we use yours as one: retrying a placement that
timed out with the same id returns the original order instead of opening
a second position. Without it, a retry is a new order — which is
Binance's behaviour too, and the reason this is worth saying.
transfer
| endpoint | parameters | what |
|---|---|---|
POST /broker/v1/transfer | amount > 0, direction = IN | OUT; requestId optional | Move money in or out. A sidecar, not a Binance path. Pass your own requestId to make a retry idempotent. |
operator
House endpoints. They need an operate key, which a client
account cannot create — listed so the surface is complete, not because
you can call them.
| endpoint | what |
|---|---|
GET /broker/v1/exposure | Net exposure per instrument. |
GET /broker/v1/report/pnl | P&L attribution. |
GET /broker/v1/report/risk | Per-client risk rows. |
GET /broker/v1/venue-margin | Margin held at each hedge venue. |
GET /broker/v1/hedge/live | Whether this process sends real orders to a venue, and the state of its budget. |
POST /broker/v1/hedge/live/arm | Arm live hedging, for a limited time. |
POST /broker/v1/hedge/live/kill | Stop sending anything to a venue, now. |
errors
Binance's codes, with Binance's meanings, so an existing client's error
branch needs no change. Every failure is { "code": …, "msg": … }.
| code | meaning |
|---|---|
-1003 | Too many requests. Sent with Retry-After in seconds. |
-1013 | Filter failure — tick size, lot size or minimum notional. See exchangeInfo. |
-1021 | timestamp outside recvWindow, ahead of our clock, or a signature replayed after its window passed. |
-1022 | The signature did not verify. Distinct from -2015 on purpose: a wrong signature and a key that may not do this are different problems. |
-1102 | A mandatory parameter was missing, empty or malformed. |
-1111 | Too many decimal places for this asset. |
-1116 / -1117 | Invalid type / invalid side. |
-1121 | Invalid symbol. |
-1122 | We are not quoting that symbol right now. A state, not a fault — our reference price is stale and we will not deal blind. |
-2010 | New order rejected. |
-2011 / -2013 | Unknown order on cancel / order does not exist on query. |
-2015 | Invalid key, address not allowed, or the key lacks the permission. |
-2019 | Margin is insufficient — you cannot afford this. |
-2021 | The order would trigger immediately. |
-2022 | reduceOnly rejected. |
-2027 | Exceeded the maximum position at this leverage. Not a collateral problem: depositing more will not help, so reduce size. |
-4003 / -4005 | Quantity below zero / above the maximum. |
-4028 | That leverage is not valid for this symbol. |
-4046 / -4047 | Margin type already set / cannot be changed while a position or order is open. |
-4131 | Requote. The price moved past what we quoted; send it again. |
-4141 | Symbol closed — halted or delisted. Not a scheduled session break. |
where we differ from Binance
- We are the counterparty. There is no order book of other clients and no public trade tape, so there is no
/fapi/v1/depthor/fapi/v1/trades./broker/v1/quote/{symbol}is our price. - Anything of ours that is not in Binance's API lives under
/broker/v1/. We add no fields to a/fapi/response, so a strict client will not trip over them. - No
/fapi/v1/timeyet. - No websocket user stream yet. Poll
/fapi/v2/positionRiskand/fapi/v1/userTrades.