Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Developer tools
Get started
Payments
Finance automation
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Overview
Billing
    Overview
    About the Billing APIs
    Subscriptions
      Overview
      Quickstart
      Use cases
      Build your integration
        Design a subscriptions integration
        Build a subscriptions integration
        Integrate with Salesforce
        Subscription event definitions
      Subscription features
      Analytics
    Invoicing
    Usage-based billing
    Connect and Billing
    Tax and Billing
    Quotes
    Revenue recovery
    Automations
    Scripts
    Revenue recognition
    Customer management
    Entitlements
    Test your integration
Tax
Reporting
Data
Startup incorporation
HomeFinance automationBillingSubscriptionsBuild your integration

Using webhooks with subscriptions

Learn to use webhooks to receive notifications of subscription activity.

Copy page

You receive notifications from Stripe in your app through webhook events. Use webhook events to manage subscriptions, as most activity happens asynchronously. Process these events at a webhook endpoint or other destinations like Amazon EventBridge by creating an event destination.

To use webhooks with your subscriptions:

  1. Create a webhook endpoint in your app.
  2. Register your webhook endpoint in Workbench
  3. Add logic to handle Stripe events. For subscriptions, these include payment failures and subscription state changes (like moving from trial to an active state). You can use the webhook quickstart to build a minimal webhook endpoint.
  4. Test your webhook endpoint to confirm that it’s working as expected.

If your application runs on AWS, you can configure Stripe to send events directly to AWS EventBridge in your AWS account.

Subscription events

Stripe triggers events every time a subscription is created or changed. Some events are sent immediately when a subscription is created, while others recur on regular billing intervals.

Make sure that your integration properly handles the events. For example, you may want to email a customer if a payment fails or revoke a customer’s access when a subscription is canceled.

The following table describes the most common events related to subscriptions and, where applicable, suggests actions for handling the events.

customer.createdSent when a Customer is successfully created.
customer.subscription.createdSent when the subscription is created. The subscription status might be incomplete if customer authentication is required to complete the payment or if you set payment_behavior to default_incomplete. View subscription payment behavior to learn more.
customer.subscription.deletedSent when a customer’s subscription ends.
customer.subscription.pausedSent when a subscription’s status changes to paused. For example, this is sent when a subscription is configured to pause when a free trial ends without a payment method. Invoicing won’t occur until the subscription is resumed. We don’t send this event if payment collection is paused because invoices continue to be created during that time period.
customer.subscription.resumedSent when a subscription previously in a paused status is resumed. This doesn’t apply when payment collection is unpaused.
customer.subscription.trial_will_endSent three days before the trial period ends. If the trial is less than three days, this event is triggered.
customer.subscription.updatedSent when a subscription starts or changes. For example, renewing a subscription, adding a coupon, applying a discount, adding an invoice item, and changing plans all trigger this event.
entitlements.active_entitlement_summary.updatedSent when a customer’s active entitlements are updated. When you receive this event, you can provision or de-provision access to your product’s features. Read more about integrating with entitlements.
invoice.createdSent when an invoice is created for a new or renewing subscription. If Stripe fails to receive a successful response to invoice.created, then finalizing all invoices with automatic collection is delayed for up to 72 hours. Read more about finalizing invoices.
  • Respond to the notification by sending a request to the Finalize an invoice API.
invoice.finalizedSent when an invoice is successfully finalized and ready to be paid.
  • You can send the invoice to the customer. View invoice finalization to learn more.
  • Depending on your settings, we automatically charge the default payment method or attempt collection. View emails after finalization to learn more.
invoice.finalization_failedThe invoice couldn’t be finalized. Learn how to handle invoice finalization failures by reading the guide. Learn more about invoice finalization in the invoices overview guide.
  • Inspect the Invoice’s last_finalization_error to determine the cause of the error.
  • If you’re using Stripe Tax, check the Invoice object’s automatic_tax field.
  • If automatic_tax[status]=requires_location_inputs, the invoice can’t be finalized and payments can’t be collected. Notify your customer and collect the required customer location.
  • If automatic_tax[status]=failed, retry the request later.
