Reference · Errores
Códigos HTTP que la API de Neuroon puede devolver y la estructura del body. La mayoría de respuestas vienen del GlobalExceptionHandler (api/src/main/java/.../rest/GlobalExceptionHandler.java); las excepciones se documentan abajo.
Envoltura estándar
{
"timestamp": "2026-05-06T10:15:00",
"status": 400,
"error": "Bad Request",
"message": "field-level error joined with commas",
"path": "/api/widget/search"
}
Generada en
GlobalExceptionHandler.java:147-156.
| Campo | Tipo | Notas |
|---|---|---|
timestamp | string | LocalDateTime.now().toString() (servidor en UTC, sin zona explícita). |
status | number | Código HTTP. |
error | string | Reason phrase del status (Bad Request, Unauthorized, …). |
message | string | Detalle. En 400 incluye errores de validación concatenados con , . |
path | string | Ruta sin el prefijo uri= que añade WebRequest. |
Códigos HTTP que emite el handler global
| Status | Excepción Java que lo dispara | Significado |
|---|---|---|
| 400 Bad Request | MethodArgumentNotValidException, ConstraintViolationException, MissingServletRequestParameterException, IllegalStateException, IllegalArgumentException | Validación fallida (@Valid, @RequestParam ausente, regla de dominio). |
| 401 Unauthorized | BadCredentialsException | Credenciales inválidas. |
| 403 Forbidden | AccessDeniedException | Token no autorizado para el recurso. |
| 404 Not Found | ResponseStatusException(NOT_FOUND) lanzada desde un controller | Recurso inexistente (shopId, producto). |
| 500 Internal Server Error | Exception (catch-all) | Excepción no controlada. Reportar con timestamp y path. |
| 502 Bad Gateway | PaymentGatewayException | Stripe inaccesible. |
| 503 Service Unavailable | CallNotPermittedException (circuit breaker abierto) | Proveedor externo en estado abierto. Reintentar con backoff. |
Otros status (
405,409,415, …) los emite Spring por defecto sin pasar por el handler — el body llega con la envoltura estándar de Spring ({ timestamp, status, error, path }) sinmessage.
Casos especiales (envoltura distinta)
429 Too Many Requests — rate limit
Lo emiten los filtros (WidgetRateLimitFilter, RateLimitFilter), no el handler global. La envoltura es distinta:
{
"error": "rate_limit_exceeded",
"message": "Too many requests. Please try again later.",
"retryAfter": 60,
"limit": 200,
"remaining": 0,
"timestamp": "2026-05-06T10:15:00Z"
}
Construido en
WidgetRateLimitFilter.java:90-93. Headers asociados:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining. Ver Rate Limits.
401 / 403 desde ApiKeyAuthenticationFilter
Cuando la Shop API Key falla la validación, el filtro de autenticación emite directamente sin pasar por el handler global:
{
"error": "Invalid or missing X-Shop-API-Key header",
"status": 401
}
En
ApiKeyAuthenticationFilter.java:131. Mismo formato cuando el origen no está autorizado pero constatus: 403.
Validation errors (400)
MethodArgumentNotValidException y ConstraintViolationException se concatenan en message con formato field: descripción:
{
"timestamp": "2026-05-06T10:15:00",
"status": 400,
"error": "Bad Request",
"message": "products[0].externalId: must not be blank, products[0].price: must be positive",
"path": "/api/plugin/shops/123/products/sync"
}
GlobalExceptionHandler.java:22-47.
Buenas prácticas
- No parsees el
messagecon regex — el formato no es estable. - Reintenta sólo en
429,502,503con backoff exponencial + jitter. - No reintentes en
400,401,403,404— son fallos del cliente. - Loguea
timestamp,pathy, si lo tienes, elrequestIdpara correlacionar con el lado servidor cuando abras un ticket. - Diferencia las dos envolturas — la mayoría usa
{ timestamp, status, error, message, path }; rate-limit y filtros de auth usan formatos propios.