Crear y autenticar cuenta en Binance API

Lectura
20 min~6 min lectura

Concepto clave

La API de Binance es la interfaz programática que permite a tu código interactuar directamente con los servidores de Binance para ejecutar operaciones de trading, consultar datos de mercado y gestionar tu cuenta. Piensa en ella como el control remoto digital de tu cuenta de trading: en lugar de hacer clic en la interfaz web, envías comandos estructurados que la plataforma interpreta y ejecuta automáticamente.

La autenticación mediante API Key y Secret Key funciona como un sistema de credenciales de doble factor para aplicaciones. La API Key identifica tu aplicación (similar a un nombre de usuario), mientras que el Secret Key firma digitalmente cada solicitud para probar que eres el propietario legítimo (como una firma única en cada transacción). Esta combinación garantiza que solo tu código autorizado pueda operar con tus fondos, manteniendo la seguridad incluso si la API Key se expone.

Cómo funciona en la práctica

El proceso completo para comenzar a operar programáticamente consta de estos pasos:

  1. Crear una cuenta en Binance.com (si no la tienes) y habilitar la autenticación de dos factores (2FA) para seguridad básica.
  2. Acceder al API Management desde el dashboard de usuario y generar un nuevo par de claves.
  3. Configurar permisos específicos: solo lectura, trading, o retiros (recomendado: empezar con trading sin retiros).
  4. Implementar la lógica de firma en tu código Python usando HMAC SHA256.
  5. Probar la conexión con endpoints públicos primero, luego con endpoints privados usando tus claves.

Un detalle crítico: Binance ofrece dos tipos de APIs - Spot API para trading regular y Futures API para derivados. Cada una requiere su propio conjunto de claves y tiene endpoints diferentes. Para este curso, nos enfocaremos en Spot API, que es donde la mayoría de los bots algorítmicos comienzan.

Código en acción

Antes de usar claves reales, prueba con endpoints públicos para verificar tu configuración:

import requests
import hashlib
import hmac
import time
from urllib.parse import urlencode

# Configuración básica (NO uses estas claves, son de ejemplo)
API_KEY = "tu_api_key_aqui"
SECRET_KEY = "tu_secret_key_aqui"
BASE_URL = "https://api.binance.com"

# 1. Prueba de conexión con endpoint público
def test_public_connection():
    endpoint = "/api/v3/ping"
    response = requests.get(BASE_URL + endpoint)
    print(f"Conexión pública: {response.status_code}")
    return response.status_code == 200

