Errores y códigos de estado
La llamada funciona en desarrollo. Ahora estás escribiendo la parte que se ejecuta en producción: el bloque catch. Por sí solo, un error HTTP de una API de terceros no dice mucho: 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 es mi solicitud, mi clave, mi plan o sus servidores? Y, de todos estos errores, ¿cuáles reintento y cuáles le muestro al usuario?
Lingo.dev responde con una estructura clara. Todos los errores de los puntos de conexión de estas páginas, síncronos o asíncronos, devuelven el mismo objeto JSON con un código de estado de una única tabla fija. La API de plataforma en /v2 usa, en cambio, el formato estándar de detalles del problema; consulta Errores de la API de plataforma. El código de estado no es una etiqueta: es una instrucción. Te indica si debes corregir la solicitud, rotar la clave, recargar la cuenta, esperar antes de volver a intentarlo o reintentar. Lee el código y sabrás qué hacer. Un solo manejador de errores, basado en el código de estado, cubre toda la API.
En esta página
- Estructura de los errores
- Códigos de estado
- Qué errores reintentar
- 402 frente a 429: dos límites distintos
- Dónde se registran los errores de los trabajos asíncronos
- Errores de la API de plataforma
Estructura de los errores#
Todas las respuestas fuera del rango 2xx tienen el mismo cuerpo: un objeto JSON con un único campo message que describe qué salió mal.
{
"message": "Invalid API key"
}Ese es todo el contrato. No hay una estructura contenedora que desarmar ni formatos de error específicos de cada punto de conexión 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.
Basa el manejo en el código de estado, no en el texto del mensaje
El código de estado HTTP es la señal estable: úsalo para decidir cómo manejar el error. La cadena message está escrita para una persona que lee un registro; trátala como una descripción, no como un código de error para procesamiento automático, y no dependas de coincidencias con su redacción exacta.
Códigos de estado#
Siete códigos de estado cubren todas las respuestas. Aquí se agrupan según quién los resuelve, porque esa agrupación también define tu política de reintentos.
Enviaste algo que la solicitud no puede procesar (corrige la solicitud, no reintentes a ciegas):
| Estado | Significado |
|---|---|
400 Bad Request | Falló la validación de la solicitud: falta un campo, hay un idioma no válido, un callbackUrl HTTP (no HTTPS) o un cuerpo de solicitud con formato incorrecto. |
401 Unauthorized | Falta el encabezado X-API-Key o no es válido. Consulta Autenticación. |
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 alcanzó un límite de la cuenta (resuélvelo en facturación):
| Estado | Significado |
|---|---|
402 Payment Required | La organización alcanzó su límite de crédito. |
429 Too Many Requests | La organización alcanzó su cuota diaria de tokens. Cambia a un plan superior para aumentar el límite. |
Algo falló de nuestro lado (es transitorio: reintenta):
| Estado | Significado |
|---|---|
500 Internal Server Error | Una falla inesperada: un error de base de datos o una llamada de traducción que falló con todos los modelos configurados en el motor. |
Un 401 y un 403 se parecen, pero no son el mismo problema: 401 significa que no pudimos identificar a quien hizo la llamada; 403 significa que identificamos la clave, pero no tiene permitido el acceso. La solución para 401 está en la propia clave (rótala o revísala); la solución para 403 está en los permisos de acceso de la clave.
Qué errores reintentar#
Al integrar una API, es natural mirar cualquier tabla de errores con escepticismo y hacerse la pregunta que suele quedar sin respuesta: ¿cuáles de estos errores debo reintentar? La agrupación anterior tiene la respuesta.
- 4xx: no reintentes a ciegas. Un
400,401,403o404describe una condición en tu solicitud. Reintentar la misma solicitud produce el mismo error. Corrige los datos de entrada, la clave o el ID del recurso y vuelve a enviarla. - 402 y 429: espera y luego resuelve el límite. No son errores transitorios a nivel de solicitud; la siguiente solicitud se encontrará con el mismo obstáculo hasta que cambie el límite subyacente. Deja de reintentar en un bucle sin pausas, informa del límite y resuélvelo (recarga la cuenta o cambia a un plan superior).
- 500: reintenta con esperas progresivas. Esta es la única clase de error realmente transitorio. Un
500puede significar que todos los modelos configurados agotaron su tiempo de espera en esa llamada; un reintento podría llegar a un modelo que funcione correctamente. Usa esperas exponenciales y un número máximo de reintentos.
La API asíncrona informa los resultados de otra manera
Esta política de reintentos se aplica a las llamadas síncronas que haces directamente. La API de localización asíncrona no te devuelve un código de estado con el resultado del trabajo: una 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. Para obtener el resultado, consultas el trabajo o recibes un webhook, en lugar de capturar un código de estado en la llamada original. Consulta dónde se registran los errores de los trabajos asíncronos.
402 frente a 429: dos límites distintos#
Los dos códigos a nivel de cuenta se parecen —ambos suenan a «se te acabó»— y confundirlos lleva a aplicar la solución equivocada durante el desarrollo. Son límites distintos con soluciones distintas:
402 Payment Required: la organización alcanzó su límite de crédito. Es una restricción de facturación. Las llamadas seguirán fallando hasta que cambie el estado de facturación de tu organización.429 Too Many Requests: la organización alcanzó su cuota diaria de tokens. Es un tope de uso que se restablece y que puedes aumentar al cambiar a un plan superior.
Por eso conviene distinguirlos en tu manejador de errores: un 402 requiere que una persona realice una acción de facturación; un 429 es una cuota que puedes esperar a que se restablezca o aumentar al cambiar a un plan superior. Si ambos llevan a un mensaje genérico de «problema de pago», no queda claro qué medida debe tomar quien opera el sistema.
El cuerpo de un 402 es igual al de cualquier otro error: el código de estado es lo que indica que se trata de un límite de crédito:
{
"message": "Organization has reached its credit limit"
}Dónde se registran los errores de los trabajos asíncronos#
Conviene hacer una distinción: marca el punto en el que un manejador de códigos de estado deja de ser la herramienta adecuada.
Los códigos de estado de esta página son de nivel de transporte: describen si la API aceptó y pudo atender tu solicitud HTTP. Un 202 de la API asíncrona significa que tu solicitud fue aceptada, no que la traducción se completó correctamente. Un trabajo asíncrono puede aceptarse sin problemas y aun así fallar después, cuando un modelo agota su tiempo de espera durante la ejecución. Esa falla no aparece como un código de estado HTTP en tu llamada original: se registra en el propio trabajo.
Por eso, las fallas asíncronas aparecen en tres lugares, ninguno de ellos en esta tabla:
- Estado de cada trabajo. Cuando falla un idioma, el trabajo incluye
status: "failed"y unerrorMessage. Consulta estados de los trabajos. - Estado del grupo. Cuando algunos idiomas se completan correctamente y otros fallan, el grupo informa
partial; los idiomas completados correctamente se entregan de todos modos. Consulta seguimiento de un grupo de trabajos. - Entrega de webhooks. Una falla se entrega como un evento
translation.failedcon un campoerror. Consulta entrega de webhooks.
Hay otra distinción que suele sorprender: si falla una etapa no crítica del proceso, el trabajo no falla. Se completa con completed_with_warnings y advertencias por paso, en lugar de un error. Es una cuestión de observabilidad del proceso, no un código de error; consulta observar las ejecuciones del proceso.
Errores de la API de plataforma#
La API de plataforma en https://api.lingo.dev/v2 responde a los errores de otra manera. Devuelve detalles del problema según RFC 9457, enviados como application/problem+json:
{
"type": "https://lingo.dev/docs/api/errors/glossary-in-use",
"status": 409,
"title": "Glossary in use",
"detail": "Glossary gls_1 cannot be deleted while 2 engines apply it. Detach it from those engines first.",
"id": "gls_1",
"engineCount": 2
}typeidentifica el problema. Es un enlace a la página específica de ese problema, que enumera sus campos y los puntos de conexión que lo devuelven. Usatypepara decidir cómo manejarlo.statusrepite el código de estado HTTP.titlees un resumen breve que se mantiene igual cada vez que ocurre un problema de ese tipo.detailindica qué ocurrió esta vez y qué hacer a continuación. Está escrito para una persona, así que muéstralo en lugar de analizarlo mediante código.- Los demás miembros contienen los datos de este caso, como
idyengineCounten el ejemplo anterior.detailse construye únicamente a partir de ellos, de modo que un cliente puede generar su propio texto, en su propio idioma, a partir detypey estos campos.
Si una solicitud no supera la validación, la respuesta devuelve 400 y enumera cada valor no válido en errors, como pares { "path", "message" }. Todos los puntos de conexión también pueden responder con service-unavailable (503), que se puede reintentar de forma segura con esperas progresivas, y internal-server-error (500).
Cada código de estado sigue una regla:
| Estado | Significado |
|---|---|
401 | No se ha identificado a quien realiza la llamada. |
402 | Un límite del plan o de un derecho que se elimina al cambiar a un plan superior o recargar la cuenta. |
403 | Se ha identificado a quien realiza la llamada, pero no tiene permitido hacer esto. |
404 | El recurso no existe o quien realiza la llamada no puede verlo. |
409 | La solicitud entra en conflicto con el estado actual; por ejemplo, un recurso que sigue en uso. |
422 | La solicitud tiene un formato correcto, pero una regla la rechaza. |
429 | Un límite que se restablece con el tiempo. |
502 | Falló un proveedor del que depende el servicio. |
503 | Una falla temporal de nuestro lado. Reintenta con esperas progresivas. |
Próximos pasos#
Un manejador de errores bien diseñado empieza por los dos temas que encontrarás primero durante la integración: la autenticación y los puntos en los que el trabajo asíncrono informa su propio resultado.