Volver al inicio

API WB Ozon: manejo de errores 429 y 50x

El artículo describe estrategias para el manejo de errores 429 y 50x al trabajar con API de Wildberries y Ozon. Cubre lógica de reintentos con backoff, lotes diarios de solicitudes y monitoreo en segundo plano para automatización completa de recopilación de datos.

Sin errores 429 de APIs de marketplaces: código y tácticas
Advertisement 728x90

Manejo de errores 429 y 50x en APIs de Wildberries y Ozon

Al extraer datos de las APIs de Wildberries y Ozon, los desarrolladores suelen encontrarse con errores 429 (demasiadas solicitudes) y 50x (errores del servidor). Estos surgen por la alta carga en los endpoints. La solución típica del soporte técnico son los reintentos. Vamos a ver tres estrategias sólidas: manejo básico de reintentos, optimización del volumen de solicitudes y monitoreo con recargas parciales.

Manejo básico de reintentos

Empieza tratando los errores 429 y 50x como interrupciones normales. Implementa lógica de reintentos con retroceso exponencial y analiza cabeceras como X-Ratelimit-Retry. Esto reduce bloqueos y aumenta la resistencia.

Aquí va una función de ejemplo para solicitudes POST con reintentos:

Google AdInline article slot
def get_oz(url, heads, params, max_retries=5, timeout=30):
    result = {}
    for retries in range(1, max_retries + 1):  
        
        try:
            response = requests.post(url, headers=heads, json=params, timeout=timeout)
        except requests.RequestException as e:
            print(f'!!! Error de red en intento {retries}: {e}!!!')
            time.sleep(2 * retries)
            continue  
                
        # 200 significa éxito    
        if response.status_code == 200:
            return response.json()
            
        # 429 - Demasiadas solicitudes, pausa inteligente y reintento
        elif response.status_code == 429:    
            pause_time = 2 ** retries
            
            # X-Ratelimit-Retry - Truco de Wildberries, Ozon podría agregarlo algún día
            if 'X-Ratelimit-Retry' in response.headers:
                pause_time = int(response.headers['X-Ratelimit-Retry']) + 5
            print(f'get_oz: ! -Demasiadas solicitudes- en intento {retries}. Pausando {pause_time} seg')
            time.sleep(pause_time)
        
        # Errores 5xx - pausa y reintento                    
        elif 500 <= response.status_code < 600:
            pause_time = 2 ** retries
            print(f'get_oz: ! -Error {response.status_code}- en intento {retries}. Pausando {pause_time} seg')
            time.sleep(pause_time)
        
        # Cualquier otro error - ¡sal de ahí!                
        else:
            print(f'get_oz: !!! ¡Fallo al obtener datos de API! código: {response.status_code}')
            return None


    print(f'get_oz: !!! Todos los {max_retries} intentos fallaron')
  
    return None
  • 5 reintentos manejan la mayoría de cargas típicas.
  • Maneja bucles de paginación (offset/página) a un nivel superior.
  • En fallo total, retrocede una hora o más.

Esto encaja perfectamente en cualquier pipeline ETL para APIs.

Optimización del volumen de datos

Solicitudes grandes (como transacciones de una semana) provocan errores en páginas posteriores de paginación. Divídelas en lotes pequeños e independientes: por día, categoría o filtros. Guarda cada lote en tu base de datos de inmediato — perder uno no borra tu progreso.

Ventajas:

Google AdInline article slot
  • Menos páginas por solicitud (1–3 vs. 20).
  • Reintentos independientes por lote.
  • Guardados parciales en fallos.

Ejemplo: Carga de transacciones de Ozon por día:

date_from = today() - timedelta(days=7)
date_to = today() - timedelta(days=1)
current_date = date_from
delta = timedelta(days=1)

# Bucle por días desde date_from hasta date_to
while current_date <= date_to:  
    transactions_oneday = pd.DataFrame([])           
    url = "https://api-seller.ozon.ru/v3/finance/transaction/list"
    ipage = 1
    all_pages_data = []
    while True:
        data = {
            "filter": {
                "date": {
                    "from": str(current_date) + "T00:00:00.000Z",
                    "to": str(current_date) + "T23:59:59.999Z"
                }
            },
            "page": ipage,
            "page_size": 1000
            }
        dd = []
        apioz_response = get_oz(url, headers, data, 5)
        if len(apioz_response) > 0 :
            dd = apioz_response['result']['operations']
            all_pages_data.extend(dd)
        else:
            print(f'!!! Respuesta vacía de API')    

        # Si la página tiene <1000 filas, es la última - salir    
        if len(dd) < 1000: break

        ipage +=1
            
    transactions_oneday = pd.DataFrame(all_pages_data)        
    # Exporta a BD inmediatamente lo obtenido de la API
    export_to_db('oz_transactions', transactions_oneday)

    # Siguiente día
    current_date += delta    

Bucles anidados pueden parecer desordenados, pero la fiabilidad se dispara.

Monitoreo y recargas parciales

Para automatización total, añade una red de seguridad: monitoreo en segundo plano. Tras la ejecución principal (digamos, 6–7 AM), revisa logs/BD cada hora (8–12 AM).

Google AdInline article slot
  • Revisa estado de la última tarea.
  • Verifica integridad de datos (huecos en fechas).
  • Activa reintentos dirigidos solo para fragmentos faltantes.

Esto minimiza intervenciones manuales, sobre todo en actualizaciones diarias.

Lecciones clave

  • Usa retroceso exponencial con cabeceras de reintento para 429.
  • Divide solicitudes grandes en lotes diarios/filtros con guardados inmediatos.
  • Añade monitoreo horario post-colección para rellenar huecos.
  • 5 reintentos cubren el 95% de fallos; fallos totales esperan una hora+.
  • Integra en ETL sin ataduras estrictas a paginación.

— Editorial Team

Advertisement 728x90

Leer después