Manejo de Errores

Códigos de estado HTTP, formato de errores y referencia completa de códigos de error.

Sobre de Error

Todas las respuestas de error — independientemente del código de estado — usan un sobre JSON consistente:

{
  "error": {
    "code": "SCREAMING_SNAKE_CASE",
    "message": "Descripción legible por humanos",
    "details": [
      { "field": "nombre_campo", "message": "Descripción del problema" }
    ]
  }
}

Garantías:

  • Toda respuesta de error es application/json — nunca text/plain
  • code siempre es una cadena en SCREAMING_SNAKE_CASE
  • details solo está presente en respuestas VALIDATION_ERROR; se omite en los demás casos

Códigos de Estado HTTP

EstadoSignificadoCuándo
200OKPetición exitosa
201CreatedRecurso creado exitosamente
401UnauthorizedAPI key faltante o inválida
403ForbiddenClave válida pero scope insuficiente o límite del plan alcanzado
404Not FoundEl recurso no existe
409ConflictRecurso duplicado (ej. nombre de categoría ya existe)
422Unprocessable EntityEntrada inválida — ver details[] para errores por campo
429Too Many RequestsLímite de tasa excedido
500Internal Server ErrorError inesperado del servidor

Referencia de Códigos de Error

AUTHENTICATION_ERROR — 401

Retornado cuando el header X-API-Key está ausente, malformado, inválido, expirado o inactivo.

{
  "error": {
    "code": "AUTHENTICATION_ERROR",
    "message": "Missing X-API-Key header"
  }
}

Otros mensajes para este código:

  • "Invalid API key format" — la clave no comienza con wk_live_ o wk_test_
  • "Invalid or inactive API key" — clave no encontrada o desactivada
  • "API key has expired" — la fecha de expiración de la clave ha pasado

SCOPE_INSUFFICIENT — 403

Retornado cuando la API key no tiene el scope requerido para el endpoint.

{
  "error": {
    "code": "SCOPE_INSUFFICIENT",
    "message": "This API key does not have the 'write:products' scope"
  }
}

PLAN_LIMIT_EXCEEDED — 403

Retornado cuando una operación de creación excedería el límite del plan de la tienda.

{
  "error": {
    "code": "PLAN_LIMIT_EXCEEDED",
    "message": "Plan limit exceeded for products: 100/100"
  }
}

NOT_FOUND — 404

Retornado cuando el recurso solicitado no existe.

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Resource not found"
  }
}

También retornado para rutas desconocidas (endpoint no encontrado):

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Route GET /v1/unknown not found"
  }
}

CONFLICT — 409

Retornado cuando un recurso ya existe (ej. nombre duplicado).

{
  "error": {
    "code": "CONFLICT",
    "message": "Resource already exists"
  }
}

VALIDATION_ERROR — 422

Retornado cuando la entrada falla la validación. Siempre incluye un arreglo details con errores por campo.

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request parameters",
    "details": [
      { "field": "price", "message": "Number must be greater than 0" },
      { "field": "name", "message": "Required" }
    ]
  }
}

La propiedad field usa notación de punto para campos anidados (ej. "address.city").


RATE_LIMITED — 429

Retornado cuando la API key excede su cuota de peticiones por minuto. Incluye un header Retry-After (en segundos).

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Retry after 23 seconds."
  }
}

Headers de respuesta en respuestas de límite de tasa:

HeaderValor
X-RateLimit-LimitPeticiones permitidas por minuto
X-RateLimit-RemainingPeticiones restantes en la ventana actual
X-RateLimit-ResetTimestamp Unix (segundos) cuando la ventana se resetea
Retry-AfterSegundos a esperar antes de reintentar

INTERNAL_ERROR — 500

Retornado para fallos inesperados del lado del servidor. El mensaje es intencionalmente genérico — los detalles internos nunca se exponen.

{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An unexpected error occurred"
  }
}

Mejores Prácticas

  1. Verifica error.code primero, no solo el estado HTTP — múltiples códigos pueden compartir un estado
  2. Para VALIDATION_ERROR, itera error.details para mostrar mensajes a nivel de campo a los usuarios
  3. Para RATE_LIMITED, respeta el header Retry-After con backoff exponencial
  4. No reintentes errores 4xx (excepto RATE_LIMITED) — indican un problema del lado del cliente
  5. Reintenta errores 5xx con backoff — indican problemas temporales del servidor
  6. Registra error.code + error.message en tu tracking de errores para debugging rápido

On this page