Interacting with a third-party API like Stripe's often suffers from two important 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 in your account, Stripe creates an
Event object. This object contains all the relevant information, including the type of event and the data associated with that event. Stripe then sends an HTTP POST request with the
Event object to any URLs in your account's webhooks settings. You can find a full list of all event types in the API docs.
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 can be configured in the webhooks settings section of the Dashboard. Clicking Add URL reveals a form to add a new URL for receiving webhooks.
You can enter any URL you'd like to have receive the events. 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 (application webhooks do not follow this rule). You may add as many URLs as you like.
Receiving a webhook notification
Configuring your server to receive a new webhook 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. Remember, with webhooks, your server is the server receiving the request.
Webhook data is sent as JSON in the request's body. The full event details are included and can be used directly. Alternatively, the event is also available through the API. If security is a concern, or if it's important to confirm that Stripe sent the webhook, you should only use the ID sent in your webhook and should request the remaining details from the API directly. We also advise you to guard against replay-attacks by recording which events you receive, and never processing events twice.
Receiving webhooks with a CSRF-protected server
If you're using Rails, Django, or another web framework, your server may automatically check that POST request bodies it receives contain a CSRF token. This is an important security feature that helps protect you and your users from cross-site request forgery. However, it may also prevent your server from receiving legitimate webhooks. You may need to exempt from CSRF protection the Rails route or Django view you use to receive webhooks.
Responding to a webhook
To acknowledge you received the webhook without any problem, your server 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. When a webhook is not received for whatever reason, Stripe will continue trying to send the webhook once an hour for up to 3 days.
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.