or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

billing.mdcheckout.mdconfiguration.mdcore-resources.mdidentity.mdindex.mdissuing.mdradar.mdsubscriptions.mdtax.mdterminal.mdtreasury.mdwebhooks.md

subscriptions.mddocs/

0

# Subscriptions

1

2

Stripe's subscription system provides comprehensive recurring billing capabilities with flexible pricing models, prorations, trials, and lifecycle management. This module handles everything from simple monthly subscriptions to complex usage-based billing.

3

4

## Core Subscription Resources

5

6

### Subscriptions

7

8

The primary resource for managing recurring billing relationships:

9

10

```typescript { .api }

11

interface Subscription {

12

id: string;

13

object: 'subscription';

14

customer: string;

15

status: 'incomplete' | 'incomplete_expired' | 'trialing' | 'active' | 'past_due' | 'canceled' | 'unpaid';

16

items: {

17

object: 'list';

18

data: SubscriptionItem[];

19

};

20

current_period_start: number;

21

current_period_end: number;

22

trial_start?: number;

23

trial_end?: number;

24

cancel_at_period_end: boolean;

25

default_payment_method?: string;

26

}

27

28

// Create subscription

29

const subscription = await stripe.subscriptions.create({

30

customer: 'cus_123',

31

items: [

32

{

33

price: 'price_monthly_premium',

34

quantity: 1

35

}

36

],

37

payment_behavior: 'default_incomplete',

38

payment_settings: {

39

save_default_payment_method: 'on_subscription'

40

},

41

expand: ['latest_invoice.payment_intent']

42

});

43

44

// Create subscription with trial

45

const trialSubscription = await stripe.subscriptions.create({

46

customer: 'cus_123',

47

items: [{ price: 'price_123' }],

48

trial_period_days: 14,

49

trial_settings: {

50

end_behavior: {

51

missing_payment_method: 'cancel'

52

}

53

}

54

});

55

56

// Create subscription with custom billing cycle

57

const customBilling = await stripe.subscriptions.create({

58

customer: 'cus_123',

59

items: [{ price: 'price_123' }],

60

billing_cycle_anchor: Math.floor(Date.now() / 1000) + 86400, // Start tomorrow

61

proration_behavior: 'create_prorations'

62

});

63

64

// Retrieve subscription

65

const retrieved = await stripe.subscriptions.retrieve('sub_123', {

66

expand: ['customer', 'default_payment_method', 'items.data.price']

67

});

68

69

// Update subscription

70

const updated = await stripe.subscriptions.update('sub_123', {

71

items: [

72

{

73

id: 'si_existing_item',

74

price: 'price_new_plan',

75

quantity: 2

76

}

77

],

78

proration_behavior: 'always_invoice',

79

payment_behavior: 'pending_if_incomplete'

80

});

81

82

// List subscriptions

83

const subscriptions = await stripe.subscriptions.list({

84

customer: 'cus_123',

85

status: 'active',

86

limit: 10

87

});

88

89

// Cancel subscription at period end

90

const canceled = await stripe.subscriptions.update('sub_123', {

91

cancel_at_period_end: true,

92

cancellation_details: {

93

comment: 'Customer requested cancellation'

94

}

95

});

96

97

// Cancel subscription immediately

98

const immediatelyCanceled = await stripe.subscriptions.cancel('sub_123', {

99

prorate: true,

100

invoice_now: true

101

});

102

103

// Resume canceled subscription

104

const resumed = await stripe.subscriptions.resume('sub_123', {

105

billing_cycle_anchor: 'now',

106

proration_behavior: 'create_prorations'

107

});

108

109

// Search subscriptions

110

const searchResults = await stripe.subscriptions.search({

111

query: 'status:"active" AND metadata["plan_type"]:"premium"'

112

});

113

```

114

115

### SubscriptionItems

116

117

Individual line items within a subscription:

118

119

