Introduction to Binance API
The Binance API provides developers with programmatic access to Binance's trading platform, allowing them to build trading bots, applications, and tools that interact with the exchange. This tutorial will guide you through the process of using the Binance API, from setting up authentication to making various types of requests.
While many developers have traditionally relied on Postman for API testing, Apidog offers a more streamlined and specialized experience for working with cryptocurrency APIs like Binance. With its intuitive interface, enhanced authentication handling, and built-in crypto-specific features, Apidog significantly reduces the setup time needed to begin testing and implementing Binance API endpoints.

The platform's real-time collaboration tools and comprehensive documentation generation capabilities make it particularly valuable for teams working on crypto trading applications.

If you're serious about efficient Binance API integration, making the switch to Apidog will notably improve your development workflow and reduce time-to-deployment for your crypto projects.
Setting Up Binance API Authentication
Before using the Binance API, you need to create API keys from your Binance account. This section covers how to set up and secure your API keys.
Creating Binance API Keys
- Log in to your Binance account
- Navigate to "API Management" in your account settings
- Create a new API key
- Note down your API key and secret key
- Configure restrictions (IP whitelisting, trading permissions, etc.)
Types of API Keys Supported by Binance API
Binance supports three types of API key authentication methods:
- HMAC Keys - The most common authentication method
- RSA Keys - Offers enhanced security features
- Ed25519 Keys - Provides the best performance and security
HMAC Authentication Example
Here's how to authenticate with HMAC keys:
import hmac
import hashlib
import time
import requests
from urllib.parse import urlencode
# API credentials
api_key = 'your_api_key'
api_secret = 'your_api_secret'
# Base URL for Binance API
base_url = '<https://api.binance.com>'
# Function to create a signature for authenticated endpoints
def get_signature(query_string):
return hmac.new(
api_secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
# Example request to get account information
def get_account():
endpoint = '/api/v3/account'
timestamp = int(time.time() * 1000)
params = {
'timestamp': timestamp,
'recvWindow': 5000 # Optional parameter
}
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.get(url, headers=headers)
return response.json()
# Call the function
account_info = get_account()
print(account_info)
Understanding Binance API Endpoints
The Binance API is organized into several categories of endpoints based on their functionality.
General Binance API Endpoints
These endpoints provide general information about the exchange:
# Test connectivity
def test_connectivity():
endpoint = '/api/v3/ping'
url = f"{base_url}{endpoint}"
response = requests.get(url)
return response.json()
# Get server time
def get_server_time():
endpoint = '/api/v3/time'
url = f"{base_url}{endpoint}"
response = requests.get(url)
return response.json()
# Get exchange information
def get_exchange_info():
endpoint = '/api/v3/exchangeInfo'
url = f"{base_url}{endpoint}"
response = requests.get(url)
return response.json()
Market Data Binance API Endpoints
These endpoints provide access to market data:
# Get order book for a symbol
def get_order_book(symbol, limit=100):
endpoint = '/api/v3/depth'
params = {
'symbol': symbol,
'limit': limit
}
url = f"{base_url}{endpoint}?{urlencode(params)}"
response = requests.get(url)
return response.json()
# Get recent trades
def get_recent_trades(symbol, limit=500):
endpoint = '/api/v3/trades'
params = {
'symbol': symbol,
'limit': limit
}
url = f"{base_url}{endpoint}?{urlencode(params)}"
response = requests.get(url)
return response.json()
# Get candlestick data
def get_klines(symbol, interval, start_time=None, end_time=None, limit=500):
endpoint = '/api/v3/klines'
params = {
'symbol': symbol,
'interval': interval,
'limit': limit
}
if start_time:
params['startTime'] = start_time
if end_time:
params['endTime'] = end_time
url = f"{base_url}{endpoint}?{urlencode(params)}"
response = requests.get(url)
# Format the response
klines = response.json()
formatted_klines = []
for k in klines:
formatted_klines.append({
'open_time': k[0],
'open': float(k[1]),
'high': float(k[2]),
'low': float(k[3]),
'close': float(k[4]),
'volume': float(k[5]),
'close_time': k[6],
'quote_volume': float(k[7]),
'trades': k[8],
'taker_buy_base_volume': float(k[9]),
'taker_buy_quote_volume': float(k[10])
})
return formatted_klines
Trading with Binance API
The trading endpoints allow you to place and manage orders.
Placing Orders with Binance API
Here's how to place different types of orders:
# Place a LIMIT order
def place_limit_order(symbol, side, quantity, price):
endpoint = '/api/v3/order'
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'side': side, # 'BUY' or 'SELL'
'type': 'LIMIT',
'timeInForce': 'GTC', # Good Till Canceled
'quantity': quantity,
'price': price,
'timestamp': timestamp,
'recvWindow': 5000
}
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.post(url, headers=headers)
return response.json()
# Place a MARKET order
def place_market_order(symbol, side, quantity):
endpoint = '/api/v3/order'
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'side': side, # 'BUY' or 'SELL'
'type': 'MARKET',
'quantity': quantity,
'timestamp': timestamp,
'recvWindow': 5000
}
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.post(url, headers=headers)
return response.json()
# Place a STOP_LOSS order
def place_stop_loss_order(symbol, side, quantity, stop_price):
endpoint = '/api/v3/order'
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'side': side,
'type': 'STOP_LOSS',
'quantity': quantity,
'stopPrice': stop_price,
'timestamp': timestamp,
'recvWindow': 5000
}
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.post(url, headers=headers)
return response.json()
Managing Orders with Binance API
Here's how to query, cancel, and track orders:
# Query order status
def query_order(symbol, order_id=None, orig_client_order_id=None):
endpoint = '/api/v3/order'
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'timestamp': timestamp,
'recvWindow': 5000
}
if order_id:
params['orderId'] = order_id
elif orig_client_order_id:
params['origClientOrderId'] = orig_client_order_id
else:
raise ValueError("Either order_id or orig_client_order_id must be provided")
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.get(url, headers=headers)
return response.json()
# Cancel an order
def cancel_order(symbol, order_id=None, orig_client_order_id=None):
endpoint = '/api/v3/order'
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'timestamp': timestamp,
'recvWindow': 5000
}
if order_id:
params['orderId'] = order_id
elif orig_client_order_id:
params['origClientOrderId'] = orig_client_order_id
else:
raise ValueError("Either order_id or orig_client_order_id must be provided")
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.delete(url, headers=headers)
return response.json()
# Get all open orders
def get_open_orders(symbol=None):
endpoint = '/api/v3/openOrders'
timestamp = int(time.time() * 1000)
params = {
'timestamp': timestamp,
'recvWindow': 5000
}
if symbol:
params['symbol'] = symbol
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.get(url, headers=headers)
return response.json()
Account and User Data with Binance API
These endpoints allow you to access account information and stream user data.
Account Information with Binance API
# Get account information
def get_account_information():
endpoint = '/api/v3/account'
timestamp = int(time.time() * 1000)
params = {
'timestamp': timestamp,
'recvWindow': 5000
}
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.get(url, headers=headers)
return response.json()
# Get account trade list
def get_account_trades(symbol, start_time=None, end_time=None, limit=500):
endpoint = '/api/v3/myTrades'
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'timestamp': timestamp,
'limit': limit,
'recvWindow': 5000
}
if start_time:
params['startTime'] = start_time
if end_time:
params['endTime'] = end_time
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.get(url, headers=headers)
return response.json()
User Data Streams with Binance API
# Start a user data stream
def start_user_data_stream():
endpoint = '/api/v3/userDataStream'
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.post(f"{base_url}{endpoint}", headers=headers)
return response.json()
# Keep alive a user data stream
def keep_alive_user_data_stream(listen_key):
endpoint = '/api/v3/userDataStream'
params = {
'listenKey': listen_key
}
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.put(f"{base_url}{endpoint}?{urlencode(params)}", headers=headers)
return response.json()
# Close a user data stream
def close_user_data_stream(listen_key):
endpoint = '/api/v3/userDataStream'
params = {
'listenKey': listen_key
}
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.delete(f"{base_url}{endpoint}?{urlencode(params)}", headers=headers)
return response.json()
Advanced Binance API Features
This section covers some of the more advanced features of the Binance API.
Working with Order Lists (OCO) in Binance API
One-Cancels-the-Other (OCO) orders allow you to place a pair of orders where if one gets triggered, the other is automatically canceled:
# Place an OCO order
def place_oco_order(symbol, side, quantity, price, stop_price):
endpoint = '/api/v3/orderList/oco'
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'side': side,
'quantity': quantity,
'price': price,
'stopPrice': stop_price,
'timestamp': timestamp,
'recvWindow': 5000
}
# Define the types for the OCO order based on side
if side == 'SELL':
params['aboveType'] = 'STOP_LOSS'
params['belowType'] = 'LIMIT_MAKER'
else:
params['aboveType'] = 'LIMIT_MAKER'
params['belowType'] = 'STOP_LOSS'
params['aboveTimeInForce'] = 'GTC'
params['belowTimeInForce'] = 'GTC'
query_string = urlencode(params)
signature = get_signature(query_string)
url = f"{base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': api_key
}
response = requests.post(url, headers=headers)
return response.json()
Handling Rate Limits in Binance API
Binance applies rate limits to API requests. Here's how to handle them:
import time
from functools import wraps
# Decorator to handle rate limits
def handle_rate_limit(max_retries=3, retry_delay=30):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
retries = 0
while retries <= max_retries:
try:
response = func(*args, **kwargs)
if 'code' in response and response['code'] == -1429: # Rate limit exceeded
retries += 1
if retries > max_retries:
raise Exception(f"Rate limit exceeded after {max_retries} retries")
print(f"Rate limit exceeded. Waiting {retry_delay} seconds before retry...")
time.sleep(retry_delay)
else:
return response
except Exception as e:
if "429" in str(e) or "418" in str(e):
retries += 1
if retries > max_retries:
raise
print(f"Rate limit exceeded. Waiting {retry_delay} seconds before retry...")
time.sleep(retry_delay)
else:
raise
return wrapper
return decorator
# Example usage
@handle_rate_limit()
def get_exchange_info_with_retry():
endpoint = '/api/v3/exchangeInfo'
url = f"{base_url}{endpoint}"
response = requests.get(url)
return response.json()
Building a Complete Binance API Trading Bot
Now let's put everything together to build a simple trading bot:
import hmac
import hashlib
import time
import requests
import json
import websocket
import threading
from urllib.parse import urlencode
class BinanceTrader:
def __init__(self, api_key, api_secret, symbol='BTCUSDT'):
self.api_key = api_key
self.api_secret = api_secret
self.base_url = '<https://api.binance.com>'
self.symbol = symbol
self.ws = None
self.listen_key = None
self.keep_alive_thread = None
def get_signature(self, query_string):
return hmac.new(
self.api_secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
def get_server_time(self):
endpoint = '/api/v3/time'
response = requests.get(f"{self.base_url}{endpoint}")
return response.json()['serverTime']
def get_account_info(self):
endpoint = '/api/v3/account'
timestamp = int(time.time() * 1000)
params = {
'timestamp': timestamp,
'recvWindow': 5000
}
query_string = urlencode(params)
signature = self.get_signature(query_string)
url = f"{self.base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': self.api_key
}
response = requests.get(url, headers=headers)
return response.json()
def place_market_order(self, side, quantity):
endpoint = '/api/v3/order'
timestamp = int(time.time() * 1000)
params = {
'symbol': self.symbol,
'side': side,
'type': 'MARKET',
'quantity': quantity,
'timestamp': timestamp,
'recvWindow': 5000
}
query_string = urlencode(params)
signature = self.get_signature(query_string)
url = f"{self.base_url}{endpoint}?{query_string}&signature={signature}"
headers = {
'X-MBX-APIKEY': self.api_key
}
response = requests.post(url, headers=headers)
return response.json()
def start_user_data_stream(self):
endpoint = '/api/v3/userDataStream'
headers = {
'X-MBX-APIKEY': self.api_key
}
response = requests.post(f"{self.base_url}{endpoint}", headers=headers)
self.listen_key = response.json()['listenKey']
return self.listen_key
def keep_alive_user_data_stream(self):
while True:
if self.listen_key:
endpoint = '/api/v3/userDataStream'
params = {
'listenKey': self.listen_key
}
headers = {
'X-MBX-APIKEY': self.api_key
}
requests.put(f"{self.base_url}{endpoint}?{urlencode(params)}", headers=headers)
time.sleep(30 * 60) # Keep alive every 30 minutes
def on_message(self, ws, message):
data = json.loads(message)
# Handle account updates
if data.get('e') == 'outboundAccountPosition':
print("Account update received:")
print(f"Update time: {data['u']}")
print("Balances:")
for balance in data['B']:
print(f"Asset: {balance['a']}, Free: {balance['f']}, Locked: {balance['l']}")
# Handle order updates
elif data.get('e') == 'executionReport':
print("Order update received:")
print(f"Symbol: {data['s']}")
print(f"Side: {data['S']}")
print(f"Order type: {data['o']}")
print(f"Order status: {data['X']}")
print(f"Price: {data['p']}")
print(f"Quantity: {data['q']}")
print(f"Executed quantity: {data['z']}")
# Implement trading logic here based on order updates
if data['X'] == 'FILLED' and data['S'] == 'BUY':
# Example: Place a sell order when buy is filled
sell_price = float(data['p']) * 1.05 # 5% profit target
self.place_limit_order('SELL', data['q'], sell_price)
def on_error(self, ws, error):
print(f"Error: {error}")
def on_close(self, ws, close_status_code, close_msg):
print("WebSocket connection closed")
def on_open(self, ws):
print("WebSocket connection opened")
def start_websocket(self):
self.start_user_data_stream()
socket_url = f"wss://stream.binance.com:9443/ws/{self.listen_key}"
self.ws = websocket.WebSocketApp(
socket_url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close,
on_open=self.on_open
)
# Start keep-alive thread
self.keep_alive_thread = threading.Thread(target=self.keep_alive_user_data_stream)
self.keep_alive_thread.daemon = True
self.keep_alive_thread.start()
# Run the WebSocket in a separate thread
ws_thread = threading.Thread(target=self.ws.run_forever)
ws_thread.daemon = True
ws_thread.start()
return ws_thread
# Example usage
if __name__ == "__main__":
api_key = "your_api_key"
api_secret = "your_api_secret"
trader = BinanceTrader(api_key, api_secret, 'BTCUSDT')
# Get account information
account_info = trader.get_account_info()
print("Account Information:")
print(f"Can Trade: {account_info['canTrade']}")
print(f"Can Withdraw: {account_info['canWithdraw']}")
print(f"Can Deposit: {account_info['canDeposit']}")
# Print balances
print("\\\\nBalances:")
for balance in account_info['balances']:
if float(balance['free']) > 0 or float(balance['locked']) > 0:
print(f"Asset: {balance['asset']}, Free: {balance['free']}, Locked: {balance['locked']}")
# Start the WebSocket for real-time updates
ws_thread = trader.start_websocket()
try:
# Keep the main thread running
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Stopping...")
trader.ws.close()
Best Practices for Using Binance API
Here are some best practices to follow when working with the Binance API:
Security Practices for Binance API
- Restrict API Key Permissions: Only enable the permissions you need (e.g., read-only, trading, withdrawals)
- Whitelist IP Addresses: Restrict your API keys to only work from specific IP addresses
- Secure API Key Storage: Never hardcode API keys in your code, use environment variables or secure vaults
- Regular Key Rotation: Change your API keys periodically to mitigate risk
import os
# Load API keys from environment variables
api_key = os.environ.get('BINANCE_API_KEY')
api_secret = os.environ.get('BINANCE_API_SECRET')
if not api_key or not api_secret:
raise ValueError("API keys not found in environment variables")
Error Handling with Binance API
Implement robust error handling to deal with API errors and connection issues:
def safe_request(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
response = func(*args, **kwargs)
# Check for API error codes
if isinstance(response, dict) and 'code' in response:
print(f"API Error: Code {response['code']}, Message: {response.get('msg', 'No message')}")
# Handle specific error codes
if response['code'] == -1021: # INVALID_TIMESTAMP
print("Server and local time are not synchronized. Adjusting timestamp...")
# Implement timestamp adjustment logic here
elif response['code'] == -2010: # INSUFFICIENT_BALANCE
print("Insufficient balance for order.")
# Add more specific error handling as needed
return response
except requests.exceptions.RequestException as e:
print(f"Request Error: {e}")
# Implement retry logic or fallback behavior
return None
except json.JSONDecodeError:
print("Failed to decode JSON response")
return None
except Exception as e:
print(f"Unexpected error: {e}")
return None
return wrapper
@safe_request
def get_account_info_safe():
# Implementation of get_account_info with proper error handling
# ...
Conclusion
The Binance API offers a powerful way to interact with the Binance exchange programmatically. This tutorial covered the essential aspects of using the API, from authentication to placing orders and managing your account. By following best practices and implementing proper error handling, you can build robust applications and trading bots that leverage Binance's extensive feature set.
Remember to keep your API keys secure, respect the rate limits, and thoroughly test your code in a test environment before using it with real funds. As Binance updates their API, make sure to stay informed about any changes to the endpoints or parameters to ensure your applications continue to function correctly.
With the knowledge gained from this tutorial, you should be well-equipped to start building your own trading tools and applications using the Binance API.