The shortest path to getting started with the Binance Spot API is: Once you have your API Key + Secret, first call /api/v3/ping to verify connectivity, then use /api/v3/time to synchronize server time, and finally pull your balance via /api/v3/account (a signed endpoint) to confirm permissions are correct. The entire process takes about 10 minutes to complete your first order. This article provides complete curl and Python code for each step, with all endpoints using the actual https://api.binance.com addresses. If you haven't prepared your API keys yet, please visit the Binance Official Website to complete KYC. If you don't have a Binance account, you can Register for Free.
1. Layering of Spot API Endpoints
The Binance Spot REST API is divided into four categories based on Authentication Level:
| Category | Endpoint Example | Signature Required | Header Requirement | Typical Interface |
|---|---|---|---|---|
| NONE | /api/v3/ping, /api/v3/time | No | None | Server time, system status |
| MARKET_DATA | /api/v3/depth, /api/v3/klines | No | None | Market price, depth, K-lines |
| USER_DATA | /api/v3/account, /api/v3/order | Yes | X-MBX-APIKEY + signature | Order, cancel, balance |
| TRADE | /api/v3/order (POST) | Yes | X-MBX-APIKEY + signature | Buy/sell order placement |
| USER_STREAM | /api/v3/userDataStream | API Key only | X-MBX-APIKEY | WebSocket listenKey |
Authenticated endpoints must append signature=<HMAC-SHA256 signature> to the end of the query parameters and include X-MBX-APIKEY in the request header.
2. Environment Preparation and Connectivity Testing
1. Install Dependencies
# Python 3.8+
pip install requests python-dotenv
# Or use the official SDK
pip install python-binance
2. Base URL Selection
Binance provides 5 mirror entries for the Spot API. It is recommended to use api.binance.com in your code, falling back to api-gcp.binance.com if it fails:
ENDPOINTS = [
"https://api.binance.com", # Default
"https://api-gcp.binance.com", # Google Cloud route
"https://api1.binance.com",
"https://api2.binance.com",
"https://api3.binance.com",
]
3. First Request: Ping
curl -X GET "https://api.binance.com/api/v3/ping"
# Returns {} indicating connectivity
4. Sync Server Time
curl -X GET "https://api.binance.com/api/v3/time"
# {"serverTime":1713027384562}
If the gap between local time and serverTime exceeds 1000ms, signed endpoints will return a -1021 error. Quant servers must have NTP enabled.
3. Query Account Balance (Signed Endpoint)
Below is a complete, runnable Python wrapper that handles signing, retries, and timestamp offsets:
import hmac, hashlib, time, requests
from urllib.parse import urlencode
API_KEY = "YOUR_API_KEY"
SECRET_KEY = "YOUR_SECRET_KEY"
BASE_URL = "https://api.binance.com"
def _sign(params: dict) -> dict:
params["timestamp"] = int(time.time() * 1000)
params["recvWindow"] = 5000
query = urlencode(params)
params["signature"] = hmac.new(
SECRET_KEY.encode(),
query.encode(),
hashlib.sha256
).hexdigest()
return params
def _request(method: str, path: str, params: dict = None, signed: bool = False):
params = params or {}
headers = {"X-MBX-APIKEY": API_KEY} if signed else {}
if signed:
params = _sign(params)
url = f"{BASE_URL}{path}"
r = requests.request(method, url, params=params, headers=headers, timeout=10)
r.raise_for_status()
return r.json()
def get_account():
return _request("GET", "/api/v3/account", signed=True)
# Calling the function
balances = get_account()["balances"]
non_zero = [b for b in balances if float(b["free"]) > 0]
for b in non_zero:
print(f"{b['asset']}: {b['free']} (Locked {b['locked']})")
Example response structure:
{
"makerCommission": 10,
"takerCommission": 10,
"canTrade": true,
"canWithdraw": true,
"canDeposit": true,
"accountType": "SPOT",
"balances": [
{"asset": "BTC", "free": "0.00123456", "locked": "0.00000000"},
{"asset": "USDT", "free": "128.45", "locked": "0.00"}
]
}
4. Query Market Price and K-lines (Public Endpoints)
Market data endpoints do not require a signature but are still subject to weight limits:
def get_price(symbol: str) -> float:
r = _request("GET", "/api/v3/ticker/price", {"symbol": symbol})
return float(r["price"])
def get_depth(symbol: str, limit: int = 20) -> dict:
return _request("GET", "/api/v3/depth", {"symbol": symbol, "limit": limit})
def get_klines(symbol: str, interval: str = "1h", limit: int = 500):
return _request("GET", "/api/v3/klines", {
"symbol": symbol,
"interval": interval, # 1m, 5m, 15m, 1h, 4h, 1d
"limit": limit
})
print(get_price("BTCUSDT")) # 68420.12
Performance Tip: Use /ticker/price (Weight 1) for a single price. Querying all symbols via /ticker/24hr (Weight 40) is 99% more efficient than looping through individual symbols.
5. Order Placement and Cancellation (TRADE Endpoint)
The endpoint for Spot order placement is POST /api/v3/order. Required parameters vary by type:
1. Limit Order (LIMIT)
def place_limit_order(symbol: str, side: str, quantity: float, price: float):
return _request("POST", "/api/v3/order", {
"symbol": symbol,
"side": side, # BUY or SELL
"type": "LIMIT",
"timeInForce": "GTC", # GTC / IOC / FOK
"quantity": quantity,
"price": price,
}, signed=True)
order = place_limit_order("BTCUSDT", "BUY", 0.001, 60000.00)
print(order["orderId"], order["status"])
2. Market Order (MARKET)
Market orders can be placed based on Quantity (quantity) or Quote Quantity (quoteOrderQty):
# Buy by BTC quantity (consumes corresponding USDT)
_request("POST", "/api/v3/order", {
"symbol": "BTCUSDT",
"side": "BUY",
"type": "MARKET",
"quantity": 0.001
}, signed=True)
# Buy by USDT amount (more common to avoid slippage issues)
_request("POST", "/api/v3/order", {
"symbol": "BTCUSDT",
"side": "BUY",
"type": "MARKET",
"quoteOrderQty": 100 # Use 100 USDT to buy BTC
}, signed=True)
3. Query Order Status
def get_order(symbol: str, order_id: int):
return _request("GET", "/api/v3/order", {
"symbol": symbol,
"orderId": order_id
}, signed=True)
status = get_order("BTCUSDT", 12345678)
# status["status"] could be NEW / PARTIALLY_FILLED / FILLED / CANCELED / REJECTED
4. Cancel Order
def cancel_order(symbol: str, order_id: int):
return _request("DELETE", "/api/v3/order", {
"symbol": symbol,
"orderId": order_id
}, signed=True)
cancel_order("BTCUSDT", 12345678)
6. Testnet First (Avoid Real Money Mistakes)
Binance provides an independent Spot Testnet where you can claim test tokens for free:
# Testnet configuration
BASE_URL = "https://testnet.binance.vision"
# API Keys must be registered separately at testnet.binance.vision
Order placement, cancellation, and balance queries on the Testnet simulate Mainnet behavior, although coin prices may not sync with the real market. It is recommended to run all new code on the Testnet for 24 hours before switching to the Mainnet.
7. FAQ
Q1: What causes the "filter failure: LOT_SIZE" error during order placement?
A: The quantity does not comply with the trading pair's stepSize. For example, if the stepSize for BTCUSDT is 0.00001, you cannot place an order for 0.000005. Call /api/v3/exchangeInfo to query the LOT_SIZE / MIN_NOTIONAL / PRICE_FILTER rules for each pair and round your values accordingly.
Q2: Does the Spot API support canceling all open orders?
A: Yes. DELETE /api/v3/openOrders?symbol=BTCUSDT will cancel all unfilled orders for that specific pair at once with a Weight of 1. However, it does not support canceling orders across multiple trading pairs in one call.
Q3: How do I perform bulk order placement at once?
A: The Spot API does not have a native bulk order endpoint. You can call POST /api/v3/order multiple times concurrently, but be aware of the limit of 100 orders per 10 seconds. The Futures API has /fapi/v1/batchOrders for up to 5 orders per call.
Q4: What strategy orders can be combined with SIDE and type?
A: Mainstream types include LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER. Stop-loss and take-profit orders require an additional stopPrice parameter.
Q5: Is returning 500 records enough when querying order history?
A: /api/v3/allOrders returns 500 records by default. You can use startTime / endTime / fromId parameters to pull history in pages. For frequent quant trading, it's better to use WebSocket userDataStream to subscribe to real-time order changes and save weight.
For more content on the Futures API, return to the Category Navigation to view the full list in the "API Integration" category.