```typescript { .api }

120

interface SubscriptionItem {

121

id: string;

122

object: 'subscription_item';

123

subscription: string;

124

price: Price;

125

quantity?: number;

126

tax_rates?: TaxRate[];

127

created: number;

128

}

129

130

// Create subscription item (add to existing subscription)

131

const subscriptionItem = await stripe.subscriptionItems.create({

132

subscription: 'sub_123',

133

price: 'price_addon_feature',

134

quantity: 1,

135

proration_behavior: 'always_invoice',

136

payment_behavior: 'pending_if_incomplete'

137

});

138

139

// Create usage-based subscription item

140

const usageItem = await stripe.subscriptionItems.create({

141

subscription: 'sub_123',

142

price: 'price_usage_based',

143

billing_thresholds: {

144

usage_gte: 1000 // Bill when usage >= 1000 units

145

}

146

});

147

148

// Retrieve subscription item

149

const retrieved = await stripe.subscriptionItems.retrieve('si_123', {

150

expand: ['price.product']

151

});

152

153

// Update subscription item

154

const updated = await stripe.subscriptionItems.update('si_123', {

155

quantity: 3,

156

price: 'price_upgraded_plan',

157

proration_behavior: 'create_prorations'

158

});

159

160

// List subscription items

161

const items = await stripe.subscriptionItems.list({

162

subscription: 'sub_123'

163

});

164

165

// Delete subscription item

166

const deleted = await stripe.subscriptionItems.del('si_123', {

167

proration_behavior: 'always_invoice',

168

clear_usage: true

169

});

170

```

171

172

### Usage Records

173

174

Track usage for metered billing:

175

176

```typescript { .api }

177

// Create usage record

178

const usageRecord = await stripe.subscriptionItems.createUsageRecord(

179

'si_usage_based',

180

{

181

quantity: 100,

182

timestamp: Math.floor(Date.now() / 1000),

183

action: 'increment' // or 'set'

184

}

185

);

186

187

// Create usage record with idempotency

188

const idempotentUsage = await stripe.subscriptionItems.createUsageRecord(

189

'si_usage_based',

190

{

191

quantity: 50,

192

timestamp: Math.floor(Date.now() / 1000),

193

action: 'increment'

194

},

195

{

196

idempotencyKey: 'usage_' + Date.now()

197

}

198

);

199

200

// List usage record summaries

201

const usageSummaries = await stripe.subscriptionItems.listUsageRecordSummaries(

202

'si_usage_based',

203

{

204

limit: 10,

205

ending_before: Math.floor(Date.now() / 1000)

206

}

207

);

208

```

209

210

## Subscription Schedules

211

212

Manage complex subscription lifecycle changes:

213

214

```typescript { .api }

215

interface SubscriptionSchedule {

216

id: string;

217

object: 'subscription_schedule';

218

customer: string;

219

status: 'not_started' | 'active' | 'completed' | 'released' | 'canceled';

220

subscription?: string;

221

phases: SubscriptionSchedulePhase[];

222

}

223

224

// Create subscription schedule

225

const schedule = await stripe.subscriptionSchedules.create({

226

customer: 'cus_123',

227

start_date: Math.floor(Date.now() / 1000) + 86400, // Start tomorrow

228

end_behavior: 'cancel',

229

phases: [

230

{

231

// Trial phase

232

items: [{ price: 'price_123', quantity: 1 }],

233

trial: true,

234

end_date: Math.floor(Date.now() / 1000) + 86400 * 14 // 14 days

235

},

236

{

237

// Regular billing phase

238

items: [{ price: 'price_123', quantity: 1 }],

239

iterations: 12 // 12 billing cycles

240

},

241

{

242

// Discounted renewal phase

243

items: [{ price: 'price_discounted', quantity: 1 }]

244

// No end_date = continues indefinitely

245

}

246

]

247

});

248

249

// Create schedule with price changes

250

const pricingSchedule = await stripe.subscriptionSchedules.create({

251

customer: 'cus_123',

252

phases: [

253

{

254

items: [{ price: 'price_starter', quantity: 1 }],

255

end_date: Math.floor(Date.now() / 1000) + 86400 * 90 // 3 months

256

},

257

{

258

items: [{ price: 'price_professional', quantity: 1 }],

259

proration_behavior: 'create_prorations'

260

}

261

]

262

});

263

264

// Retrieve subscription schedule

265

const retrieved = await stripe.subscriptionSchedules.retrieve('sub_sched_123', {

266

expand: ['subscription', 'phases.items.price']

267

});

268

269

// Update subscription schedule

270

const updated = await stripe.subscriptionSchedules.update('sub_sched_123', {

271

phases: [

272

{

273

items: [{ price: 'price_updated', quantity: 2 }],

274

start_date: Math.floor(Date.now() / 1000),

275

end_date: Math.floor(Date.now() / 1000) + 86400 * 30

276

}

277

]

278

});

279

280

// List subscription schedules

281

const schedules = await stripe.subscriptionSchedules.list({

282

customer: 'cus_123',

283

limit: 10

284

});

285

286

// Cancel subscription schedule

287

const canceled = await stripe.subscriptionSchedules.cancel('sub_sched_123');

288

289

// Release subscription schedule (convert to regular subscription)

290

const released = await stripe.subscriptionSchedule.release('sub_sched_123', {

291

preserve_cancel_date: true

292

});

293

```

