Webhooks
The browser sees a verdict, but it reaches you through the end user's device. Webhooks are signed and server-to-server, so this is where decisions belong.
Register an endpoint
curl -X POST https://machine.cognau.com/api/v1/cockpit/webhooks \
-H "Authorization: Bearer $COGNAU_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://acme.com/hooks/cognau",
"enabledEvents": ["verification.completed"]
}'
The signing secret is returned once. Endpoints are scoped to the environment of the key that created them, so test traffic never reaches your production receiver.
verification.completed
{
"sessionId": "6a7de599a5244ea6a3e65109",
"clientReference": "user_4821",
"result": "passed",
"confidence": 0.91,
"riskFactors": [],
"personKey": null,
"personSeenBefore": null,
"completedAt": "2026-08-13T12:04:20.000Z"
}
clientReference is whatever you set at session or link creation. It is the
field that lets you join this event to your own record without having stored
our sessionId.
Verify the signature
Every delivery carries x-cognau-signature. Compute HMAC-SHA256 over the raw
body with your endpoint secret and compare in constant time. Reject anything
that does not match, and do it before parsing the body.
Delivery
Deliveries are retried with backoff and claimed atomically, so exactly one of
your instances handles each one even when several are running. Respond 2xx
quickly; do the work afterwards. A persistently failing endpoint is disabled
and can be re-enabled from the dashboard, where you can also inspect the event
log and redeliver.
Handle duplicates. Retries mean the same event can arrive more than once, so
key on sessionId.
Reading this as an agent? The raw Markdown is at /docs/webhooks.md.