Errors & step-up
Errors & step-up
The error envelope
Plane errors are JSON with a stable machine-readable code:
| HTTP | error |
Meaning |
|---|---|---|
| 400 | invalid_body |
Missing/malformed body (e.g. no data object, no file part) |
| 400 | invalid_document |
Payload fails the schema it is validated against |
| 400 | unsupported_item |
Operation not defined for the slot’s kind (e.g. create on id_document) |
| 401 | unauthenticated |
No valid caller behind the token |
| 403 | partner_token_required |
A first-party (non-partner) token was presented |
| 403 | unknown_client |
The token’s client is no longer registered |
| 403 | organization_suspended |
Your owning organization is suspended |
| 403 | connection_inactive |
The connection is revoked, withdrawn, or expired |
| 403 | verb_not_granted |
The slot does not carry the verb this operation needs |
| 403 | delete_refused |
The platform protects this document from deletion |
| 404 | not_found |
Ungranted, foreign, malformed, or nonexistent — deliberately one answer |
| 409 | ambiguous_item |
The (kind, target) pair matches several slots / records — use slot ids |
| 423 | sealed |
The user’s vault is sealed; see step-up below |
| 500 | server_error |
Transient server failure — safe to retry |
Info
Read 404 as “nothing for you here”, never as “does not exist.” The same
answer covers an item the user declined to share, an id from another user, and
an id that was never real. Probing teaches nothing — by design.
One 403 has a different body: the assurance gate (session security-level
enforcement) answers with the platform’s GraphQL-style envelope —
{"errors":[{"message":"…","extensions":{…}}]} with a machine-readable
step-up code in extensions. Treat any 403 of that shape exactly like 423 sealed: run the step-up flow below, then retry.
Sealed vaults and step-up
Geena accounts have three security levels. Standard accounts are unsealed
automatically when your tokens are issued — most calls just work. Enhanced
and Maximum accounts keep the vault sealed until the user themselves
provides fresh proof (face scan; plus PIN for Maximum). When a call needs the
vault and it is sealed, you get 423 sealed.
Your app cannot unseal anything — but it can hand the user to Geena’s hosted verification page and retry afterwards:
1. Mint a step-up hand-off (authenticated with your access token):
The token is shown exactly once and is single-use.
2. Open the hosted verification page (popup, like the connect ceremony):
The user completes the face scan (and PIN on Maximum accounts) on Geena’s origin. Completion stamps your partner session and unseals the vault.
3. Retry the refused call. No re-consent, no new tokens — the same access token now passes.
Minting a step-up for a Standard account answers 400 (“no step-up required”)
— if you see it, the original failure was something else.