# Implement advanced usage-based billing with pricing plans Bill your customers based on usage and recurring charges. You can group different pricing components into a single pricing plan to implement complex pricing models that combine multiple charging strategies. For example, create a pricing plan that includes rate cards for usage-based billing, license fees for recurring charges, and service actions for recurring credit grant allocations. When a customer subscribes, Stripe automatically enrolls and bills all recurring components at the cadence you configure. Supported pricing models include: - Pay as you go - Real-time credit burndown with top-ups - Flat fee and overages > Pricing plans are in [private preview](https://docs.stripe.com/release-phases.md) and might change in functionality and integration path before they become generally available to all Stripe users. Contact us to request access. ## Before you begin - Pricing plans use `/v2` API endpoints. Learn more about the [/v2 and /v1 namespaces](https://docs.stripe.com/api-v2-overview.md). - Use [sandboxes](https://docs.stripe.com/sandboxes.md) to test your pricing plans integration. You can’t use test mode with `/v2` APIs. You can also use a [guided API (Blueprint)](https://dashboard.stripe.com/test/workbench/blueprints/usage-based-billing?code-pane-shown=true) version of this guide in the Dashboard. ## Create a pricing plan Use the Stripe Dashboard or API to create a pricing plan that contains all the relevant billing components of your pricing model. For each pricing plan, configure: - **Currency**: Specify the currency for all the components in your pricing plan. - **Include tax in prices**: Specify whether to include tax in your price (inclusive) or to add it to the invoice subtotal (exclusive). Learn more about [inclusive and exclusive taxes for billing](https://docs.stripe.com/billing/taxes/tax-rates.md#inclusive-vs-exclusive-tax). - **Metadata**: Optionally add your own metadata to the pricing plan. After setting the currency and tax parameters, define the relevant components of your plan. Which components you include depends on your pricing model. This guide demonstrates all three components ((rate cards, license fees, and service actions). For example, pay-as-you-go pricing and real-time credit burndown with top-ups only need a rate card, flat fee and overages needs a rate card and license fee, and recurring credits with overage needs a rate card and service action. #### Dashboard ### Create the pricing plan 1. On the [Pricing plans](https://dashboard.stripe.com/test/pricing-plans) page, click **Create pricing plan**. 1. In the pricing plan editor: - Provide a display name, currency, and tax behavior. - (Optional) Under **Advanced settings**, specify the description, unique lookup key, and metadata. 1. Click **Continue**. ### Add a rate card 1. In the pricing plan editor, click + and **Rate card**. 1. In the rate card editor: - Provide a display name. - Specify the servicing period. - (Optional) Under **Advanced settings**, provide a lookup key and metadata. 1. Click **Continue**. ### Attach a rate to the rate card 1. In the rate editor: - Provide a display name for the metered item (for example, `Hypernian tokens`). - Select an existing **Meter** or create a new one by clicking +. - Select the **Price type**: **Fixed rate**, [Volume](https://docs.stripe.com/subscriptions/pricing-models/tiered-pricing.md#volume-based-pricing), or [Graduated](https://docs.stripe.com/subscriptions/pricing-models/tiered-pricing.md#graduated-pricing). For example, Hypernian uses fixed rate. - Select **Sell as** Individual units or a Packaged group of units. For example, an AI company might sell their tokens as packages of `100` units, at `0.04 USD` per package. - For packages, enter the **Units per package**. - Select whether to round up or down for **Partial packages**. If you round up, a user that uses 110 units is charged 0.08 USD. - Enter the **Price per package**. - (Optional) Configure **Advanced settings** for your metered item, such as specifying a **Product tax code** (learn more about [tax codes](https://docs.stripe.com/tax/tax-codes.md)), **Unit label**, **Lookup key**, and **Metadata**. You can also add metadata to the rate. 1. Click **Done**. 1. (Optional) Click + **Add rate** to add additional rates to the rate card. ### Add a license fee 1. In the pricing plan editor, click + and **License fee**. 1. In the license fee editor: - Provide a display name for the licensed item. - Specify the servicing period. - Select the **Price type**: **Fixed rate**, [Volume](https://docs.stripe.com/subscriptions/pricing-models/tiered-pricing.md#volume-based-pricing), or [Graduated](https://docs.stripe.com/subscriptions/pricing-models/tiered-pricing.md#graduated-pricing). For example, `50.00 USD` per unit. - (Optional) Configure **Advanced settings** for your licensed item, such as specifying a **Product tax code** (learn more about [tax codes](https://docs.stripe.com/tax/tax-codes.md)), **Unit label**, **Lookup key**, and **Metadata**. You can also add metadata to the fee. 1. Click **Done**. ### Add a service action 1. In the pricing plan editor, click + and **Credit grant**. 1. In the recurring credit grant editor: - Provide a display name for the credit grant. - Specify the servicing period. - Provide a credit amount. - (Optional) Configure **Advanced settings** for your recurring credit grant, such as specifying an **Application** or **Lookup key**. 1. Click **Done**. After you finish configuring the pricing plan, click **Create pricing plan**. #### API ### Create the pricing plan When you create a [pricing plan](https://docs.stripe.com/api/v2/pricing-plans.md?api-version=preview), provide a display name, currency, and specify the tax behavior (learn more about [tax behavior and rate cards](https://docs.stripe.com/tax/subscriptions/rate-card-tax-codes-tax-behavior.md#set-a-default-tax-behavior-recommended)). ```curl curl -X POST https://api.stripe.com/v2/billing/pricing_plans \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "display_name": "Pro Pricing Plan", "currency": "usd", "tax_behavior": "exclusive" }' ``` After you submit the pricing plan request, Stripe returns the active `Pricing Plan` object. You can’t subscribe new customers to an inactive pricing plan. ```json { "id": "bpp_test_61SjPwyNGx88hyuOg16SjPfE4ZSQFjWjdqlzQfWMCH1E", "object": "v2.billing.pricing_plan", "active": true, "created": "2025-06-14T21:52:04.000Z", "currency": "usd", "description": null, "display_name": "Pro Pricing Plan", "latest_version": "bppv_test_123", "live_version": "bppv_test_123", "lookup_key": null, "metadata": {}, "tax_behavior": "exclusive" } ``` ### Add a rate card To attach a rate card to your pricing plan to bill your customers based on usage, create a rate card and provide a display name, currency, service interval, and tax behavior. ```curl curl -X POST https://api.stripe.com/v2/billing/rate_cards \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "display_name": "Hypernian", "service_interval": "month", "service_interval_count": 1, "currency": "usd", "tax_behavior": "exclusive" }' ``` ### Create a meter ```curl curl https://api.stripe.com/v1/billing/meters \ -u "<>:" \ -d "display_name=Hypernian tokens" \ -d event_name=hypernian_tokens \ -d "default_aggregation[formula]=sum" \ -d "customer_mapping[event_payload_key]=stripe_customer_id" \ -d "customer_mapping[type]=by_id" \ -d "value_settings[event_payload_key]=value" ``` ### Create a metered item After you create a meter, create a metered item to represent the specific item that the customer is paying for, such as an LLM model or tier of token usage. ```curl curl -X POST https://api.stripe.com/v2/billing/metered_items \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "display_name": "Hypernian tokens", "meter": "{{METER_ID}}", "lookup_key": "hypernian_tokens" }' ``` ### Attach a rate to the meter After you create a metered item, attach a rate to the meter. ```curl curl -X POST https://api.stripe.com/v2/billing/rate_cards/{{RATE_CARD_ID}}/rates \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "metered_item": "{{METERED_ITEM_ID}}", "unit_amount": "5" }' ``` ### Attach a rate card to a pricing plan After you create the rate, attach the rate card to the pricing plan: ```curl curl -X POST https://api.stripe.com/v2/billing/pricing_plans/{{PRICING_PLAN_ID}}/components \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "type": "rate_card", "rate_card": { "id": "{{RATE_CARD_ID}}", "version": "{{RATE_CARD_VERSION}}" }, "metadata": { "existing_key": "updated_value", "new_key": "new value" } }' ``` ### Add a license fee License fees are fixed recurring charges, which you can use to charge up-front fees. First, create a license item: ```curl curl -X POST https://api.stripe.com/v2/billing/licensed_items \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "display_name": "Pricing Plan Licensed Item" }' ``` Then, create a license fee: ```curl curl -X POST https://api.stripe.com/v2/billing/license_fees \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "display_name": "E2E License", "licensed_item": "{{LICENSED_ITEM_ID}}", "unit_amount": "50000", "service_interval": "month", "service_interval_count": 1, "currency": "usd", "tax_behavior": "exclusive" }' ``` Finally, attach the license fee to a pricing plan: ```curl curl -X POST https://api.stripe.com/v2/billing/pricing_plans/{{PRICING_PLAN_ID}}/components \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "type": "license_fee", "license_fee": { "id": "{{LICENSE_FEE_ID}}", "version": "{{LICENSE_FEE_VERSION}}" }, "lookup_key": "monthly-fee-component", "metadata": { "existing_key": "updated_value", "new_key": "new value" } }' ``` ### Add a service action You can add new components, including recurring credit grants, to your pricing plan. Use recurring credit grants if you use a [credit burndown pricing model](https://docs.stripe.com/subscriptions/pricing-models/usage-based-pricing.md#credit-burndown). Service actions let you offer recurring credits to customers, which can offset charges for specific billable items, such as usage-based fees. When you create a service action, you configure: - Amount - Billing frequency - Applicable billable items To create a monthly credit grant of 10 USD that expires at the end of the service interval: ```curl curl -X POST https://api.stripe.com/v2/billing/service_actions \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "service_interval": "month", "service_interval_count": 1, "type": "credit_grant", "lookup_key": "credit grant 28", "credit_grant": { "name": "Credit grant 28", "expiry_config": { "type": "end_of_service_period" }, "applicability_config": { "scope": { "price_type": "metered" } }, "amount": { "type": "monetary", "monetary": { "value": 1000, "currency": "usd" } } } }' ``` Attach the service action to your pricing plan: ```curl curl -X POST https://api.stripe.com/v2/billing/pricing_plans/{{PRICING_PLAN_ID}}/components \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "type": "service_action", "service_action": { "id": "{{SERVICE_ACTION_ID}}" }, "lookup_key": "credit-grant-28", "metadata": { "existing_key": "updated_value", "new_key": "new value" } }' ``` ### Activate the pricing plan After you’ve added the relevant components for your pricing model, activate that version of the pricing plan. After the plan is activated, you can [subscribe customers to it](https://docs.stripe.com/billing/subscriptions/usage-based/pricing-plans.md#subscribe). ```curl curl -X POST https://api.stripe.com/v2/billing/pricing_plans/{{PRICING_PLAN_ID}} \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "live_version": "latest" }' ``` ## Subscribe your customer to a pricing plan After you set up a pricing plan, you can subscribe a customer to it. You can create a subscription by using the [Checkout Sessions API](https://docs.stripe.com/api/checkout/sessions.md) with [either a Stripe-hosted page or embedded components as a payment UI](https://docs.stripe.com/payments/checkout.md) (the Checkout Session also creates a customer). You can also use the API to directly create a pricing plan subscription. If you use the direct API method, you need to create [a customer](https://docs.stripe.com/api/customers/create.md), [collection setting](https://docs.stripe.com/api/v2/billing-settings/collection-settings/create.md?api-version=preview), [billing cadence](https://docs.stripe.com/api/v2/billing/cadences/create.md?api-version=preview), and [billing intent](https://docs.stripe.com/api/v2/billing-intents/intents/create.md?api-version=preview), which creates the pricing plan subscription. #### Stripe-hosted page Use the [Checkout Sessions API](https://docs.stripe.com/api/checkout/sessions.md) to create a payment page for your customers. When a customer clicks **Subscribe**, the Checkout Session creates a [Customer](https://docs.stripe.com/api/customers.md) object (if you didn’t provide a customer ID for the Session) and a pricing plan subscription. If you have multiple items in `checkout_items`, a pricing plan subscription is created for each item. Here’s an example of what a complete pricing plan looks like with Checkout. ![Pricing plan example](https://b.stripecdn.com/docs-statics-srv/assets/checkout_pricing_plan_example.2156a15535345b113c30e7efabe72867.png) A pricing plan displayed in Stripe Checkout ### Checkout Session limitations during private preview During the private preview: - You can pass a maximum of five [checkout_items](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-checkout_items). - You can only accept cards, Link, Apple Pay, and Google Pay. - You can’t pass in a specific [billing cycle anchor](https://docs.stripe.com/billing/subscriptions/billing-cycle.md). - You can’t use [tax rates](https://docs.stripe.com/billing/taxes/tax-rates.md), only automatic tax calculation. - You can’t use discounts. - You can’t [limit customers to one subscription](https://docs.stripe.com/payments/checkout/limit-subscriptions.md). - You can’t use [Connect](https://docs.stripe.com/connect.md). - You can’t add [optional items](https://docs.stripe.com/payments/checkout/optional-items.md) or [cross-sells](https://docs.stripe.com/payments/checkout/cross-sells.md). Contact [advanced-ubb-private-preview@stripe.com](mailto:advanced-ubb-private-preview@stripe.com) to gain early access and share any product feedback or requests. To [create a Checkout Session](https://docs.stripe.com/api/checkout/sessions/create.md) with pricing plans, include an object in the [checkout_items](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-checkout_items) array that has its [type](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-checkout_items-type) set to `pricing_plan_subscription_item` and includes a `pricing_plan_subscription_item` configuration. When you use `checkout_items` instead of `line_items`, you don’t need to specify the [mode](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-mode). ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -H "Stripe-Version: 2025-09-30.preview;checkout_product_catalog_preview=v1" \ -d customer={{CUSTOMER_ID}} \ -d "checkout_items[0][type]=pricing_plan_subscription_item" \ -d "checkout_items[0][pricing_plan_subscription_item][pricing_plan]={{PRICING_PLAN_ID}}" \ -d success_url={{SUCCESS_URL}} ``` If your pricing plan includes a license fee you need to include the license fee quantity: Get the license fee component ID: ```curl curl https://api.stripe.com/v2/billing/pricing_plans/{{PRICING_PLAN_ID}}/components \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2025-09-30.preview" ``` Create the Checkout Session using the license fee component ID: ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -H "Stripe-Version: 2025-09-30.preview;checkout_product_catalog_preview=v1" \ -d customer={{CUSTOMER_ID}} \ -d "checkout_items[0][type]=pricing_plan_subscription_item" \ -d "checkout_items[0][pricing_plan_subscription_item][pricing_plan]={{PRICING_PLAN_ID}}" \ -d "checkout_items[0][pricing_plan_subscription_item][component_configurations][{{LICENSE_COMPONENT_ID}}][type]=license_fee_component" \ -d "checkout_items[0][pricing_plan_subscription_item][component_configurations][{{LICENSE_COMPONENT_ID}}][license_fee_component][quantity]=1" ``` The page displays your pricing plan’s details and collects the customer’s payment information. After the customer completes the session, the pricing plan subscription is created and the customer is redirected to the URL you specified for `success_url`. Learn more about [customizing redirect behavior with Checkout](https://docs.stripe.com/payments/checkout/custom-success-page.md). #### Embedded components For more control over the appearance of your pricing plan’s payment page, you can use [embedded components](https://docs.stripe.com/payments/quickstart-checkout-sessions.md) with the Checkout Session API. The embedded components [Session](https://docs.stripe.com/js/custom_checkout/session_object) object exposes your pricing plan’s details in [session.orderSummaryItems](https://docs.stripe.com/js/custom_checkout/session_object#custom_checkout_session_object-orderSummaryItems), enabling you to render an order summary for your pricing plan, license fees, and rate cards. You still need to use the same `checkout_items` parameter when creating the Checkout Session on your server. ### Checkout Session limitations during private preview During the private preview: - You can pass a maximum of five [checkout_items](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-checkout_items). - You can only accept cards, Link, Apple Pay, and Google Pay. - You can’t pass in a specific [billing cycle anchor](https://docs.stripe.com/billing/subscriptions/billing-cycle.md). - You can’t use [tax rates](https://docs.stripe.com/billing/taxes/tax-rates.md), only automatic tax calculation. - You can’t use discounts. - You can’t [limit customers to one subscription](https://docs.stripe.com/payments/checkout/limit-subscriptions.md). - You can’t use [Connect](https://docs.stripe.com/connect.md). - You can’t add [optional items](https://docs.stripe.com/payments/checkout/optional-items.md) or [cross-sells](https://docs.stripe.com/payments/checkout/cross-sells.md). Contact [advanced-ubb-private-preview@stripe.com](mailto:advanced-ubb-private-preview@stripe.com) to gain early access and share any product feedback or requests. ### Use the product catalog beta header When initializing a Stripe instance on your front end with your publishable key, pass in the `custom_checkout_product_catalog_1` beta header. ```js const stripe = Stripe( '<>',{betas: ['custom_checkout_product_catalog_1']}, ); ``` ```javascript import {loadStripe} from '@stripe/stripe-js'; const stripe = loadStripe("<>", {betas: ['custom_checkout_product_catalog_1'], }); ``` #### API Use the APIs directly to [create a customer](https://docs.stripe.com/api/customers/create.md), then to [create a billing interval](https://docs.stripe.com/api/v2/billing-cadences/cadences/create.md?api-version=preview). You can charge the customer’s default payment method automatically or send them the invoice to pay manually. After you create a customer and a billing interval, you can [create a pricing plan subscription](https://docs.stripe.com/api/v2/billing-intents/intents/create.md?api-version=preview). By default, we charge a customer’s saved payment method automatically. To send an invoice, [create a collection setting](https://docs.stripe.com/api/v2/billing-settings/collection-settings/create.md?api-version=preview) with the `collection_method` set to `send_invoice`. Then, pass in the collection setting when you create the cadence. ## Record customer usage After you subscribe a customer to a pricing plan consisting of a rate card, record their usage of your service by sending meter events to a meter. #### Dashboard 1. Go to the [Pricing plan subscriptions](https://dashboard.stripe.com/test/pricing-plans/subscriptions) tab. 1. Click the subscription you want to record usage for. 1. Select **View** to see the underlying pricing plan components, and navigate to the rate card you want to add usage for. 1. Click the overflow menu (⋯) in the row of the item you want to record usage for, then click **View meter details**. 1. In the meter details page, click **+ Add usage** then select **Manually input usage**. 1. In the **Add usage** dialog: - Select a customer. - Enter a **Value** for the usage. - Select a date for the **Timestamp**. 1. Click **Submit**. #### API Use [meter events](https://docs.stripe.com/api/billing/meter-event.md) to [record customer usage](https://docs.stripe.com/billing/subscriptions/usage-based/recording-usage.md) for your meter. At the end of the billing interval, Stripe bills the reported usage. To test usage-based billing, send meter events through the Stripe Dashboard or API. When using the API, specify the customer ID and usage value in the `payload`. Learn more about [testing a pricing plans integration](https://docs.stripe.com/billing/subscriptions/usage-based/pricing-plans.md#test-the-integration). ```curl curl https://api.stripe.com/v1/billing/meter_events \ -u "<>:" \ -d event_name=hypernian_tokens \ -d "payload[stripe_customer_id]={{CUSTOMER_ID}}" \ -d "payload[value]=25" ``` ## Create a preview invoice Create a preview invoice to see a preview of a customer’s invoice. The preview includes the relevant line items from the various pricing plan components. #### Dashboard 1. Go to the [Pricing plan subscriptions](https://dashboard.stripe.com/test/pricing-plan/subscriptions) tab. 1. Click the subscription you want to preview an invoice for. 1. Scroll down to the **Upcoming invoice** section. The preview invoice shows the subscription amount to bill the customer on the specified date, and reflects the corresponding metered items, license items, and credits. #### API ```curl curl https://api.stripe.com/v1/invoices/create_preview \ -u "<>:" \ -H "Stripe-Version: 2025-12-15.clover" \ -d billing_cadence=bc_test_61SrjnScUwT6mNskZ16SjPfE4ZSQFjWjdqlzQfWMCVnM ``` ```json {"hosted_invoice_url": "example.com/invoice", "invoice_pdf": null, "billing_reason": "manual", "collection_method": "charge_automatically", "created": 1680644467, "currency": "usd", "custom_fields": null, "customer": "cus_NeZwdNtLEOXuvB", "customer_address": null, "customer_email": "jennyrosen@example.com", "customer_name": "Jenny Rosen", "customer_phone": null, "customer_shipping": null, "customer_tax_exempt": "none", "customer_tax_ids": [], "default_payment_method": null, "default_source": null, "default_tax_rates": [], "description": null, "discounts": [], "due_date": null, "ending_balance": null, "footer": null, "from_invoice": null, "last_finalization_error": null, "latest_revision": null, "lines": { "object": "list", "data": [], "has_more": false, "total_count": 0, "url": "/v1/invoices/in_1MtHbELkdIwHu7ixl4OzzPMv/lines" }, "id": "upcoming_in_1MtHbELkdIwHu7ixl4OzzPMv", "object": "invoice", "account_country": "US", "account_name": "Stripe Docs", "account_tax_ids": null, "amount_due": 0, "amount_paid": 0, "amount_overpaid": 0, "amount_remaining": 0, "amount_shipping": 0, "application": null, "application_fee_amount": null, "attempt_count": 0, "attempted": false, "auto_advance": false, "automatic_tax": { "enabled": false, "status": null }, "livemode": false, "metadata": {}, "next_payment_attempt": null, "number": null, "on_behalf_of": null, "parent": null, "payment_settings": { "default_mandate": null, "payment_method_options": null, "payment_method_types": null }, "period_end": 1680644467, "period_start": 1680644467, "post_payment_credit_notes_amount": 0, "pre_payment_credit_notes_amount": 0, "receipt_number": null, "shipping_cost": null, "shipping_details": null, "starting_balance": 0, "statement_descriptor": null, "status": "draft", "status_transitions": { "finalized_at": null, "marked_uncollectible_at": null, "paid_at": null, "voided_at": null }, "subtotal": 0, "subtotal_excluding_tax": 0, "test_clock": null, "total": 0, "total_discount_amounts": [], "total_excluding_tax": 0, "total_taxes": [], "webhooks_delivered_at": 1680644467 } ``` ## Monitor servicing events Pricing plan subscriptions send event notifications whenever the servicing and collection states change. Listen for these events and use them to construct your business logic: | Event | Description | | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | `v2.billing.pricing_plan_subscription.servicing_activated` | Sent when the subscription’s servicing becomes active, either when the first service period starts or when a paused subscription resumes. | | `v2.billing.pricing_plan_subscription.servicing_paused` | Sent when Stripe pauses the subscription’s servicing. | | `v2.billing.pricing_plan_subscription.servicing_canceled` | Sent when the subscription’s servicing is canceled, either by the customer or by Stripe. | | `v2.billing.pricing_plan_subscription.collection_current` | Sent when the subscription’s payment collection is current and all payments have been processed. | | `v2.billing.pricing_plan_subscription.collection_awaiting_customer_action` | Sent when payment collection requires customer action (such as 3DS authentication). | | `v2.billing.pricing_plan_subscription.collection_paused` | Sent when Stripe pauses payment collection for the subscription. | To handle these [v2 Events](https://docs.stripe.com/api/v2/core/events.md?api-version=preview), configure an [Event Destination](https://docs.stripe.com/api/v2/core/event_destinations.md?api-version=preview) and point it at your webhook endpoint. You can either: - Create the Event Destination from [Workbench](https://docs.stripe.com/workbench/event-destinations.md). - Create the Event Destination [through the Stripe API](https://docs.stripe.com/api/v2/core/event_destinations.md?api-version=preview). After you’ve created a destination, you can set up your webhook endpoint to handle these events: ```ruby require 'stripe' post '/v2_webhook_endpoint' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e status 400 return rescue Stripe::SignatureVerificationError => e status 400 return end client = Stripe::StripeClient.new("<>") case event.type when 'v2.billing.pricing_plan_subscription.servicing_activated' # Servicing becomes active, either when the first service period starts # or when a paused subscription resumes. subscription_id = event.related_object.id subscription = client.v2.billing.pricing_plan_subscriptions .retrieve(subscription_id) # Look up your user in the database using the metadata passed into # Checkout Session create user_id = subscription.metadata["my_user_id"] user = User.find_by_id(user_id) # Fill in your logic here: mark_subscription_active(user, subscription) when 'v2.billing.pricing_plan_subscription.servicing_paused' # Stripe pauses the subscription's servicing. subscription_id = event.related_object.id subscription = client.v2.billing.pricing_plan_subscriptions .retrieve(subscription_id) # Look up your user in the database using the metadata passed into # Checkout Session create user_id = subscription.metadata["my_user_id"] user = User.find_by_id(user_id) # Fill in your logic here: mark_subscription_paused(user, subscription) when 'v2.billing.pricing_plan_subscription.servicing_canceled' # Servicing is canceled, either by the customer or by Stripe. subscription_id = event.related_object.id subscription = client.v2.billing.pricing_plan_subscriptions .retrieve(subscription_id) # Look up your user in the database using the metadata passed into # Checkout Session create user_id = subscription.metadata["my_user_id"] user = User.find_by_id(user_id) # Fill in your logic here: mark_subscription_canceled(user, subscription) end status 200 end ``` ## Test the integration To test your integration: - [Create a sandbox](https://docs.stripe.com/sandboxes/dashboard/manage.md#create-a-sandbox). - Create a test pricing plan and at least one underlying pricing component in your sandbox. - Use [test cards](https://docs.stripe.com/testing.md) to simulate successful and failed payments. - Create [test meter events](https://docs.stripe.com/billing/subscriptions/usage-based/pricing-plans.md#create-meter) to simulate usage. - Use [Simulations](https://docs.stripe.com/billing/testing/test-clocks/simulate-subscriptions.md) to simulate billing. > #### Don't create test clocks in the past > > When you create a test clock for a pricing plan subscription, only create clocks in the future. If you create a clock in the past, invoice amounts won’t be correct. Create a test clock with a UNIX timestamp: ```curl curl https://api.stripe.com/v1/test_helpers/test_clocks \ -u "<>:" \ -d frozen_time=1577836800 ``` Make a note of the test clock’s ID. Next, create a test customer with the clock: ```curl curl https://api.stripe.com/v1/customers \ -u "<>:" \ --data-urlencode "email=test@example.com" \ -d test_clock={{TEST_CLOCK_ID}} ``` Create a billing profile: ```curl curl -X POST https://api.stripe.com/v2/billing/profiles \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "customer": "{{CUSTOMER_ID}}" }' ``` Create a billing interval to define when to bill the customer. Save the ID. ```curl curl -X POST https://api.stripe.com/v2/billing/cadences \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "payer": { "billing_profile": "{{BILLING_PROFILE_ID}}" }, "billing_cycle": { "type": "month", "interval_count": 3 }, "settings": { "collection": { "id": "{{COLLECTION_SETTINGS_ID}}" } } }' ``` [Create a pricing plan subscription](https://docs.stripe.com/billing/subscriptions/usage-based/pricing-plans.md#subscribe) for the test customer. Create a [billing intent](https://docs.stripe.com/api/v2/billing-intents/intents/create.md?api-version=preview) to track the status of the pricing plan subscription. First, you create a draft billing intent. Save the ID of the intent. ```curl curl -X POST https://api.stripe.com/v2/billing/intents \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "currency": "usd", "cadence": "{{CADENCE_ID}}", "actions": [ { "type": "subscribe", "subscribe": { "type": "pricing_plan_subscription_details", "pricing_plan_subscription_details": { "pricing_plan": "{{PRICING_PLAN_ID}}", "pricing_plan_version": "{{PRICING_PLAN_VERSION}}" } } } ] }' ``` Next, reserve the billing intent: ```curl curl -X POST https://api.stripe.com/v2/billing/intents/{{BILLING_INTENT_ID}}/reserve \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" ``` Next, commit the billing intent to activate the pricing plan subscription and bill the customer according to the plan and cadence. (If you configured collection settings to `automatic`, you must have a successful [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) to commit the Intent. If you have the collection setting set to `send_invoice`, you don’t need to pass the Payment Intent.) ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1000 \ -d currency=usd \ -d customer={{CUSTOMER_ID}} \ -d payment_method=pm_card_visa \ -d "return_url=example.com" \ -d confirm=true ``` For testing purposes, you can set `payment_method` to “pm_card_visa”. ```curl curl -X POST https://api.stripe.com/v2/billing/intents/{{BILLING_INTENT_ID}}/commit \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "payment_intent": "{{PAYMENT_INTENT_ID}}" }' ``` Pay the invoice generated by the subscription. After the invoice is paid, you can simulate usage and advance the clock, which triggers the next month’s billing. If you use Checkout, you can open the returned Checkout Session’s `url` in your browser and complete payment with a [test card](https://docs.stripe.com/testing.md#use-test-cards). Record some test usage: ```curl curl -X POST https://api.stripe.com/v2/billing/meter_events \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "event_name": "hypernian_tokens", "payload": { "stripe_customer_id": "{{CUSTOMER_ID}}", "value": "100" } }' ``` Advance the test clock’s frozen time forward by a month. In this example, the test clock currently has a timestamp of `1577836800`. To add a month, add `30 * 24 * 60 * 60`, or `2592000` seconds. The new timestamp a month from now is `1580428800`. ```curl curl https://api.stripe.com/v1/test_helpers/test_clocks/{{TEST_CLOCK_ID}}/advance \ -u "<>:" \ -d frozen_time=1580428800 ``` ## Optional: Collect taxes To collect taxes automatically, [create a Checkout Session ](https://docs.stripe.com/api/checkout/sessions/create.md) that includes [checkout_items](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-checkout_items) and set `automatic_tax.enabled` to true. ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -H "Stripe-Version: 2025-09-30.preview;checkout_product_catalog_preview=v1" \ -d customer={{CUSTOMER_ID}} \ -d "checkout_items[0][type]=pricing_plan_subscription_item" \ -d "checkout_items[0][pricing_plan_subscription_item][pricing_plan]={{PRICING_PLAN_ID}}" \ -d success_url={{SUCCESS_URL}} \ -d "automatic_tax[enabled]=true" ``` The page displays your pricing plan’s details and collects the customer’s payment information. After the customer completes the session, they’re redirected to the URL you specified for `success_url`. ## Optional: Set up the customer portal You can provide self-service functions to your customers by setting up a [customer portal](https://docs.stripe.com/customer-management/activate-no-code-customer-portal.md). Using the customer portal with pricing plan subscriptions is currently read-only: customers can’t cancel, change plans, or update their payment methods for pricing plan billing subscriptions. Currently, you can only configure a customer portal session through the Dashboard. Using the customer portal with pricing plan subscriptions lets your customers view: - The plan they’re subscribed to, including details of the hybrid plan you’re offering. - Upcoming invoices that help them understand how much they’ll be billed at the end of the month. - The payment method on file for the Subscription in question. - Past invoices they’ve been charged for. - Their billing information.