invoice.paidSent when the invoice is successfully paid. You can provision access to your product when you receive this event and the subscription status is active.
invoice.payment_action_requiredSent when the invoice requires customer authentication. Learn how to handle the subscription when the invoice requires action.

invoice.payment_failed

A payment for an invoice failed. The PaymentIntent status changes to requires_action. The status of the subscription continues to be incomplete only for the subscription’s first invoice. If a payment fails, there are several possible actions to take:

  • Notify the customer. Read about how you can configure subscription settings to enable Smart Retries and other revenue recovery features.
  • If you’re using PaymentIntents, collect new payment information and confirm the PaymentIntent.
  • Update the default payment method on the subscription.
invoice.upcomingSent a few days prior to the renewal of the subscription. The number of days is based on the number set for Upcoming renewal events in the Dashboard. For existing subscriptions, changing the number of days takes effect on the next billing period. You can still add extra invoice items, if needed.
invoice.updatedSent when a payment succeeds or fails. If payment is successful the paid attribute is set to true and the status is paid. If payment fails, paid is set to false and the status remains open. Payment failures also trigger a invoice.payment_failed event.
payment_intent.createdSent when a PaymentIntent is created.
payment_intent.succeededSent when a PaymentIntent has successfully completed payment.
subscription_schedule.abortedSent when a subscription schedule is canceled because payment delinquency terminated the related subscription.
subscription_schedule.canceledSent when a subscription schedule is canceled, which also cancels any active associated subscription.
subscription_schedule.completedSent when all phases of a subscription schedule complete.
subscription_schedule.createdSent when a new subscription schedule is created.
subscription_schedule.expiringSent 7 days before a subscription schedule is set to expire.
subscription_schedule.releasedSent when a subscription schedule is released, or stopped and disassociated from the subscription, which remains.
subscription_schedule.updatedSent when a subscription schedule is updated.

Handle payment failures

Events provide a reliable way for Stripe to notify you of payment failures on subscription invoices. Some payment failures are temporary-for example, a card issuer might decline the initial charge but allow an automatic retry. Other payment failures are final and require action, like not having a usable payment method for the customer.

EventDescription

invoice.payment_failed

A payment for an invoice failed. The status of the PaymentIntent changes to requires_payment_method. The status of the subscription changes to incomplete. If a payment fails, there are several possible actions to take:

  • Notify the customer.
  • If you’re using PaymentIntents, collect new payment information and confirm the PaymentIntent.
  • Update the default payment method on the subscription.
  • Consider enabling Smart Retries.

Handle payments that require additional action

Some payment methods might require additional steps to complete, such as customer authentication. If you receive these events, your app must notify the customer to complete the required action. To learn how to handle events that require additional action, read the subscription overview guide.

EventDescription
invoice.finalization_failedThe invoice couldn’t be finalized. Learn how to handle invoice finalization failures by reading the guide. Learn more about invoice finalization in the invoices overview guide.
  • Inspect the Invoice’s last_finalization_error to determine the cause of the error.
  • If you’re using Stripe Tax, check the Invoice object’s automatic_tax field.
  • If automatic_tax[status]=requires_location_inputs, the invoice can’t be finalized and payments can’t be collected. Notify your customer and collect the required customer location.
  • If automatic_tax[status]=failed, retry the request later.

invoice.payment_failed

A payment for an invoice failed. The PaymentIntent status changes to requires_action. The status of the subscription changes to incomplete. If a payment fails, there are several possible actions to take:

  • Notify the customer.
  • If you’re using PaymentIntents, collect new payment information and confirm the PaymentIntent.
  • Update the default payment method on the subscription.
  • Consider enabling Smart Retries.

invoice.payment_action_required

