Errors
One envelope for every failure, the status and code table, and what is safe to retry.
The envelope
Every non-2xx response uses one envelope:
{
"error": {
"code": "validation_failed",
"message": "The request could not be processed.",
"details": [
{ "field": "phone", "code": "invalid", "message": "Phone must be in international format, e.g. +4520123456." }
]
}
}
details is present only for validation_failed.
Status and code
| Status | code |
When |
|---|---|---|
| 400 | invalid_request |
malformed query string or route parameters |
| 401 | unauthenticated |
missing, invalid, expired or revoked API key |
| 403 | insufficient_scope |
the key does not hold the scope this endpoint needs |
| 403 | not_available |
reseller (platform-mode) account — not supported in v1 |
| 403 | forbidden |
the person is managed by SnapKey and cannot be modified |
| 403 | lock_not_allowed |
the lock is not on this API key's allowlist |
| 404 | not_found |
no such row — including rows outside the key's scope |
| 405 | invalid_request |
that method is not supported on this path |
| 409 | iloq_rejected |
the locking system refused the create, change or delete |
| 409 | invitation_not_pending |
resend or cancel on an invitation that is activated, expired or cancelled |
| 409 | idempotency_conflict |
this Idempotency-Key was already used for a different body |
| 409 | idempotency_in_progress |
the first call with this Idempotency-Key is still running |
| 409 | subscription_paused |
redeliver on a paused subscription |
| 409 | lock_not_remote |
the lock is an iLOQ lock and cannot be opened over the network |
| 409 | lock_offline |
the lock's device has not been heard from recently |
| 422 | validation_failed |
the body failed validation; see details |
| 422 | entitlement_exceeded |
the account's plan limit for phone keys is reached — POST /keys, POST /invitations/{id}/resend |
| 429 | rate_limited |
rate limit exceeded; see Retry-After |
| 500 | server_error |
unexpected failure — safe to retry with backoff |
| 502 | publish_failed |
the command could not be handed to the device |
| 503 | not_available |
key revocation is not enabled on this server |
Field-level details
Each entry in details names the offending field — e.g. phone or security_groups[0] — a
code from the list below, and a message you can show or log.
invalid— the value is wrong for that field, such as a phone number that is not in international format.unknown_field— the body carried a field the endpoint does not accept. Unknown fields are rejected rather than ignored, so typos surface at once.reserved_name— thenameis one of SnapKey's reserved service names (SnapKey,Admin,ServiceUser), matched as the whole name or as the first word.unknown_security_group— a code insecurity_groupsdoes not exist at the API key's location. The detail names the offending index.sms_disabled— SMS delivery was asked for on an account without SMS.limit_reached— the location already holds the maximum of 5 active webhook subscriptions.
What is safe to retry
server_error(500) — an unexpected failure. Retry with backoff.rate_limited(429) — retry after the number of seconds inRetry-After.idempotency_in_progress(409) — the first call with thisIdempotency-Keyis still running. Retry after the 2 seconds inRetry-After.
Never retry these unchanged; they answer the same way every time:
validation_failed(422) — fix the body first;detailssays what is wrong.not_found(404) — the row does not exist, or is outside the key's scope.insufficient_scope(403) — the key does not hold the scope this endpoint needs. Issue a key that does.
iloq_rejected (409) means the locking system refused the create, change or delete, and nothing was
saved locally. Retry it only after checking the locking system — a blind retry meets the same
refusal.
Use an Idempotency-Key on POST /people, POST /keys and POST /webhooks so a retry after a
timeout cannot create a duplicate. Note that 5xx responses and 409 iloq_rejected are never
stored, so a retry with the same key re-executes.