Skip to content

Rate Limits y Throttling ​

Resumen rápido ​

Amazon SP-API limita el número de peticiones que puedes hacer usando el algoritmo token bucket. Cada API tiene dos parámetros: rate (peticiones por segundo que se reponen) y burst (máximo acumulable). Si superas el burst, recibirás un error 429 QuotaExceeded. La clave es respetar los límites para evitar baneos y diseñar el código para funcionar dentro de ellos en lugar de ignorarlos.


Conceptos importantes ​

  • Rate limit: El número de tokens (peticiones) por segundo que se recargan en el bucket. Si haces peticiones a esta tasa exacta, nunca serás bloqueado.
  • Burst: El tamaño máximo del bucket. Puedes acumular hasta este número de peticiones y lanzarlas rápidamente al inicio.
  • Token bucket algorithm: Algoritmo estándar de control de flujo. El bucket se llena a la tasa rate hasta un máximo de burst. Cada petición consume un token.
  • QuotaExceeded: El error 429 que recibes cuando el bucket está vacío.
  • x-amz-rate-limit-limit: Header HTTP que Amazon devuelve en cada respuesta con tu límite real actual. Más fiable que los valores documentados porque refleja si Amazon te ha subido el límite dinámicamente.
  • Dynamic usage plans: Amazon puede subir o bajar tus límites automáticamente según el histórico de uso de tu app. Si haces muchas peticiones de forma consistente, Amazon puede triplicar tu rate.
  • NextToken: Token de paginación que devuelven las APIs cuando hay más de 100 resultados. Debes hacer una petición por página, lo que consume tokens del bucket.

Cómo funciona ​

El algoritmo token bucket explicado ​

Bucket capacidad = burst (ej. 20 tokens)
Tasa de recarga = rate (ej. 0.0167 tokens/seg = 1 token/60 seg)

Estado inicial: bucket lleno (20 tokens)

→ Hago 20 peticiones rápidas → bucket vacío
→ Siguiente petición → ERROR 429 (QuotaExceeded)
→ Espero 60 segundos → el bucket tiene 1 token
→ Puedo hacer 1 petición más
→ Espero 60 segundos más → 1 token más
...

Rate limits de las APIs principales ​

APIOperaciónRate (req/s)Burst
OrdersGetOrders0.0167 (1/min)20
OrdersGetOrder0.530
OrdersGetOrderItems0.530
Catalog ItemsSearchCatalogItems25
Catalog ItemsGetCatalogItem22
ReportsCreateReport0.016715
ReportsGetReport215
ListingspatchListingsItem510
NotificationscreateDestination15

Estos valores son los predeterminados. El header x-amz-rate-limit-limit te da tu valor real.


Pasos prácticos ​

Leer el rate limit real desde el header de respuesta ​

python
import requests

def make_api_request(access_token: str, url: str, params: dict) -> dict:
    response = requests.get(
        url,
        headers={"x-amz-access-token": access_token},
        params=params,
    )

    # Leer el rate limit real desde el header
    rate_limit = response.headers.get("x-amz-rate-limit-limit")
    if rate_limit:
        print(f"Tu rate limit actual: {rate_limit} req/s")

    if response.status_code == 429:
        print("Rate limit excedido (QuotaExceeded). Esperando...")
        # El header Retry-After puede indicar cuántos segundos esperar
        retry_after = response.headers.get("Retry-After", "60")
        return {"error": "throttled", "retry_after": int(retry_after)}

    response.raise_for_status()
    return response.json()

Rate limiter básico en Python (siguiendo el modelo de Amazon) ​

python
import threading
import time


class RateLimiter:
    """
    Implementa el token bucket algorithm de Amazon SP-API.
    tokens_per_second: el valor del campo 'rate' de la documentación
    capacity: el valor del campo 'burst' de la documentación
    """

    def __init__(self, tokens_per_second: float, capacity: int):
        self.tokens_per_second = tokens_per_second
        self.capacity = capacity
        self.tokens = float(capacity)
        self.last_refill = time.time()
        self.lock = threading.Lock()

    def _refill(self):
        now = time.time()
        elapsed = now - self.last_refill
        tokens_to_add = elapsed * self.tokens_per_second
        self.tokens = min(self.capacity, self.tokens + tokens_to_add)
        self.last_refill = now

    def acquire(self):
        """Espera hasta que haya un token disponible."""
        while True:
            with self.lock:
                self._refill()
                if self.tokens >= 1:
                    self.tokens -= 1
                    return
            wait_time = 1.0 / self.tokens_per_second
            time.sleep(wait_time)


