Stripe API wrapper for Node.js providing comprehensive payment processing, subscription management, and financial services integration.
—
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.
The primary resource for managing recurring billing relationships:
interface Subscription {
id: string;
object: 'subscription';
customer: string;
status: 'incomplete' | 'incomplete_expired' | 'trialing' | 'active' | 'past_due' | 'canceled' | 'unpaid';
items: {
object: 'list';
data: SubscriptionItem[];
};
current_period_start: number;
current_period_end: number;
trial_start?: number;
trial_end?: number;
cancel_at_period_end: boolean;
default_payment_method?: string;
}
// Create subscription
const subscription = await stripe.subscriptions.create({
customer: 'cus_123',
items: [
{
price: 'price_monthly_premium',
quantity: 1
}
],
payment_behavior: 'default_incomplete',
payment_settings: {
save_default_payment_method: 'on_subscription'
},
expand: ['latest_invoice.payment_intent']
});
// Create subscription with trial
const trialSubscription = await stripe.subscriptions.create({
customer: 'cus_123',
items: [{ price: 'price_123' }],
trial_period_days: 14,
trial_settings: {
end_behavior: {
missing_payment_method: 'cancel'
}
}
});
// Create subscription with custom billing cycle
const customBilling = await stripe.subscriptions.create({
customer: 'cus_123',
items: [{ price: 'price_123' }],
billing_cycle_anchor: Math.floor(Date.now() / 1000) + 86400, // Start tomorrow
proration_behavior: 'create_prorations'
});
// Retrieve subscription
const retrieved = await stripe.subscriptions.retrieve('sub_123', {
expand: ['customer', 'default_payment_method', 'items.data.price']
});
// Update subscription
const updated = await stripe.subscriptions.update('sub_123', {
items: [
{
id: 'si_existing_item',
price: 'price_new_plan',
quantity: 2
}
],
proration_behavior: 'always_invoice',
payment_behavior: 'pending_if_incomplete'
});
// List subscriptions
const subscriptions = await stripe.subscriptions.list({
customer: 'cus_123',
status: 'active',
limit: 10
});
// Cancel subscription at period end
const canceled = await stripe.subscriptions.update('sub_123', {
cancel_at_period_end: true,
cancellation_details: {
comment: 'Customer requested cancellation'
}
});
// Cancel subscription immediately
const immediatelyCanceled = await stripe.subscriptions.cancel('sub_123', {
prorate: true,
invoice_now: true
});
// Resume canceled subscription
const resumed = await stripe.subscriptions.resume('sub_123', {
billing_cycle_anchor: 'now',
proration_behavior: 'create_prorations'
});
// Search subscriptions
const searchResults = await stripe.subscriptions.search({
query: 'status:"active" AND metadata["plan_type"]:"premium"'
});Individual line items within a subscription:
interface SubscriptionItem {
id: string;
object: 'subscription_item';
subscription: string;
price: Price;
quantity?: number;
tax_rates?: TaxRate[];
created: number;
}
// Create subscription item (add to existing subscription)
const subscriptionItem = await stripe.subscriptionItems.create({
subscription: 'sub_123',
price: 'price_addon_feature',
quantity: 1,
proration_behavior: 'always_invoice',
payment_behavior: 'pending_if_incomplete'
});
// Create usage-based subscription item
const usageItem = await stripe.subscriptionItems.create({
subscription: 'sub_123',
price: 'price_usage_based',
billing_thresholds: {
usage_gte: 1000 // Bill when usage >= 1000 units
}
});
// Retrieve subscription item
const retrieved = await stripe.subscriptionItems.retrieve('si_123', {
expand: ['price.product']
});
// Update subscription item
const updated = await stripe.subscriptionItems.update('si_123', {
quantity: 3,
price: 'price_upgraded_plan',
proration_behavior: 'create_prorations'
});
// List subscription items
const items = await stripe.subscriptionItems.list({
subscription: 'sub_123'
});
// Delete subscription item
const deleted = await stripe.subscriptionItems.del('si_123', {
proration_behavior: 'always_invoice',
clear_usage: true
});Track usage for metered billing:
// Create usage record
const usageRecord = await stripe.subscriptionItems.createUsageRecord(
'si_usage_based',
{
quantity: 100,
timestamp: Math.floor(Date.now() / 1000),
action: 'increment' // or 'set'
}
);
// Create usage record with idempotency
const idempotentUsage = await stripe.subscriptionItems.createUsageRecord(
'si_usage_based',
{
quantity: 50,
timestamp: Math.floor(Date.now() / 1000),
action: 'increment'
},
{
idempotencyKey: 'usage_' + Date.now()
}
);
// List usage record summaries
const usageSummaries = await stripe.subscriptionItems.listUsageRecordSummaries(
'si_usage_based',
{
limit: 10,
ending_before: Math.floor(Date.now() / 1000)
}
);Manage complex subscription lifecycle changes:
interface SubscriptionSchedule {
id: string;
object: 'subscription_schedule';
customer: string;
status: 'not_started' | 'active' | 'completed' | 'released' | 'canceled';
subscription?: string;
phases: SubscriptionSchedulePhase[];
}
// Create subscription schedule
const schedule = await stripe.subscriptionSchedules.create({
customer: 'cus_123',
start_date: Math.floor(Date.now() / 1000) + 86400, // Start tomorrow
end_behavior: 'cancel',
phases: [
{
// Trial phase
items: [{ price: 'price_123', quantity: 1 }],
trial: true,
end_date: Math.floor(Date.now() / 1000) + 86400 * 14 // 14 days
},
{
// Regular billing phase
items: [{ price: 'price_123', quantity: 1 }],
iterations: 12 // 12 billing cycles
},
{
// Discounted renewal phase
items: [{ price: 'price_discounted', quantity: 1 }]
// No end_date = continues indefinitely
}
]
});
// Create schedule with price changes
const pricingSchedule = await stripe.subscriptionSchedules.create({
customer: 'cus_123',
phases: [
{
items: [{ price: 'price_starter', quantity: 1 }],
end_date: Math.floor(Date.now() / 1000) + 86400 * 90 // 3 months
},
{
items: [{ price: 'price_professional', quantity: 1 }],
proration_behavior: 'create_prorations'
}
]
});
// Retrieve subscription schedule
const retrieved = await stripe.subscriptionSchedules.retrieve('sub_sched_123', {
expand: ['subscription', 'phases.items.price']
});
// Update subscription schedule
const updated = await stripe.subscriptionSchedules.update('sub_sched_123', {
phases: [
{
items: [{ price: 'price_updated', quantity: 2 }],
start_date: Math.floor(Date.now() / 1000),
end_date: Math.floor(Date.now() / 1000) + 86400 * 30
}
]
});
// List subscription schedules
const schedules = await stripe.subscriptionSchedules.list({
customer: 'cus_123',
limit: 10
});
// Cancel subscription schedule
const canceled = await stripe.subscriptionSchedules.cancel('sub_sched_123');
// Release subscription schedule (convert to regular subscription)
const released = await stripe.subscriptionSchedule.release('sub_sched_123', {
preserve_cancel_date: true
});Legacy pricing model (use Prices for new integrations):
interface Plan {
id: string;
object: 'plan';
amount?: number;
currency: string;
interval: 'day' | 'week' | 'month' | 'year';
interval_count: number;
nickname?: string;
product: string;
}
// Create plan (legacy - use Prices instead)
const plan = await stripe.plans.create({
id: 'gold-monthly',
amount: 2000,
currency: 'usd',
interval: 'month',
product: 'prod_gold_plan'
});
// Retrieve plan
const retrieved = await stripe.plans.retrieve('gold-monthly');
// Update plan
const updated = await stripe.plans.update('gold-monthly', {
nickname: 'Gold Monthly Plan',
metadata: { tier: 'premium' }
});
// List plans
const plans = await stripe.plans.list({
limit: 10,
active: true
});
// Delete plan
const deleted = await stripe.plans.del('gold-monthly');Billing documents for subscriptions and one-off charges:
interface Invoice {
id: string;
object: 'invoice';
customer: string;
subscription?: string;
status: 'draft' | 'open' | 'paid' | 'uncollectible' | 'void';
amount_due: number;
amount_paid: number;
currency: string;
due_date?: number;
}
// Create invoice
const invoice = await stripe.invoices.create({
customer: 'cus_123',
collection_method: 'send_invoice',
days_until_due: 30,
description: 'Custom invoice for services'
});
// Create subscription invoice preview
const preview = await stripe.invoices.retrieveUpcoming({
customer: 'cus_123',
subscription: 'sub_123',
subscription_items: [
{
id: 'si_123',
quantity: 2
}
]
});
// Retrieve invoice
const retrieved = await stripe.invoices.retrieve('in_123', {
expand: ['payment_intent', 'customer']
});
// Update invoice
const updated = await stripe.invoices.update('in_123', {
description: 'Updated invoice description',
footer: 'Thank you for your business!',
metadata: { order_id: '12345' }
});
// List invoices
const invoices = await stripe.invoices.list({
customer: 'cus_123',
status: 'open',
limit: 10
});
// Finalize invoice
const finalized = await stripe.invoices.finalizeInvoice('in_123', {
auto_advance: true
});
// Pay invoice
const paid = await stripe.invoices.pay('in_123', {
payment_method: 'pm_card_visa',
paid_out_of_band: false
});
// Send invoice
const sent = await stripe.invoices.sendInvoice('in_123', {
delivery_method: 'email'
});
// Mark uncollectible
const uncollectible = await stripe.invoices.markUncollectible('in_123');
// Void invoice
const voided = await stripe.invoices.voidInvoice('in_123');
// Delete draft invoice
const deleted = await stripe.invoices.del('in_123');
// Search invoices
const searchResults = await stripe.invoices.search({
query: 'total>1000 AND status:"paid"'
});
// Get upcoming invoice line items
const upcomingLines = await stripe.invoices.upcomingLines({
customer: 'cus_123',
subscription: 'sub_123'
});Individual line items on invoices:
interface InvoiceItem {
id: string;
object: 'invoiceitem';
customer: string;
amount: number;
currency: string;
description?: string;
invoice?: string;
subscription?: string;
}
// Create invoice item
const invoiceItem = await stripe.invoiceItems.create({
customer: 'cus_123',
amount: 2500,
currency: 'usd',
description: 'One-time setup fee'
});
// Create invoice item for specific invoice
const specificItem = await stripe.invoiceItems.create({
customer: 'cus_123',
amount: 1000,
currency: 'usd',
description: 'Custom charge',
invoice: 'in_123'
});
// Create invoice item with price
const priceBasedItem = await stripe.invoiceItems.create({
customer: 'cus_123',
price: 'price_setup_fee',
quantity: 1
});
// Retrieve invoice item
const retrieved = await stripe.invoiceItems.retrieve('ii_123');
// Update invoice item
const updated = await stripe.invoiceItems.update('ii_123', {
description: 'Updated setup fee',
amount: 3000,
metadata: { type: 'setup' }
});
// List invoice items
const invoiceItems = await stripe.invoiceItems.list({
customer: 'cus_123',
limit: 10
});
// Delete invoice item
const deleted = await stripe.invoiceItems.del('ii_123');Reusable discount definitions:
interface Coupon {
id: string;
object: 'coupon';
name?: string;
percent_off?: number;
amount_off?: number;
currency?: string;
duration: 'forever' | 'once' | 'repeating';
duration_in_months?: number;
max_redemptions?: number;
times_redeemed: number;
valid: boolean;
}
// Create percentage coupon
const percentCoupon = await stripe.coupons.create({
id: 'SUMMER20',
percent_off: 20,
duration: 'repeating',
duration_in_months: 3,
max_redemptions: 100,
name: 'Summer Sale 20% Off'
});
// Create amount-based coupon
const amountCoupon = await stripe.coupons.create({
amount_off: 500,
currency: 'usd',
duration: 'once',
name: '$5 Off First Order'
});
// Create coupon with restrictions
const restrictedCoupon = await stripe.coupons.create({
percent_off: 15,
duration: 'forever',
applies_to: {
products: ['prod_premium_plan']
},
currency_options: {
eur: { amount_off: 450 },
gbp: { amount_off: 400 }
}
});
// Retrieve coupon
const retrieved = await stripe.coupons.retrieve('SUMMER20');
// Update coupon
const updated = await stripe.coupons.update('SUMMER20', {
name: 'Extended Summer Sale',
metadata: { campaign: 'summer_2024' }
});
// List coupons
const coupons = await stripe.coupons.list({
limit: 10
});
// Delete coupon
const deleted = await stripe.coupons.del('SUMMER20');Customer-facing codes that apply coupons:
interface PromotionCode {
id: string;
object: 'promotion_code';
code: string;
coupon: Coupon;
active: boolean;
customer?: string;
expires_at?: number;
max_redemptions?: number;
times_redeemed: number;
}
// Create promotion code
const promotionCode = await stripe.promotionCodes.create({
coupon: 'SUMMER20',
code: 'SAVE20NOW',
max_redemptions: 50,
expires_at: Math.floor(Date.now() / 1000) + 86400 * 30 // 30 days
});
// Create customer-specific promotion code
const customerCode = await stripe.promotionCodes.create({
coupon: 'VIP10',
customer: 'cus_123',
code: 'VIPCUSTOMER'
});
// Auto-generate promotion code
const autoCode = await stripe.promotionCodes.create({
coupon: 'SUMMER20',
restrictions: {
minimum_amount: 1000,
minimum_amount_currency: 'usd'
}
});
// Retrieve promotion code
const retrieved = await stripe.promotionCodes.retrieve('promo_123');
// Update promotion code
const updated = await stripe.promotionCodes.update('promo_123', {
active: false,
metadata: { reason: 'expired_campaign' }
});
// List promotion codes
const promotionCodes = await stripe.promotionCodes.list({
coupon: 'SUMMER20',
active: true,
limit: 10
});Issue credits for invoices:
interface CreditNote {
id: string;
object: 'credit_note';
invoice: string;
customer: string;
amount: number;
currency: string;
status: 'issued' | 'void';
type: 'pre_payment' | 'post_payment';
}
// Create credit note
const creditNote = await stripe.creditNotes.create({
invoice: 'in_123',
lines: [
{
type: 'invoice_line_item',
invoice_line_item: 'il_123',
quantity: 1
}
],
reason: 'product_unsatisfactory'
});
// Create partial credit note
const partialCredit = await stripe.creditNotes.create({
invoice: 'in_123',
amount: 500,
reason: 'order_change'
});
// Preview credit note
const preview = await stripe.creditNotes.preview({
invoice: 'in_123',
amount: 1000
});
// Retrieve credit note
const retrieved = await stripe.creditNotes.retrieve('cn_123');
// Update credit note
const updated = await stripe.creditNotes.update('cn_123', {
memo: 'Refund for damaged item',
metadata: { return_id: '12345' }
});
// List credit notes
const creditNotes = await stripe.creditNotes.list({
customer: 'cus_123',
limit: 10
});
// Void credit note
const voided = await stripe.creditNotes.voidCreditNote('cn_123');
// List credit note line items
const lineItems = await stripe.creditNotes.listLineItems('cn_123');Define tax rates for automatic tax calculation:
interface TaxRate {
id: string;
object: 'tax_rate';
percentage: number;
display_name: string;
description?: string;
jurisdiction?: string;
inclusive: boolean;
active: boolean;
}
// Create tax rate
const taxRate = await stripe.taxRates.create({
display_name: 'VAT',
description: 'UK Value Added Tax',
percentage: 20.0,
inclusive: false,
jurisdiction: 'UK',
active: true
});
// Create inclusive tax rate
const inclusiveTax = await stripe.taxRates.create({
display_name: 'GST',
percentage: 10.0,
inclusive: true,
country: 'AU',
state: 'NSW'
});
// Retrieve tax rate
const retrieved = await stripe.taxRates.retrieve('txr_123');
// Update tax rate
const updated = await stripe.taxRates.update('txr_123', {
display_name: 'Updated VAT Rate',
active: false
});
// List tax rates
const taxRates = await stripe.taxRates.list({
active: true,
limit: 10
});
// Apply tax rate to subscription
const subscription = await stripe.subscriptions.create({
customer: 'cus_123',
items: [{
price: 'price_123',
tax_rates: ['txr_123']
}],
default_tax_rates: ['txr_123'] // Apply to all items by default
});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.
Install with Tessl CLI
npx tessl i tessl/npm-stripe