Platform

How do I verify a webhook signature?

Verify a webhook signature by checking the signed request against your endpoint secret before trusting its contents.

A public receiving URL can receive requests from anyone. An attacker can send a fabricated event to that URL, so the request needs authentication before it triggers work.

Bird uses the Standard Webhooks signing scheme. It authenticates the event identifier and attempt time along with the body, so changing any of them invalidates the signature.

What does Bird sign?

Bird signs the event identifier, delivery-attempt timestamp and raw request body joined with periods.

Keep the request body unchanged until you verify the signature. Parsing and serializing JSON can change the bytes Bird signed.

HeaderWhat it carries
webhook-idThe event identifier, reused across retries and replays.
webhook-timestampThe attempt time as a Unix timestamp in seconds.
webhook-signatureOne or more signatures, separated by spaces. Each begins with v1,.

Convert the timestamp from seconds before comparing it with a clock that reports milliseconds.

Remove the whsec_ prefix from your endpoint secret and base64-decode the remainder to recover the key bytes.

Join the identifier, timestamp and untouched body with periods. Compute HMAC-SHA256 over that string using the decoded key. Compare the result with each supplied signature using a constant-time comparison, whose running time does not reveal which bytes match.

Why does my signature never match?

A wrong secret or a changed request body can make every signature check fail.

Web frameworks often parse JSON before your handler runs. Serializing that object again can change whitespace, key order or numeric formatting. The resulting JSON can mean the same thing while producing a different signature.

Configure this route to preserve its raw body. Check that the secret belongs to this endpoint, especially after a deployment or rotation.

What should my handler reject?

Reject a request when no signature matches or its signed timestamp falls outside the allowed time window.

Try every signature in webhook-signature. During secret rotation, a delivery carries signatures from multiple valid secrets. Accepting any matching signature lets receivers using either secret keep working.

Use a five-minute timestamp tolerance on either side of your clock. A captured request from ten minutes earlier then fails even if its signature is unchanged. Keep your server clock accurate so it does not reject genuine deliveries.

Check webhook-id against events you already stored. A recognized duplicate should receive success without repeating its work, since retrying the same delivery adds no new event.

What happens if I reject a delivery?

Bird retries a delivery that receives an error response or no response before its timeout.

A 400 response, for example, records rejection and leaves the delivery eligible for retry. All non-2xx responses follow the retry policy. The code helps you diagnose the failure in your logs.

The schedule spans roughly 27.5 hours before adjustments, giving you time to repair a wrong secret. Failed webhook retries describes the schedule and how to replay missed events afterward.

Return 2xx only after you have verified and safely stored the event, or recognized an already stored duplicate. Bird skips successful deliveries during replay, so acknowledging an unverified request prevents recovery through that mechanism.

Do I have to implement verification myself?

You do not need to implement verification yourself when you use webhooks.unwrap in a Bird SDK. Pass it the raw body and request headers.

The helper checks the signature and timestamp before returning the decoded event. Your application still deduplicates by webhook-id, because it owns the record of completed work.

A compatible Standard Webhooks verification library can perform the same checks. The webhooks guide includes examples and a manual implementation.

In short

  1. Verify the original bytes.

    Parsing and serializing JSON can change the bytes that Bird signed. Preserve the raw body for verification.

  2. Check time as well as the signature.

    A five-minute timestamp tolerance limits reuse of captured requests. Deduplicate stored events by webhook-id separately.

  3. Try every supplied signature.

    Rotation creates overlapping signatures. A match against any valid signature allows the deployment to continue.

  4. Acknowledge only verified, stored events.

    Bird retries non-2xx responses and skips successful deliveries during replay. Return success for duplicates already stored without repeating their work.

Put it into practice.

Continue with the documentation, guides and examples for this topic. Resources are in English.

Try the practice and get an implementation brief

Build on the same network.

A test API key is yours immediately. Production unlocks when you add a payment method and verify a sender.

Your next idea.
Ready to connect.