Quick Summary — TL;DR
An inbound webhook is a webhook that your application receives from an external service. When Stripe notifies you about a payment, when GitHub tells you about a push, when Shopify alerts you to a new order — those are all inbound webhooks. The external service is the sender; your application is the receiver.
The term "inbound" distinguishes the direction of the webhook. From your application's perspective, the request is coming in from an external source. This is the opposite of an outbound webhook, where your application is the sender.
Your webhook endpoint must be publicly accessible over HTTPS. It needs to accept POST requests and parse JSON bodies. The URL path is up to you — /webhooks/stripe, /api/webhooks/github, or whatever makes sense for your routing.
Before trusting the payload, verify the request signature. The external service signs each request with a shared secret (usually HMAC-SHA256), and includes the signature in a header. Compute the expected signature from the raw request body and compare using constant-time comparison. Reject the request with 401 if signatures don't match. See webhook signature for implementation details.
Parse the JSON body, check the event type, and route to the appropriate handler. Only process event types your application cares about — return 200 immediately for events you don't handle.
The sender expects a response within a few seconds. If your processing takes longer, queue the work as a background job and return 200 immediately. Most providers treat slow responses the same as failures and will retry the delivery.
Parse the payload, do the work, return 200. This works when processing is fast (under a second) and the operation is simple — updating a status flag, recording an event, sending a notification. The downside: if processing fails mid-way, you may return a 500 and trigger a retry that partially re-processes the same event.
Verify the signature, write the raw event to a queue or database, return 200 immediately. A background worker picks up the event and processes it at its own pace. This is the safer pattern for anything non-trivial because it decouples receipt from processing — your endpoint stays fast, retries don't pile up, and you can replay failed events from your own queue.
For most production applications, queue-first is the right choice. The webhook endpoint becomes a thin ingestion layer, and all the business logic lives in the worker. You can use our webhook tester to verify your endpoint handles requests correctly during development.
An inbound webhook is a webhook your application receives from an external service. The external service sends an HTTP POST request to your registered URL when an event occurs, delivering the event data for your application to process.
Verify the webhook signature on every request using the shared secret provided by the sender. Use HTTPS for all webhook endpoints. Where the provider publishes IP ranges, add IP allowlisting as an additional layer. Check timestamps to prevent replay attacks. For more detail, see our guide on securing webhook endpoints.
For anything beyond trivial operations, process asynchronously. Verify the signature, persist the raw event to a queue or database, return 200 immediately, and let a background worker handle the business logic. This keeps your endpoint fast, prevents timeouts, and gives you the ability to replay failed events.
Inbound webhooks are one side of the webhook model — your application receives data that an outbound webhook system on the other end is sending. Always verify the signature before trusting the payload, and process events idempotently since retries are a normal part of webhook delivery.
Recuro handles cron scheduling, retries, alerts, and execution logs -- so you can focus on building your product.
No credit card required