Errors
Every API error response follows the same structure. This page documents it and lists the possible codes.
Body structure
{
"timestamp": "2026-05-06T10:15:00",
"status": 400,
"error": "Bad Request",
"message": "externalId: External ID is required, price: Price must be positive",
"path": "/api/plugin/shops/shop_abc/products/sync"
}
| Field | Type | Description |
|---|---|---|
timestamp | string (ISO-8601) | Time of the error on the server |
status | integer | HTTP code (same as the response) |
error | string | Short phrase (Bad Request, Unauthorized, etc.) |
message | string | Readable detail. For 400 Bean Validation: comma-separated list field: reason |
path | string | Request path |
HTTP codes
| Code | Meaning | Client action |
|---|---|---|
400 Bad Request | Payload validation (Bean Validation) | Read message and fix the indicated field |
401 Unauthorized | Missing or invalid auth header (X-Widget-Token or X-Shop-API-Key) | Regenerate/rotate credentials or check the environment |
403 Forbidden | Origin mismatch, cross-tenant, insufficient role | Check the shop's configured domain and shopId |
404 Not Found | Resource does not exist (shop, product, etc.) | Verify the ID |
409 Conflict | Resource state incompatible (e.g. double verify) | Read message |
422 Unprocessable Entity | Logical error (e.g. parentExternalId not present in batch or DB) | Adjust payload |
429 Too Many Requests | Rate limit | Wait Retry-After, see Rate Limits |
500 Internal Server Error | Unexpected backend error | Retry with backoff; if persistent, Support with request id |
Field-level errors (400)
Bean Validation errors are concatenated in the message field, separated by commas, with the format field: reason. Real examples:
externalId: External ID is required
name: Product name is required
price: Price must be positive
description: size must be between 0 and 5000
currency: size must be between 0 and 3
rating: must be less than or equal to 5.0
products: Must provide between 1 and 500 products per batch
Validations declared in ShopRequestDTO.java (
PluginProductDTO) and ShopRequestDTO.java (1–500 batch).
Validation table for PluginProductDTO
| Field | Validation | Message |
|---|---|---|
externalId | @NotBlank | External ID is required |
name | @NotBlank @Size(max=512) | Product name is required / size must be between 0 and 512 |
description | @Size(max=5000) | size must be between 0 and 5000 |
price | @NotNull @DecimalMin(0.0) | Price is required / Price must be positive |
currency | @Size(max=3) | size must be between 0 and 3 |
url | @NotBlank | Product URL is required |
rating | @DecimalMin(0) @DecimalMax(5) | must be greater than or equal to 0.0 / must be less than or equal to 5.0 |
reviewCount | @Min(0) | must be greater than or equal to 0 |
stockQuantity | @Min(0) | must be greater than or equal to 0 |
salePrice | @DecimalMin(0) | must be greater than or equal to 0.0 |
Partial sync errors (200 with errors[])
The endpoint POST /api/plugin/shops/{shopId}/products/sync may return 200 OK with partial success when some products fail logical validation:
{
"totalReceived": 50,
"newProducts": 35,
"updatedProducts": 12,
"skipped": 0,
"failed": 3,
"errors": [
{
"externalId": "wc_prod_999",
"reason": "parentExternalId 'wc_parent_x' not found"
},
{
"externalId": "wc_prod_1000",
"reason": "Currency code must be ISO 4217 (3 characters)"
},
{
"externalId": "wc_prod_1001",
"reason": "Image URL is not a valid HTTP/HTTPS URL"
}
],
"productsCount": 7847,
"remainingProducts": 2153
}
Your integration must inspect errors[] and retry only the failed products after fixing the payload.
Log correlation
When you report an incident to the team:
- Capture the
timestamp,path, andmessageof the response. - If your HTTP client emits a
request id(X-Request-IDheader), include it. - Anonymize the payload (strip real
externalIdvalues if they carry sensitive information) before sending it to Support.
Further reading
- Rate Limits — backoff and headers.
- Shop API Key —
Originand403. - Widget Token — 24 h TTL and
401.