Diseño de Errores en APIs REST
En el diseño de APIs REST, es fácil enfocarse en los casos de éxito: respuestas 200 OK
, datos bonitos y endpoints funcionando. Pero en la vida real, las cosas fallan: usuarios envían datos inválidos, ocurren errores de autenticación, recursos no existen o el servidor simplemente colapsa.
Diseñar bien los errores no es solo cuestión de mostrar un código HTTP. Es una práctica esencial para que los consumidores de tu API puedan:
- Diagnosticar y manejar fallos automáticamente
- Entender qué salió mal sin adivinar
- Solucionar problemas sin leer tu backend
Este artículo te enseña cómo diseñar respuestas de error robustas, consistentes y útiles, con ejemplos y buenas prácticas.
¿Por qué es importante el diseño de errores?
Una buena respuesta de error:
- Ahorra tiempo a los integradores
- Reduce la carga de soporte
- Mejora la confiabilidad de los clientes frente a fallos
- Da visibilidad en logs y sistemas de monitoreo
- Permite a los usuarios reaccionar de forma programada (reintentos, mensajes claros, fallback)
Una mala respuesta de error puede llevar a frustración, ambigüedad, o integraciones que fallan silenciosamente.
Uso correcto de códigos HTTP
Los códigos de estado HTTP comunican qué tipo de error ocurrió:
Código | Nombre | Cuándo usarlo |
---|---|---|
400 | Bad Request | Datos inválidos, formato incorrecto, campos requeridos |
401 | Unauthorized | Token faltante o inválido (no está autenticado) |
403 | Forbidden | Autenticado pero sin permisos suficientes |
404 | Not Found | Recurso inexistente |
409 | Conflict | Duplicación o conflicto con el estado actual |
422 | Unprocessable Entity | Datos válidos en estructura pero inválidos en contenido |
429 | Too Many Requests | Rate limiting o throttling |
500 | Internal Server Error | Fallo inesperado del servidor |
503 | Service Unavailable | Sistema en mantenimiento o indisponibilidad temporal |
Muchos desarrolladores usan solo
400
y500
, pero esto pierde mucha semántica útil.
Estructura recomendada para respuestas de error
Además del código HTTP, deberías incluir un cuerpo (body) de respuesta estructurado. Ejemplo:
{
"status": 400,
"error": "Bad Request",
"message": "El campo 'email' es obligatorio.",
"code": "ERR_VALIDATION_EMAIL_REQUIRED",
"timestamp": "2024-04-13T10:15:30Z",
"path": "/api/v1/usuarios"
}
Campos útiles:
Campo | Propósito |
---|---|
status |
Refleja el código HTTP |
error |
Nombre estándar del error (opcional si ya está en status ) |
message |
Mensaje legible para humanos |
code |
Código interno para manejo automático (útil para clientes) |
timestamp |
Trazabilidad en logs y soporte |
path |
Ayuda en diagnósticos |
errors |
Lista de errores de validación (cuando hay múltiples) |
Ejemplo con errores múltiples de validación
{
"status": 422,
"error": "Unprocessable Entity",
"message": "La solicitud contiene errores de validación.",
"errors": [
{
"field": "email",
"message": "Debe ser un correo electrónico válido."
},
{
"field": "password",
"message": "Debe tener al menos 8 caracteres."
}
]
}
Este patrón es especialmente útil en formularios complejos o endpoints de creación masiva.
Buenas prácticas
Sé consistente
Usa la misma estructura en todos tus errores, sin importar el endpoint o la causa.
Usa mensajes claros, no técnicos
Piensa que quien consume la API puede no conocer tu backend.
Incluye códigos internos
Los code (como ERR_USER_NOT_FOUND) ayudan a mapear errores en el frontend, logs o i18n.
No expongas información sensible
Nunca devuelvas traces, nombres de tablas o errores SQL en producción.
Utiliza errores genéricos para 500
Ejemplo: "message": "Ocurrió un error inesperado. Intente nuevamente más tarde."
Documenta tus errores
En Swagger/OpenAPI, especifica ejemplos de respuestas 4xx y 5xx.
Traza errores críticos
Agrega un traceId o requestId para conectar con logs en sistemas como Datadog o ELK.
¿Cómo documentar errores en OpenAPI (Swagger)?
Ejemplo para un endpoint POST /usuarios
:
responses:
400:
description: Error de validación
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorValidation'
401:
description: Token inválido o no enviado
Esto permite que los integradores vean ejemplos de errores antes de usarlos.
Conclusión
Un buen diseño de errores en tu API no solo mejora la experiencia de desarrollo, sino que reduce los tickets de soporte, mejora la trazabilidad y fortalece la percepción de calidad de tu producto.
No se trata solo de poner 500
cuando algo falla: se trata de comunicar bien, ser predecible, y dar al cliente lo necesario para entender, reaccionar y corregir.