Skip to content
SP StackPractices
beginner Por StackPractices

Guia de Manejo de Errores de API

Guia para estandarizar respuestas de error, codigos de estado y payloads de error en APIs REST y GraphQL.

Nota para desarrolladores hispanohablantes: Esta guía incluye ejemplos y convenciones de nomenclatura adaptadas a equipos que trabajan en español. Cuando existen diferencias significativas en terminología técnica entre el inglés y el español, se indican explícitamente para facilitar la comunicación en equipos multiculturales.

Resumen

Las respuestas de error inconsistentes confunden a los consumidores de API y aumentan el tiempo de integracion. Un endpoint retorna texto plano, otro retorna JSON anidado, y un tercero retorna HTML. Esta guia estandariza como tus APIs comunican fallas para que los consumidores puedan manejar errores programaticamente sin adivinar formatos.

Cuando Usar

Usa este recurso cuando:

  • Disenes una API nueva o versiones una existente
  • Incorpores un nuevo equipo que construira endpoints de API
  • Revises una API para consistencia antes del lanzamiento publico
  • Los consumidores reporten que el manejo de errores es dificil o impredecible

Solucion

# Estandar de Manejo de Errores de API

## 1. Codigos de Estado HTTP

| Estado | Significado | Cuando Usar |
|--------|-------------|-------------|
| 400 | Solicitud Incorrecta | Errores de validacion, JSON malformado, campos requeridos faltantes |
| 401 | No Autorizado | Credenciales de autenticacion faltantes o invalidas |
| 403 | Prohibido | Autenticado pero no autorizado para este recurso |
| 404 | No Encontrado | El recurso no existe |
| 409 | Conflicto | El recurso ya existe, entrada duplicada, conflicto de estado |
| 422 | Entidad No Procesable | Semanticamente correcto pero violacion de regla de negocio |
| 429 | Demasiadas Solicitudes | Limite de tasa excedido |
| 500 | Error Interno del Servidor | Falla inesperada del servidor (evitar exponer detalles) |
| 503 | Servicio No Disponible | Interrupcion temporal, header Retry-After proporcionado |

## 2. Formato de Respuesta de Error (REST)

```json
{
  "error": {
    "id": "err_7f8a9b2c",
    "code": "INVALID_PARAMETER",
    "message": "El campo 'email' debe ser una direccion de correo valida.",
    "details": [
      {
        "field": "email",
        "issue": "invalid_format",
        "value": "no-es-email"
      }
    ],
    "timestamp": "2026-06-26T10:00:00Z",
    "path": "/v1/users",
    "retryable": false,
    "documentation_url": "https://docs.ejemplo.com/errors/INVALID_PARAMETER"
  }
}

3. Formato de Respuesta de Error (GraphQL)

{
  "data": null,
  "errors": [
    {
      "message": "El campo 'email' debe ser una direccion de correo valida.",
      "extensions": {
        "code": "INVALID_PARAMETER",
        "errorId": "err_7f8a9b2c",
        "field": "email",
        "retryable": false,
        "documentationUrl": "https://docs.ejemplo.com/errors/INVALID_PARAMETER"
      }
    }
  ]
}

4. Registro de Codigos de Error

CodigoEstado HTTPDescripcion
INVALID_PARAMETER400Fallo de validacion de campo
MISSING_REQUIRED_FIELD400Campo requerido no proporcionado
AUTHENTICATION_FAILED401Credenciales invalidas o expiradas
PERMISSION_DENIED403Permisos insuficientes
RESOURCE_NOT_FOUND404Recurso solicitado no encontrado
DUPLICATE_RESOURCE409El recurso ya existe
RATE_LIMIT_EXCEEDED429Demasiadas solicitudes
INTERNAL_ERROR500Error inesperado del servidor

5. Comportamiento de Reintento

Codigo de ErrorEstrategia de ReintentoReintentos MaximosBackoff
RATE_LIMIT_EXCEEDEDEsperar header Retry-After3Exponencial
INTERNAL_ERRORReintentar con jitter3Exponencial 1s, 2s, 4s
SERVICE_UNAVAILABLEReintentar con jitter5Exponencial
INVALID_PARAMETERNo reintentar0N/A
AUTHENTICATION_FAILEDNo reintentar0N/A

6. Requisitos de Logging

Cada respuesta de error debe ser logueada con:

  • ID de Error (para correlacion)
  • ID de Solicitud (de la solicitud entrante)
  • ID de Usuario (si esta autenticado)
  • Ruta del endpoint y metodo
  • Payload completo de error
  • Stack trace (solo errores 500, logs internos)
  • Timestamp

## Explicacion

La guia obliga a que cada error incluya un codigo legible por maquina (`INVALID_PARAMETER`) y un mensaje legible por humanos. El `errorId` permite a los consumidores referenciar la falla exacta al contactar soporte. El booleano `retryable` indica a los SDKs si el reintento automatico es seguro. Separar los formatos REST y GraphQL reconoce que GraphQL retorna 200 OK incluso para errores, por lo que la informacion de error vive en el arreglo `errors`.

## Variantes

| Contexto | Enfoque | Notas |
|----------|---------|-------|
| API Publica | Formato completo con URLs de docs | Los consumidores necesitan debugging autoservicio |
| API Interna | Formato ligero | Payload menor, consumidores mas simples |
| Microservicios | Incluir request ID para tracing | Esencial para debugging distribuido |

## Mejores Practicas

1. **Nunca retornar stack traces o SQL en respuestas de error** — loguearlos internamente
2. **Usar un registro de errores centralizado** para prevenir que los equipos inventen nuevos codigos
3. **Siempre incluir un request ID** para tracing entre servicios
4. **Documentar cada codigo de error** en una pagina de referencia publica
5. **Retornar 404 para recursos faltantes** sin distinguir "existe pero esta prohibido"

## Errores Comunes

1. **Retornar 200 OK para errores** — rompe la deteccion de errores del cliente
2. **Nombres de campo inconsistentes** (`error_message` vs `message` vs `detail`)
3. **No distinguir errores reintentables vs no reintentables**
4. **Exponer detalles de implementacion interna** en mensajes de error
5. **Usar 500 para errores de validacion** — 500 significa bug del servidor, no error del usuario

## Preguntas Frecuentes

### Las APIs GraphQL deberian retornar HTTP 200 para todas las solicitudes?

Si para errores de transporte, pero los errores de aplicacion deben estar en el arreglo `errors`. HTTP 400 es aceptable para sintaxis GraphQL malformada. HTTP 401/403 son aceptables para fallas de autenticacion.

### Como manejo errores de validacion con multiples campos?

Incluir un arreglo `details` con una entrada por campo en error. Cada entrada contiene el nombre del campo, el tipo de problema y el valor invalido.

### Que pasa si un consumidor envia una version de API invalida?

Retornar `400 Bad Request` con codigo `UNSUPPORTED_API_VERSION` y un mensaje apuntando a las versiones soportadas. No retornar 404 — el endpoint existe, la version no.