Skip to content

API reference

Interactive OpenAPI (try-it-out, schemas): {BASE}/docs

Backend (API key — Authorization: Bearer …)

Section titled “Backend (API key — Authorization: Bearer …)”
Method & pathPurpose
POST /v1/verificationsCreate verification → handoff token + URL
GET /v1/verifications/{id}Status, reasons, extracted fields
DELETE /v1/verifications/{id}/dataCryptographic erasure
POST /v1/attestations/{id}Issue signed attestation (approved only)
GET /v1/review/queueManual review queue (oldest first)
POST /v1/review/{id}Approve/reject with mandatory note

Device (handoff token — X-Handoff-Token: …)

Section titled “Device (handoff token — X-Handoff-Token: …)”
Method & pathPurpose
GET /v1/capture/statusBare status + next_step (no PII, ever)
POST /v1/capture/document?side=front|backUpload ID photo (multipart file)
POST /v1/capture/challengeGet the liveness pose sequence
POST /v1/capture/selfie?step=NUpload one challenge frame; processing starts after the last
Method & pathPurpose
GET /Landing + transparency statement
GET /healthLiveness probe
GET /docsOpenAPI UI
GET /v/{token}Hosted capture page (token enforced by the API it calls)
GET /v1/attestations/public-keyEd25519 public key (PEM)
ConstraintValue
Content typesimage/jpeg, image/png, image/webp
Max size15 MB
Min size1 KB (rejects junk/empty captures)
Frames per challenge stepExactly one; re-uploads rejected (409)

Per client IP, sliding window:

ScopeLimit
/v1/capture/*40 requests / minute
/v1/* overall240 requests / minute

On 429, honour the Retry-After header. Front with a CDN/WAF for volumetric protection beyond this.

All errors return {"detail": "human-readable reason"} with conventional status codes — the full table with causes and handling advice: Errors.