Limitacion de velocidad
Limitacion de velocidad de la API The Trade Hub - encabezados de respuesta, gestion de errores 429 y estrategia de backoff exponencial.
La API The Trade Hub aplica limitacion de velocidad (rate limiting) para garantizar la disponibilidad y equidad del servicio. El limite es configurable por clave API.
Encabezados de respuesta
Cada respuesta de la API incluye encabezados que indican su consumo actual:
| Encabezado | Descripcion |
|---|---|
X-RateLimit-Limit | Numero maximo de solicitudes permitidas por minuto |
X-RateLimit-Remaining | Numero de solicitudes restantes en la ventana actual |
Retry-After | Numero de segundos antes de poder reintentar (solo en respuestas 429) |
Ejemplo de encabezados
HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
Content-Type: application/jsonLimites por defecto
La API utiliza buckets separados para las solicitudes de escritura y lectura:
| Parametro | Valor |
|---|---|
| Escrituras por minuto (POST, PUT, PATCH, DELETE) | 10 (operaciones LLM, cada SSE permanece abierto ~90s) |
| Lecturas por minuto (GET) | 60 (polling, verificacion de estado) |
| Lote max | 1 000 elementos (10 MB max) |
| Payload max (clasificacion) | 1 MB |
Una llamada batch cuenta como una sola solicitud de escritura. El limite por clave API puede reducirse (pero no aumentarse) desde el panel de desarrollador.
Respuesta 429 (Too Many Requests)
Cuando se alcanza el limite, la API devuelve un error 429 Too Many Requests con un encabezado Retry-After:
HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Content-Type: application/json
{
"detail": "rate limit exceeded"
}El valor de Retry-After indica el numero de segundos restantes antes del reinicio de la ventana.
Gestion del rate limiting
Estrategia recomendada: backoff exponencial
Cuando reciba una respuesta 429, espere la duracion indicada por Retry-After antes de reintentar. Si el encabezado esta ausente, utilice un backoff exponencial:
import httpx
import time
def request_with_retry(client: httpx.Client, method: str, url: str, max_retries: int = 5, **kwargs):
delay = 1
for attempt in range(max_retries):
response = client.request(method, url, **kwargs)
if response.status_code != 429:
return response
# Respetar Retry-After si esta presente
retry_after = response.headers.get("Retry-After")
if retry_after:
wait = int(retry_after)
else:
wait = delay
delay = min(delay * 2, 60)
print(f"Rate limited. Reintentando en {wait}s (intento {attempt + 1}/{max_retries})")
time.sleep(wait)
raise Exception("Numero maximo de intentos alcanzado")
client = httpx.Client(
base_url="https://api.thetradehub.eu",
headers={"X-API-Key": "th_live_su_clave_api"},
)
response = request_with_retry(client, "POST", "/v1/classify/jobs", json={
"content": "Auriculares Bluetooth inalambricos"
})async function requestWithRetry(url, options, maxRetries = 5) {
let delay = 1000;
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status !== 429) {
return response;
}
// Respetar Retry-After si esta presente
const retryAfter = response.headers.get("Retry-After");
const wait = retryAfter ? parseInt(retryAfter) * 1000 : delay;
delay = Math.min(delay * 2, 60000);
console.log(`Rate limited. Reintentando en ${wait / 1000}s (intento ${attempt + 1}/${maxRetries})`);
await new Promise((r) => setTimeout(r, wait));
}
throw new Error("Numero maximo de intentos alcanzado");
}
const response = await requestWithRetry(
"https://api.thetradehub.eu/v1/classify/jobs",
{
method: "POST",
headers: {
"X-API-Key": "th_live_su_clave_api",
"Content-Type": "application/json",
},
body: JSON.stringify({ content: "Auriculares Bluetooth inalambricos" }),
}
);Facturacion
La API utiliza un modelo pay-per-use sin cuotas fijas. Cada clasificacion exitosa (SH o control de exportacion) se factura por unidad con tarificacion graduada:
| Nivel (unidades/mes) | Precio |
|---|---|
| 1 - 100 | 0,75 EUR/unidad |
| 101 - 1 000 | 0,55 EUR/unidad |
| 1 001 - 10 000 | 0,40 EUR/unidad |
| 10 001 - 50 000 | 0,30 EUR/unidad |
| 50 001+ | 0,25 EUR/unidad |
Los volumenes mensuales de clasificacion aduanera y control de exportaciones se agregan para el calculo del nivel. Las declaraciones (importacion, exportacion, transito) usan una tarifa fija de 1,50 EUR/unidad.
Solo las clasificaciones completadas con exito se facturan. Los fallos y reintentos no generan costo.
Modos de facturacion
| Modo | Descripcion |
|---|---|
| Balance (prepago) | Creditos deducidos en tiempo real. Recarga manual o automatica. |
| Invoice (empresa) | Facturacion mensual net-30. Limite de gasto configurable. |
Si el saldo de creditos llega a cero (balance) o se alcanza el limite de gasto (invoice), la API devuelve un error 402 Payment Required.
Buenas practicas
Supervise sus encabezados
Verifique X-RateLimit-Remaining despues de cada solicitud. Si el valor se acerca a cero, reduzca proactivamente la frecuencia de sus llamadas.
Utilice la clasificacion por lotes
Para procesar varios productos, privilegie el endpoint batch en lugar de llamadas individuales en serie. Una llamada batch cuenta como una sola solicitud para el rate limiter.
Espacie sus solicitudes
Si procesa grandes volumenes, distribuya sus solicitudes uniformemente en el tiempo en lugar de enviarlas en rafaga.
Almacene en cache los resultados
Guarde los resultados de clasificacion del lado del cliente para evitar clasificar el mismo producto varias veces. Consulte el endpoint historial para recuperar una clasificacion pasada.
Nunca reintente inmediatamente
Reintentar inmediatamente despues de un 429 agrava la situacion. Siempre respete el retraso Retry-After o aplique un backoff exponencial.
Última actualización