Claude Code Boilerplate
FeaturesPricingBlogDocs
Get started →

Product

  • Features
  • Pricing
  • Skills

Compare

  • vs ShipFast
  • vs MakerKit
  • vs supastarter

Resources

  • Docs
  • Blog
  • Discord

Legal

  • License
  • Privacy Policy
  • Terms of Service
Claude Code Boilerplate

© 2026 Claude Code Boilerplate. All rights reserved.

← All posts

How to Add Customer Webhooks to Your Next.js SaaS -- Let Users Connect to Zapier and Their Own Stack

October 1, 2026
nextjssaasdrizzle-ormboilerplatewebhooks

Six weeks after you launch, someone will send you a message: "Do you have webhooks? I want to pipe new signups into our CRM."

You have two choices. You build a native Zapier integration -- which takes a week, covers one tool, and leaves every other integration request on the backlog. Or you add outbound webhooks -- one afternoon of work that handles Zapier, Make, Slack, and any internal system your customers write.

Webhooks are how customers connect your SaaS to their stack without asking you first. If your product does anything worth reacting to -- a new user signed up, a subscription changed, a file was processed -- webhooks let customers automate around those events without waiting for you.

What "outbound webhooks" actually means

There are two kinds of webhooks, and they flow in opposite directions.

Inbound webhooks are what Stripe sends you: Stripe posts an event to your server when a customer pays. You probably already handle these if you have billing in your app.

Outbound webhooks are the opposite: your SaaS posts an event to your customer's server when something happens in your app. The customer registers a URL, you deliver events to it, and their system reacts.

This post is about outbound webhooks -- the kind customers use to build integrations on top of your product.

The three things you need to build

A webhook system has three moving parts:

  1. An endpoint registry -- a database table where customers store their webhook URLs and which events they want to receive. Each row has an endpoint URL, a secret for verification, and a list of subscribed event types.

  2. An event dispatcher -- the part of your codebase that fires when something happens. After a user is created, after a subscription changes, after a file is processed -- you call a dispatch function, which looks up matching subscriptions and delivers the event.

  3. A delivery log -- a record of every delivery attempt with the HTTP status, the payload, and the timestamp. This is what you show customers when they ask "did my webhook fire?" and what you use to retry failed deliveries.

None of this needs an external queue. With a Next.js app and Drizzle ORM on Neon, you can build a production-ready version using database tables you already know how to work with.

Which events to expose

Start with fewer events than you think you need. Pick the five things customers are most likely to react to:

  • user.created -- someone signed up
  • subscription.activated -- a customer started paying
  • subscription.cancelled -- a customer cancelled
  • [resource].created -- whatever the core object in your app is (a project, a report, a listing)
  • [resource].updated -- the same object changed

Give each event a stable string name and document them. Never rename them after customers start using them -- it breaks every integration silently, and you will only find out when a customer's automation stops working.

How delivery works

When an event fires in your app:

  1. Look up all active webhook subscriptions that include this event type.
  2. For each subscription, POST the event payload to the customer's URL. Include a signature header (X-Webhook-Signature) so they can verify the payload came from you.
  3. Write the result -- HTTP status, response body, timestamp -- to your delivery log table.
  4. If the response is not 2xx, mark the attempt failed. Retry with exponential backoff up to three times over the next hour.

The signature is an HMAC-SHA256 of the raw payload, keyed with the per-subscription secret you generate at registration time. The customer verifies it the same way you verify Stripe's signatures today -- both sides hash the same payload with the same key and compare.

What customers actually do with it

Once you expose webhooks, your customers can connect your product to:

  • Zapier and Make -- no-code automation platforms that accept webhooks as triggers. A customer can pipe every new signup into a Google Sheet, send a Slack DM for every cancellation, or add paying customers to their CRM without writing code.
  • Their own backend -- developers at larger customers will write their own listeners. Webhooks are how they keep your data in sync with their internal systems without polling your API.
  • Retool or internal dashboards -- many B2B teams use internal tools that react to events. Webhooks make your product a first-class citizen in their stack.

Every integration you would have had to build yourself becomes something customers can wire up in an afternoon.

Wiring it into your Next.js boilerplate

With the Next.js SaaS boilerplate, you already have Drizzle ORM, a JWT-authenticated API layer, and a DDD-lite module structure that keeps this clean.

The webhook system lives in two modules: a webhookEndpoint module (schema, repo, service for managing customer subscriptions) and a webhookDelivery module (dispatching events and writing delivery logs). Your service layer calls webhookService.dispatch('user.created', payload) after any event worth exporting -- the rest handles itself.

For the API routes, the registration endpoint sits behind your existing auth middleware (see the authentication docs). Customers create and delete webhook subscriptions using the same API key they already have. If you have already built a customer-facing API, webhook management is a natural extension of it.

The difference between early and late

The customer who pipes your events into their CRM is not leaving. The customer who has not connected your product to anything yet has no switching cost at all.

Webhooks are one of those features that feel like a nice-to-have until your first enterprise deal requires them, at which point you are retrofitting them into a codebase that was never designed for it. Adding them early -- when the module structure is clean and the event surface is small -- takes a weekend. Adding them after 50 services each trigger events takes much longer.

Ready to ship a Next.js SaaS that customers can actually integrate with? Get the boilerplate and start with auth, payments, email, and a clean architecture that makes webhook delivery a feature, not a refactor.