294

295

## Legacy Plans

296

297

Legacy pricing model (use Prices for new integrations):

298

299

```typescript { .api }

300

interface Plan {

301

id: string;

302

object: 'plan';

303

amount?: number;

304

currency: string;

305

interval: 'day' | 'week' | 'month' | 'year';

306

interval_count: number;

307

nickname?: string;

308

product: string;

309

}

310

311

// Create plan (legacy - use Prices instead)

312

const plan = await stripe.plans.create({

313

id: 'gold-monthly',

314

amount: 2000,

315

currency: 'usd',

316

interval: 'month',

317

product: 'prod_gold_plan'

318

});

319

320

// Retrieve plan

321

const retrieved = await stripe.plans.retrieve('gold-monthly');

322

323

// Update plan

324

const updated = await stripe.plans.update('gold-monthly', {

325

nickname: 'Gold Monthly Plan',

326

metadata: { tier: 'premium' }

327

});

328

329

// List plans

330

const plans = await stripe.plans.list({

331

limit: 10,

332

active: true

333

});

334

335

// Delete plan

336

const deleted = await stripe.plans.del('gold-monthly');

337

```

338

339

## Invoicing

340

341

### Invoices

342

343

Billing documents for subscriptions and one-off charges:

344

345

```typescript { .api }

346

interface Invoice {

347

id: string;

348

object: 'invoice';

349

customer: string;

350

subscription?: string;

351

status: 'draft' | 'open' | 'paid' | 'uncollectible' | 'void';

352

amount_due: number;

353

amount_paid: number;

354

currency: string;

355

due_date?: number;

356

}

357

358

// Create invoice

359

const invoice = await stripe.invoices.create({

360

customer: 'cus_123',

361

collection_method: 'send_invoice',

362

days_until_due: 30,

363

description: 'Custom invoice for services'

364

});

365

366

// Create subscription invoice preview

367

const preview = await stripe.invoices.retrieveUpcoming({

368

customer: 'cus_123',

369

subscription: 'sub_123',

370

subscription_items: [

371

{

372

id: 'si_123',

373

quantity: 2

374

}

375

]

376

});

377

378

// Retrieve invoice

379

const retrieved = await stripe.invoices.retrieve('in_123', {

380

expand: ['payment_intent', 'customer']

381

});

382

383

// Update invoice

384

const updated = await stripe.invoices.update('in_123', {

385

description: 'Updated invoice description',

386

footer: 'Thank you for your business!',

387

metadata: { order_id: '12345' }

388

});

389

390

// List invoices

391

const invoices = await stripe.invoices.list({

392

customer: 'cus_123',

393

status: 'open',

394

limit: 10

395

});

396

397

// Finalize invoice

398

const finalized = await stripe.invoices.finalizeInvoice('in_123', {

399

auto_advance: true

400

});

401

402

// Pay invoice

403

const paid = await stripe.invoices.pay('in_123', {

404

payment_method: 'pm_card_visa',

405

paid_out_of_band: false

406

});

407

408

// Send invoice

409

const sent = await stripe.invoices.sendInvoice('in_123', {

410

delivery_method: 'email'

411

});

412

413

// Mark uncollectible

414

const uncollectible = await stripe.invoices.markUncollectible('in_123');

415

416

// Void invoice

417

const voided = await stripe.invoices.voidInvoice('in_123');

418

419

// Delete draft invoice

420

const deleted = await stripe.invoices.del('in_123');

421

422

// Search invoices

423

const searchResults = await stripe.invoices.search({

424

query: 'total>1000 AND status:"paid"'

425

});

426

427

// Get upcoming invoice line items

428

const upcomingLines = await stripe.invoices.upcomingLines({

429

customer: 'cus_123',

430

subscription: 'sub_123'

431

});

432

```

