Barrierepruefung.de Web Accessibility Checker

Setting up webhooks and verifying signatures

How your system learns when a scan has finished or a statement is outdated – with events, payload, signature verification and retries.

Diesen Artikel auf Deutsch lesen

A webhook saves your system from polling. It belongs to the organization, not to a single website: one endpoint fires for all websites. “Owner” and “Administration” may set it up.

Setting it up

  1. Open “Organization” → webhooks.
  2. Under “Create webhook”, enter the address – it must start with https:// – and optionally a description.
  3. Under “Events”, choose what you want to receive. Choosing nothing means: all.
  4. Use “Test event” to check that your endpoint is reachable and verifies the signature correctly.

The page shows the signing secret via “Show signing secret”. “Generate a new secret” replaces it – only the new one is valid afterwards.

Events

Event When
scan.completed A scan has finished.
scan.failed A scan has failed.
declaration.published A new version of a statement has been published.
declaration.outdated A published statement has been marked as outdated: Versions, “outdated” and PDF.

Structure of a call

Every call is a POST with a JSON body:

{
  "id": "01J…",
  "type": "scan.completed",
  "created_at": "2026-09-13T08:14:00+00:00",
  "data": { }
}

data contains the details of the event. id is the same for all endpoints of the same delivery. Process each id only once – a retry can bring the same message a second time.

Verifying the signature

The A11y-Signature header looks like this:

A11y-Signature: t=1789286400,v1=5257a869e7…
  • t is the timestamp in seconds,
  • v1 is HMAC-SHA256 over <t>.<body> with the endpoint’s signing secret, in hexadecimal.

To verify:

  1. Read t and v1 from the header.
  2. Take the unmodified body – do not parse it as JSON and serialise it again first.
  3. Compute HMAC-SHA256 over t, a dot and the body, and compare it with v1 in constant time.
  4. Reject calls whose timestamp is older than 5 minutes. The timestamp is part of the signature – so a captured call cannot be replayed later.

Example in PHP:

[$t, $v1] = [null, null];
foreach (explode(',', $_SERVER['HTTP_A11Y_SIGNATURE'] ?? '') as $part) {
    [$key, $value] = array_pad(explode('=', trim($part), 2), 2, null);
    if ($key === 't') { $t = (int) $value; }
    if ($key === 'v1') { $v1 = $value; }
}

$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $t.'.'.$body, $secret);

$valid = $t !== null && $v1 !== null
    && hash_equals($expected, $v1)
    && abs(time() - $t) <= 300;

Delivery, retries, switching off

  • Successful is a delivery your endpoint answers within 15 seconds with a 2xx status code. Respond quickly and process afterwards.
  • Retried are timeouts, server errors and the status codes 408 and 429 – several times, with growing intervals of up to two hours.
  • Not retried are other 4xx status codes: the problem is in the request or configuration, and a retry would change nothing.
  • Switched off is an endpoint after repeated failures in a row, and also when its address points to an internal network. The page shows the last error; after fixing it, switch the endpoint on again.

“Show recent deliveries” lists each delivery’s time, event and result. You can pause an endpoint temporarily.

Tokens of the organization

The same page lists all API tokens of your organization. A token is created on the respective website: Setting up and connecting the WordPress plugin.

Last checked against the product on September 13, 2026. As Markdown

Related articles

Still have a question?

Tell us which question is still open. Questions we hear more than once become new help articles.

Contact form All help articles