Errors
Errors are returned as RFC 7807
application/problem+json:
{
"type": "urn:smartepi:error:forbidden",
"title": "Forbidden",
"status": 403,
"detail": "source IP not allowed"
}
The type is a stable URN identifier for the error class (urn:smartepi:error:<token>),
not a link to fetch — branch on it programmatically; do not expect it to resolve.
Application (RFC 7807) error responses carry an X-Request-Id header — include it
when reporting an issue. Gateway-level rejections (401 from a missing/invalid
key, 429 rate-limit) are produced before the application runs and do not
carry X-Request-Id.
Status codes
| Status | Meaning | What to do |
|---|---|---|
400 | Malformed request (bad JSON, invalid field, an invalid cursor), or a missing If-Match/_version on update/delete. | Fix the request body/params; only ever send back a cursor you received; send If-Match on writes. |
401 | Missing or invalid API key. | Check the Authorization header. |
403 | Authenticated but not allowed — e.g. the key's IP allow-list blocked the source IP (type: urn:smartepi:error:forbidden). | Call from an allowed IP, or remove/adjust the key's IP allow-list. |
404 | Not found, or not yours to access. | The id does not exist for you. |
405 | Method not allowed on this resource. | e.g. writing a read-only resource, or get-by-id on a list-only transaction. |
409 | Version conflict (stale _version, type: urn:smartepi:error:conflict), a duplicate entity name within your tenant (type: urn:smartepi:error:duplicate_name), or a delete blocked because the entity is still referenced (type: urn:smartepi:error:resource_in_use). | Re-read then retry for conflicts (see Concurrency); use a different name for duplicates; re-point or remove the dependents before deleting. |
422 | Foreign-key validation failed. | A referenced id is missing or not yours. |
429 | Rate limit exceeded. | Back off and retry after the indicated window. |
500 | Server error. | Retry with backoff; report the X-Request-Id. |
Notes on 404 vs 403
A 404 is returned both when a record genuinely does not exist and when it
isn't accessible to your API key — the API never reveals the existence of data
outside your organization. Do not treat 404 as "definitely deleted".
422 — foreign-key validation
On a write, every foreign key you set (e.g. costCenterId, sectorId,
jobRoleId, groupId, a group rule's productId) must reference a record that
belongs to your organization. If any does not, the whole write is rejected
with 422 and a detail naming the offending field — nothing is persisted.