Add signed, retried webhooks to your product with one API call.
You describe your events once. Your customers subscribe their endpoints. Each event you send fans out to the right ones.
Name each event, give it a JSON Schema and an example, and version it as it changes.
Use your own customer IDs. Each endpoint picks the event types it wants and gets its own signing secret.
One call creates a delivery for every subscribed endpoint. Each one is signed, retried and logged on its own.
Plain HTTPS with a workspace key. Your customers verify with any Standard Webhooks or Svix library they already use.
If the payload doesn't match the event type's schema you get a 422 with the errors, and nothing is sent.
Send the same idempotency key within 24 hours and you get the original message back, not a second one.
webhook-id stays the same across retries, so receivers can drop repeats.
curl https://api.getensue.com/v1/dispatch/events \ -H "Authorization: Bearer ens_live_…" \ -H "Content-Type: application/json" \ -d '{ "type": "order.shipped", "customer": "acme", "idempotency_key": "ship_8812", "data": { "order_id": "ord_8812", "carrier": "dhl" } }'
const res = await fetch('https://api.getensue.com/v1/dispatch/events', { method: 'POST', headers: { Authorization: `Bearer ${process.env.ENSUE_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ type: 'order.shipped', customer: 'acme', // your own customer ID idempotency_key: 'ship_8812', data: { order_id: 'ord_8812', carrier: 'dhl' }, }), });
import { Webhook } from 'svix'; // any Standard Webhooks library works const wh = new Webhook(process.env.WEBHOOK_SECRET); // whsec_… // throws if the signature or timestamp is wrong const event = wh.verify(rawBody, { 'webhook-id': req.headers['webhook-id'], 'webhook-timestamp': req.headers['webhook-timestamp'], 'webhook-signature': req.headers['webhook-signature'], });
Signing, retries and history from the first event you send.
Every event type has versions, a JSON Schema and an example payload. Deprecate old ones without breaking anyone, and see who subscribes to what.
Every delivery is signed over its ID, timestamp and body with a per-endpoint whsec_ secret.
webhook-id: msg_4c8d… webhook-timestamp: 1793001600 webhook-signature: v1,K5oZ…
Rotate an endpoint's secret and the old one keeps signing alongside it for 24 hours while the customer switches over.
Send to every subscriber, to one customer's endpoints, or to a single endpoint.
The same delivery engine as Gateway: backoff, Retry-After and a circuit breaker per endpoint.
A customer was down all weekend? Resend everything that failed to their endpoint since Friday.
Create or update a customer with a single PUT on your own ID, at sign-up or on first send. You never store an Ensue ID.
Every delivery, attempt and response sits next to your Gateway traffic, filtered by customer or event type. Retry one, or replay a message to every endpoint.
Send a customer a signed link, or embed it in your settings page. They add endpoints, pick event types, read the catalog, see their deliveries, retry, rotate secrets and send test events, under your logo and on your domain.
Receiving webhooks from Stripe or GitHub? See Gateway.