Use webhooks to be notified about events that happen in a Stripe account. If you need help after reading this, check out our answers to common questions or chat live with other developers in #stripe on freenode.

Interacting with a third-party API like Stripe's can introduce two problems:

  • Services not directly responsible for making an API request may still need to know the response of that request
  • Some events, like disputed charges and many recurring billing events, are not the result of a direct API request

Webhooks solve these problems by letting you register a URL that we will notify anytime an event happens in your account. When the event occurs—for example, when a successful charge is made on a customer's subscription, Stripe creates an Event object. This object contains all the relevant information about what just happened, including the type of event and the data associated with that event. Stripe then sends the Event object to any URLs in your account's webhooks settings via an HTTP POST request. You can find a full list of all event types in the API docs.

You might use webhooks to:

  • Update a customer's membership record in your database when a subscription payment succeeds
  • Email a customer when a subscription payment fails
  • Check out the Dashboard if you see that a dispute was filed
  • Make adjustments to an invoice when it's created (but before it's been paid)
  • Log an accounting entry when a transfer is paid

Understand that you only need to use webhooks for behind-the-scenes transactions. The results of most Stripe requests—including charge attempts and customer creations—are reported synchronously to your code, and don't require webhooks for verification. (For example, with a charge request, the charge will immediately succeed and a Charge object returned, or the charge will immediately fail and an exception will be thrown.)

Configuring your webhook settings

Webhooks are configured in the webhooks settings section of the Dashboard. Clicking Add endpoint reveals a form to add a new URL for receiving webhooks.

Stripe supports two webhook types: Account and Connect. You'll likely want to create an account webhook, unless you've created a Connect application.

You can enter any URL you'd like to have receive the events, but this should be a dedicated page on your server, coded per the instructions below. The mode determines whether test events or live events are sent to this URL; if you want to send both live and test events to the same URL, you need to create two separate settings. You may add as many URLs as you like.

You can also choose to be notified of all event types, or only specific ones.

Receiving a webhook notification

Creating a webhoook endpoint on your server is no different from creating any page on your website. With PHP, you might create a new .php file on your server; with a framework like Sinatra, you would add a new route with the desired URL.

Webhook data is sent as JSON in the POST request body. The full event details are included and can be used directly, after parsing the JSON into an Event object.

Receiving webhooks with a CSRF-protected server

If you're using Rails, Django, or another web framework, your site may automatically check that every POST request contains a CSRF token. This is an important security feature that helps protect you and your users from cross-site request forgery attempts. However, this security measure may also prevent your site from processing legitimate webhooks. If so, you may need to exempt the webhooks route from CSRF protection.

Receiving webhooks with an HTTPS server

If you use an HTTPS URL for your webhook endpoint, Stripe will validate that the connection to your server is secure before sending your webhook data. For this to work, your server must be correctly configured to support HTTPS with a valid server certificate. See our guide on SSL/TLS for details on setting this up.

Responding to a webhook

To acknowledge receipt of a webhook, your endpoint should return a 2xx HTTP status code. Any other information you return in the request headers or request body will be ignored. Any response code outside the 2xx range, including 3xx codes, will indicate to Stripe that you did not receive the webhook. This does mean that a URL redirection or a "Not Modified" response will be treated as a failure.

When a webhook is not successfully received for any reason, Stripe will continue trying to send the webhook once an hour for up to 3 days.

Best practices

Before going live, test that your webhook is working properly. You can do so by sending dummy test events from the webhooks settings pane. Understand that as these are fake, test events, they will not map to real customers, invoices, charges, or other objects in your account.

If your webhook script performs complex logic, or makes network calls, it's possible the script would timeout before Stripe sees its complete execution. For that reason, you may want to have your webhook endpoint immediately acknowledge receipt by returning a 2xx HTTP status code, and then perform the rest of its duties.

Webhook endpoints may occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing idempotent. One way of doing this is logging the events you've processed, and then not processing already-logged events.

For optimum security, you can confirm the event data with Stripe before acting upon it. To do so:

  1. Parse the JSON data as above.
  2. Grab the received Event object ID value.
  3. Use the Event object ID in a retrieve event API call.
  4. Take action using the returned Event object.

Webhooks and API versions

The structure of an Event object sent in a webhook is dictated by the API version in your account settings at the time of the event's occurrence. For example, if your account is set to an older API version, such as 2015-02-16, and you change the API version for a specific request via versioning, the Event object generated still aligns with the 2015-02-16 API version.

Further, an Event object will never be changed after the fact. Subsequent updates to your account's API version do not retroactively alter existing Event objects. Fetching older events using a newer API version also has no impact on the event's structure.

More information