Quick Summary — TL;DR
An outbound webhook is a webhook that your application sends to an external URL when something happens in your system. If you're building a platform and want to notify your customers' systems about events — new orders, status changes, completed jobs — you're building an outbound webhook system. Stripe's payment notifications, GitHub's repository events, and Shopify's order alerts are all outbound webhooks from those platforms' perspective.
This is the opposite of an inbound webhook, where your application is the receiver. With outbound webhooks, you're the sender.
Your application needs to know when a webhook-worthy event happens. Common approaches: fire events from your application code (most direct), use database triggers or change data capture (more decoupled), or poll for state changes (simplest but least real-time). For most applications, emitting events from the business logic layer is the cleanest approach.
Every outbound webhook should include:
order.created or payment.failedKeep payloads focused. Include the data the receiver needs to act on the event, but don't dump your entire database record. If they need more detail, they can call your API.
Send the webhook as an HTTP POST with a JSON body. Set Content-Type: application/json. Include a signature header computed from the payload and a shared secret (see webhook signature). Set a reasonable timeout — 5 to 30 seconds. Don't wait indefinitely for a slow receiver.
When delivery fails (timeout, 5xx, network error), retry with exponential backoff. A typical schedule: 1 minute, 5 minutes, 30 minutes, 2 hours, 24 hours. After all retries are exhausted, move the delivery to a dead letter queue and optionally alert your customer that their endpoint is failing.
Don't retry on 4xx errors (except 429 Too Many Requests). A 400 or 404 means the receiver explicitly rejected the request or the endpoint doesn't exist — retrying won't help.
Most outbound webhook systems guarantee at-least-once delivery, not exactly-once. If the receiver processed the webhook but the response was lost, you'll retry and they'll get it again. This is why including an event ID is critical — it lets receivers deduplicate.
Don't promise ordered delivery unless you can actually guarantee it. Retries naturally cause out-of-order delivery. If a subscription.updated event fails and retries an hour later, meanwhile a subscription.cancelled event was delivered successfully, the receiver gets them out of order. Include timestamps and let receivers sort.
Track consecutive failures per endpoint. If an endpoint has failed 10 times in a row, it's probably down — not just temporarily slow. Disable the webhook after a threshold and notify the customer via email. Let them re-enable it when their endpoint is back up.
An outbound webhook is a webhook that your application sends to an external URL when an event occurs in your system. Your customers register a URL, and your system POSTs event data to that URL automatically. It's the sending side of the webhook pattern.
Persist events before attempting delivery so nothing is lost if the process crashes. Retry failed deliveries with exponential backoff. Track consecutive failures per endpoint and disable endpoints that are consistently down. Provide delivery logs so your customers can debug issues on their end. For a deeper dive, see our post on webhook retry best practices.
It's a matter of perspective. An inbound webhook is one your application receives from an external service. An outbound webhook is one your application sends to an external URL. When Stripe sends you a payment event, that's inbound for you and outbound for Stripe.
Outbound webhooks are how your application pushes events to your customers, and they sit on the opposite side of the inbound webhook pattern. Sign every delivery with a webhook signature so receivers can trust the payload. When deliveries fail, your retry policy and exponential backoff strategy determine how long you keep trying before the event lands in a dead letter queue.
Recuro handles cron scheduling, retries, alerts, and execution logs -- so you can focus on building your product.
No credit card required