Langsung ke konten utama

Documentation Index

Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt

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

Subscriptions let you sell ongoing access with automated renewals. Use flexible billing cycles, free trials, plan changes, and add‑ons to tailor pricing for each customer.

Upgrade & Downgrade

Control plan changes with proration and quantity updates.

On‑Demand Subscriptions

Authorize a mandate now and charge later with custom amounts.

Customer Portal

Let customers manage plans, billing, and cancellations.

Subscription Webhooks

React to lifecycle events like created, renewed, and canceled.

What Are Subscriptions?

Subscriptions are recurring products customers purchase on a schedule. They’re ideal for:
  • SaaS licenses: Apps, APIs, or platform access
  • Memberships: Communities, programs, or clubs
  • Digital content: Courses, media, or premium content
  • Support plans: SLAs, success packages, or maintenance

Key Benefits

  • Predictable revenue: Recurring billing with automated renewals
  • Flexible cycles: Monthly, annual, custom intervals, and trials
  • Plan agility: Proration for upgrades and downgrades
  • Add‑ons and seats: Attach optional, quantifiable upgrades
  • Seamless checkout: Hosted checkout and customer portal
  • Developer-first: Clear APIs for creation, changes, and usage tracking

Creating Subscriptions

Create subscription products in your Dodo Payments dashboard, then sell them through checkout or your API. Separating products from active subscriptions lets you version pricing, attach add‑ons, and track performance independently.

Subscription product creation

Configure the fields in the dashboard to define how your subscription sells, renews, and bills. The sections below map directly to what you see in the creation form.

Product details

  • Product Name (required): The display name shown in checkout, customer portal, and invoices.
  • Product Description (required): A clear value statement that appears in checkout and invoices.
  • Product Image (required): PNG/JPG/WebP up to 3 MB. Used on checkout and invoices.
  • Brand: Associate the product with a specific brand for theming and emails.
  • Tax Category (required): Choose the category (for example, SaaS) to determine tax rules.
Pick the most accurate tax category to ensure correct tax collection per region.

Pricing

  • Pricing Type: Choose Subscription (this guide). Alternatives are Single Payment and Usage Based Billing.
  • Price (required): Base recurring price with currency.
  • Discount Applicable (%): Optional percentage discount applied to the base price; reflected in checkout and invoices.
  • Repeat payment every (required): Interval for renewals, e.g., every 1 Month. Select the cadence (months or years) and quantity.
  • Subscription Period (required): Total term for which the subscription remains active (e.g., 10 Years). After this period ends, renewals stop unless extended.
  • Trial Period Days (required): Set trial length in days. Use 0 to disable trials. The first charge occurs automatically when the trial ends.
  • Select add‑on: Attach up to 10 add‑ons that customers can purchase alongside the base plan.
Changing pricing on an active product affects new purchases. Existing subscriptions follow your plan‑change and proration settings.
Add‑ons are ideal for quantifiable extras such as seats or storage. You can control allowed quantities and proration behavior when customers change them.

Advanced settings

  • Tax Inclusive Pricing: Display prices inclusive of applicable taxes. Final tax calculation still varies by customer location.
  • Generate license keys: Issue a unique key to each customer after purchase. See the License Keys guide.
  • Digital Product Delivery: Deliver files or content automatically after purchase. Learn more in Digital Product Delivery.
  • Metadata: Attach custom key–value pairs for internal tagging or client integrations. See Metadata.
Use metadata to store identifiers from your system (e.g., accountId) so you can reconcile events and invoices later.

Subscription Trials

Trials let customers access subscriptions without immediate payment. The first charge occurs automatically when the trial ends.

Configuring Trials

Set Trial Period Days in the product pricing section (use 0 to disable). You can override this when creating subscriptions:
// Via subscription creation
const subscription = await client.subscriptions.create({
  customer_id: 'cus_123',
  product_id: 'prod_monthly',
  trial_period_days: 14  // Overrides product's trial period
});

// Via checkout session
const session = await client.checkoutSessions.create({
  product_cart: [{ product_id: 'prod_monthly', quantity: 1 }],
  subscription_data: { trial_period_days: 14 }
});
The trial_period_days value must be between 0 and 10,000 days.

Detecting Trial Status

Currently, there is no direct field to detect trial status. The following is a workaround that requires querying payments, which is inefficient. We are working on a more efficient solution.
To determine if a subscription is in trial, retrieve the list of payments for the subscription. If there is exactly one payment with amount 0, the subscription is in trial period:
const subscription = await client.subscriptions.retrieve('sub_123');
const payments = await client.payments.list({
  subscription_id: subscription.subscription_id
});

