El camino más corto para empezar con la API Spot de Binance es: una vez que tengas tu API Key + Secret, primero llama a /api/v3/ping para verificar la conectividad, luego usa /api/v3/time para sincronizar la hora del servidor y, finalmente, obtén tu saldo a través de /api/v3/account (interfaz firmada) para confirmar que tus permisos son correctos. Puedes completar tu primera orden en unos 10 minutos. Este artículo proporciona código completo en curl y Python para cada paso, utilizando la dirección real https://api.binance.com. Si aún no tienes tus claves API, completa primero el KYC en el sitio oficial de Binance; si no tienes cuenta, puedes registrarte gratis.
I. Niveles de las interfaces de la API Spot
La API REST de Binance Spot se divide en tres categorías según su nivel de autenticación:
| Categoría | Ejemplo de prefijo de endpoint | ¿Requiere firma? | Requisito de Header | Interfaz típica |
|---|---|---|---|---|
| NONE | /api/v3/ping, /api/v3/time | No | Ninguno | Hora del servidor, estado del sistema |
| MARKET_DATA | /api/v3/depth, /api/v3/klines | No | Ninguno | Mercado, profundidad, velas (K-lines) |
| USER_DATA | /api/v3/account, /api/v3/order | Sí | X-MBX-APIKEY + signature | Órdenes, cancelaciones, saldo |
| TRADE | /api/v3/order (POST) | Sí | X-MBX-APIKEY + signature | Compra y venta |
| USER_STREAM | /api/v3/userDataStream | Solo API Key | X-MBX-APIKEY | WebSocket listenKey |
Las interfaces autenticadas deben incluir signature=<firma HMAC-SHA256> al final de los parámetros de consulta y llevar el X-MBX-APIKEY en el encabezado de la solicitud.
II. Preparación del entorno y prueba de conectividad
1. Instalar dependencias
# Python 3.8+
pip install requests python-dotenv
# O usar el SDK oficial
pip install python-binance
2. Elección de la URL base
Binance Spot ofrece varios espejos; se recomienda usar api.binance.com en el código y recurrir a api-gcp.binance.com en caso de fallo:
ENDPOINTS = [
"https://api.binance.com", # Predeterminado
"https://api-gcp.binance.com", # Línea de Google Cloud
"https://api1.binance.com",
"https://api2.binance.com",
"https://api3.binance.com",
]
3. Primera solicitud: ping
curl -X GET "https://api.binance.com/api/v3/ping"
# Un retorno de {} significa que hay conexión
4. Sincronizar hora del servidor
curl -X GET "https://api.binance.com/api/v3/time"
# {"serverTime":1713027384562}
Si la diferencia entre tu hora local y serverTime supera los 1000ms, las interfaces firmadas darán el error -1021. Los servidores de trading deben tener activado NTP.
III. Consultar saldo de la cuenta (interfaz firmada)
Aquí tienes un ejemplo de Python listo para ejecutar que maneja la firma, los reintentos y el desfase de tiempo:
import hmac, hashlib, time, requests
from urllib.parse import urlencode
API_KEY = "TU_API_KEY"
SECRET_KEY = "TU_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)
# Llamada
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']} (Bloqueado {b['locked']})")
Ejemplo de estructura de respuesta:
{
"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"}
]
}
IV. Consultar mercado y velas (interfaces públicas)
Las interfaces de mercado no requieren firma, pero tienen límites de peso:
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")) # Ejemplo: 68420.12
Consejo de rendimiento: usar /ticker/price para un solo precio tiene un peso de 1; usar /ticker/24hr para todos los pares tiene un peso de 40, lo cual ahorra un 99% de peso comparado con un bucle individual.
V. Colocación y cancelación de órdenes (interfaz TRADE)
El endpoint para órdenes spot es POST /api/v3/order. Los parámetros obligatorios varían según el type:
1. Orden Límite (LIMIT)
def place_limit_order(symbol: str, side: str, quantity: float, price: float):
return _request("POST", "/api/v3/order", {
"symbol": symbol,
"side": side, # BUY o 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. Orden de Mercado (MARKET)
Las órdenes de mercado se pueden realizar por cantidad (quantity) o monto (quoteOrderQty):
# Comprar por cantidad de BTC (consumirá el USDT correspondiente)
_request("POST", "/api/v3/order", {
"symbol": "BTCUSDT",
"side": "BUY",
"type": "MARKET",
"quantity": 0.001
}, signed=True)
# Comprar por monto en USDT (más común para evitar variaciones de precio)
_request("POST", "/api/v3/order", {
"symbol": "BTCUSDT",
"side": "BUY",
"type": "MARKET",
"quoteOrderQty": 100 # Comprar 100 USDT de BTC
}, signed=True)
3. Consultar estado de una orden
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"] puede ser NEW / PARTIALLY_FILLED / FILLED / CANCELED / REJECTED
4. Cancelar orden
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)
VI. Probar en la Testnet (evita errores con dinero real)
Binance ofrece una Spot Testnet independiente con monedas de prueba gratuitas:
# Configuración de Testnet
BASE_URL = "https://testnet.binance.vision"
# El API Key debe registrarse por separado en testnet.binance.vision
El comportamiento de órdenes y saldos en la Testnet simula perfectamente la red principal (Mainnet), aunque los precios no estarán sincronizados. Se recomienda probar todo código nuevo en Testnet durante 24 horas antes de pasar a Mainnet.
VII. Preguntas frecuentes (FAQ)
P1: ¿Por qué recibo el error filter failure: LOT_SIZE al colocar una orden?
R: La cantidad no cumple con el stepSize (paso mínimo) del par. Por ejemplo, si el stepSize de BTCUSDT es 0.00001, no puedes pedir 0.000005. Consulta las reglas de LOT_SIZE / MIN_NOTIONAL / PRICE_FILTER llamando a /api/v3/exchangeInfo.
P2: ¿La API Spot admite cancelar todas las órdenes abiertas a la vez?
R: Sí. DELETE /api/v3/openOrders?symbol=BTCUSDT cancelará todas las órdenes no ejecutadas de ese par con un peso de 1. No admite cancelaciones masivas entre diferentes pares en una sola llamada.
P3: ¿Cómo realizo órdenes por lotes (batch)?
R: Spot no tiene una interfaz nativa de órdenes por lotes; puedes llamar a POST /api/v3/order varias veces de forma concurrente, respetando el límite de 100 órdenes cada 10 segundos. En cambio, Futuros sí tiene /fapi/v1/batchOrders.
P4: ¿Qué estrategias puedo usar combinando SIDE y type?
R: Los tipos principales son LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER. Las órdenes de stop loss o take profit requieren el parámetro adicional stopPrice.
P5: ¿Es suficiente que la consulta de historial devuelva 500 registros?
R: /api/v3/allOrders devuelve 500 por defecto, pero puedes paginar el historial usando los parámetros startTime/endTime/fromId. Para trading intensivo, se recomienda usar el WebSocket userDataStream para recibir cambios de órdenes en tiempo real y ahorrar peso de API.
Para más contenido sobre APIs de Futuros, vuelve a la lista completa en la categoría «Integración API» de nuestra navegación por categorías.