Langsung ke konten utama
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
UpgradeBiaya prorata untuk hari yang tersisaSelisih harga penuh dikenakanHarga paket baru penuh dikenakanTidak ada biaya — langsung beralih
DowngradeKredit prorata untuk hari yang tersisaSelisih harga penuh sebagai kreditTidak ada kredit, biaya penuhTidak ada kredit — langsung beralih
Siklus penagihanDireset ke hari iniDireset ke hari iniDireset ke hari iniTetap sama
Terbaik untukPenagihan berbasis waktu yang adilPerubahan tier sederhanaReset siklus penagihanMigrasi gratis atau penggantian sebagai keramahan

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
Pembaharuan berikutnya pada 15 Februari (16 Januari + 30 hari): $80.00/bulan.
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

Sebuah langganan bergerak melalui serangkaian status yang telah ditentukan selama masa hidupnya. Tabel ini adalah referensi untuk setiap status, penyebabnya, dan cara (atau apakah) Anda dapat memulihkannya.
StatusArtinyaDapat Pulih?Jalur Pemulihan / langkah selanjutnya
pendingLangganan sedang dibuat atau diprosesTunggu subscription.active (atau subscription.failed)
activeLangganan aktif dan akan diperbarui secara otomatisTidak ada tindakan yang diperlukan
on_holdPembayaran pembaruan (atau biaya perubahan paket) gagal; langganan dijedaYaPerbarui metode pembayaran untuk mengaktifkan kembali — secara otomatis melalui Payment Retries dan Dunning, atau secara manual melalui Update Payment Method API
cancelledLangganan dibatalkan dan tidak akan diperbaruiHanya pembelian ulangPelanggan harus memulai langganan baru; Dunning dapat memantik pembelian ulang
failedPembuatan langganan gagal (mandat awal atau pembayaran tidak berhasil)Tidak — terminalPelanggan harus membuat langganan baru dengan metode pembayaran yang berfungsi
expiredLangganan mencapai akhir masa berlakunyaPelanggan harus memulai langganan baru jika diinginkan
on_hold dan failed sering kali membingungkan. on_hold adalah keadaan dapat dipulihkan untuk langganan yang sudah aktif yang pembaruannya gagal. failed adalah keadaan terminal yang hanya terjadi ketika pembuatan langganan awal gagal — tidak dapat diaktifkan kembali.

Mesin Status

Status Ditahan

Sebuah langganan masuk ke dalam status on_hold ketika:
  • Pembayaran pembaruan gagal (dana tidak mencukupi, kartu kedaluwarsa, dll.)
  • Biaya perubahan paket gagal
  • Otorisasi metode pembayaran gagal
Ketika langganan berada dalam status on_hold, itu tidak akan diperbarui secara otomatis. Anda harus memperbarui metode pembayaran untuk mengaktifkan kembali langganan.

Mengaktifkan Kembali dari Ditahan

Untuk mengaktifkan kembali langganan dari status on_hold, perbarui metode pembayaran. Ini secara otomatis:
  1. Membuat biaya untuk hutang yang tersisa
  2. Menghasilkan faktur
  3. Memproses pembayaran menggunakan metode pembayaran baru
  4. Mengaktifkan kembali langganan ke status active setelah pembayaran berhasil
// 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
}
Setelah berhasil memperbarui metode pembayaran untuk langganan on_hold, Anda akan menerima acara webhook payment.succeeded diikuti oleh subscription.active.

Acara Webhook oleh Transisi

Setiap transisi memancarkan webhook sehingga Anda dapat menggerakkan logika hak tanpa pemindaian:
TransisiAcara
Langganan diaktifkansubscription.active
Pembaruan berhasilsubscription.renewed
Pembaruan gagal → jedasubscription.on_hold
Pembuatan gagalsubscription.failed
Paket diperbarui/dikurangisubscription.plan_changed
Dibatalkansubscription.cancelled
Masa berakhirsubscription.expired
Perubahan pada setiap bidangsubscription.updated

Subscription Webhook Payloads

Lihat skema payload lengkap untuk acara siklus hidup langganan.

Manajemen API

Gunakan POST /subscriptions untuk membuat langganan secara programatis dari produk, dengan uji coba dan add-on opsional.

API Reference

Lihat API pembuatan langganan.
Gunakan PATCH /subscriptions/{id} untuk memperbarui kuantitas, membatalkan pada tanggal penagihan berikutnya, atau memodifikasi metadata.

API Reference

Pelajari cara memperbarui detail langganan.
Ubah produk aktif dan kuantitas dengan kontrol proration.

API Reference

Tinjau opsi perubahan paket.
Untuk langganan berdasarkan permintaan, kenakan jumlah tertentu sesuai permintaan.

API Reference

Tagih langganan sesuai permintaan.
Gunakan GET /subscriptions untuk menyusun daftar semua langganan dan GET /subscriptions/{id} untuk mendapatkan satu langganan.

API Reference

Jelajahi API penyusunan daftar dan pengambilan.
Ambil penggunaan yang terukur untuk model harga metered atau hybrid.

API Reference

Lihat API riwayat penggunaan.
Perbarui metode pembayaran untuk langganan. Untuk langganan aktif, ini memperbarui metode pembayaran untuk pembaruan di masa depan. Untuk langganan dalam status on_hold, ini mengaktifkan kembali langganan dengan membuat biaya untuk hutang yang tersisa.Ketika menghasilkan tautan metode pembayaran baru (tipe permintaan New), Anda dapat memasukkan allowed_payment_method_types untuk membatasi metode pembayaran mana yang dilihat pelanggan di halaman itu. Pelanggan tidak akan pernah melihat metode yang tidak ada dalam daftar, meskipun memasukkan metode tidak menjamin metode itu muncul (ketersediaan masih bergantung pada faktor seperti lokasi pelanggan dan pengaturan bisnis Anda).