433

434

### InvoiceItems

435

436

Individual line items on invoices:

437

438

```typescript { .api }

439

interface InvoiceItem {

440

id: string;

441

object: 'invoiceitem';

442

customer: string;

443

amount: number;

444

currency: string;

445

description?: string;

446

invoice?: string;

447

subscription?: string;

448

}

449

450

// Create invoice item

451

const invoiceItem = await stripe.invoiceItems.create({

452

customer: 'cus_123',

453

amount: 2500,

454

currency: 'usd',

455

description: 'One-time setup fee'

456

});

457

458

// Create invoice item for specific invoice

459

const specificItem = await stripe.invoiceItems.create({

460

customer: 'cus_123',

461

amount: 1000,

462

currency: 'usd',

463

description: 'Custom charge',

464

invoice: 'in_123'

465

});

466

467

// Create invoice item with price

468

const priceBasedItem = await stripe.invoiceItems.create({

469

customer: 'cus_123',

470

price: 'price_setup_fee',

471

quantity: 1

472

});

473

474

// Retrieve invoice item

475

const retrieved = await stripe.invoiceItems.retrieve('ii_123');

476

477

// Update invoice item

478

const updated = await stripe.invoiceItems.update('ii_123', {

479

description: 'Updated setup fee',

480

amount: 3000,

481

metadata: { type: 'setup' }

482

});

483

484

// List invoice items

485

const invoiceItems = await stripe.invoiceItems.list({

486

customer: 'cus_123',

487

limit: 10

488

});

489

490

// Delete invoice item

491

const deleted = await stripe.invoiceItems.del('ii_123');

492

```

493

494

## Coupons and Discounts

495

496

### Coupons

497

498

Reusable discount definitions:

499

500

```typescript { .api }

501

interface Coupon {

502

id: string;

503

object: 'coupon';

504

name?: string;

505

percent_off?: number;

506

amount_off?: number;

507

currency?: string;

508

duration: 'forever' | 'once' | 'repeating';

509

duration_in_months?: number;

510

max_redemptions?: number;

511

times_redeemed: number;

512

valid: boolean;

513

}

514

515

// Create percentage coupon

516

const percentCoupon = await stripe.coupons.create({

517

id: 'SUMMER20',

518

percent_off: 20,

519

duration: 'repeating',

520

duration_in_months: 3,

521

max_redemptions: 100,

522

name: 'Summer Sale 20% Off'

523

});

524

525

// Create amount-based coupon

526

const amountCoupon = await stripe.coupons.create({

527

amount_off: 500,

528

currency: 'usd',

529

duration: 'once',

530

name: '$5 Off First Order'

531

});

532

533

// Create coupon with restrictions

534

const restrictedCoupon = await stripe.coupons.create({

535

percent_off: 15,

536

duration: 'forever',

537

applies_to: {

538

products: ['prod_premium_plan']

539

},

540

currency_options: {

541

eur: { amount_off: 450 },

542

gbp: { amount_off: 400 }

543

}

544

});

545

546

// Retrieve coupon

547

const retrieved = await stripe.coupons.retrieve('SUMMER20');

548

549

// Update coupon

550

const updated = await stripe.coupons.update('SUMMER20', {

551

name: 'Extended Summer Sale',

552

metadata: { campaign: 'summer_2024' }

553

});

554

555

// List coupons

556

const coupons = await stripe.coupons.list({

557

limit: 10

558

});

559

560

// Delete coupon

561

const deleted = await stripe.coupons.del('SUMMER20');

562

```

563

564

### PromotionCodes

565

566

Customer-facing codes that apply coupons:

567

568

