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": [],
  "riskClasses": [],
  "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.

riskClasses

riskFactors names the individual reasons behind a liveness result. The codes are detailed and can change as the check improves, so rather than matching on them, route on riskClasses: the kinds of reason present, deduplicated. It is an empty array when there are none, and it can hold more than one class.

Class What it means What to do
spoof Evidence about the medium: what was in front of the camera did not behave like a live person in a room. Send a result that did not pass to a human review before you let the person try again.
compliance The person did not do what they were asked, or not fully. Offer another attempt with clearer guidance.
capture Our own measurement failed: not enough usable frames, too little light, a poor connection. This is not evidence of fraud. Offer another attempt, ideally with a hint about light and position.

Only spoof adds anything to the result on its own account. The other two are reported so you can tell a person who needs another go from a case that needs a person. A result can still be not passed with only capture or compliance present, because a check we could not measure, or a prompt that was not performed, gives the score nothing to pass on. Such a check is a result like any other and is billed as one.

A sandbox session whose result you forced with a test key ran no detection, so it has no class: riskClasses is empty and riskFactors marks the result as simulated. Pass or fail, route it on result alone.

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.