Skip to main content
The session-based flow is the recommended integration path when:
  • Your app runs on a device that may not have a camera (desktop web app, kiosk)
  • You want the verification UI to live on the user’s mobile device while the rest of your app runs elsewhere
  • You want to embed Tuteliq’s verified UI in a webview without rebuilding the capture flow yourself
You create a session on your server, hand the user a URL or QR code that opens Tuteliq’s hosted capture page (or embed that page in a webview), and your server gets the result back via Server-Sent Events or polling. No image data passes through your servers; Tuteliq processes the documents and selfie directly from the mobile device.

Age Verification Quick Start

Verify a user’s age in three steps with a hosted verification session. This is the exact flow you can try interactively in the API Playground in your dashboard, the document scan, selfie, and liveness checks all happen on Tuteliq’s hosted page, so you never handle the user’s ID or biometric data yourself.
Hosted age verification requires the Pro plan or above and costs 5 credits per completed verification. You’ll need an API key, create one under API Keys in your dashboard.

How it works

Tuteliq creates a short-lived, hosted verification session and returns a URL. You send your user to that URL, they complete the checks on Tuteliq’s page, and you poll the session until it reaches a terminal status.
  1. Create a session with mode: "age".
  2. Redirect the user to the returned verification URL.
  3. Poll the session for the result.

1. Create a session

Send a POST to /api/v1/verify/session with the mode set to age.
The response contains the session ID, the hosted verification URL, and an expiry timestamp (Unix milliseconds):

2. Send the user to verify

Open the mobile_url in a new tab, redirect to it, or surface it as a QR code / deep link. The user scans their ID document and completes a selfie liveness check on Tuteliq’s hosted page.

3. Poll for the result

Poll GET /api/v1/verify/session/{session_id} every few seconds until the top-level status reaches a terminal value: completed, failed, expired, or cancelled. The verification outcome lives at result.status.
A completed, successful age-mode session has this shape:
The fields most integrations care about are result.status (verified, failed, or needs_review), result.is_minor (boolean), result.age (integer years), and result.failure_reasons (array, empty on success). The full result.document, result.document_validation, result.face_match, and result.liveness sub-objects are available when you need detailed evidence for your own audit logs or moderator UI.

Full example

The complete create → redirect → poll flow in TypeScript:
The rest of this page covers the deeper integration patterns: live updates via Server-Sent Events instead of polling, embedding the verification UI in a mobile webview, and handling identity verification (full KYC, Business plan and above).

Flow at a glance

Step 1: Create a session (server-side)

Always create the session on your server with your API key. Never expose your API key on the client.

Response

expires_at is a Unix millisecond timestamp; sessions are valid for 15 minutes after creation. The mobile_url is single-use and tied to the session. Tokens are revoked the moment the session completes, fails, or expires.

Modes and tier availability

Both modes return the verified data to your server so you can act on it. Tuteliq does not retain any of it after the response is sent. See Zero retention below.

Step 2: Hand the URL to the user

Three patterns, pick the one that fits your product:

Pattern A: Embed in a webview (same-device flow)

The user’s session lives inside your app. The webview loads mobile_url, the user completes capture without leaving your app, you get the result back via SSE. This is the most common pattern for mobile apps.
The Info.plist must include NSCameraUsageDescription and NSMicrophoneUsageDescription for the in-page capture to work.

Pattern B: QR code (desktop-to-mobile handoff)

The session is created on your desktop app or website; the user scans a QR code with their phone and completes verification on the phone.
Node
The user scans, completes capture on their phone, and the desktop UI auto-advances when the SSE stream emits status: "completed".

Pattern C: Redirect (single-device, browser-only)

Best for low-friction onboarding flows where the user is already on mobile in your web app.
Node
The user is sent away to Tuteliq’s capture UI; on completion, they’re redirected back to your redirect_url. Your redirect_url handler then calls your backend to read the result.

Step 3: Watch status updates

Two ways to know when the verification is done. Server-Sent Events is the recommended primary channel; polling is the fallback. The session emits real-time events you can listen to with no polling overhead. Works from any client (browser, mobile, server).
Web / browser
The events endpoint does not require authentication. The session ID has 128 bits of entropy and is single-use; treat it as a secret-equivalent for the lifetime of the session.

Option B: Polling

If your environment can’t hold an open SSE connection (e.g. serverless functions with short timeouts), poll instead:

Step 4: Read the final result

The result is included in the SSE result event AND accessible via GET /api/v1/verify/session/:id once the session is in a terminal state.

Age verification result

See the full shape in Step 3 above. The body is identical whether you receive it through SSE or the polled GET.

Identity verification result

Identity mode (Business plan and above) returns the same outer envelope as age mode (session_id, status, result, created_at, expires_at), but the inner result object differs:
Compared with age mode, identity mode returns the full full_name and date_of_birth PII required for KYC, plus a face_match score, but does not include the document-validation sub-checks block.

Status states

Common pitfalls

Webview camera permission

iOS and Android webviews deny camera access by default. You must explicitly grant it in both the webview configuration and the host app’s permission manifest. The samples above include the right configuration for each platform.

CORS for the iframe pattern

If you embed via <iframe>, browsers require allow="camera; microphone" on the iframe element, AND your parent page must be served from an HTTPS origin (browsers block camera permission on plain HTTP).

SSE behind reverse proxies

If your client connects through nginx, Cloudflare, or other proxies, SSE connections need:
  • proxy_buffering off
  • proxy_cache off
  • Connection timeout > 5 minutes (Tuteliq holds the SSE open for the full session lifetime)
If the SSE connection is dropped at the proxy layer, fall back to polling (see Step 3 Option B).

Server-side session ownership

Only the API key that created a session can call GET /api/v1/verify/session/:id or DELETE. The mobile capture URL and the SSE events endpoint are session-token-authenticated (the URL contains the token) and do not need your API key. Keep the API key on your server, never expose it to the client.

Session expiry

Sessions expire 15 minutes after creation. If the user is slow, give them a fresh session rather than extending the old one; the expiry is a security feature, not a quota.

Zero retention

There are two things to keep separate:
  1. What’s returned to your server. The verification result includes the fields you need to act on: verified age, full name (identity mode), date of birth, document type, country, face match, liveness, and the document-validation sub-checks. Your application is the only place this data lives going forward. You are the controller for it under GDPR; Tuteliq is the processor for the duration of the API call and nothing more.
  2. What Tuteliq retains. Nothing. The uploaded document images, the selfie, the captured liveness frames, and the extracted PII are all held in memory only for the duration of the request, then destroyed when the response is sent. No persistent storage, no derived hashes, no embeddings, no fingerprints, no training corpus contribution.
The only artifact that outlives the request on Tuteliq’s side is the signed audit receipt — a cryptographic attestation that a verification happened, with no PII inside it. The receipt is verifiable out-of-band against the published Tuteliq public key and exists to satisfy EU AI Act Article 12 logging requirements without re-introducing data-protection liability. If your customer is later asked to prove what happened (regulator request, civil discovery, NCMEC subpoena), the audit receipt + your application’s own record of the result is the audit trail. Tuteliq has no way to reproduce the inputs even if compelled.

Reference: full Node.js end-to-end

Next steps