Skip to content
Last updated

Signable signs each webhook request so you can verify that the request came from Signable and that the payload was not modified.

Early access

This feature is in early access and is currently available to selected customers.

How are webhooks signed?

When you create a webhook using POST /webhooks, we generate a secret for that webhook.

We return this value in the response as webhook_secret.

  • This field is only returned when the webhook is created.
  • You must store it securely.
  • You need it later to verify webhook signatures.
  • If you lose it, you must create a new webhook.

Each webhook request is signed using HMAC-SHA256, then encoded using Base64 before it is sent.

Example Request

POST /your-webhook-endpoint HTTP/1.1
Host: example.com
Content-Type: application/json
Signature: bXlfc2lnbmF0dXJl
X-Signable-Webhook: 1710000000

Verify the signature

To verify a webhook request:

  1. Read the raw request body exactly as received.
  2. Generate the signature using your webhook secret: HMAC_SHA256(your_secret, payload)
  3. Base64 encode the result.
  4. Compare your generated value with the Signature header.
  5. Reject the request if the values do not match.

Signature format

The signature is generated using:

  • algorithm: HMAC-SHA256
  • encoding: base64
  • signed content:
<raw_body>

The timestamp is included in the payload and in the X-Signable-Webhook header.

Prevent replay attacks

Each request includes a timestamp in both the payload and the X-Signable-Webhook header.

To reduce replay risk:

  • Check that the timestamp is recent (for example, within 5 minutes).
  • Reject requests with timestamps outside your allowed window.

This limits the usefulness of captured requests.

Webhook secret

Each webhook subscription has its own secret.

Store the secret securely. Anyone with access to the secret could generate valid signatures for that webhook subscription.

⬅️ Back to Webhook improvements