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— nuncatext/plain codesiempre es una cadena enSCREAMING_SNAKE_CASEdetailssolo está presente en respuestasVALIDATION_ERROR; se omite en los demás casos
Códigos de Estado HTTP
| Estado | Significado | Cuándo |
|---|---|---|
200 | OK | Petición exitosa |
201 | Created | Recurso creado exitosamente |
401 | Unauthorized | API key faltante o inválida |
403 | Forbidden | Clave válida pero scope insuficiente o límite del plan alcanzado |
404 | Not Found | El recurso no existe |
409 | Conflict | Recurso duplicado (ej. nombre de categoría ya existe) |
422 | Unprocessable Entity | Entrada inválida — ver details[] para errores por campo |
429 | Too Many Requests | Límite de tasa excedido |
500 | Internal Server Error | Error 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 conwk_live_owk_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:
| Header | Valor |
|---|---|
X-RateLimit-Limit | Peticiones permitidas por minuto |
X-RateLimit-Remaining | Peticiones restantes en la ventana actual |
X-RateLimit-Reset | Timestamp Unix (segundos) cuando la ventana se resetea |
Retry-After | Segundos 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
- Verifica
error.codeprimero, no solo el estado HTTP — múltiples códigos pueden compartir un estado - Para
VALIDATION_ERROR, iteraerror.detailspara mostrar mensajes a nivel de campo a los usuarios - Para
RATE_LIMITED, respeta el headerRetry-Aftercon backoff exponencial - No reintentes errores 4xx (excepto
RATE_LIMITED) — indican un problema del lado del cliente - Reintenta errores 5xx con backoff — indican problemas temporales del servidor
- Registra
error.code+error.messageen tu tracking de errores para debugging rápido