Skip to main content
Every webhook request is signed with the secret returned when you create the endpoint. Verify the signature before parsing or acting on the JSON body.

Signed headers

Header names are case-insensitive. Your framework may expose them in lowercase.

Signing input

Wircle signs the following UTF-8 string:
The HMAC key is the Base64-decoded value after the whsec_ prefix in your endpoint secret. The resulting SHA-256 digest is Base64-encoded and returned with a v1, prefix. Do not parse and re-serialize the body before verification. Whitespace, property order, and character encoding are part of the signed value, so verification must use the exact raw bytes received over HTTP.

Verification procedure

  1. Read webhook-id, webhook-timestamp, and webhook-signature from the request headers.
  2. Reject missing headers and unrecognized secret or signature prefixes.
  3. Parse the timestamp and reject requests outside a short tolerance. Five minutes is recommended.
  4. Construct the signing input using the raw request body.
  5. Calculate the HMAC-SHA256 digest using the decoded endpoint secret.
  6. Compare the expected and received signatures with a constant-time comparison.
  7. Parse and process the JSON only after verification succeeds.

Node.js example

Call the verifier with the raw body supplied by your HTTP framework. If it returns false, respond with 400 or 401 and do not process the event.

Replay protection and idempotency

Signature verification proves that Wircle signed the request, but it does not prevent an already valid request from being replayed within your timestamp tolerance. After the signature is valid, use webhook-id as an idempotency key:
  • Store the ID before performing side effects.
  • If the ID has already been processed, return a 2xx response without repeating those side effects.
  • Keep processed IDs for at least as long as the delivery retry window.

Retries

The body and webhook-id stay the same across retries. Each attempt has a new webhook-timestamp, so it also has a new webhook-signature. Always verify the headers on the current request instead of storing an earlier signature.

Secret handling

  • Store signing secrets only in server-side secret storage.
  • Never expose a secret in browser code, logs, or error responses.
  • Each endpoint has its own secret. Select the secret using trusted endpoint configuration, not an unsigned body field.
  • If a secret may be compromised, create a replacement endpoint, switch traffic to it, and revoke the old endpoint.