Skip to content
Reference

API reference

Server routes use your App API key. Applicant-side routes (used by the hosted flow and by custom SDKs) are scoped by the unguessable session id.

Authentication

Server-to-server routes (init, info) require x-api-key: <App API key>. A company-level key also works as a fallback. Applicant-side routes do not use the key: the session id acts as the capability, so never log or share it publicly. Keys belong on your server only.

Create a session

POST/api/session/init

See the quickstart for the body. Returns 201 with session, verificationUrl and resultPasskey. Additional optional fields: skipWelcomePage, enableAmerican (FATCA/US person question), enablePPE (PEP question), enableGeneralInformation, sessionInfo. Body values override App settings, which override defaults.

Errors: 400 invalid or missing field or unsafe webhook URL; 401 bad key; 402 monthly quota; 403 flow not enabled; 429 rate limit.

Get session info

GET/api/session/{id}/info

Requires x-api-key. Returns the session (without resultPasskey) and the application data. 404 if unknown; 403 if the session belongs to another company.

json
{
  "success": true,
  "session": { "sessionId": "…", "status": "FINISHED", "decision": "APPROVED", "riskScore": 6, "…": "…" },
  "application": { "…": "extracted fields, verification reports" },
  "ephemeral": false
}

Upload routes for SDK use

If you build your own capture UI instead of the hosted flow, use these routes. They are the same ones the hosted flow calls.

Document image

POST/api/session/{id}/upload

Multipart form with file (JPEG/PNG/WebP, max 10 MB), type=cin and side=front|back. PDFs are rejected on purpose. The response reports success or an errorCode (for example PDF_NOT_ACCEPTED, UNSUPPORTED_FILE_TYPE, DUPLICATE_CIN_NUMBER) that tells the user what to retake.

bash
curl -X POST https://YOUR_HOST/api/session/SESSION_ID/upload \
  -F "file=@front.jpg" \
  -F "type=cin" \
  -F "side=front"

Selfie

POST/api/session/{id}/selfie

JSON body { "image": "<base64>" }. A data-URL prefix is accepted. Returns { success: true, faceId }, or 400 on failure.

bash
curl -X POST https://YOUR_HOST/api/session/SESSION_ID/selfie \
  -H "Content-Type: application/json" \
  -d "{\"image\": \"$(base64 < selfie.jpg | tr -d '\n')\"}"

Update step

PATCH/api/session/{id}/update

Only step (and optionally language) may be set. Status is always computed by the server; a status in the body is ignored. Steps can advance or repeat but not go backwards.

bash
curl -X PATCH https://YOUR_HOST/api/session/SESSION_ID/update \
  -H "Content-Type: application/json" \
  -d '{"step": 3}'

Errors

StatusMeaningWhat to do
401Missing or invalid API key.Check the x-api-key header and that the app is active.
402QUOTA_EXCEEDED: monthly verification limit reached. Body includes limit and used.Raise the plan limit or wait for the next month (UTC).
403Flow not enabled for the account, or session belongs to another company.Check allowed flows and which key you use.
409Session is closed (APPROVED, DECLINED, EXPIRED), or a duplicate ID number.Create a new session.
413File larger than 10 MB.Resize or compress the photo.
415Unsupported file type, or a PDF.Send a JPEG, PNG or WebP photo.
429Rate limit hit. Retry-After header gives seconds.Back off and retry.

Rate limits

Limits are per client IP and per process, in fixed windows. They protect the service; do not design around them.

RouteLimit
POST /api/session/init60 requests / minute
PATCH /api/session/{id}/update60 requests / minute
POST /api/session/{id}/upload20 requests / minute
The limiter is in-memory. If you run several instances, each counts separately unless a shared store is added.

Status lifecycle

INITIATEDPENDINGFINISHEDVERIFICATIONAPPROVEDDECLINEDchecks cleanneeds reviewreviewer decision (either state)EXPIRED: terminal status (set by an admin); closed like APPROVED and DECLINED.
StatusMeaning
INITIATEDSession created, user has not started.
PENDINGUser is in the flow (capturing or submitting).
FINISHEDApplicant finished and every automatic check passed (auto-approve rules met). Webhook: verification.completed.
VERIFICATIONApplicant finished but something needs manual review. Webhook: verification.review_required.
APPROVEDFinal: a reviewer (or the result-link holder) approved. Webhook: verification.approved.
DECLINEDFinal: a reviewer declined. Webhook: verification.declined.
EXPIREDFinal: closed without a decision; no further uploads accepted.

FINISHED means the automatic rules found nothing to flag (see auto-approval); it is not the same as APPROVED, which is an explicit decision recorded with the actor and an optional reason. A decision can be made from FINISHED or VERIFICATION and corrected later. Decisions are made in the admin console, or through PATCH /api/session/{id}/decision with a signed-in admin session or the result passkey; it is not an API-key route.