Subscriptions

Manage recurring billing with trials, discounts, and lifecycle events

Subscriptions automate recurring billing by charging customers at regular intervals. RevKeen handles billing dates, invoicing, payment collection, and dunning automatically.

Subscription Lifecycle

StatusDescriptionBillable
trialingIn trial periodNo
activeActively billingYes
past_duePayment failed, retryingYes (retry)
pausedTemporarily pausedNo
cancelledCancelled, ending at period endUntil period end
expiredEndedNo

Creating Subscriptions

const subscription = await client.subscriptions.create({
  customerId: 'cus_xxxxxxxx',
  productId: 'prod_monthly',
  
  // Optional: Start with a trial
  trialDays: 14,
  
  // Optional: Apply a discount
  discountId: 'disc_xxxxxxxx',
  
  // Optional: Custom billing anchor (day of month)
  billingCycleAnchor: 1, // Bill on the 1st
});

console.log(subscription.data.status); // 'trialing' or 'active'
If the product has a trial period defined, it will be applied automatically unless you explicitly set trialDays: 0.

Changing Plans

// Upgrade or downgrade immediately
const subscription = await client.subscriptions.update('sub_xxxxxxxx', {
  productId: 'prod_enterprise',
  proration: 'create_prorations', // Prorate the difference
});

// Proration options:
// - 'create_prorations': Credit for unused time, charge for new plan
// - 'none': No proration, new price starts next billing cycle
// - 'always_invoice': Create and finalize proration invoice immediately

Cancelling Subscriptions

// Cancel at end of billing period (recommended)
await client.subscriptions.cancel('sub_xxxxxxxx', {
  cancelAtPeriodEnd: true,
});

// Cancel immediately (stop access now)
await client.subscriptions.cancel('sub_xxxxxxxx', {
  cancelAtPeriodEnd: false,
});
Immediate cancellation stops access right away. Use cancelAtPeriodEnd: true to let customers use their remaining time.

Pausing Subscriptions

// Pause immediately
await client.subscriptions.pause('sub_xxxxxxxx', {
  pauseAt: 'now',
  resumeAt: '2025-03-01T00:00:00Z', // Optional: Auto-resume date
});

// Pause at end of current billing period (recommended)
await client.subscriptions.pause('sub_xxxxxxxx', {
  pauseAt: 'period_end',
});

// Resume manually
await client.subscriptions.resume('sub_xxxxxxxx');
Using pauseAt: 'period_end' lets customers use their remaining paid time before pausing.

Billing Anchor Day

Set a specific day of the month for billing. The first invoice will be prorated to align with the anchor.

// Set billing anchor to the 15th of each month
await client.subscriptions.setBillingAnchor('sub_xxxxxxxx', {
  day: 15, // 1-31
});

// For days 29-31, falls back to last day of short months

Proration Preview

Preview proration calculations before changing plans to show customers what they'll be charged.

// Get proration preview (newPlanId must be a UUID)
const preview = await client.subscriptions.prorationPreview('sub_xxxxxxxx', {
  newPlanId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',  // UUID of the new plan/price
});

console.log({
  credit: preview.data.creditAmountMinor / 100,  // Credit for unused time
  debit: preview.data.debitAmountMinor / 100,    // Charge for new plan  
  net: preview.data.netAmountMinor / 100,        // Net charge/credit
  daysRemaining: preview.data.daysRemaining,
});

Smart Payment Retry

RevKeen automatically retries failed payments using smart logic that distinguishes between temporary and permanent failures.

Failure TypeExamplesRetry Behavior
Soft DeclineInsufficient funds, expired cardRetry on days 1, 3, 7
Hard DeclineLost/stolen card, fraudNo retry, request new card

Subscription Webhook Events

EventDescription
subscription.createdNew subscription started
subscription.updatedPlan changed or details updated
subscription.cancelledSubscription cancelled
subscription.pausedSubscription paused
subscription.resumedSubscription resumed
subscription.trial_endingTrial ends in 3 days
subscription.past_duePayment failed
subscription.expiredSubscription ended

Related