// Check if subscription is in trial
const isInTrial = payments.items.length === 1 && 
                  payments.items[0].total_amount === 0;

Updating Trial Period

Extend the trial by updating next_billing_date:
await client.subscriptions.update('sub_123', {
  next_billing_date: '2025-02-15T00:00:00Z'  // New trial end date
});
You cannot set next_billing_date to a past time. The date must be in the future.

Subscription Plan Changes

Plan changes let you upgrade or downgrade subscriptions, adjust quantities, or migrate to different products. Depending on the proration mode you select, a change may trigger an immediate charge, create credit, or apply no billing adjustment.
You can change subscription plans and update the next billing date directly from the Dodo Payments dashboard. This provides a quick way to adjust subscriptions for customer support requests, promotional upgrades, or plan migrations without making API calls.
Enable self-service plan changes: Want customers to upgrade or downgrade their own subscriptions via the Customer Portal? Add your subscription products to a Product Collection and enable “Allow Subscription Updates” in your Subscription Settings.

Product Collections

Group related products into collections to enable seamless upgrade/downgrade paths in the Customer Portal.

Proration Modes

Choose how customers are billed when changing plans:
Quick comparison of the four proration modes:
prorated_immediatelydifference_immediatelyfull_immediatelydo_not_bill
UpgradeProrated charge for remaining daysFull price difference chargedFull new plan price chargedNo charge — switch immediately
DowngradeProrated credit for remaining daysFull price difference as creditNo credit, full chargeNo credit — switch immediately
Billing cycleStays the sameStays the sameResets to todayStays the same
Best forFair time-based billingSimple tier changesBilling cycle resetsFree migrations or courtesy switches

prorated_immediately

Charges prorated amount based on remaining time in the current billing cycle. Best for fair billing that accounts for unused time.
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
});

difference_immediately

Charges the price difference immediately (upgrade) or adds credit for future renewals (downgrade). Best for simple upgrade/downgrade scenarios.
// Upgrade: charges $50 (difference between $30 and $80)
// Downgrade: credits remaining value, auto-applied to renewals
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
});
Credits from downgrades using difference_immediately are subscription-scoped and auto-applied to future renewals. They’re distinct from Credit-Based Billing entitlements.
When a customer downgrades with difference_immediately, the unused value becomes a subscription-scoped credit that automatically offsets future renewals:

full_immediately

Charges full new plan amount immediately, ignoring remaining time. Best for resetting billing cycles.
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_monthly',
  quantity: 1,
  proration_billing_mode: 'full_immediately'
});

do_not_bill

Switches to the new plan without any billing adjustment. No proration charges, no credits — the customer simply moves to the new plan. Best for courtesy migrations, free plan switches, or scenarios where you want to absorb the cost difference.
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new_plan',
  quantity: 1,
  proration_billing_mode: 'do_not_bill'
});
Scenario: Customer on Basic (30/month)upgradestoPro(30/month) upgrades to Pro (80/month) on day 16 of a 30-day cycle using prorated_immediately.
Unused credit from Basic = $30 × (15 remaining / 30 total) = $15.00
Prorated cost of Pro     = $80 × (15 remaining / 30 total) = $40.00
────────────────────────────────────────────────────────────────────
Immediate charge         = $40.00 − $15.00 = $25.00
Next renewal on the original billing date: $80.00/month.
For more detailed calculation examples and edge cases, see our full Upgrade & Downgrade Guide.
Scenario: Customer on Pro (80/month)downgradestoStarter(80/month) downgrades to Starter (20/month) using difference_immediately.
Credit = Old plan − New plan = $80 − $20 = $60.00
The $60 credit auto-applies to future renewals:
  • Renewal 1: 2020 − 20 (credit) = **0.00(0.00** (40 credit remaining)
  • Renewal 2: 2020 − 20 (credit) = **0.00(0.00** (20 credit remaining)
  • Renewal 3: 2020 − 20 (credit) = $0.00 (credit exhausted)
  • Renewal 4: $20.00 (full price)
Learn more about how credits are managed in the Upgrade & Downgrade Guide.

Changing Plans with Add-ons

Modify add-ons when changing plans. Add-ons are included in proration calculations:
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [{ addon_id: 'addon_extra_seats', quantity: 2 }]  // Add add-ons
  // addons: []  // Empty array removes all existing add-ons
});
Plan changes trigger immediate charges. Failed charges may move the subscription to on_hold status. Track changes via subscription.plan_changed webhook events.

