Sessions
The production shape. Your backend creates a session with your secret key; the browser receives only a single-use session token.
1. Server: create the session
curl -X POST https://machine.cognau.com/api/v1/session/create \
-H "Authorization: Bearer $COGNAU_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"platform": "web",
"clientReference": "user_4821"
}'
{
"success": true,
"data": {
"sessionId": "6a7de599a5244ea6a3e65109",
"sessionToken": "cgn_st_…",
"environment": "live",
"livemode": true,
"challengeSequence": [{ "type": "headTurn", "index": 0, "params": {} }],
"wsEndpoint": "/api/v1/ws/session/6a7de599a5244ea6a3e65109",
"expiresAt": 1760000000000
}
}
clientReference
Your own identifier for whoever is being verified: a user id, an application
id, an order number. It is opaque to us, never parsed and never matched across
accounts, and it comes back on the webhook. Without it you must store our
sessionId at create time to know whose result arrived later.
Other options
| Field | Effect |
|---|---|
riskHint |
low shortens the sequence to 3 challenges; anything else uses 4 |
simulate |
sandbox only: pass or fail, chooses the fake verdict |
enablePersonId |
opt-in re-recognition; requires you to have collected consent |
deviceId |
your own device identifier, if you have one |
trainingConsent |
the user agreed their video may be retained for training |
/session/createcreates a sandbox session with a test keyKept in this page only. Never stored, never sent anywhere but the API.
2. Browser: run the check
Hand the session to the widget. Two shapes, both ending in the same place.
Let the widget fetch it. Give it your own route and it POSTs there when it is ready, which keeps the session from being created until someone actually reaches the step:
<script src="https://verify.cognau.com/embed.js"></script>
<script>
const v = Cognau.open({
sessionEndpoint: '/api/start-verification',
onVerdict: r => { v.close(); showPending(); },
});
</script>
Your route just proxies POST /session/create with your secret key. Return our
response verbatim if you like: the widget accepts the raw session or the
{ success, data } envelope.
Or hand it over yourself, if you already created the session:
const session = await fetch('/api/start-verification', { method: 'POST' })
.then(r => r.json());
const v = Cognau.open({ session, onVerdict: r => { v.close(); showPending(); } });
Pass the whole session object, not just the token: a session that also collects a document carries a second credential the widget needs.
Whichever you use, the token is delivered to the iframe over postMessage
after it signals readiness, never as a query parameter. A session token in a
URL would land in browser history, in the Referer of anything the page loads
next, and in the access log of whatever served it.
There is no publishable key to add. Nothing account-level goes to the browser; the session token is the only credential your page holds. See Authentication.
More on mounting, sizing and events: Embedding.
The optional document check
A session can also collect an identity document. It is a separate check, switched on per account, and it is metered separately from liveness, so a session that runs both is billed for both. A composite session reaches the document step only if liveness passes.
Be precise about what it does, because the name invites the wrong assumption.
| It does | It does not |
|---|---|
| Store the submitted image, encrypted | Read anything printed on it |
| Check the sides submitted match the declared type | Parse an MRZ or run OCR |
| Judge blur, glare, resolution and framing | Check an expiry date |
| Produce a recommendation for a reviewer | Compare the portrait against the liveness capture |
| Extract a name, date of birth or address | |
| Decide the outcome on its own, unless the account opts in |
There is no text extraction anywhere in this stack. If you need parsed identity fields, expiry checking, tampering analysis, or AML screening, this is not the tool for that part of the job, and it pairs with one rather than replacing it.
The decision is made by a person reviewing the submission, and the automated signal is a recommendation shown to them. An account can opt in to having a sufficiently clear-cut recommendation applied automatically; that is off unless you ask for it.
Accepted types are passport, id_card, residence_permit and
drivers_license. A document image is kept on its own retention schedule,
separate from liveness frames: see the biometric data
policy.
3. Server: trust the webhook
The verdict the browser sees is convenient for UX, but it arrives over a channel the end user controls. Make decisions from the webhook, which is signed and server-to-server. See Webhooks.
Sessions expire
A session is short-lived by design, measured in minutes. Create one when the user is about to verify, not when the page is built. If you need something that survives an email, use a verification link instead.
Reading results
curl "https://machine.cognau.com/api/v1/cockpit/sessions?clientReference=user_4821" \
-H "Authorization: Bearer $COGNAU_SECRET_KEY"
Filtering by your own reference is the point of setting it: you can answer "did user 4821 ever pass?" without having kept our identifiers.
Reading this as an agent? The raw Markdown is at /docs/sessions.md.