Subscriptions
Subscriptions
Subscriptions represent recurring billing relationships between customers and plans.
Subscription Lifecycle
┌─────────┐ ┌──────────┐ ┌────────┐ ┌───────────┐│ Created │───▶│ Trialing │───▶│ Active │───▶│ Cancelled │└─────────┘ └──────────┘ └────────┘ └───────────┘ │ ▼ ┌──────────┐ │ Past Due │ └──────────┘ │ ▼ ┌──────────┐ │ Unpaid │ └──────────┘Creating Subscriptions
Basic Subscription
const subscription = await billing.subscriptions.create({ customerId: 'cus_123', planId: 'price_pro_monthly'});With Trial Period
const subscription = await billing.subscriptions.create({ customerId: 'cus_123', planId: 'price_pro_monthly', trialDays: 14});With Promo Code
const subscription = await billing.subscriptions.create({ customerId: 'cus_123', planId: 'price_pro_monthly', promoCodeId: 'promo_launch50'});Subscription Status
| Status | Description |
|---|---|
trialing | In trial period, no payment yet |
active | Paid and active |
past_due | Payment failed, grace period |
unpaid | Multiple payment failures |
paused | Temporarily paused |
cancelled | Cancelled, may have access until period end |
Managing Subscriptions
Upgrading/Downgrading
const subscription = await billing.subscriptions.update('sub_123', { planId: 'price_enterprise_monthly', proration: 'create_prorations' // or 'none'});Pausing
const subscription = await billing.subscriptions.pause('sub_123');Resuming
const subscription = await billing.subscriptions.resume('sub_123');Cancelling
// Cancel at period endconst subscription = await billing.subscriptions.cancel('sub_123', { atPeriodEnd: true});
// Cancel immediatelyconst subscription = await billing.subscriptions.cancel('sub_123', { atPeriodEnd: false});Retrieving Subscriptions
Single Subscription
const subscription = await billing.subscriptions.get('sub_123');Customer’s Subscriptions
const subscriptions = await billing.subscriptions.getByCustomerId('cus_123');All Subscriptions
const subscriptions = await billing.subscriptions.list({ status: 'active', planId: 'price_pro_monthly', limit: 10});Subscription Object
interface Subscription { id: string; customerId: string; planId: string; status: SubscriptionStatus; currentPeriodStart: Date; currentPeriodEnd: Date; trialStart?: Date; trialEnd?: Date; cancelAt?: Date; // Scheduled cancellation date canceledAt?: Date; // When cancellation occurred cancelAtPeriodEnd: boolean; metadata: Record<string, string>; externalIds: Record<string, string>; createdAt: Date; updatedAt: Date;}Events
| Event | Description |
|---|---|
subscription.created | New subscription created |
subscription.updated | Subscription was modified |
subscription.canceled | Subscription was canceled |
subscription.paused | Subscription was paused |
subscription.resumed | Subscription was resumed |
subscription.trial_ending | Trial ends in 3 days |
billing.on('subscription.created', async (event) => { const { customerId, planId } = event.data; await provisionFeatures(customerId, planId);});
billing.on('subscription.canceled', async (event) => { await sendCancellationSurvey(event.data.customerId);});Best Practices
- Always handle status changes via webhooks
- Implement grace periods for failed payments
- Send trial ending reminders before conversion
- Track cancellation reasons for analytics
- Use cancel at period end for better UX