A payment for an invoice failed. The PaymentIntent status changes to requires_action. The status of the subscription changes to incomplete. If a payment fails, there are several possible actions to take:

  • Notify the customer.
  • If you’re using PaymentIntents, collect new payment information and confirm the PaymentIntent.
  • Update the default payment method on the subscription.
  • Consider enabling Smart Retries.

Track active subscriptions

Subscriptions require coordination between your site and Stripe-the success or failure of a customer’s recurring payments determines whether they can continue to access to your product or service.

For typical integrations, you store customers’ credentials and a mapped timestamp value that represents the access expiration date for that customer on your site when a customer subscribes. When the customer logs in, you check whether the timestamp is still in the future. If the timestamp is in the future when the customer logs in, the account is active and the customer should still have access to the service.

When the subscription renews, Stripe bills the customer and tries to collect payment by either automatically charging the payment method on file, or emailing the invoice to customers. Stripe notifies your site of the invoice status by sending a webhook event:

  1. Your site receives an invoice.paid event.

    • When automatically charging a payment method, your site first receives an invoice.upcoming event to your configured webhook endpoint a few days before renewal. You can listen for this event to add extra invoice items to the upcoming invoice. If collection_method=send_invoice, Stripe doesn’t send an invoice.upcoming event.
  2. Your application finds the customer the payment was made for.

  3. Your application updates the customer’s access expiration date in your database to the appropriate date in the future (plus a day or two for leeway).

Catch subscription status changes

Make sure that your integration properly monitors and handles transitions between the subscription statuses described in the following table.

Some status changes require special attention:

  • A few days before a trial ends and the subscription moves from trialing to active, you receive a customer.subscription.trial_will_end event. When you receive this event, verify that you have a payment method on the customer so you can bill them. Optionally, notify the customer that they will be charged.

  • When a subscription changes to past_due, notify the customer directly and ask them to update their payment details. Stripe offers several features that help automate this process-read more about revenue recovery.

  • When a subscription changes to canceled or unpaid, revoke access to your product.

StatusDescription
trialingThe subscription is currently in a trial period and you can safely provision your product for your customer. The subscription transitions automatically to active when a customer makes the first payment.
activeThe subscription is in good standing. For past_due subscriptions, paying the latest associated invoice or marking it uncollectible transitions the subscription to active. Note that active doesn’t indicate that all outstanding invoices associated with the subscription have been paid. You can leave other outstanding invoices open for payment, mark them as uncollectible, or void them as you see fit.
incompleteThe customer must make a successful payment within 23 hours to activate the subscription. Or the payment requires action, such as customer authentication. Subscriptions can also be incomplete if there’s a pending payment and the PaymentIntent status is processing.
incomplete_expiredThe initial payment on the subscription failed and the customer didn’t make a successful payment within 23 hours of subscription creation. These subscriptions don’t bill customers. This status exists so you can track customers that failed to activate their subscriptions.
past_duePayment on the latest finalized invoice either failed or wasn’t attempted. The subscription continues to create invoices. Your subscription settings determine the subscription’s next state. If the invoice is still unpaid after all attempted smart retries, you can configure the subscription to move to canceled, unpaid, or leave it as past_due. To move the subscription to active, pay the most recent invoice before its due date.
canceledThe subscription was canceled. During cancellation, automatic collection for all unpaid invoices is disabled (auto_advance=false). This is a terminal state that can’t be updated.
unpaidThe latest invoice hasn’t been paid but the subscription remains in place. The latest invoice remains open and invoices continue to generate, but payments aren’t attempted. Revoke access to your product when the subscription is unpaid because payments were already attempted and retried while past_due. To move the subscription to active, pay the most recent invoice before its due date.
pausedThe subscription has ended its trial period without a default payment method and the trial_settings.end_behavior.missing_payment_method is set to pause. Invoices are no longer created for the subscription. After attaching a default payment method to the customer, you can resume the subscription.

Webhook endpoints and invoices

Register a webhook endpoint to keep track of invoice statuses. Your subscription integration depends on correctly finalizing invoices and properly handling invoice finalization failures.

