Skip to content
Test Candidates

Webhooks

The two events, what each payload contains, how deliveries are signed, and how to pause them.

Last updated 21 September 2026

A webhook tells your system something happened, the moment it happens, without you polling for it.

Account menu, then Integrations, then Webhooks.

The webhooks section of the integrations page, with an endpoint URL field and checkboxes for the two events.

Setting a webhook up

Give us an endpoint URL and choose the events you want. We POST to that URL when they happen.

The endpoint must be a public HTTPS URL. An address inside your own network cannot be reached, and plain HTTP is not accepted.

The two events

candidateCreated fires when someone registers for one of your assessments, before they have taken anything. The payload carries the candidate's identifier, email address, first name, surname and when they were created.

testCompleted fires when a candidate submits a test. The payload carries the candidate's identifier, which test it was, when it was completed, the score, how long it took, how many questions were correct, incorrect and in total, and the result detail.

Note that testCompleted fires per test, not per assessment. A candidate taking three tests produces three deliveries.

Verifying a delivery

Every delivery carries two headers:

  • X-Webhook-Timestamp, the time the request was signed.
  • X-Webhook-Signature, of the form sha256= followed by an HMAC-SHA256.

The HMAC is keyed with your signing secret and computed over the timestamp, a full stop, and the raw request body:

sha256=HMAC-SHA256(secret, "{timestamp}.{raw body}")

Your signing secret is shown on the webhooks section once an endpoint is set.

Verify every delivery before you act on it, and compute the HMAC over the raw body rather than over a re-serialised version of the parsed JSON. Treat the secret with the same care as your API key.

Responding to a webhook

Answer quickly with a success status and do your real work afterwards. Deliveries have a short connection and response timeout, and a slow endpoint looks like a failed one.

Build your handler to tolerate the same event arriving twice. That is ordinary webhook hygiene and it costs a few lines.

Pausing webhook delivery

Clear both event selections. The endpoint stays saved and nothing is sent until you select an event again. That is the tidy way to stop deliveries while you redeploy, without losing your configuration.

Changing the endpoint

Change the URL and save. Existing event names and payload shapes stay the same, so moving an endpoint does not mean rewriting your handler.

Webhooks and the API together

A webhook is a good trigger and a poor source of truth. A common pattern is to use testCompleted as the signal and then read the full record from the API, which gives you the candidate's whole history rather than one attempt.