Gareth Wilson Gareth Wilson

Guide to Svix Webhooks: Features and Best Practices

Published


Svix is webhook-sending infrastructure that many SaaS products use to deliver their webhooks. If you're integrating a service that runs on Svix, the webhooks you receive carry Svix's signature headers, and verifying them works the same way no matter which upstream product sent them. This guide is about receiving and verifying those deliveries reliably.

Because Svix is the sending side, the event types and payloads you get are defined by the upstream service, not by Svix. What Svix standardizes is the delivery mechanics: the headers, the signature scheme, secret rotation, and the replay window. Get those right once and every Svix-powered provider works the same way.

What are Svix webhooks?

A Svix-delivered webhook is an HTTP POST with a JSON body and three signature headers. The signature scheme is the basis of the Standard Webhooks specification, so if you've verified Standard Webhooks deliveries before, this will look familiar. Each provider that sends through Svix gives you a signing secret (prefixed whsec_) in its own dashboard or Svix App Portal, which you use to verify deliveries.

Svix webhook features

FeatureDetails
Signature headerssvix-id, svix-timestamp, svix-signature
Header aliaseswebhook-id, webhook-timestamp, webhook-signature (accept both)
Signature schemebase64 HMAC-SHA256 over {id}.{timestamp}.{body}
Signing keybase64-decoded portion of the secret after the whsec_ prefix
Signature formatspace-delimited v1,<sig> entries; match any (for rotation)
Replay protectionReject timestamps more than 5 minutes off
Verification targetRaw request body
Event typesDefined by the upstream sender, not by Svix
SDKsOfficial svix libraries (Node, Python, and more)

Setting up and finding your signing secret

You don't configure Svix directly; you configure webhooks in the upstream product that uses it. That product exposes your endpoint's signing secret (the whsec_... value) in its dashboard or in the Svix App Portal it embeds. Register your HTTPS endpoint there, subscribe to the event types the provider offers, and copy the signing secret into your environment.

Event names follow whatever convention the sender uses. A common envelope is {"type": "<event.name>", "data": {...}}, but that shape is a convention, not something Svix enforces, so branch on the field the provider documents.

Securing Svix webhooks

Each delivery is signed with HMAC-SHA256 over the string {svix-id}.{svix-timestamp}.{body}. The key is the base64-decoded portion of your secret after the whsec_ prefix. The svix-signature header can contain multiple space-delimited v1,<signature> entries (this is how secret rotation works), and a delivery is valid if any entry matches. Svix's libraries also reject timestamps more than five minutes from now, which is what gives the scheme its replay protection.

The official svix library handles all of this, including the header aliases and the multi-signature rotation case:

const { Webhook } = require("svix");

// The whsec_-prefixed secret from the provider's dashboard / App Portal
const wh = new Webhook(process.env.WEBHOOK_SECRET);

app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  try {
    // Throws on a bad signature or a timestamp outside the 5-minute window
    const payload = wh.verify(req.body, {
      "svix-id": req.headers["svix-id"],
      "svix-timestamp": req.headers["svix-timestamp"],
      "svix-signature": req.headers["svix-signature"],
    });

    res.sendStatus(200); // acknowledge fast
    processQueue.add(payload); // process asynchronously
  } catch {
    res.sendStatus(400);
  }
});

The same check in Python:

from svix.webhooks import Webhook, WebhookVerificationError

wh = Webhook(os.environ["WEBHOOK_SECRET"])  # whsec_-prefixed


@app.post("/webhook")
def webhook():
    try:
        payload = wh.verify(request.get_data(), dict(request.headers))
    except WebhookVerificationError:
        return "", 400

    # enqueue payload for async processing
    return "", 200

If you verify manually instead of using the library, remember three things: base64-decode the secret after whsec_ before using it as the HMAC key, verify against the raw body, and accept the webhook-id / webhook-timestamp / webhook-signature aliases some senders use in place of the svix- prefix.

Svix webhook limitations and pain points

Event types and payloads are the sender's, not Svix's

The Problem: Svix standardizes delivery, not content. There's no universal catalog of event types; each provider defines its own, and the {type, data} envelope is a convention you can't assume is present.

Why It Happens: Svix is infrastructure the sender builds on. The domain events belong to the sender.

Workarounds:

  • Read the specific provider's event reference and branch on the field they document.
  • Validate each parsed payload against the schema you expect rather than assuming a shape.

How Hookdeck Can Help: Hookdeck gives you a consistent inspection and routing layer across every provider you receive from, Svix-powered or not, so you're not reasoning about each sender's quirks in your handler.

Secret rotation produces multiple signatures

The Problem: During rotation, svix-signature carries more than one v1,<sig> entry. Verification code that reads only the first signature will reject valid deliveries signed with the other secret.

Why It Happens: Overlapping signatures are what let a sender rotate a secret without dropping in-flight deliveries.

Workarounds:

  • Match against any entry in the header, not just the first.
  • Use the official svix library, which handles this for you.

How Hookdeck Can Help: Hookdeck verifies Svix signatures at the edge, including the rotation case, so your application only ever sees pre-verified events.

The five-minute timestamp window

The Problem: Deliveries with a svix-timestamp more than five minutes off are rejected as replay protection. If your handler is slow or briefly backed up, deliveries can age out before you verify them.

Why It Happens: The freshness window is what stops a captured signed payload from being replayed indefinitely.

Workarounds:

  • Acknowledge fast and process asynchronously so verification happens within the window.
  • Keep NTP in sync on your servers; clock skew eats into the tolerance.

How Hookdeck Can Help: Hookdeck verifies each delivery once at the edge and durably queues it, so a downstream backlog no longer risks deliveries aging out of the freshness window.

Best practices

Use the official Svix library

It handles the base64 secret decoding, the {id}.{timestamp}.{body} construction, the multi-signature rotation case, the header aliases, and the timestamp tolerance. Manual verification has to get all five right.

Verify against the raw body

The signature is computed over the exact bytes sent. Capture the raw body before any JSON middleware parses it.

Accept both header sets

Some senders emit webhook-id / webhook-timestamp / webhook-signature instead of the svix- prefix. Accept either so you're not caught out by a Professional/Enterprise-tier sender.

Dedupe on the message ID

Use svix-id as an idempotency key so retries and replays don't double-process. See our guide to webhook idempotency.

Acknowledge fast, process asynchronously

Return 200 as soon as the signature verifies, then hand the event to a queue. See why to process webhooks asynchronously.

Make Svix-delivered webhooks production-ready

Hookdeck verifies Svix signatures, deduplicates, and durably queues events from every provider you integrate

Conclusion

Svix standardizes the delivery side of webhooks for the many providers built on it: consistent svix-id / svix-timestamp / svix-signature headers, an HMAC-SHA256 scheme over id.timestamp.body, overlapping signatures for rotation, and a five-minute replay window. Learn it once and every Svix-powered sender verifies the same way, though the event types and payloads always belong to the upstream service.

The receiving-side responsibilities are still yours: verify against the raw body, handle rotation and the header aliases, stay inside the freshness window, and dedupe on svix-id. For teams integrating several providers at once, Hookdeck verifies Svix signatures, deduplicates, and durably queues events at the edge, giving you one reliable ingestion layer across every source.

Get started with Hookdeck for free and handle Svix-delivered webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.