```typescript { .api }

569

interface PromotionCode {

570

id: string;

571

object: 'promotion_code';

572

code: string;

573

coupon: Coupon;

574

active: boolean;

575

customer?: string;

576

expires_at?: number;

577

max_redemptions?: number;

578

times_redeemed: number;

579

}

580

581

// Create promotion code

582

const promotionCode = await stripe.promotionCodes.create({

583

coupon: 'SUMMER20',

584

code: 'SAVE20NOW',

585

max_redemptions: 50,

586

expires_at: Math.floor(Date.now() / 1000) + 86400 * 30 // 30 days

587

});

588

589

// Create customer-specific promotion code

590

const customerCode = await stripe.promotionCodes.create({

591

coupon: 'VIP10',

592

customer: 'cus_123',

593

code: 'VIPCUSTOMER'

594

});

595

596

// Auto-generate promotion code

597

const autoCode = await stripe.promotionCodes.create({

598

coupon: 'SUMMER20',

599

restrictions: {

600

minimum_amount: 1000,

601

minimum_amount_currency: 'usd'

602

}

603

});

604

605

// Retrieve promotion code

606

const retrieved = await stripe.promotionCodes.retrieve('promo_123');

607

608

// Update promotion code

609

const updated = await stripe.promotionCodes.update('promo_123', {

610

active: false,

611

metadata: { reason: 'expired_campaign' }

612

});

613

614

// List promotion codes

615

const promotionCodes = await stripe.promotionCodes.list({

616

coupon: 'SUMMER20',

617

active: true,

618

limit: 10

619

});

620

```

621

622

## Credit Notes

623

624

Issue credits for invoices:

625

626

```typescript { .api }

627

interface CreditNote {

628

id: string;

629

object: 'credit_note';

630

invoice: string;

631

customer: string;

632

amount: number;

633

currency: string;

634

status: 'issued' | 'void';

635

type: 'pre_payment' | 'post_payment';

636

}

637

638

// Create credit note

639

const creditNote = await stripe.creditNotes.create({

640

invoice: 'in_123',

641

lines: [

642

{

643

type: 'invoice_line_item',

644

invoice_line_item: 'il_123',

645

quantity: 1

646

}

647

],

648

reason: 'product_unsatisfactory'

649

});

650

651

// Create partial credit note

652

const partialCredit = await stripe.creditNotes.create({

653

invoice: 'in_123',

654

amount: 500,

655

reason: 'order_change'

656

});

657

658

// Preview credit note

659

const preview = await stripe.creditNotes.preview({

660

invoice: 'in_123',

661

amount: 1000

662

});

663

664

// Retrieve credit note

665

const retrieved = await stripe.creditNotes.retrieve('cn_123');

666

667

// Update credit note

668

const updated = await stripe.creditNotes.update('cn_123', {

669

memo: 'Refund for damaged item',

670

metadata: { return_id: '12345' }

671

});

672

673

// List credit notes

674

const creditNotes = await stripe.creditNotes.list({

675

customer: 'cus_123',

676

limit: 10

677

});

678

679

// Void credit note

680

const voided = await stripe.creditNotes.voidCreditNote('cn_123');

681

682

// List credit note line items

683

const lineItems = await stripe.creditNotes.listLineItems('cn_123');

684

```

685

686

## Tax Management

687

688

### TaxRates

689

690

Define tax rates for automatic tax calculation:

691

692

```typescript { .api }

693

interface TaxRate {

694

id: string;

695

object: 'tax_rate';

696

percentage: number;

697

display_name: string;

698

description?: string;

699

jurisdiction?: string;

700

inclusive: boolean;

701

active: boolean;

702

}

703

704

// Create tax rate

705

const taxRate = await stripe.taxRates.create({

706

display_name: 'VAT',

707

description: 'UK Value Added Tax',

708

percentage: 20.0,

709

inclusive: false,

710

jurisdiction: 'UK',

711

active: true

712

});

713

714

// Create inclusive tax rate

715

const inclusiveTax = await stripe.taxRates.create({

716

display_name: 'GST',

717

percentage: 10.0,

718

inclusive: true,

719

country: 'AU',

720

state: 'NSW'

721

});

722

723

// Retrieve tax rate

724

const retrieved = await stripe.taxRates.retrieve('txr_123');

725

726

// Update tax rate

727

const updated = await stripe.taxRates.update('txr_123', {

728

display_name: 'Updated VAT Rate',

729

active: false

730

});

731

732

// List tax rates

733

const taxRates = await stripe.taxRates.list({

734

active: true,

735

limit: 10

736

});

737

738

// Apply tax rate to subscription

739

const subscription = await stripe.subscriptions.create({

740

customer: 'cus_123',

741

items: [{

742

price: 'price_123',

743

tax_rates: ['txr_123']

744

}],

745

default_tax_rates: ['txr_123'] // Apply to all items by default

746

});

747

```

748

749

This comprehensive subscription system supports everything from simple recurring billing to complex multi-phase pricing strategies, usage-based billing, and sophisticated tax handling across global markets.