Errors & idempotency
How the API reports problems, and how to retry safely.
Error format
Every error has the same JSON shape. code is stable and safe to branch on; message is for people and may change; field names the offending field, when there is one.
{
"error": {
"code": "invalid_state",
"message": "Application SPL-APP-2026-040 is rejected and can't be confirmed.",
"field": null
}
}Status codes
| Status | Meaning | Retry? |
|---|---|---|
400 | The request is malformed or a field is invalid. | No — fix the request |
401 | The key is missing, wrong or revoked. | No |
403 | The record belongs to another insurer. | No |
404 | No record with that reference. | No |
409 | The record is in the wrong state, e.g. confirming a rejected application. | No — fetch the current state |
422 | A business rule refused it. | No |
429 | Rate limited. | Yes, after Retry-After seconds |
5xx | A problem on our side. | Yes, with backoff and the same Idempotency-Key |
Idempotency
Send an Idempotency-Key header — a UUID you generate — with every POST. If the same key arrives again within 24 hours, you get the original response back and nothing happens twice. That makes it safe to retry after a timeout, when you can't tell whether the first attempt landed.
Use a new key for each distinct operation, and the same key only when retrying one.
Rate limits
Limits apply per key. When you exceed one, the API answers 429 with a Retry-After header saying how many seconds to wait.
Pagination
List endpoints take page and per_page (up to 200) and return a meta object with page, per_page and total. To keep your systems in sync, poll with updated_since rather than re-reading everything.