API Reference

Pelajari cara memperbarui metode pembayaran dan mengaktifkan kembali langganan.

Kasus Penggunaan Umum

  • SaaS dan API: Akses bertingkat dengan add-on untuk kursi atau penggunaan
  • Konten dan media: Akses bulanan dengan uji coba pengantar
  • Paket dukungan B2B: Kontrak tahunan dengan add-on dukungan premium
  • Alat dan plugin: Kunci lisensi dan rilis versi

Contoh Integrasi

Sesi Pembayaran (langganan)

Saat membuat sesi pembayaran, sertakan produk langganan Anda dan add-on opsional:
const session = await client.checkoutSessions.create({
  product_cart: [
    {
      product_id: 'prod_subscription',
      quantity: 1
    }
  ]
});

Perubahan paket dengan proration

Upgrade atau downgrade langganan dan kontrol perilaku proration:
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
});

Batalkan pada tanggal penagihan berikutnya

Jadwal pembatalan yang berlaku pada akhir periode penagihan saat ini:
await client.subscriptions.update('sub_123', {
  cancel_at_next_billing_date: true
});

Langganan berdasarkan permintaan

Buat langganan berdasarkan permintaan dan tagih nanti sesuai kebutuhan:
const onDemand = await client.subscriptions.create({
  customer_id: 'cus_123',
  product_id: 'prod_on_demand',
  on_demand: true
});

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

Perbarui metode pembayaran untuk langganan aktif

Perbarui metode pembayaran untuk langganan aktif:
// 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'
});

Mengaktifkan kembali langganan dari on_hold

Aktifkan kembali langganan yang dijeda karena pembayaran gagal:
// 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
}

Langganan dengan Mandat Sesuai RBI

Langganan UPI dan kartu India beroperasi di bawah regulasi RBI (Bank Sentral India) dengan persyaratan mandat tertentu:

Batas Mandat

Jenis dan jumlah mandat bergantung pada biaya berulang langganan Anda:
  • Biaya di bawah batas bawah mandat (default ₹15,000): Kami membuat mandat berdasarkan permintaan untuk jumlah batas bawah. Jumlah langganan dikenakan secara berkala sesuai dengan frekuensi langganan Anda, hingga batas mandat.
  • Biaya di atau di atas batas bawah mandat: Kami membuat mandat langganan (atau mandat berdasarkan permintaan) untuk jumlah langganan yang tepat.
Batas bawah mandat dapat dikonfigurasi per pedagang atau per permintaan melalui mandate_min_amount_inr_paise (INR paise). Jumlah yang didaftarkan dengan bank adalah max(mandate_floor, billing_amount) — sehingga batas bawah secara efektif menjadi batas otorisasi yang terlihat oleh pelanggan setiap kali penagihan lebih rendah. Untuk informasi terperinci tentang mandat yang sesuai dengan RBI dan batas bawah mandat yang dapat dikonfigurasi untuk metode pembayaran India, lihat halaman India Payment Methods.

Pertimbangan Dalam Upgrade dan Downgrade

Penting: Saat melakukan upgrade atau downgrade langganan, pertimbangkan dengan cermat batas mandat:
  • Jika upgrade/downgrade menghasilkan jumlah biaya yang melebihi Rs 15,000 dan melampaui batas pembayaran berdasarkan permintaan yang ada, biaya transaksi mungkin gagal.
  • Dalam kasus seperti itu, pelanggan mungkin perlu memperbarui metode pembayaran mereka atau mengubah langganan lagi untuk membentuk mandat baru dengan batas yang benar.

Otorisasi untuk Biaya Bernilai Tinggi

Untuk biaya langganan sebesar Rs 15,000 atau lebih:
  • Pelanggan akan diberitahukan oleh bank mereka untuk mengotorisasi transaksi.
  • Jika pelanggan gagal mengotorisasi transaksi, transaksi akan gagal dan langganan akan dijeda.

Keterlambatan Proses 48 Jam

Garis Waktu Pemrosesan: Biaya berulang untuk langganan kartu India dan UPI mengikuti pola pemrosesan unik:
  • Biaya dimulai pada tanggal yang dijadwalkan sesuai dengan frekuensi langganan Anda.
  • Pengurangan sebenarnya dari akun pelanggan terjadi hanya setelah 48 jam dari inisiasi pembayaran.
  • Jendela 48 jam ini dapat 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 untuk langganan kartu dan UPI AutoPay India).
  • Namun, pengurangan sebenarnya mungkin gagal, dan dalam hal itu, kami akan menempatkan langganan dalam penangguhan.
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 masa tenggang atau akses sementara
  • Memonitor 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 paket dengan perbedaan yang jelas
  • Komunikasikan harga: Perlihatkan total, proration, dan pembaruan berikutnya
  • Gunakan uji coba dengan bijak: Konversi dengan onboarding, bukan hanya waktu
  • Manfaatkan add-on: Jaga agar paket dasar tetap sederhana dan tawarkan tambahan
  • Uji perubahan: Validasi perubahan paket dan proration dalam mode uji
Langganan adalah fondasi fleksibel untuk pendapatan berulang. Mulailah dengan sederhana, uji secara menyeluruh, dan iterasi berdasarkan adopsi, churn, dan metrik ekspansi.
Terakhir diubah pada 18 Juni 2026