# 2. Solicitud autenticada para información de cuenta
def get_account_info():
    endpoint = "/api/v3/account"
    timestamp = int(time.time() * 1000)
    
    # Parámetros requeridos
    params = {
        "timestamp": timestamp,
        "recvWindow": 5000  # Ventana de recepción de 5 segundos
    }
    
    # Crear firma
    query_string = urlencode(params)
    signature = hmac.new(
        SECRET_KEY.encode('utf-8'),
        query_string.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    
    params["signature"] = signature
    
    # Headers con API Key
    headers = {
        "X-MBX-APIKEY": API_KEY
    }
    
    response = requests.get(
        BASE_URL + endpoint,
        params=params,
        headers=headers
    )
    
    if response.status_code == 200:
        return response.json()
    else:
        print(f"Error: {response.status_code}, {response.text}")
        return None

if __name__ == "__main__":
    if test_public_connection():
        print("Conexión pública exitosa")
        # Descomenta cuando tengas claves reales
        # account_info = get_account_info()
        # if account_info:
        #     print(f"Saldo total: {account_info.get('totalWalletBalance', 'N/A')}")
    else:
        print("Fallo en conexión pública")

Después de verificar que funciona, refactoriza para mejor mantenibilidad:

class BinanceAPIClient:
    def __init__(self, api_key, secret_key, base_url="https://api.binance.com"):
        self.api_key = api_key
        self.secret_key = secret_key
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({"X-MBX-APIKEY": self.api_key})
    
    def _generate_signature(self, params):
        query_string = urlencode(params)
        return hmac.new(
            self.secret_key.encode('utf-8'),
            query_string.encode('utf-8'),
            hashlib.sha256
        ).hexdigest()
    
    def _add_timestamp(self, params):
        params["timestamp"] = int(time.time() * 1000)
        if "recvWindow" not in params:
            params["recvWindow"] = 5000
        return params
    
    def private_request(self, method, endpoint, params=None):
        if params is None:
            params = {}
        
        params = self._add_timestamp(params)
        params["signature"] = self._generate_signature(params)
        
        url = self.base_url + endpoint
        
        if method.upper() == "GET":
            response = self.session.get(url, params=params)
        elif method.upper() == "POST":
            response = self.session.post(url, data=params)
        else:
            raise ValueError(f"Método no soportado: {method}")
        
        if response.status_code != 200:
            raise Exception(f"API Error: {response.status_code} - {response.text}")
        
        return response.json()
    
    def get_account_balance(self):
        """Obtiene el balance total de la cuenta"""
        data = self.private_request("GET", "/api/v3/account")
        balances = {}
        for asset in data["balances"]:
            if float(asset["free"]) > 0 or float(asset["locked"]) > 0:
                balances[asset["asset"]] = {
                    "free": float(asset["free"]),
                    "locked": float(asset["locked"])
                }
        return balances

# Uso mejorado
# client = BinanceAPIClient(API_KEY, SECRET_KEY)
# balances = client.get_account_balance()
# print(f"Balances activos: {list(balances.keys())}")

Errores comunes

  • Timestamp desincronizado: Si la hora de tu servidor difiere más de 1 minuto de Binance, todas las solicitudes fallarán. Solución: Usa NTP o sincroniza con time.time() * 1000 como en el ejemplo.
  • Firma incorrecta por codificación: No encodes el query_string dos veces o uses codificación diferente a UTF-8. El parámetro signature debe ser el último en la URL.
  • Permisos insuficientes: Generar claves solo con permiso de lectura cuando necesitas trading. Verifica en API Management que tengas "Enable Trading" activado.
  • Exponer el Secret Key: Nunca lo incluyas en código versionado. Usa variables de entorno o archivos de configuración seguros.
  • Ignorar rate limits: Binance impone límites por IP y por API Key. Implementa retry logic con backoff exponencial para evitar bans temporales.

Checklist de dominio

  1. ✓ Tengo una cuenta Binance con 2FA activado y he generado API Keys con permisos de trading
  2. ✓ Puedo conectarme a endpoints públicos (como /api/v3/ping) sin errores
  3. ✓ He implementado correctamente la firma HMAC SHA256 para solicitudes privadas
  4. ✓ Mi código puede obtener información de cuenta (balances) usando mis claves reales
  5. ✓ He configurado variables de entorno para las claves, no las tengo hardcodeadas
  6. ✓ Entiendo la diferencia entre Spot API y Futures API, y cuál estoy usando
  7. ✓ He probado manejo de errores para status codes comunes (429, 418, 401)

Implementa un cliente robusto de Binance API con manejo de errores

En este ejercicio, crearás una clase Python completa para interactuar con Binance API que incluya manejo robusto de errores y características de seguridad.

  1. Configuración inicial: Crea un archivo binance_client.py y configura tus claves de API usando variables de entorno (os.getenv). No hardcodees las claves.
  2. Clase base: Implementa la clase BinanceTradingClient con métodos para:
    • test_connectivity() - Prueba endpoints públicos
    • get_exchange_info() - Obtiene información del exchange (símbolos, límites)
    • get_account_balance() - Devuelve balances filtrados (solo activos con fondos)
  3. Manejo de errores: Añade decorador o método que maneje:
    • Errores de red (timeout, conexión)
    • Rate limiting (código 429) con retry automático
    • Errores de autenticación (401) con mensaje claro
  4. Característica avanzada: Implementa place_test_order() que use el endpoint POST /api/v3/order/test para verificar órdenes sin ejecutarlas realmente.
  5. Pruebas: Crea un script test_client.py que demuestre todas las funcionalidades con datos reales (usa claves con permisos de trading).
Pistas
  • Usa el patrón de retry con backoff exponencial para rate limits (429). La librería 'tenacity' puede ayudar si la implementas manualmente.
  • Para el endpoint de test order, recuerda que necesita parámetros como symbol, side, type, quantity. Consulta la documentación oficial de Binance.
  • Considera implementar un decorador @handle_binance_errors que envuelva tus métodos y centralice el manejo de excepciones.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.