API Integration

How to Use Binance Spot API? Executable Code from Zero to Your First Order

A complete introduction to Binance Spot REST API: endpoint list, authentication mechanism, balance query, market/limit order placement, order status query, and cancellation examples in Python and curl, covering all essential endpoints.

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.

Keep reading

Still have Binance questions? Head back to the category page for more tutorials on the same topic.

Categories

Related tutorials

How to Apply for Binance API? Common Guide for Key Generation and Signatures 2026-04-14 What are the Differences Between Binance Futures and Spot APIs? Endpoint, Parameter, and Weight Comparison 2026-04-14 Will My IP Get Banned? Detailed Explanation of Binance API Rate Limits and Weights 2026-04-14 How to Subscribe to Binance WebSocket Market Data? Single vs. Combined Stream Code 2026-04-14