When you enable automatic collection, Stripe automatically finalizes and begins automatic collection of the invoice.

  • If Stripe fails to receive a successful response to invoice.created, we delay finalizing all invoices with automatic collection for up to 72 hours, excluding those where you have set a custom scheduled finalization time.
  • Responding properly to invoice.created includes handling all webhook endpoints configured for your account, along with the webhook endpoints of any platforms that you’ve connected to. This doesn’t include any webhook endpoints configured in an organization. While you can listen to invoice.created at the organization, a successful response doesn’t affect invoice finalization when using automatic collection.
  • Updating a subscription in a way that synchronously attempts payment (on the initial invoice, and on some kinds of updates) doesn’t cause this delay.
  • Invoice finalization failure prevents payment collection for the invoice. Make sure you listen for the invoice.finalization_failed event in your webhook endpoint.

Webhook events related to invoice finalization

See a complete list of invoice event types.

EventDescription
invoice.createdThe invoice was successfully created and is ready to be finalized. Read the docs to learn more about finalizing invoices.
  • Respond to the notification by sending a request to the Finalize an invoice API.
invoice.finalizedThe invoice was successfully finalized and is ready to be paid.
  • You can send the invoice to the customer. Read more about invoice finalization.
  • Depending on your settings, Stripe automatically charges the default payment method or attempts collection. Read more about emails after finalization.
invoice.finalization_failedThe invoice couldn’t be finalized. Learn how to handle invoice finalization failures by reading the guide. Learn more about invoice finalization in the invoices overview guide.
  • Inspect the Invoice’s last_finalization_error to determine the cause of the error.
  • If you’re using Stripe Tax, check the Invoice object’s automatic_tax field.
  • If automatic_tax[status]=requires_location_inputs, the invoice can’t be finalized and payments can’t be collected. Notify your customer and collect the required customer location.
  • If automatic_tax[status]=failed, retry the request later.

Successful invoice finalization

Stripe waits an hour after receiving a successful response to the invoice.created event before attempting payment. If we don’t receive a successful response within 72 hours, we attempt to finalize and send the invoice.

In case you want to treat one-off invoices differently than subscription invoices, check the subscription property in the webhook body. This indicates whether the invoice was created for a subscription.

In live mode, if your webhook endpoint doesn’t respond properly, Stripe continues retrying the webhook notification for up to 3 days with an exponential back off. In a sandbox, we retry three times over a few hours. During that time, we won’t attempt to charge the customer unless we receive a successful response. We’ll also send you an email to notify you that the webhook is failing.

This behavior applies to all webhook endpoints defined on your account, including cases where a Connect application or other third-party service is having trouble handling incoming webhooks.

Invoice finalization failure

If Stripe can’t finalize an invoice, it sends a invoice.finalization_failed event to your webhook endpoint. Subscriptions remain active if invoices can’t be finalized, which means that users may still be able to access your product while you’re not able to collect payments. Make sure to take action on invoices that fail finalization. You can’t collect payments on an invoice that isn’t finalized.

To determine why the invoice finalization failed, look at the Invoice object’s last_finalization_error field, which provides more information about the failure, including how to proceed.

If you’re using Stripe Tax, check if the automatic_tax.status field is requires_location_inputs, indicating that the address details are invalid or insufficient. If Stripe Tax can’t find a recognized customer location, we can’t finalize the invoice. Learn how to handle invoice finalization failures.

Testing

To test your webhook endpoint or event destination, choose one of these two options:

  1. Perform actions in a sandbox that send legitimate events to your event destination. For example, to trigger the charge.succeeded event, you can use a test card that produces a successful charge.
  2. Trigger events using the Stripe CLI or using Stripe for Visual Studio Code.

See also

  • Subscription lifecycle
  • Testing subscriptions
Was this page helpful?
YesNo
Need help? Contact Support.
Join our early access program.
Check out our changelog.
Questions? Contact Sales.
LLM? Read llms.txt.
Powered by Markdoc