πŸ”’Validating Webhook Signatures

How to verify that a webhook was genuinely sent by PlannrCRM

Every webhook request sent by Plannr includes an X-Signature header. This is an HMAC-SHA256 signature of the raw request body, computed using your webhook subscription's signing_secret. By verifying this signature before processing a webhook, you can be confident the payload was sent by Plannr and has not been tampered with in transit.


Step 1 β€” Retrieve your signing secret

A unique 60-character signing_secret is automatically generated when a webhook subscription is created. It is returned in the response body whenever you create, update, or retrieve a webhook subscription through the API.

circle-info

The signing secret is not currently displayed in the Plannr UI. Retrieve it via the API and store it securely in your application.

Make a GET request to retrieve all of your webhook subscriptions and their secrets:

GET /api/v2/webhook-subscriptions

Example response:

{
  "data": [
    {
      "uuid": "53f22fe4-3731-4cdc-aa12-e65bd0b15e52",
      "created_at": "2024-01-15T10:30:00+00:00",
      "updated_at": "2024-01-15T10:30:00+00:00",
      "signing_secret": "AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOpQrSt",
      "url": "https://api.example.com/webhooks",
      "events": ["account.created", "client.updated"],
      "last_outgoing_webhook_call_at": "2024-03-01T14:22:11+00:00"
    }
  ]
}
triangle-exclamation

Step 2 β€” Understand the signature

When Plannr sends a webhook to your endpoint, the request will include:

  • X-Signature β€” an HMAC-SHA256 hex digest of the raw request body, keyed with your signing_secret

  • Content-Type: application/json β€” the body is a JSON payload

Example headers received on your endpoint:


Step 3 β€” Verify the signature

To validate the webhook, compute your own HMAC-SHA256 signature of the raw request body using your signing_secret, then compare it against the X-Signature header. If they match, the webhook is genuine.

circle-exclamation

Security recommendations

Recommendation
Detail

Use a timing-safe comparison

Always compare signatures using a constant-time function (e.g. hmac.compare_digest, CryptographicOperations.FixedTimeEquals, hash_equals). Standard string equality leaks timing information that attackers can exploit.

Read the raw body

Compute the HMAC over the raw request bytes, before any JSON parsing.

Store secrets in environment variables

Never hardcode your signing_secret in source code. Use environment variables or a dedicated secrets manager.

Rotate secrets if compromised

If you suspect a secret has been exposed, delete the webhook subscription and create a new one to obtain a fresh secret.

Respond promptly

Return a 2xx response as quickly as possible β€” ideally before doing any heavy processing. Plannr may retry deliveries that do not receive a timely response.

Last updated

Was this helpful?