# Ejemplo de uso: Orders API (rate=0.0167, burst=20)
orders_limiter = RateLimiter(tokens_per_second=0.0167, capacity=20)

def get_orders_with_rate_limit(access_token: str, endpoint: str, marketplace_id: str):
    all_orders = []
    next_token = None
    page = 0

    while True:
        orders_limiter.acquire()  # Esperar hasta tener un token disponible

        params = {"MarketplaceIds": marketplace_id}
        if next_token:
            params["NextToken"] = next_token
        else:
            params["CreatedAfter"] = "2024-01-01T00:00:00Z"

        response = requests.get(
            f"{endpoint}/orders/v0/orders",
            headers={"x-amz-access-token": access_token},
            params=params,
        )
        response.raise_for_status()
        data = response.json().get("payload", {})

        orders = data.get("Orders", [])
        all_orders.extend(orders)
        page += 1
        print(f"Página {page}: {len(orders)} pedidos obtenidos")

        next_token = data.get("NextToken")
        if not next_token:
            break

    return all_orders

Retry con backoff exponencial ​

python
import time
import random

def request_with_retry(func, max_retries: int = 3, *args, **kwargs):
    """Reintenta en caso de throttling con backoff exponencial."""
    for attempt in range(max_retries):
        try:
            return func(*args, **kwargs)
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 429:
                wait = (2 ** attempt) + random.uniform(0, 1)
                print(f"Throttled. Reintentando en {wait:.1f}s (intento {attempt + 1})")
                time.sleep(wait)
            else:
                raise
    raise Exception(f"Máximo de reintentos alcanzado ({max_retries})")

Estrategias de optimización ​

EstrategiaReducción de llamadas
Usar Notifications API en lugar de pollingHasta 100x menos
Usar Reports API en lugar de Get repetitivoHasta 50x menos
SearchCatalogItems (20 items/llamada) en lugar de GetCatalogItem20x menos
Usar ORDER_CHANGE en lugar de sondear Orders APIMiles de llamadas menos
Programar llamadas por la noche (menos tráfico)Mejor respuesta

Errores comunes ​

  • Hardcodear los rate limits: Los valores de la documentación son los mínimos garantizados. Tu app puede tener valores más altos (o más bajos). Lee siempre el header x-amz-rate-limit-limit.
  • No manejar el 429: Si no capturas este error, tu app fallará silenciosamente o lanzará excepciones no controladas.
  • Hacer polling agresivo: Bucles que consultan la API cada pocos segundos consumen el burst rápidamente y terminan bloqueados.
  • Abusar demasiado: Amazon puede penalizarte o incluso banearte si haces demasiadas peticiones que superan límites de forma continuada.
  • Confundir rate y burst: rate es la velocidad de recarga. burst es cuánto puedes hacer de golpe.

Qué debo saber antes de programarlo ​

  • Para obtener órdenes de historial (cientos de páginas con NextToken), el rate de GetOrders (1 req/min) es muy lento. Es mejor usar Reports API (GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_GENERAL) que te da todo en un solo archivo.
  • Si tu app tiene muchos clientes (SaaS), cada cliente tiene sus propias credenciales y sus propios rate limits. No compartes quota entre clientes.
  • Un patrón de producción sólido: cola de trabajos + worker que respeta el rate limiter. Nunca llames a la API directo desde una petición HTTP al usuario final.

Pendiente de revisar ​

  • ¿Amazon penaliza o banea por exceder el throttle repetidamente, o solo devuelve 429?
  • ¿El dynamic usage plan se aplica por aplicación o por cuenta de vendedor?
  • ¿Cómo funcionan exactamente los rate limits en apps con múltiples cuentas de vendedor (SaaS)?

Documentación basada en más de 40 tutoriales sobre Amazon SP-API. Actualizada a junio de 2026.