← Back to Blog
APIsIntegrationsTechnical Sales

What Is a Webhook? How Event Data Reaches a Buyer's System

What is a webhook? How a delivery reaches a buyer's endpoint, how signatures prove the sender, and how GitHub and Stripe handle failed deliveries.

Polling means a buyer's system keeps asking yours whether anything has changed. A webhook turns that around: GitHub's documentation says webhooks "let you subscribe to events happening in a software system and automatically receive a delivery of data to your server whenever those events occur." For your product, that means sending an HTTP request to the buyer's server each time a subscribed event happens on your side.

How a delivery works

The setup starts on the receiving side. In GitHub's overview, "When you create a webhook, you specify a URL and subscribe to events that occur on GitHub." When one of those events occurs, GitHub "will send an HTTP request with data about the event to the URL that you specified."

That URL is the endpoint. It belongs to the buyer and has to be reachable from the sending service. Stripe's webhook documentation describes its endpoint function as one that "Handles POST requests with a JSON payload that includes event information."

GitHub defines polling as "calling an API intermittently" to check for new data. GitHub's own comparison says webhooks "require less effort and less resources than polling an API" and that checking many resources by API calls "may cause you to hit your API rate limit quota quickly." It also notes the reverse case: if you only need information once or intermittently, from a small set of resources, "you can call the API when you need the relevant information." How to explain APIs to buyers puts the same contrast in one line: an API waits to be asked.

Proving the delivery came from you

An endpoint is a public URL, so the buyer's engineers will want to know how to tell a real delivery from a forged one. Both GitHub and Stripe answer this with a signature in a request header.

GitHub's page on validating deliveries explains that GitHub uses a secret token "to create a hash signature that's sent to you with each payload," carried in the X-Hub-Signature-256 header. The receiving code calculates its own hash with the same secret and checks that the two match. GitHub also warns, "Never use a plain == operator," and points to a constant-time comparison instead.

Stripe follows the same pattern under a different header name. "Stripe signs every webhook event by including a signature in the Stripe-Signature header." Stripe also warns that verification needs the request body exactly as sent: "Any manipulation to the raw body of the request causes the verification to fail."

GitHub's best practices page adds a warning about where secrets should not go: "do not include sensitive information in your payload URL. This includes your own API keys and other authentication credentials."

When a delivery fails

GitHub expects a reply quickly. "Your server should respond with a 2XX response within 10 seconds of receiving a webhook delivery." If the server is slower, GitHub "terminates the connection and considers the delivery a failure." GitHub then leaves recovery to the receiver: "GitHub does not automatically redeliver failed deliveries." Failed deliveries can be redelivered by hand or by a script that calls GitHub's REST API.

Stripe takes the opposite approach. It "attempts to deliver events to your destination for up to three days with an exponential back off in live mode." In a sandbox, Stripe retries "three times over the course" of a shorter window.

Retries bring a second issue. Stripe states that "Webhook endpoints might occasionally receive the same event more than once," and recommends "logging the event IDs you've processed, and then not processing already-logged events." Order is not promised either: "Stripe doesn't guarantee the delivery of events in the order that they're generated." GitHub offers an X-GitHub-Delivery header that can be used "to ensure that each delivery is unique per event," and notes that a redelivery keeps the same value as the original.

A buyer conversation, sketched

Imagine a hypothetical buyer, Northwind, whose operations lead wants new records from your product to appear in their internal tool. Their engineer asks four things: which events you send, how the payload is signed, what happens if their server is down for an hour, and whether a single event can arrive twice.

Each answer is a product fact. GitHub and Stripe already differ on the third question: Stripe retries for up to three days in live mode, and GitHub doesn't redeliver automatically. Your product's answer belongs in its webhook documentation.

Two smaller items concern the network. GitHub lets receivers set up an IP allow list using the addresses returned by its GET /meta endpoint, and Stripe publishes a list of the IP addresses it sends from. Stripe also requires HTTPS once an endpoint is publicly accessible, while allowing plain HTTP during development on a local machine.

What to have ready

  • The list of event types your product can send.
  • The header name and method used to sign payloads.
  • The timeout and retry schedule, including what happens after the last retry.
  • Whether duplicate or out-of-order deliveries are possible, and which field identifies an event.
  • Any published IP ranges for allow lists.

GitHub's failed-delivery records give a reason for each failure. If your product keeps a similar delivery log, say where it lives, alongside any audit log the buyer has already asked about.

Need help with this on live sales calls?

VoiceVocab gives reps prospect-stack context and plain-English technical explanations before and during the call.

Try VoiceVocab →