Skip to main content
A session is one user-facing verification flow containing one or more primitive steps. You create it server-to-server; the user completes it on UIP’s hosted page; you receive results by webhook.

Lifecycle

1

created

POST /v1/sessions returns the session and its hosted url. Nothing is charged.
2

in_progress

The user opens the hosted page and begins; each step’s wallet response is verified and emits step.completed.
3

awaiting_decision (optional)

If a step is a gate, the session pauses here until you continue or stop it.
4

completed / stopped / failed / expired

A terminal state. The matching session.* webhook fires; any uploaded documents are purged.
StatusMeaning
createdMade, not yet opened by the user
in_progressUser is working through the steps
awaiting_decisionPaused at a gate, awaiting your continue/stop
completedAll steps verified
stoppedYou ended it at a gate
failedA step failed verification, or funds ran out
expiredThe session or a step window elapsed

The hosted page & capability URLs

The session url (https://uip.digital/s/{id}) is a capability URL — holding the link is what lets a user open the session. Treat it like a secret: deliver it over a channel only the intended user controls (your authenticated app, their phone).
First-open binding. The first browser to open a session is cryptographically bound to it; only that browser can submit a wallet response. A second device that later opens the same link is refused. This stops a leaked link from being completed by anyone but the user who started it — so don’t “preview” the URL server-side before handing it over.

Reading a session

GET /v1/sessions/{id} returns operational status and progress only — never the verified claims. Disclosed data and signatures are delivered exclusively by webhook; the capability URL holder can’t read them back out. Use the GET for polling progress or reconciling state, not for fetching results.

Create options

Beyond steps, POST /v1/sessions accepts:
FieldTypePurpose
client_reference_idstringYour own id, echoed on every webhook and stamped into the audit
metadataobjectUp to 50 string-valued keys; operational only (webhooks + reads), never shown to the user
return_urlhttps URLRenders a “Return to ” button on the hosted page after completion (never an auto-redirect)
expires_insecondsOverride the session TTL (60s–24h)
Plus an optional Idempotency-Key header so a retried create returns the original session instead of a duplicate. See Create a session for the full reference.

Expiry

Sessions have an overall TTL (default capped at 1 hour, or your expires_in), and each step has its own shorter window once started. Expiry is enforced lazily — an expired session resolves to expired on next access and emits no further steps.

Next: Wallets & coverage

Which wallets and countries can complete a session today.