Errores y rate limits
Esta página describe el formato estándar de error de la API de vario, los códigos de aplicación posibles, los límites de tasa por plan y las recomendaciones para manejar fallos de manera resiliente.
Formato de error estándar
Todos los errores retornan un objeto JSON con la siguiente estructura:
{
"error": {
"code": "ERROR_CODE",
"message": "Descripción legible del error."
}
}
El campo code es un identificador estable en inglés que puedes usar en tu lógica de manejo de errores. El campo message es orientativo y puede cambiar entre versiones; no dependas de él para lógica de negocio.
Tabla de códigos de error
| HTTP | Código | Descripción | Qué hacer |
|---|---|---|---|
400 | TEXT_TOO_LONG | El campo text supera 8.000 caracteres. | Dividir el texto en chunks y enviar múltiples requests. |
400 | INVALID_LANGUAGE | El idioma enviado no está soportado para el playbook seleccionado. | Usar "es" o "pt". Consultar GET /v1/playbooks. |
400 | INVALID_PLAYBOOK | El valor de playbook no existe en el catálogo. | Consultar GET /v1/playbooks para obtener la lista de valores válidos. |
400 | INVALID_MODE | El valor de mode no es válido. | Usar "screening", "fast" o "full". |
400 | CONTEXT_TOO_LONG | thread_context supera 10 elementos, o algún elemento supera 500 caracteres. | Reducir la cantidad de mensajes de contexto o truncar los elementos más largos. |
400 | VALIDATION_ERROR | El schema del request es inválido. | Revisar la estructura del body contra la referencia de POST /v1/analyze. |
401 | INVALID_API_KEY | La API key no existe, está expirada o fue revocada. | Verificar la key en el portal. |
401 | MISSING_AUTH | El header Authorization está ausente. | Incluir Authorization: Bearer vario_TU_API_KEY. |
402 | SUBSCRIPTION_REQUIRED | El tenant no tiene una suscripción activa. | Revisar el estado de la cuenta en el portal. |
402 | INSUFFICIENT_CREDITS | El balance de créditos del tenant es cero. | Adquirir créditos adicionales. Ver Compra de créditos. |
403 | INSUFFICIENT_SCOPE | La API key no tiene el scope requerido. | Generar una nueva key con los scopes necesarios. |
409 | email_already_registered | El email ya tiene una cuenta API-only registrada. | Recuperar la key existente o revocarla y crear una nueva desde el portal. |
429 | RATE_LIMIT_EXCEEDED | Se superó el límite de llamadas permitido. | Implementar backoff exponencial. Respetar el header Retry-After. |
503 | DEEP_ANALYSIS_UNAVAILABLE | Retornado solo cuando el request incluye Prefer: deep-analysis-required y el análisis profundo no está disponible. | Omitir el header para recibir una respuesta parcial, o reintentar con backoff. |
503 | PRICING_NOT_CONFIGURED | El pack de créditos solicitado aún no tiene precio configurado. | Consultar GET /api/public/checkout/credits/preview o contactar a [email protected]. |
500 | PIPELINE_ERROR | Error interno del pipeline. El texto no fue analizado. | Reintentar. Si el error persiste, reportar a [email protected] con el timestamp del request. |
Rate limits por plan
Los límites de tasa se aplican por API key y se miden en dos ventanas: por minuto y por día.
| Plan | Llamadas por minuto | Llamadas por día |
|---|---|---|
| API-only (trial / sin seats) | 60 | 10.000 |
| Essentials | 60 | 10.000 |
| Professional | 300 | 100.000 |
| Enterprise | 1.000 | 500.000 |
Cuando se alcanza el límite, el servidor responde con 429 RATE_LIMIT_EXCEEDED e incluye el header Retry-After con los segundos que debes esperar antes de reintentar.
Recomendaciones de resiliencia
Backoff exponencial con jitter
Al recibir un 429 o un 503, no reintentes inmediatamente. Implementa un backoff exponencial con componente aleatorio (jitter) para evitar que múltiples clientes golpeen el servidor al mismo tiempo:
import time
import random
def call_with_backoff(fn, max_retries=5):
for attempt in range(max_retries):
response = fn()
if response.status_code not in (429, 503):
return response
retry_after = int(response.headers.get("Retry-After", 2 ** attempt))
sleep_time = retry_after + random.uniform(0, 1)
time.sleep(sleep_time)
raise Exception("Max retries exceeded")
Monitorear X-RateLimit-Remaining
Si el header X-RateLimit-Remaining está presente en la respuesta, úsalo para anticipar el agotamiento del límite antes de recibir un 429. Cuando el valor sea bajo, reduce la cadencia de requests.
Estrategia de modo por volumen
Para corpus masivos, usa mode=fast como primera pasada. Reserva mode=full para los textos que requieran análisis más profundo. Esto reduce el consumo de créditos y el riesgo de alcanzar el rate limit en ventanas cortas.
Degradación del análisis
Cuando el request no incluye el header Prefer: deep-analysis-required, un fallo del análisis profundo retorna 200 con bedrock_available: false y un análisis parcial. Verifica este campo si necesitas garantizar la profundidad completa del análisis antes de tomar una decisión.
Ejemplo: manejo de error INSUFFICIENT_CREDITS
import httpx
response = httpx.post(
"https://api.vario.lat/v1/analyze",
headers={"Authorization": "Bearer vario_TU_API_KEY"},
json={"text": "...", "playbook": "price_fixing", "language": "es"}
)
if response.status_code == 402:
error = response.json()["error"]
if error["code"] == "INSUFFICIENT_CREDITS":
# Notificar al equipo para recargar créditos
raise InsufficientCreditsError("Recarga de créditos requerida.")