Error codes
This page is the single source of truth for error handling. SDK-specific error codes are documented in each SDK's Error handling page; this page covers errors at the API contract level.
HTTP status codes
| Code | Meaning | Where it applies |
|---|---|---|
200 OK | Request succeeded. | All contracts. |
201 Created | Resource created (rare; most creations return 200). | API contract. |
400 Bad Request | Payload is malformed or required fields are missing. The body identifies the problematic fields. | All contracts. |
401 Unauthorized | Authentication missing, expired, or invalid. | All contracts. |
403 Forbidden | Authentication is valid but the tenant is not enabled for the requested resource (e.g., calling a capability not in your APIKEY). | Web & SDK, API. |
404 Not Found | Resource does not exist or does not belong to the authenticated tenant. | All contracts. |
409 Conflict | The resource exists but is not in the right state for this operation (e.g., fetching documents from a process still in progress). | Web & SDK, API. |
410 Gone | The resource existed but was deleted per the retention policy (document fetch endpoints), or the process exists but ended in an error state — see Get Process. | Document fetch endpoints; API Get Process. |
429 Too Many Requests | You hit the rate limit. Retry with exponential backoff. | All contracts. |
5xx | Platform error. Retry with backoff; if persistent, contact support with the response body and timestamp. | All contracts. |
Authentication errors (401)
| Cause | Symptom |
|---|---|
| Wrong private key (assertion signed with the wrong key) | 401, Authentication failed (1.2.21) |
aud does not match the environment URL | 401 |
exp claim in the past | 401, Authentication failed |
Unsupported algorithm (use RS256) | 401 |
| Mixed sandbox / production credentials | 401, even though credentials look correct |
Missing APIKEY header (API contract only) | 401 |
Invalid x-api-key (Magic Link only) | 401 |
See Authentication > Common errors for the full troubleshooting checklist.
Capability-level outcomes (200 with negative result)
A 200 OK does not mean the user passed the verification — it means the platform completed the work. The user-facing decision lives in the response body, not the HTTP status:
| Field | Negative value | Where it appears |
|---|---|---|
process.result | PROCESS_RESULT_FAILED | Web & SDK |
process.authenticationInfo.livenessResult | NO | Web & SDK |
liveness | 2 | API |
unicoId.result | no | API |
data.result.status | not_verified | Magic Link |
Retry policy
| Status | Should retry? | How |
|---|---|---|
5xx | Yes | Exponential backoff (1s, 2s, 4s, 8s, …). Cap at 5 attempts. |
429 | Yes | Honor the Retry-After header if present; otherwise exponential backoff. |
4xx (other) | No | The request is wrong. Fix the input before retrying. |
401 | Conditionally | Refresh the access token once. If the new request also returns 401, the issue is structural — don't retry. |
The IDCloud platform does not currently expose an idempotency-key mechanism on creation endpoints. Be cautious when retrying POST /client/v1/process or POST /processes/v1 — a network error on a 5xx may have actually succeeded server-side, and a retry would create a duplicate process. When in doubt, retrieve recent processes by your internal correlation ID before retrying.
Where SDK errors live
The error catalogs of the Web SDK, Android SDK, iOS SDK, and Flutter SDK are documented in each SDK's dedicated Error handling page:
- Web SDK > Error handling
- Android SDK > Error handling
- iOS SDK > Error handling
- Flutter SDK > Error handling
These cover device-side errors (camera permission denied, capture timeout, network unreachable on the device) — separate from the API-side errors documented here.