Previewing Plan Changes

Before committing to a plan change, preview the exact charge and resulting subscription:
const preview = await client.subscriptions.previewChangePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
});

// Show customer the charge before confirming
console.log('You will be charged:', preview.immediate_charge.summary);

Preview Change Plan API

Preview plan changes before committing to them.

Subscription States

Subscriptions can be in different states throughout their lifecycle:
  • active: Subscription is active and will renew automatically
  • on_hold: Subscription is paused due to failed payment. Payment method update required to reactivate
  • cancelled: Subscription is cancelled and will not renew
  • expired: Subscription has reached its end date
  • pending: Subscription is being created or processed

On Hold State

A subscription enters on_hold state when:
  • A renewal payment fails (insufficient funds, expired card, etc.)
  • A plan change charge fails
  • Payment method authorization fails
When a subscription is in on_hold state, it will not renew automatically. You must update the payment method to reactivate the subscription.

Reactivating from On Hold

To reactivate a subscription from on_hold state, update the payment method. This automatically:
  1. Creates a charge for remaining dues
  2. Generates an invoice
  3. Processes the payment using the new payment method
  4. Reactivates the subscription to active state upon successful payment
// Reactivate subscription from on_hold
const response = await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'new',
  return_url: 'https://example.com/return'
});

// For on_hold subscriptions, a charge is automatically created
if (response.payment_id) {
  console.log('Charge created:', response.payment_id);
  // Redirect customer to response.payment_link to complete payment
  // Monitor webhooks for payment.succeeded and subscription.active
}
After successfully updating the payment method for an on_hold subscription, you’ll receive payment.succeeded followed by subscription.active webhook events.

API Management

Use POST /subscriptions to create subscriptions programmatically from products, with optional trials and add‑ons.

API Reference

View the create subscription API.
Use PATCH /subscriptions/{id} to update quantities, cancel at next billing date, or modify metadata.

API Reference

Learn how to update subscription details.
Change the active product and quantities with proration controls.

API Reference

Review plan change options.
For on‑demand subscriptions, charge specific amounts on demand.

API Reference

Charge an on‑demand subscription.
Use GET /subscriptions to list all subscriptions and GET /subscriptions/{id} to retrieve one.

API Reference

Browse listing and retrieval APIs.
Fetch recorded usage for metered or hybrid pricing models.

API Reference

See usage history API.
Update the payment method for a subscription. For active subscriptions, this updates the payment method for future renewals. For subscriptions in on_hold state, this reactivates the subscription by creating a charge for remaining dues.

API Reference

Learn how to update payment methods and reactivate subscriptions.

Common Use Cases

  • SaaS and APIs: Tiered access with add‑ons for seats or usage
  • Content and media: Monthly access with introductory trials
  • B2B support plans: Annual contracts with premium support add‑ons
  • Tools and plugins: License keys and versioned releases

Integration Examples

Checkout Sessions (subscriptions)

When creating checkout sessions, include your subscription product and optional add‑ons:
const session = await client.checkoutSessions.create({
  product_cart: [
    {
      product_id: 'prod_subscription',
      quantity: 1
    }
  ]
});

Plan changes with proration

Upgrade or downgrade a subscription and control proration behavior:
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
});

Cancel at next billing date

Schedule a cancellation that takes effect at the end of the current billing period:
await client.subscriptions.update('sub_123', {
  cancel_at_next_billing_date: true
});

On‑demand subscriptions

Create an on‑demand subscription and charge later as needed:
const onDemand = await client.subscriptions.create({
  customer_id: 'cus_123',
  product_id: 'prod_on_demand',
  on_demand: true
});

await client.subscriptions.createCharge(onDemand.id, {
  amount: 4900,
  currency: 'USD',
  description: 'Extra usage for September'
});

Update payment method for active subscription

Update the payment method for an active subscription:
// Update with new payment method
const response = await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'new',
  return_url: 'https://example.com/return'
});

// Or use existing payment method
await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'existing',
  payment_method_id: 'pm_abc123'
});

Reactivate subscription from on_hold

Reactivate a subscription that went on hold due to failed payment:
// Update payment method - automatically creates charge for remaining dues
const response = await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'new',
  return_url: 'https://example.com/return'
});

if (response.payment_id) {
  // Charge created for remaining dues
  // Redirect customer to response.payment_link
  // Monitor webhooks: payment.succeeded → subscription.active
}

Subscriptions with RBI-Compliant Mandates

