Identity Platform · Errors
Identity Platform-specific error codes you'll see, on top of the suite-wide list in Errors.
Verification-specific
| HTTP | Error string | Meaning |
|---|---|---|
| 400 | flash challenge expired | TTL elapsed before capture submit. Request a fresh challenge. |
| 400 | flash challenge nonce mismatch | Bundle's flashChallengeNonce doesn't match an issued challenge for this customer. |
| 400 | flash challenge already consumed | Single-use — you've already submitted a capture for this challenge. |
| 400 | bundle signature invalid | HMAC over the canonical bundle JSON doesn't verify with the provided hmacKey. |
| 400 | frames empty or too large | At least 1 frame required; max 12 MB base64 per frame. |
| 409 | replay detected | Bundle signature + timestamp seen before. Idempotency-deduped to original response. |
| 422 | liveness verdict failed | Bundle persisted, but antiSpoof.fused !== "live". Customer can retry. |
| 422 | tamper verdict failed | KTP capture passed liveness but failed tamper checks (e.g. NIK checksum). |
Match-specific
| HTTP | Error string | Meaning |
|---|---|---|
| 400 | captureBundleId or liveImage required | Provide exactly one source for the probe face. |
| 400 | at most one reference may be provided | Don't pass both faceEnrollmentId and referenceImage. |
| 404 | capture bundle not found or expired | Bundle ID is wrong, belongs to another customer, or has been retention-swept. |
| 422 | no active enrollments for customer | Match against pool requested but customer has no active reference. Enroll first. |
| 422 | bundle liveness verdict not passed | You're trying to match a bundle whose liveness check failed. Capture again. |
KYC tier
| HTTP | Error string | Meaning |
|---|---|---|
| 403 | org capability disabled: dukcapil | POST /nik/dukcapil requires per-org capability. Contact support. |
| 409 | cannot upgrade more than one tier above eligible | E.g. eligible is basic, you tried to upgrade straight to premium. Get the |
| intermediate verifications first or upgrade in two steps with reasons each. | ||
| 400 | reason too short | Analyst tier override requires at least 20-char reason. |
Auth
| HTTP | Error string | Meaning |
|---|---|---|
| 401 | missing scope: verifications:view | API key issued without this scope. Issue a new key with the right scopes. |
| 401 | webauthn challenge expired | Passkey enrollment/auth challenges have 5-minute TTL. |
| 429 | rate limit exceeded: ktp.capture | 20/min per key. Back off — see Rate limits. |
Troubleshooting
"All my captures are landing in requires_review." Check antiSpoof.voters[] and tamper.voters[] in the response. Often the culprit is flash_reflectance (camera flash off, or front-light too bright) or hologram_check (KTP is a scan/photocopy, not original).
"Face match similarity is always low." Look at perReference[]. If all sources are ktp_extract and the KTP photo was glare-damaged, the enrollment quality is poor. Resolve by re-running KTP capture in better lighting, or by ingesting a Dukcapil verdict (which gives you a clean photo).
"replay detected but I'm not replaying." Two clients submitted captures with the same bundle signature within the dedup window. Usually means a client retried after a network error without regenerating its signature. SDK clients handle this for you; raw API clients must generate a fresh signature for each retry.