Error codes
Every error from the Center's API shares one shape. If you are integrating against the API, this is the contract to code against.
The envelope
{
"code": "NOT_FOUND",
"statusCode": 404,
"path": "/api/v1/projects/018f3a1e-…",
"timestamp": "2026-08-20T09:15:00.000Z"
}
| Field | Meaning |
|---|---|
code | Stable, machine-readable. Branch on this. |
statusCode | The HTTP status, repeated in the body. |
path | The request path that failed. |
timestamp | When it failed, ISO-8601. |
message | Sometimes present. Developer-facing, not localised, not stable. |
code is part of the API contract and will not change without notice. message
is a developer aid — its wording can change at any time, and it is never
translated. Building UI text from it will break.A NOT_FOUND also carries entity and id, naming what was not found.
The codes
| Code | HTTP | Means | Do |
|---|---|---|---|
VALIDATION_ERROR | 400, 422 | The body or query is malformed, or carries a field the endpoint does not accept. | Check the request against the API reference. Unknown fields are rejected, not ignored. |
UNAUTHENTICATED | 401 | Token missing, malformed or expired. | Refresh the token, or sign in again. |
UNAUTHORIZED | 403 | Authenticated, but not permitted. | Check the member's role, and the active tenant. |
NOT_FOUND | 404 | No such record in the caller's tenant. | Check the id — and the tenant. See below. |
CONFLICT | 409 | The change collides with an existing record. | Usually a duplicate identifier or slug. |
SIGFOX_LIVE_DISABLED | 403 | Live provider writes are switched off here. | Use the plan endpoints, or ask an operator to enable it. |
INTERNAL_ERROR | 500 | Something failed unexpectedly. | Retry; if it persists, it is a bug worth reporting. |
Why cross-tenant reads are 404
Asking for a record belonging to another tenant returns 404, not 403.
That is deliberate. A 403 would confirm the id exists, which leaks information across tenant boundaries. From outside a tenant, its records are indistinguishable from records that were never created.
The practical consequence: a 404 on an id you are sure exists usually means the
wrong tenant, not a wrong id. Check the x-tenant-id you sent.
Unknown fields are rejected
The API rejects request bodies carrying properties it does not recognise, rather than silently ignoring them.
This catches typos that would otherwise fail quietly — sending deviceID instead
of deviceId is an error you see immediately, not a field that goes missing.
If you are seeing VALIDATION_ERROR on a request that looks correct, check for a
stray or misspelled property before anything else.
Errors at ingest
The ingest endpoints behave differently, because they are not authenticated with a Center token:
| Status | Means |
|---|---|
| 201 | Accepted, with something to return — a downlink, for instance. |
| 204 | Accepted, nothing to say back. The normal success. |
| 401 | The source adapter rejected the payload — wrong shared secret, failed signature, or a missing required header. Not a login problem. |
| 404 | No such integration, key or slug. Often a rotated key still in use by the sender. |