Skip to content

Paths and domains

Webhook endpoints can live under your app domain or on a dedicated hostname.

Use path when the provider should call your app domain:

Terminal window
const stripe = webhooks.stripe({
path: "/webhooks/stripe",
secret: secret("STRIPE_WEBHOOK_SECRET"),
handler: async (event) => {
await processStripeEvent(event.payload)
},
})

Provider URL:

Terminal window
https://api.example.com/webhooks/stripe

Path placement is a good default for most apps. It keeps operational ownership with the app endpoint you already deploy.

Use host when a provider or partner should call a dedicated hostname:

Terminal window
const vendor = webhooks.custom({
name: "vendor",
host: "hooks.example.com",
path: "/vendor",
signature: {
header: "x-vendor-signature",
secret: secret("VENDOR_WEBHOOK_SECRET"),
},
handler: async (event) => {
await processVendorEvent(event.payload)
},
})

Provider URL:

Terminal window
https://hooks.example.com/vendor

Host placement is useful when:

  • A partner requires a dedicated webhook domain.
  • You want a separate DNS name for inbound integrations.
  • You need separate routing or firewall rules for webhook traffic.

Use url to derive both host and path:

Terminal window
const partner = webhooks.custom({
name: "partner",
url: "https://hooks.example.com/partner",
signature: {
header: "x-partner-signature",
secret: secret("PARTNER_WEBHOOK_SECRET"),
},
handler: async (event) => {
await processPartnerEvent(event.payload)
},
})

Use stable names. The name participates in event records, dedupe records, delivery state, and replay views:

Terminal window
webhooks.custom({
name: "github",
path: "/webhooks/github",
handler: async (event) => {
await processGithubEvent(event.payload)
},
})

For multiple teams or product areas, use the platform namespace model:

Terminal window
webhooks.custom({
namespace: "billing",
name: "stripe",
path: "/billing/webhooks/stripe",
signature: {
header: "stripe-signature",
secret: secret("BILLING_STRIPE_WEBHOOK_SECRET"),
},
handler: async (event) => {
await processBillingEvent(event.payload)
},
})