La llamada funciona en desarrollo. Ahora te toca escribir la parte que se ejecuta en producción: el bloque catch. Un error HTTP de una API de terceros, por sí solo, no dice gran cosa: un código de estado en rojo y ninguna respuesta clara a la única pregunta que importa a las 3 de la mañana: ¿el problema está en mi solicitud, en mi clave, en mi plan o en sus servidores? Y, de todos esos casos, ¿cuáles debo reintentar y cuáles debo mostrar al usuario?
Lingo.dev resuelve eso con estructura. Todos los errores, de todos los endpoints, síncronos o asíncronos, devuelven el mismo objeto JSON con un código de estado extraído de una tabla fija. El código de estado no es una etiqueta: es una instrucción. Te dice si debes corregir la solicitud, rotar la clave, recargar la cuenta, bajar el ritmo o reintentar. Lee el código y sabrás cuál es el siguiente paso. Un único gestor de errores, basado en el estado, cubre toda la API.
En esta página
- La estructura del error
- Códigos de estado
- Qué errores reintentar
- 402 frente a 429: dos límites distintos
- Dónde aparecen los errores de los trabajos asíncronos
La estructura del error#
Toda respuesta que no sea 2xx tiene el mismo cuerpo: un objeto JSON con un único campo message que describe qué ha ido mal.
{
"message": "Invalid API key"
}Ese es todo el contrato. No hay ningún contenedor que desempaquetar ni formatos de error por endpoint que requieran un tratamiento especial. Un 400 de /process/localize y un 404 al consultar un trabajo devuelven la misma estructura: solo cambian el código de estado y el texto de message.
Guíate por el código de estado, no por el texto del mensaje
El código de estado HTTP es la señal estable: basa en él tu gestión de errores. La cadena message está escrita para que la lea una persona en un log; trátala como una descripción, no como un código de error legible por máquina, y no dependas de su redacción exacta.
Códigos de estado#
Siete códigos de estado cubren todas las respuestas. Aquí están agrupados por quién los resuelve, porque esa agrupación también marca tu política de reintentos.
Has enviado algo que la solicitud no puede resolver (corrige la solicitud, no reintentes a ciegas):
| Estado | Significado |
|---|---|
400 Bad Request | La validación de la solicitud ha fallado: falta un campo, hay un idioma no válido, una callbackUrl HTTP (no HTTPS) o una carga útil malformada. |
401 Unauthorized | Falta la cabecera X-API-Key o no es válida. Consulta Authentication. |
403 Forbidden | La clave es válida, pero no tiene acceso al recurso solicitado. |
404 Not Found | El recurso —un motor, un trabajo o un grupo de trabajos— no existe. |
Tu organización ha alcanzado un límite de la cuenta (se resuelve en facturación):
| Estado | Significado |
|---|---|
402 Payment Required | La organización ha alcanzado su límite de crédito. |
429 Too Many Requests | La organización ha alcanzado su cuota diaria de tokens. Mejora el plan para aumentar el límite. |
Algo ha fallado por nuestra parte (transitorio: reintenta):
| Estado | Significado |
|---|---|
500 Internal Server Error | Un fallo inesperado: un error de base de datos o un fallo en la llamada de traducción en todos los modelos configurados en el motor. |
Un 401 y un 403 pueden parecerse, pero no son el mismo problema: 401 significa que no hemos podido identificar en absoluto a quien hace la llamada; 403 significa que hemos identificado la clave, pero no tiene permiso de acceso. La solución para 401 está en la propia clave (rótala o compruébala); la solución para 403 está en los permisos de esa clave.
Qué errores reintentar#
La primera pregunta que se hace cualquier integrador escéptico ante una tabla de errores es justo la que normalmente se queda sin respuesta: ¿cuáles de estos debo reintentar? La agrupación anterior te da la respuesta.
- 4xx: no reintentes a ciegas. Un
400,401,403o404describe una condición de tu solicitud. Si reintentas exactamente la misma solicitud, obtendrás exactamente el mismo error. Corrige la entrada, la clave o el ID del recurso y vuelve a enviarla. - 402 y 429: baja el ritmo y luego resuelve el límite. No son errores transitorios a nivel de solicitud: la siguiente llamada chocará contra el mismo límite hasta que cambie la restricción subyacente. Deja de reintentar en bucle, muestra cuál es el límite y resuélvelo (recargando saldo o mejorando el plan).
- 500: reintenta con backoff. Esta es la única clase realmente transitoria. Un
500puede significar que todos los modelos configurados agotaron el tiempo de espera en esa llamada; un reintento puede acabar en un modelo operativo. Usa backoff exponencial y un límite de reintentos.
La API asíncrona informa de los resultados de otra manera
Esta política de reintentos es para las llamadas síncronas que haces tú mismo. La API de localización asíncrona no te devuelve un código de estado para el resultado del trabajo: una respuesta POST devuelve 202 una vez aceptada la solicitud, y cada idioma de destino se ejecuta como un trabajo independiente mediante flujos de trabajo duraderos en segundo plano. En lugar de capturar un código de estado en la llamada original, consultas el trabajo o recibes un webhook con el resultado. Consulta dónde aparecen los errores de los trabajos asíncronos.
402 frente a 429: dos límites distintos#
Los dos códigos a nivel de cuenta suenan parecidos —ambos vienen a decir “te has quedado sin”— y confundirlos lleva al desarrollador a la solución equivocada. Son límites distintos y requieren resoluciones distintas:
402 Payment Required: la organización ha alcanzado su límite de crédito. Es un límite de facturación. La siguiente llamada seguirá fallando hasta que cambie el estado de facturación de tu organización.429 Too Many Requests: la organización ha alcanzado su cuota diaria de tokens. Es un techo de uso que se restablece y que puedes elevar mejorando el plan.
Por eso conviene mantenerlos separados en tu gestor: un 402 requiere una acción de facturación por parte de una persona; un 429 es una cuota que puedes esperar a que se restablezca o elevar mejorando el plan. Reducir ambos a un mensaje genérico de “problema de pago” oculta qué palanca tiene que accionar realmente el operador.
El cuerpo de un 402 se parece al de cualquier otro error: lo que te indica que se trata de un límite de crédito es el código de estado:
{
"message": "Organization has reached its credit limit"
}Dónde aparecen los errores de los trabajos asíncronos#
Aquí conviene trazar una línea, porque es justo donde un gestor basado en códigos de estado deja de ser la herramienta adecuada.
Los códigos de estado de esta página son a nivel de transporte: describen si la API ha aceptado y podido atender tu solicitud HTTP. Un 202 de la API asíncrona significa que tu solicitud ha sido aceptada, no que la traducción se haya completado con éxito. Un trabajo asíncrono puede aceptarse sin problemas y aun así fallar más tarde, por ejemplo si un modelo agota el tiempo de espera a mitad de ejecución. Ese fallo no aparece como código de estado HTTP en la llamada original: queda registrado en el propio trabajo.
Así que los fallos asíncronos aparecen en tres sitios, y ninguno es esta tabla:
- Estado por trabajo. Un idioma fallido incluye
status: "failed"y unerrorMessageen el trabajo. Consulta job statuses. - Estado del grupo. Cuando algunos idiomas se completan correctamente y otros fallan, el grupo informa
partial; los idiomas que sí han salido bien se siguen entregando. Consulta tracking a job group. - Entrega de webhook. Un fallo se entrega como un evento
translation.failedcon un campoerror. Consulta webhook delivery.
Hay otra distinción que suele confundir: que falle una fase no crítica del pipeline no hace que falle el trabajo. El trabajo se completa con completed_with_warnings y advertencias por paso, en lugar de devolver un error. Eso es una cuestión de observabilidad del pipeline, no de códigos de error; consulta observe pipeline runs.
Siguientes pasos#
Un gestor de errores limpio empieza por los dos códigos que verás primero al integrar: autenticación y los puntos en los que el trabajo asíncrono informa de su propio resultado.
