Errors
Every error is JSON, with a status code that tells you what kind of problem it is.
Shape
The ordinary shape is a single message:
JSON
{
"error": "unknown retailer"
}Status codes
| Status | Meaning |
|---|---|
| 400 | The request is malformed or refers to something that does not exist, for example an unknown retailer_id. |
| 401 | No token, or the token is not recognised. |
| 402 | Billing required: see below. |
| 403 | The token is valid but its role cannot do this. |
| 404 | Not found, or it belongs to a different factory or retailer than the one you authenticated as. |
| 409 | A conflict with the current state, for example scanning a piece that is already dispatched, or a duplicate retailer code. |
| 422 | The request body failed validation. See below. |
| 429 | Too many requests. See Rate limits. |
| 5xx | Something went wrong on our side. Every 5xx is logged for us automatically; retrying later is safe. |
402 billing required
Reading always works. Once a trial ends without a plan chosen, or a plan is cancelled, writes (creating orders, scanning, registering a webhook) return 402 with a machine readable code, so your integration can show a clear message instead of a generic failure:
JSON
{
"error": "Your Skuflo trial has ended. Choose a plan in Settings, Billing to keep going.",
"code": "billing_required"
}422 validation
Endpoints that accept a batch, such as POST /v1/orders/import or a sheet upload, validate every line before saving anything: if any line fails, nothing is saved, and every problem is reported at once rather than one at a time.
JSON
{
"error": "sheet has errors, nothing was saved",
"errors": [
{
"line": 4,
"error": "qty \"abc\" must be a whole number 1 to 500"
},
{
"line": 9,
"error": "SKU is blank"
}
]
}