Reference · Errores
Esta página enumera los códigos HTTP que la API de Neuroon puede devolver y la estructura común del body. Todas las respuestas de error vienen del el backend salvo casos puntuales.
Estructura del body
{
"timestamp": "2026-05-06T10:15:00",
"status": 400,
"error": "Bad Request",
"message": "field-level error joined with commas",
"path": "/api/widget/search"
}
| Campo | Tipo | Notas |
|---|---|---|
timestamp | string | LocalDateTime.now.toString — sin timezone explícito (servidor en UTC). |
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
| Status | Causa típica | Cómo resolver |
|---|---|---|
| 400 Bad Request | Validación fallida (@Valid, @RequestParam ausente, IllegalArgumentException, IllegalStateException). | Revisar los nombres de campos del message y volver a enviar. |
| 401 Unauthorized | credenciales inválidas o token ausente/inválido. La cabecera esperada es X-Widget-Token o X-Shop-API-Key según endpoint. | Comprobar la cabecera; refrescar token si caducó. |
| 403 Forbidden | permiso denegado: origin mismatch del Widget Token o cross-tenant en plugin endpoints. | Verificar que el token pertenece al shopId solicitado y que el dominio en Origin coincide con los permitidos. |
| 404 Not Found | Recurso inexistente (shopId, producto, plan). | Comprobar el id; en sync de productos, verificar que el shop existe primero. |
| 409 Conflict | Duplicado de identidad (p. ej. externalId ya registrado en full sync). | Considerar si debe ser INCREMENTAL en lugar de FULL. |
| 422 Unprocessable Entity | Reglas de negocio: parent product not found, currency mismatch entre items, etc. | Inspeccionar message; corregir el payload. |
| 429 Too Many Requests | Rate limit excedido. | Esperar lo indicado en Retry-After y reintentar con jitter. Ver Rate Limits. |
| 500 Internal Server Error | Excepción no controlada (Exception genérico). | Reportar a soporte con timestamp y path. |
| 502 Bad Gateway | Fallo de un proveedor externo del que depende esta ruta. | Reintentar con backoff; si persiste, contactar soporte. |
| 503 Service Unavailable | Circuit breaker abierto sobre proveedor externo. | Esperar y reintentar con backoff. |
Errores específicos del dominio
Estos no son status HTTP nuevos: viajan en message con el mismo body genérico, pero conviene reconocerlos porque tu integración suele querer tratarlos distinto.
| Mensaje (clave) | Status | Significado |
|---|---|---|
DUPLICATE_EXTERNAL_ID | 409 | El externalId ya existe en FULL sync. Cambiar a INCREMENTAL o limpiar el shop. |
PARENT_PRODUCT_NOT_FOUND | 422 | Estás sincronizando una variante cuyo parentProductId no existe. Sincroniza el padre primero. |
SHOP_NOT_FOUND | 404 | El shopId del path no existe. |
WIDGET_TOKEN_EXPIRED | 401 | El token ha caducado (TTL 24 h). Regenerar y re-render. |
ORIGIN_NOT_ALLOWED | 403 | El header Origin no coincide con los dominios autorizados. Añadirlo desde el Dashboard. |
RATE_LIMIT_EXCEEDED | 429 | Cuota superada. Ver Retry-After y X-RateLimit-*. |
Si tu plataforma necesita códigos de error estables como contrato, contacta a soporte para activar el formato extendido
{ "code": "...", ... }. El default actual es texto plano.
Validation errors (400)
errores de validación y errores de validación 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"
}
.
Buenas prácticas
- No parsees el
messagecon regex — el formato puede cambiar. Usa elstatusy, si necesitas semántica, el código del dominio. - Reintenta en 429, 502, 503 con backoff exponencial + jitter.
- No reintentes en 400, 401, 403, 404, 409, 422 — son fallos del cliente.
- Loguea el
timestampypathpara correlacionar con el lado servidor cuando abras un ticket.