# Use Trial Offers with Checkout

Offer paid introductory prices for individual subscription items.

Use [Trial Offers](https://docs.stripe.com/billing/subscriptions/trials.md) to charge a discounted recurring price for a number of billing intervals, then transition the subscription item to its regular recurring Price.

> This feature is in private preview.

### Trial offers on Checkout

Enter your email to request access.

```bash
curl https://docs.stripe.com/preview/register \
  -X POST \
  -H "Content-Type: application/json" \
  -H "Referer: https://docs.stripe.com/payments/checkout/trial-offers" \
  -d '{"email": "EMAIL", "preview": "checkout_beta_preview"}'
```

## How paid trials work

Checkout creates the subscription after successful checkout. Stripe Billing bills the introductory price for the offer’s configured number of intervals, then transitions the item to its regular recurring price. A paid introductory period doesn’t imply that the subscription has `trialing` status. Use the subscription item’s `current_trial` to track the offer.

## Before you begin

- Confirm that your private preview invitation enables using trial offers on Checkout.
- Use [API version](https://docs.stripe.com/api/versioning.md) `2026-09-30.preview` and the supported preview [server SDK](https://docs.stripe.com/sdks.md) specified in your invitation. Set `Stripe-Version: 2026-09-30.preview` for direct HTTP requests.
- Use a restricted API key with `subscription_write` permission to create trial offers and `checkout_session_write` permission to create Checkout Sessions. See the [API permissions reference](https://docs.stripe.com/keys/permissions-reference.md).
- Review the private preview [limitations](https://docs.stripe.com/payments/checkout/trial-offers.md#limitations). To use Trial Offers, billing mode must be [flexible](https://docs.stripe.com/billing/subscriptions/billing-mode.md#create-a-new-subscription-with-flexible-billing-mode) on the Checkout Session.

## Create a trial offer [Server]

Create two active, fixed-amount recurring [prices](https://docs.stripe.com/products-prices/manage-prices.md#create-price), one to charge during the trial and one to charge after the trial. Both prices must belong to the same Stripe account and the same sandbox or live environment as the Checkout Session, and have the same currency and tax behavior.

Create a trial offer with these two prices, and define how many `price.recurring` intervals the trial lasts.

```curl
curl https://api.stripe.com/v1/product_catalog/trial_offers \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Version: 2026-09-30.preview" \
  -d price={{TRIAL_PRICE_ID}} \
  -d "duration[type]=relative" \
  -d "duration[relative][iterations]=1" \
  -d "end_behavior[transition][price]={{REGULAR_PRICE_ID}}"
```

Save the returned trial offer ID for the Session request. See [Configure trial offers on subscriptions](https://docs.stripe.com/billing/subscriptions/trials.md) for trial offer management.

## Create a Checkout Session [Server]

Create a Checkout Session with `billing_mode.type` = `flexible` and `items[].subscription`. If you use a [restricted API key](https://docs.stripe.com/keys/restricted-api-keys.md), grant it **Trial Offers: Write** (`trial_offer_write`) to create the offer and **Checkout Sessions: Write** (`checkout_session_write`) to create the Session. Store API keys in a secrets manager or environment variable, and follow the [API key security recommendations](https://docs.stripe.com/keys-best-practices.md).

In this Checkout Session integration, `items` replace `mode` and `line_items`. The subscription item can contain multiple sub-items, and each sub-item can use a Trial Offer or an ordinary Price. All initial recurring prices, including trial prices, must have matching billing intervals and interval counts. A trial offer’s post-trial price can use a different interval. The top-level item creates one subscription, and its nested items describe the recurring subscription items. See the [subscription item API reference](https://docs.stripe.com/api/checkout/sessions/create.md?api-version=2026-09-30.preview#create_checkout_session-items-subscription).

Attach your trial offer with `current_trial.trial_offer` in the nested `items` array. Don’t set `price` or `price_data` on that nested item.

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Version: 2026-09-30.preview" \
  -d ui_mode=hosted_page \
  -d currency=usd \
  -d "allowed_payment_method_types[0]=card" \
  --data-urlencode "success_url=https://example.com/checkout/success?session_id={CHECKOUT_SESSION_ID}" \
  --data-urlencode "cancel_url=https://example.com/pricing" \
  -d "items[0][type]=subscription" \
  -d "items[0][subscription][billing_mode][type]=flexible" \
  -d "items[0][subscription][items][0][current_trial][trial_offer]={{TRIAL_OFFER_ID}}" \
  -d "items[0][subscription][items][0][quantity]=1"
```

The response contains `session.url`. The created subscription reference is populated after completion.

### Update an existing Checkout integration

Existing subscription-mode integrations remain supported. For this paid-trial flow, change the request and the location of the created subscription reference:

| Existing integration | Unified-mode integration |
| --- | --- |
| `mode=subscription` | Omit `mode`; use `items[].type=subscription`. |
| Recurring prices in `line_items[]` | Recurring prices or trial offers in `items[].subscription.items[]`. |
| Settings in `subscription_data` | Settings in `items[].subscription`. |
| Created subscription at `session.subscription` | Created subscription at `session.items[].subscription.subscription`. |

## Redirect your customer to Checkout [Server]

Return an HTTP `303` redirect to `session.url` from your Session-creation endpoint.

## Provision and monitor the subscription [Server]

Set up webhooks to listen to subscription change events, such as upgrades and cancellations. [Verify incoming webhook signatures](https://docs.stripe.com/webhooks.md#verify-events) before using events to change subscription access. If you restrict inbound traffic by IP address, allow Stripe [public webhook IP addresses](https://docs.stripe.com/ips.md). Learn more about [subscription webhooks](https://docs.stripe.com/billing/subscriptions/webhooks.md). You can view events in the [Dashboard](https://dashboard.stripe.com/test/events) or with the [Stripe CLI](https://docs.stripe.com/webhooks.md#test-webhook).

For more details, see [testing your Billing integration](https://docs.stripe.com/billing/testing.md).

## Optional: Configure billing after the trial ends

By default, the subscription’s billing cycle anchor resets when the last trial offer ends.

Set `trial_settings.end_behavior.billing_cycle_anchor` to `unchanged` to preserve the existing anchor. You can prorate the period through the next anchor. An anchor reset can also affect other items on the subscription.

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Version: 2026-09-30.preview" \
  -d ui_mode=hosted_page \
  -d currency=usd \
  -d "allowed_payment_method_types[0]=card" \
  --data-urlencode "success_url=https://example.com/checkout/success?session_id={CHECKOUT_SESSION_ID}" \
  --data-urlencode "cancel_url=https://example.com/pricing" \
  -d "items[0][type]=subscription" \
  -d "items[0][subscription][billing_mode][type]=flexible" \
  -d "items[0][subscription][items][0][current_trial][trial_offer]={{TRIAL_OFFER_ID}}" \
  -d "items[0][subscription][items][0][quantity]=1" \
  -d "items[0][subscription][trial_settings][end_behavior][missing_payment_method]=create_invoice" \
  -d "items[0][subscription][trial_settings][end_behavior][billing_cycle_anchor]=unchanged"
```

## Test your integration

Review [trial and promotion compliance requirements](https://docs.stripe.com/billing/subscriptions/trials/manage-trial-compliance.md) before launching.

### Test payment methods

Use the following table to test different payment methods and scenarios.

| Payment method | Scenario | How to test |
| --- | --- | --- |
| BECS Direct Debit | Your customer successfully pays with BECS Direct Debit. | Fill out the form using the account number `900123456` and BSB `000000`. The confirmed PaymentIntent initially transitions to `processing`, then transitions to the `succeeded` status three minutes later. |
| BECS Direct Debit | Your customer’s payment fails with an `account_closed` error code. | Fill out the form using the account number `111111113` and BSB `000000`. |
| Credit card | The card payment succeeds and doesn’t require authentication. | Fill out the credit card form using the credit card number `4242 4242 4242 4242` with any expiration, CVC, and postal code. |
| Credit card | The card payment requires *authentication* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase). | Fill out the credit card form using the credit card number `4000 0025 0000 3155` with any expiration, CVC, and postal code. |
| Credit card | The card is declined with a decline code like `insufficient_funds`. | Fill out the credit card form using the credit card number `4000 0000 0000 9995` with any expiration, CVC, and postal code. |
| SEPA Direct Debit | Your customer successfully pays with SEPA Direct Debit. | Fill out the form using the account number `AT321904300235473204`. The confirmed PaymentIntent initially transitions to processing, then transitions to the succeeded status three minutes later. |
| SEPA Direct Debit | Your customer’s PaymentIntent status transitions from `processing` to `requires_payment_method`. | Fill out the form using the account number `AT861904300235473202`. |

## Limitations

The private preview has these limitations:

- Hosted `ui_mode` is supported, Elements and embedded page Checkout Sessions aren’t.
- Payment Links and Pricing Table isn’t supported.
- The Checkout Session item is immutable after creation.
- Initial payable amount must meet the [minimum charge](https://docs.stripe.com/currencies.md#minimum-and-maximum-charge-amounts). A nonzero trial price isn’t enough if it’s below the minimum or customer credit makes the initial bill non-chargeable.
- Stripe Tax is supported.
- Discounts, promotion codes, and coupons on the Checkout Session aren’t supported.
- Recurring commit schedules aren’t supported.
- The Checkout Session won’t support the following payment methods. If they’re passed to the Checkout Session, they’re filtered out.
  - ACSS Debit
  - Konbini
  - Swish
  - Vipps
- The Checkout Session won’t support payment method options for the following. If they’re passed into the Checkout Session, the payment method and its corresponding payment method option is filtered out:
  - ACSS Debit
  - BACS Debit
  - Blik
  - Customer Balance
  - Konbini
  - Klarna
  - Pay By Bank
  - PayPal
  - Payto
  - Pix
  - Sepa Debit
  - UPI
  - US Bank Account
- Card installments aren’t supported.
- Card brand filtering isn’t supported.
- Cross-sells and optional items aren’t supported.
- Surcharging isn’t supported.
- Managed Payments isn’t supported.
