Skip to main content

How to let SaaS customers subscribe to webhook events

To let SaaS customers subscribe to webhook events, publish a catalog of event types, let each customer register one or more HTTPS endpoints, store which event types each endpoint wants, and fan out every event only to matching endpoints. Each delivery is signed with a per-endpoint secret, retried on failure, and visible to the customer in a self-service portal.

Sending webhooks?
Svix is the enterprise-ready webhook sending service. It handles signing, retries, and delivery observability, so you can ship a reliable webhook platform in minutes instead of months. Start sending webhooks with Svix.

How do I add webhooks to my API product?​

Adding webhooks to an API product takes five parts: a versioned list of event types, an endpoint registration API, a subscription filter per endpoint, a delivery worker that signs and retries requests, and a customer-facing UI for logs and replays. The first three are product decisions. The last two are infrastructure that most teams underestimate.

If you need a refresher on the mechanics, start with what a webhook is. The steps below assume you already know you want to push events to customers instead of making them poll your API.

Step 1: Define an event type catalog​

Customers subscribe to event types, so the catalog is the contract. Use a consistent resource.action pattern such as invoice.paid, invoice.payment_failed, and user.deleted, and keep names in the past tense because they describe something that already happened. The event naming conventions guide covers the edge cases.

Attach a JSON Schema and an example payload to every event type, and publish them in your docs. That schema is what lets customers write handlers before they receive a single real event. Decide early whether you send full objects or just IDs; the tradeoffs are in fat vs thin payloads and designing webhook payloads.

Treat the catalog as additive. Adding a field or a new event type is safe; renaming or removing one breaks production integrations you can’t see.

Step 2: Let customers register endpoints​

A customer registers a webhook endpoint by giving you a URL and the event types they care about. Expose this in both your API and your dashboard, since some customers automate setup and others click through it once.

Validate the URL at registration time. Require HTTPS, resolve the hostname, and reject private, loopback, and link-local addresses such as 127.0.0.1, 10.0.0.0/8, and 169.254.169.254. Without that check, a customer can point your delivery workers at your own internal network, which is a classic SSRF hole. Re-check at send time too, because DNS can change after registration.

Generate a unique webhook secret per endpoint, show it to the customer once, and support secret rotation with an overlap window so they can rotate without downtime.

Step 3: Store subscriptions and filter at send time​

The data model is small. An endpoint belongs to a customer (a tenant), and it either subscribes to a list of event types or to all of them.

CREATE TABLE endpoints (
id uuid PRIMARY KEY,
tenant_id uuid NOT NULL,
url text NOT NULL,
secret text NOT NULL,
event_types text[], -- NULL means all event types
disabled boolean NOT NULL DEFAULT false
);

-- Endpoints that should receive invoice.paid for one tenant
SELECT id, url, secret FROM endpoints
WHERE tenant_id = $1
AND NOT disabled
AND (event_types IS NULL OR 'invoice.paid' = ANY(event_types));

When your application emits an event, write it to a durable store in the same transaction as the business change, then enqueue one delivery job per matching endpoint. That fanout step is where tenant isolation matters: one customer’s slow endpoint should never delay another customer’s deliveries. The multi-tenant webhook service guide goes deeper on queue layout.

Step 4: Sign, deliver, and retry​

Every request should carry a webhook signature, typically an HMAC-SHA256 over a message ID, a timestamp, and the raw body. Including the timestamp lets receivers enforce a timestamp tolerance and block replay attacks. The open Standard Webhooks spec defines the webhook-id, webhook-timestamp, and webhook-signature headers so you don’t have to invent a scheme.

Treat any 2xx response within a short timeout (around 15 seconds) as success and everything else as a failure to retry with exponential backoff. A schedule spanning a day or more covers most customer outages. After the final attempt, park the message where the customer can replay it, and disable endpoints that have failed continuously for days. Since retries mean duplicates, tell customers to deduplicate on the message ID; see idempotency and deduplication. The retry best practices page covers schedules in detail.

Step 5: Give customers a self-service portal​

This is the step that decides whether webhooks reduce support load or add to it. Customers need to add and edit endpoints, pick event types from your catalog with the schemas visible, send a test event, see every delivery attempt with its status code and response body, and replay failed messages. Without that UI, every broken integration turns into a “can you check the logs” ticket, which is the top complaint in reasons your users hate webhooks.

Build the subscription layer, buy the delivery pipeline​

The event catalog and the decision about which business actions emit events belong to you, because they are your product. The rest (SSRF-safe endpoint validation, per-endpoint secrets and rotation, fanout queues, signing, retries, delivery logs, and the portal) is the same for every SaaS company and takes months to build well. The webhook sender guide shows what the DIY path involves.

Svix maps directly onto this model: you create an application per customer, define event types with JSON Schemas, and customers subscribe their endpoints to specific event types through an embeddable App Portal that includes delivery logs, test events, and replays. Signing, retries, and endpoint disabling come built in, so your code sends one API call per event and Svix handles filtering and delivery.

Whichever route you take, start with a small, well-named event catalog and a portal customers can use without contacting you. Those two decisions shape how much your webhooks get adopted more than any other part of the system.