Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.flexprice.io/llms.txt

Use this file to discover all available pages before exploring further.

Overview

A trial period lets customers use a plan for a defined number of days before their first invoice is generated. When a subscription enters trialing status, no invoice is created. Billing begins only after the trial ends and the subscription transitions to active. Common use cases: product-led growth, freemium-to-paid conversion, and enterprise evaluation periods.

How It Works

Trial subscriptions move through three statuses:
trialing ──(trial_end reached)──► incomplete ──(invoice paid / zero amount)──► active
StatusWhat it meansBilling
trialingTrial window is activeNo invoice generated
incompleteTrial ended, invoice issuedAwaiting payment of trial-end invoice
activeTrial converted, billing liveNormal billing cycle begins
While in trialing, current_period_start equals trial_start and current_period_end equals trial_end. When the trial ends, the billing anchor resets to trial_end. The first paid billing period runs from trial_end to trial_end + billing_period. There is no shortened first period. Trial-end detection is fully automated. No manual trigger is required.

Configuring a Trial Period

Trial configuration is a two-step process: set the trial days on the price, then create a subscription.

Step 1: Set trial_period_days on the price

trial_period_days is only valid on recurring fixed prices (billing_cadence: RECURRING, price_type: FIXED). It cannot be set on usage-based or tiered prices. If omitted, it defaults to 0 (no trial).
curl -X POST https://api.flexprice.io/v1/prices \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4900,
    "currency": "USD",
    "billing_cadence": "RECURRING",
    "billing_period": "MONTHLY",
    "billing_period_count": 1,
    "price_type": "FIXED",
    "trial_period_days": 14
  }'
Response (abbreviated):
{
  "id": "price_01abc123",
  "billing_cadence": "RECURRING",
  "price_type": "FIXED",
  "trial_period_days": 14
}

Step 2: Create a subscription (trial inherited automatically)

When all recurring fixed prices on a plan share the same trial_period_days, that value is inherited by the subscription automatically. No trial fields are required in the subscription request.
curl -X POST https://api.flexprice.io/v1/subscriptions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cust_01xyz",
    "plan_id": "plan_01abc",
    "currency": "USD",
    "billing_cadence": "RECURRING",
    "billing_period": "MONTHLY",
    "billing_period_count": 1,
    "start_date": "2025-05-01T00:00:00Z"
  }'
Response:
{
  "id": "sub_01def456",
  "status": "trialing",
  "trial_start": "2025-05-01T00:00:00Z",
  "trial_end": "2025-05-15T00:00:00Z",
  "current_period_start": "2025-05-01T00:00:00Z",
  "current_period_end": "2025-05-15T00:00:00Z"
}
No invoice is created at subscription creation.

Overriding trial days at subscription creation

Pass trial_period_days in the subscription request to override the plan-level value.
curl -X POST https://api.flexprice.io/v1/subscriptions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cust_01xyz",
    "plan_id": "plan_01abc",
    "currency": "USD",
    "billing_cadence": "RECURRING",
    "billing_period": "MONTHLY",
    "billing_period_count": 1,
    "start_date": "2025-05-01T00:00:00Z",
    "trial_period_days": 0
  }'
ValueEffect
OmittedInherits trial_period_days from plan prices
0Disables trial; subscription starts as active immediately
> 0Overrides plan-level value with this number of days
To shorten or lengthen the plan-level trial, pass a positive integer:
curl -X POST https://api.flexprice.io/v1/subscriptions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cust_01xyz",
    "plan_id": "plan_01abc",
    "currency": "USD",
    "billing_cadence": "RECURRING",
    "billing_period": "MONTHLY",
    "billing_period_count": 1,
    "start_date": "2025-05-01T00:00:00Z",
    "trial_period_days": 30
  }'

What Happens at Trial End

Trial end is detected automatically. When trial_end <= now:
  1. Subscription status changes to incomplete.
  2. Billing anchor resets to trial_end.
  3. A SUBSCRIPTION_TRIAL_END invoice is created covering [trial_end, trial_end + billing_period].
  4. If the invoice amount is zero: subscription immediately converts to active. No payment event needed.
  5. If the invoice amount is non-zero: subscription stays incomplete until the invoice is paid.
