Skip to main content

What are some webhook examples?

A webhook is one HTTP POST sent from one application to another the moment something happens. Stripe posts payment_intent.succeeded when a charge clears. GitHub posts a push event when code lands on a branch. Shopify posts orders/create when a customer checks out. Each request carries a JSON body and a signature header.

Sending webhooks?
Svix is the enterprise-ready webhook sending service. It handles signing, retries, and delivery observability, so you can ship a reliable webhook platform in minutes instead of months. Start sending webhooks with Svix.

What a webhook request actually looks like

Every example below is the same shape underneath: a POST to a URL you registered, a few headers that identify and authenticate the request, and a payload describing what happened. Written out in full, a delivery following the Standard Webhooks specification looks like this:

POST /webhooks/billing HTTP/1.1
Host: api.example.com
Content-Type: application/json
webhook-id: msg_2dW7XkQpLm3
webhook-timestamp: 1780000000
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=

{
"type": "invoice.paid",
"timestamp": "2026-08-31T09:14:22Z",
"data": {
"invoice_id": "in_9Kd82",
"customer_id": "cus_4Ba71",
"amount_cents": 4900,
"currency": "usd"
}
}

Three details in there do most of the work. The webhook-id is a unique message ID, so a receiver can store it and skip a duplicate when the same event arrives twice. The webhook-timestamp lets the receiver reject anything older than a tolerance window, commonly five minutes, which is what stops a captured request from being replayed. The webhook-signature is an HMAC-SHA256 over the ID, the timestamp, and the raw body, so verifying it proves the request came from the sender and was not modified in transit. See webhook signature for how the verification works.

Examples from providers you already use

Names differ by provider, but the pattern does not.

  • Stripe sends payment_intent.succeeded, charge.refunded, and invoice.payment_failed, signed with a Stripe-Signature header. This is how an app fulfills an order without polling the payments API.
  • GitHub sends push, pull_request, and issues, with the event type in an X-GitHub-Event header and an HMAC-SHA256 digest in X-Hub-Signature-256. Our GitHub webhook example walks through receiving one.
  • Shopify sends topics like orders/create, products/update, and app/uninstalled, signed in X-Shopify-Hmac-Sha256, keeping inventory and fulfillment systems in sync.
  • Twilio posts delivery status callbacks as application/x-www-form-urlencoded rather than JSON, verified through X-Twilio-Signature. Not every webhook is JSON, which is worth knowing before you write a handler that assumes it is.
  • Slack and Discord run the other direction: you post to them. A message to a Slack or Discord webhook URL appears in a channel, which is why these are the webhooks most developers meet first.

Webhook URL examples

The URL is just an HTTPS endpoint you control, or one a provider generated for you:

  • https://api.example.com/webhooks/stripe is a webhook endpoint on your own service, one path per sender so logs stay separable.
  • https://hooks.slack.com/services/T0000000/B0000000/XXXXXXXXXXXX is a Slack incoming webhook, where the trailing segments are the secret.
  • https://discord.com/api/webhooks/1234567890/aBcDeF... is a Discord channel webhook, which replies 204 No Content when it accepts a message.

For a Slack or Discord URL, the secret is the URL itself, so anyone holding it can post as you. Treat it like a password and rotate it by deleting and recreating the webhook.

What the receiver does with the example above

A handler that survives production does four things in order. It verifies the signature before reading the body, because an unauthenticated POST to a public URL is just a stranger's input. It returns a 2xx immediately, since senders enforce a timeout measured in seconds and will record a success as a failure if you finish the work first. It writes the event to a queue and processes it in a background worker. And it keys that processing on the message ID, so the retry that inevitably arrives twice only takes effect once. Our receiving best practices covers each step in detail.

The fastest way to see a real one is to catch it. Svix Play gives you a throwaway URL that displays the full headers and body of anything posted to it, so you can register it with Stripe or GitHub in test mode and read the actual payload rather than a documented one. The webhook testing guide covers the other approaches.

If you are on the sending side and want your own events to look like the examples above, Svix handles the signing, the retry schedule, and the per-endpoint delivery log so your payloads are the only part you have to design.

Frequently asked questions

What is a simple example of a webhook?

A payment provider posts {"type": "invoice.paid", "data": {...}} to https://api.example.com/webhooks/billing the moment an invoice is paid. Your server verifies the signature header, returns 200, and marks the invoice paid in its own database. No polling is involved.

What does a webhook payload look like?

Almost always a JSON object with an event type, a timestamp, and a data object describing the changed resource. Some providers, including Twilio, send form-encoded bodies instead, so check the docs before parsing.

How do I test a webhook example without a server?

Point the sender at a hosted capture URL such as Svix Play, which records the full request and shows the headers and body in a browser. That removes the need for a public endpoint or a tunnel while you are still exploring the payload.

Ready to send webhooks?

Svix handles signing, retries, rate limiting, and delivery observability for the webhooks you send to your users, so your team can stay focused on your product.