Skip to content
Sign in
An image of the Stripe logo
Create account
Sign in
Home
Payments
Finance automation
Banking as a service
Developer tools
No-code
All products
Home
Payments
Finance automation
Home
Payments
Finance automation
Banking as a service
Developer tools
Overview
Building your integration
Developer tools
    Test mode
    Stripe Shell
    Stripe CLI
    Dashboard
    Stripe for Visual Studio Code
    Webhooks
      Events overview
      Listen for events
      Webhook builder
      Test webhooks
      Check signatures
      Best practices
      Go live
    File uploads
    Feedback
SDKs
API
Security
Sample projects
Videos
Stripe Apps
Stripe Connectors
Partners
HomeDeveloper toolsWebhooks

Best practices for using webhooks

Implement these best practices when using webhooks.

Webhooks allow you to track the state of transactions and to take actions within your Stripe account. Review these best practices to make sure your webhooks remain secure and function well with your integration.

API versions

The API version in your account settings when the event occurs dictates the structure of an Event object sent in a webhook. 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 with versioning, the Event object generated and sent to your endpoint is still based on the 2015-02-16 API version.

You can’t change Event objects after creation. For example, if you update a charge, the original charge event remains unchanged. This means that subsequent updates to your account’s API version don’t retroactively alter existing Event objects. Fetching older events by calling /v1/events using a newer API version also has no impact on the structure of the received events.

You can set test webhook endpoints to either your default API version or the latest API version. The Event sent to the webhook URL is structured for the endpoint’s specified version. You can also programmatically create endpoints with a specific api_version.

Event types

Configure your webhook endpoints to receive only the types of events required by your integration. Listening for extra events (or all events) puts undue strain on your server and we don’t recommend it.

You can change the events that a webhook endpoint receives in the Dashboard or with the API.

Delivery attempts and retries

Understand how to view delivery attempts, event logs, and the retry logic when webhook events aren’t acknowledged.

View events

Listening with Stripe CLI

You can also use the Stripe CLI to listen for events directly in your terminal.

In the Dashboard, you can check the number of times Stripe attempted to send a specific event to an endpoint by clicking the endpoint URL in the Webhooks section. This shows the latest response from your endpoint, a list of all attempted webhooks, and the respective HTTP status codes that Stripe received.

Retry logic

In live mode, Stripe attempts to deliver your webhooks for up to three days with an exponential back off. In the Events section of the Dashboard, you can view when the next retry will occur.

In test mode, Stripe retries three times over a few hours. You can manually retry webhooks after this time in the Dashboard, and you can also query for missed events to reconcile the data over any time period.

The automatic retries still continue, even if you manually retry webhooks and the attempt is successful.

If your endpoint has been disabled or deleted when we attempt a retry, future retries of that event are prevented. However, if you disable and then re-enable a webhook endpoint before we can retry, you can still expect to see future retry attempts.

Disable logic

In live and test mode, Stripe attempts to notify you of a misconfigured endpoint by email if the endpoint hasn’t responded with a 2xx HTTP status code for multiple days in a row. The email also states when the endpoint will be automatically disabled.

Pending webhook statuses

Various circumstances can cause webhook event delivery to enter a pending status. Refer to the table below for information on each pending status.

Pending webhook statusDescription
(Unable to connect) ERRWe’re unable to establish a connection to the destination server.
(302) ERR (or other 3XX status)The destination server attempted to redirect the request to another location. We consider redirect responses to webhook requests as failures.
(400) ERR (or other 4XX status)The destination server can’t or won’t process the request. This might occur when the server detects an error (400), when the destination URL has access restrictions, (401, 403), or when the destination URL doesn’t exist (404).
(500) ERR (or other 5XX status)The destination server encountered an error while processing the request.
(TLS error) ERRWe were unable to establish a secure connection to the destination server. These errors are usually caused by an issue with the SSL/TLS certificate or an intermediate certificate in the destination server’s certificate chain. Perform an SSL server test to find issues that might cause this error.
(Timed out) ERRThe destination server took too long to respond to the webhook request. Make sure you defer complex logic and return a successful response immediately in your webhook handling code.

Event handling

Handling webhook events correctly is crucial to making sure your integration’s business logic works as expected.

Handle duplicate events

Webhook endpoints might 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.

Order of events

Stripe doesn’t guarantee delivery of events in the order in which they’re generated. For example, creating a subscription might generate the following events:

  • customer.subscription.created
  • invoice.created
  • invoice.paid
  • charge.created (if there’s a charge)

Your endpoint shouldn’t expect delivery of these events in this order, and needs to handle delivery accordingly. You can also use the API to fetch any missing objects (for example, you can fetch the invoice, charge, and subscription objects using the information from invoice.paid if you happen to receive this event first).

Security

Keeping your endpoints secure is critical to protecting your customers’ information. Stripe provides several ways for you to verify events are coming from Stripe in a secure manner.

CSRF protection

If you’re using Rails, Django, or another web framework, your site might 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 might also prevent your site from processing legitimate events. If so, you might need to exempt the webhooks route from CSRF protection.

class StripeController < ApplicationController # If your controller accepts requests other than Stripe webhooks, # you'll probably want to use `protect_from_forgery` to add CSRF # protection for your application. But don't forget to exempt # your webhook route! protect_from_forgery except: :webhook def webhook # Process webhook data in `params` end end

Receive events with an HTTPS server

If you use an HTTPS URL for your webhook endpoint, Stripe validates 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. Live mode requires HTTPS URLs. Stripe webhooks don’t currently support TLS v1.3.

Roll endpoint secrets

The secret used for verifying that events come from Stripe is modifiable in the Webhooks section of the Dashboard. For each endpoint, click Roll secret. You can choose to immediately expire the current secret or delay its expiration for up to 24 hours to allow yourself time to update the verification code on your server. During this time, multiple secrets are active for the endpoint. Stripe generates one signature per secret until expiration.

Verify events are sent from Stripe

Verify webhook signatures to confirm that received events are sent from Stripe. Additionally, Stripe sends webhook events from a set list of IP addresses. Only trust events coming from these IP addresses.

See also

  • Take webhooks live
  • List of all event types
  • List of IP addresses Stripe uses
  • Stripe CLI
Was this page helpful?
Need help? Contact Support.
Watch our developer tutorials.
Check out our product changelog.
Questions? Contact Sales.
Powered by Markdoc
You can unsubscribe at any time. Read our privacy policy.
On this page
API versions
Event types
Delivery attempts and retries
Event handling
Security
See also
Stripe Shell
Test mode
Welcome to the Stripe Shell! Stripe Shell is a browser-based shell with the Stripe CLI pre-installed. Login to your Stripe account and press Control + Backtick on your keyboard to start managing your Stripe resources in test mode. - View supported Stripe commands: - Find webhook events: - Listen for webhook events: - Call Stripe APIs: stripe [api resource] [operation] (e.g. )
The Stripe Shell is best experienced on desktop.
$