Skip to main content
Register an https URL and you receive an event each time a twin ends. Events are signed as the Standard Webhooks specification signs them, so any Standard Webhooks library verifies them.

Endpoints

The secret is shown only once, in this response. Store it with your other secrets. To change a secret, create a new endpoint and delete the old one. The URL must be https, must not carry a user or password, and its host must resolve only to public addresses. Private, loopback, link-local and cloud metadata addresses are refused (400 webhook_url_invalid). The host is resolved and checked again on every delivery, and redirects are not followed. Endpoints are per organization and per mode: a test key’s endpoints receive only test-mode events. Each organization may have at most 16 endpoints per mode.

Events

data is the twin object at the moment the twin ended. An event is usually sent within a minute or two of the twin ending.

Delivery

Each delivery is a POST with the event as its JSON body and these headers: Answer with any 2xx status within 10 seconds. Anything else, including a redirect or a timeout, counts as a failed attempt and is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and 6 hours. That is 8 attempts over about 24 hours, after which the delivery is dropped. Delivery is at least once, so you may receive the same event more than once. Deduplicate on webhook-id. Events can also arrive out of order. If order matters, read data.completed, or retrieve the twin.

Verifying a signature

The signature is an HMAC-SHA256 over <webhook-id>.<webhook-timestamp>.<body>. The HMAC key is the secret with its whsec_ prefix removed, base64-decoded. To verify:
  1. Compute the signature over the raw body, before you parse it.
  2. Compare it in constant time with each v1, entry of webhook-signature (entries are separated by spaces).
  3. Reject a timestamp more than 5 minutes away from your clock.
Header names are lowercase in both examples. Normalize them if your framework doesn’t.