An incomplete subscription does not auto-expire. It remains incomplete until the trial-end invoice is paid or the subscription is cancelled.
payment_behavior at trial end:
ValueBehavior if payment fails
default_active (default)Subscription activates regardless of payment result
allow_incompleteSubscription stays incomplete if payment fails
error_if_incompleteSubscription stays incomplete if payment fails; wallet fallback is not attempted
default_incompleteSubscription stays incomplete; only valid with send_invoice collection method
Credit grants held pending activation are applied automatically when the subscription becomes active.

API Reference

Price fields

FieldTypeRequiredDescription
trial_period_daysintegerNoDays of free trial before first invoice. Default 0. Only valid for billing_cadence: RECURRING + price_type: FIXED. Must be >= 0.

Subscription create fields

FieldTypeRequiredDescription
trial_period_daysintegerNoOverride plan-level trial length in days. 0 disables trial. Omit to inherit from plan prices. Must be >= 0.
payment_behaviorenumNoHow to handle payment failure at trial end. Options: default_active, allow_incomplete, error_if_incomplete, default_incomplete. Default: default_active.
FieldTypeDescription
statusstringtrialing while trial is active
trial_starttimestamp (ISO 8601)When the trial began. Equals start_date.
trial_endtimestamp (ISO 8601)When the trial ends and billing begins.
current_period_starttimestamp (ISO 8601)Equals trial_start during the trial window.
current_period_endtimestamp (ISO 8601)Equals trial_end during the trial window.

Webhooks & Events

One event fires during the trial lifecycle: subscription.activated is fired when the subscription converts from trialing to active. This event fires in two scenarios:
  • The SUBSCRIPTION_TRIAL_END invoice is fully paid.
  • The trial-end invoice amount is zero (immediate auto-activation).
There is no subscription.trialing, subscription.trial_ended, or subscription.trial_ending event. Use subscription.activated to detect trial conversion.
The payload is the standard subscription object with status: "active".
{
  "subscription": {
    "id": "sub_01def456",
    "status": "active",
    "trial_start": "2025-05-01T00:00:00Z",
    "trial_end": "2025-05-15T00:00:00Z",
    "current_period_start": "2025-05-15T00:00:00Z",
    "current_period_end": "2025-06-15T00:00:00Z"
  }
}
For information on configuring webhook endpoints, see Webhooks.

Edge Cases

ScenarioBehavior
trial_period_days = 0 at subscription levelTrial disabled even if plan price has trial_period_days > 0
Plan prices have mismatched trial_period_daysSubscription creation fails: "all recurring fixed plan prices must have the same trial_period_days"
Cancellation during trialStandard cancellation applies. Trial-end processing skips subscriptions not in trialing status.
Paused subscription when trial_end is reachedTrial-end processing is skipped. Runs when the subscription is unpaused.
Zero-amount trial-end invoiceSubscription auto-activates immediately without waiting for a payment event.
Inherited (child) subscriptionsTrial status cascades from parent. Children are not processed independently.
Re-trialingNot supported. Each subscription has one trial window. To extend a trial, cancel and recreate the subscription.

Best Practices

Collect a payment method before trial ends. FlexPrice does not require a payment method to create a trialing subscription, but the trial-end invoice will fail without one on file. Prompt users to add payment details during the trial window. Set payment_behavior explicitly. The default is default_active, which activates the subscription regardless of payment result. Use allow_incomplete if you want the subscription to stay incomplete if payment fails at trial end. Use subscription.activated to gate access. This event fires for both trial conversions and normal activations. Your webhook handler needs no special-casing. Listen for subscription.activated and provision accordingly. Test with zero-amount prices in staging. Set your plan price to $0 to fast-path through trialing → active without needing a real payment method or payment gateway. Don’t rely on re-trialing. Each subscription supports one trial window. There is no API to restart a trial on an existing subscription.