Errores
Contra qué campo conviene programar, y por qué no es el cuerpo de la respuesta.
Programá contra el status HTTP. Es el único dato que viene siempre, que significa lo mismo en todos los endpoints y que no va a cambiar sin anunciarse en el changelog.
El cuerpo sirve para mostrarle algo a una persona y para depurar, pero su forma no es única: hoy conviven varias, según el endpoint y según qué falló. Si tu integración ramifica lógica leyendo el cuerpo, se va a romper al cambiar de endpoint.
Qué significa cada status
El 422 tiene dos orígenes distintos. Uno es la validación de esquema. El otro
es de negocio: los endpoints de asignación masiva devuelven 422 cuando la
llamada no terminó asignando a ningún usuario, aunque el cuerpo fuera
válido. Si tu integración asigna contenido, tratá ese caso aparte.
Las formas del cuerpo
Estas son las tres que vas a encontrar en la práctica. Las tres traen el detalle
bajo detail, y ahí se termina el parecido.
Una lista de mensajes
La más común. Es lo que devuelven los 400, 401, 403 y 404 de la mayoría
de los endpoints:
La validación de esquema
Cuando un parámetro o un campo del cuerpo no cumple el tipo o el rango. detail
acá es una lista, no un objeto, y cada elemento dice qué campo falló:
loc es el camino al campo: ["query", "limit"] es un parámetro de query,
["body", "email"] un campo del cuerpo. Es la forma más útil para mostrarle al
usuario qué corregir.
Un texto suelto
En los 500, detail puede venir como un string, o como un objeto con una sola
clave:
No trae información accionable a propósito. Si te llega uno, reintentá con backoff y si persiste reportalo con la hora y la ruta.
Cómo leer las tres con el mismo código
Alcanza con normalizar detail a una lista de textos antes de tocarlo:
Los textos que salen de acá son para un log o para mostrarle a una persona. No los compares en tu código: no son estables y pueden cambiar sin aviso. La decisión de qué hacer sale del status HTTP.
Reintentos
Reintentá solo 500 y errores de red, con backoff exponencial. Los 4xx
describen un problema del request: reintentarlos sin cambiar nada da el mismo
resultado.
Las operaciones de escritura no son idempotentes salvo que se indique lo contrario, así que antes de reintentar una que pudo haber llegado, consultá el estado actual del recurso.
Que hoy convivan varias formas de cuerpo es deuda, no diseño. Si en algún momento se unifican, se anuncia en el changelog como cualquier otro cambio del contrato. Es la razón de fondo para ramificar por status y no por cuerpo: el código que ya hace eso no se toca el día que cambie.