UPI and Indian card subscriptions operate under RBI (Reserve Bank of India) regulations with specific mandate requirements:

Mandate Limits

The mandate type and amount depend on your subscription’s recurring charge:
  • Biaya di bawah batas mandat (default ₹15.000): Kami membuat mandat on-demand untuk jumlah batas. Jumlah langganan dibebankan secara berkala sesuai dengan frekuensi langganan Anda, hingga batas mandat.
  • Biaya pada atau di atas batas mandat: Kami membuat mandat langganan (atau mandat on-demand) untuk jumlah langganan yang tepat.
Batas mandat dapat dikonfigurasi per pedagang atau per permintaan melalui mandate_min_amount_inr_paise (INR paise). Jumlah yang terdaftar dengan bank adalah max(mandate_floor, billing_amount) — sehingga batas tersebut secara efektif menjadi batas otorisasi yang terlihat oleh pelanggan kapan pun biaya lebih rendah. Untuk informasi lebih lanjut tentang mandat yang sesuai dengan RBI dan batas mandat yang dapat dikonfigurasi untuk metode pembayaran India, lihat halaman Metode Pembayaran India.

Pertimbangan Upgrade dan Downgrade

Penting: Saat melakukan upgrade atau downgrade langganan, pertimbangkan batas mandat dengan hati-hati:
  • Jika upgrade/downgrade mengakibatkan jumlah biaya melebihi Rs 15.000 dan melampaui batas pembayaran on-demand yang ada, biaya transaksi mungkin gagal.
  • Dalam kasus seperti itu, pelanggan mungkin perlu memperbarui metode pembayaran mereka atau mengubah langganan lagi untuk membuat mandat baru dengan batas yang benar.

Otorisasi untuk Biaya Bernilai Tinggi

Untuk biaya langganan sebesar Rs 15.000 atau lebih:
  • Pelanggan akan diminta oleh bank mereka untuk mengotorisasi transaksi.
  • Jika pelanggan gagal mengotorisasi transaksi, transaksi akan gagal dan langganan akan ditangguhkan.

Keterlambatan Pemrosesan 48 Jam

Linimasa Pemrosesan: Biaya berulang pada kartu India dan langganan UPI mengikuti pola pemrosesan unik:
  • Biaya dimulai pada tanggal yang dijadwalkan sesuai dengan frekuensi langganan Anda.
  • Pengurangan aktual dari akun pelanggan terjadi hanya setelah 48 jam dari inisiasi pembayaran.
  • Jendela 48 jam ini mungkin diperpanjang hingga 2-3 jam tambahan tergantung pada respons API bank.

Jendela Pembatalan Mandat

Selama jendela pemrosesan 48 jam:
  • Pelanggan dapat membatalkan mandat melalui aplikasi perbankan mereka.
  • Jika pelanggan membatalkan mandat selama periode ini, langganan akan tetap aktif (ini adalah kasus khusus yang spesifik untuk kartu India dan langganan UPI AutoPay).
  • Namun, pengurangan aktual mungkin gagal, dan dalam kasus itu, kami akan menempatkan langganan ditangguhkan.
Penanganan Kasus Khusus: Jika Anda memberikan manfaat, kredit, atau penggunaan langganan kepada pelanggan segera setelah inisiasi biaya, Anda perlu menangani jendela 48 jam ini dengan tepat dalam aplikasi Anda. Pertimbangkan:
  • Menunda aktivasi manfaat hingga konfirmasi pembayaran
  • Menerapkan periode tenggang atau akses sementara
  • Memantau status langganan untuk pembatalan mandat
  • Menangani status penangguhan langganan dalam logika aplikasi Anda
Pantau webhook langganan untuk melacak perubahan status pembayaran dan menangani kasus khusus di mana mandat dibatalkan selama jendela 48 jam.

Praktik Terbaik

  • Mulai dengan tingkatan yang jelas: 2–3 rencana dengan perbedaan yang jelas
  • Komunikasikan harga: Tampilkan total, pro-rata, dan pembaruan berikutnya
  • Gunakan percobaan dengan bijak: Konversi dengan onboarding, bukan hanya waktu
  • Manfaatkan tambahan: Jaga rencana dasar tetap sederhana dan upsell ekstra
  • Uji perubahan: Validasi perubahan rencana dan pro-rata dalam mode pengujian
Langganan adalah fondasi fleksibel untuk pendapatan berulang. Mulai simpel, uji secara menyeluruh, dan iterasi berdasarkan adopsi, churn, dan metrik ekspansi.
Last modified on May 14, 2026