Ir al contenido

Errores

La Partner API usa códigos de estado HTTP estándar y devuelve el detalle del error en el body JSON. Esta página cubre todos los códigos que puede devolver y cómo reaccionar a cada uno.

La mayoría de los errores devuelven un objeto con detail (texto legible):

{
"detail": "API key inválida o expirada"
}

Los errores de validación (422) devuelven detail como una lista, una entrada por campo inválido — es el formato estándar de FastAPI:

{
"detail": [
{
"loc": ["body", "email"],
"msg": "value is not a valid email address",
"type": "value_error.email"
}
]
}
  • loc: ubicación del campo (body, query, path + nombre).
  • msg: descripción legible.
  • type: código de error de máquina, útil para mapear mensajes propios.
CódigoSignificadoQué hacer
200 / 201 / 204Éxito
400Petición malformadaRevisá el body y los parámetros.
401API key inválida o expiradaVerificá el header Authorization. Regenerá la key si hace falta.
403Tu tenant no tiene acceso PartnerTu cuenta aún no está habilitada como partner. Contactá a soporte.
404Recurso no encontradoEl tenant_id o source_id no existe o no te pertenece.
409ConflictoEl recurso ya existe o falta un prerrequisito (p. ej. registrar un webhook sin una API key activa).
422Error de validaciónRevisá la lista detail para ver qué campo falló.
429Rate limit excedidoSuperaste 120 requests/minuto. Esperá y reintentá con backoff.
500Error internoReintentá con backoff. Si persiste, contactá a soporte con la hora del request.

El límite es de 120 requests por minuto y por API key (ventana fija). Al excederlo recibís 429:

{
"detail": "Rate limit excedido: máximo 120 req/min."
}

Recomendaciones:

  • Implementá backoff exponencial ante un 429 (p. ej. 1s, 2s, 4s).
  • Para cargas grandes (alta de muchos tenants, carga masiva de KB), serializá o agrupá las llamadas en lugar de dispararlas en paralelo.
  • El rate limit se cuenta por API key, no por tenant.
import time
import requests
def call_with_retry(method, url, headers, json=None, max_retries=4):
for attempt in range(max_retries):
resp = requests.request(method, url, headers=headers, json=json)
if resp.status_code == 429 or resp.status_code >= 500:
time.sleep(2 ** attempt) # backoff: 1s, 2s, 4s, 8s
continue
if not resp.ok:
# 4xx no recuperable: logueá detail y cortá
raise RuntimeError(f"{resp.status_code}: {resp.json().get('detail')}")
return resp.json() if resp.content else None
raise RuntimeError(f"Agotados {max_retries} intentos para {url}")
  • Reintentá solo 429 y 5xx (transitorios).
  • No reintentes 4xx de cliente (400, 401, 403, 404, 422): son errores de tu request, reintentar no los arregla.