Change Plan API
Plan Change Preview
Integration Guide
What is a subscription upgrade or downgrade?
Changing plans lets you move a customer between subscription tiers or quantities. Use it to:- Align pricing with usage or features
- Move from monthly to annual (or vice versa)
- Adjust quantity for seat-based products
When to use plan changes
- Upgrade when a customer needs more features, usage, or seats
- Downgrade when usage decreases
- Migrate users to a new product or price without cancelling their subscription
Plan Change Flow
Prerequisites
Before implementing subscription plan changes, ensure you have:- A Dodo Payments merchant account with active subscription products
- API credentials (API key and webhook secret key) from the dashboard
- An existing active subscription to modify
- Webhook endpoint configured to handle subscription events
Step-by-Step Implementation Guide
Follow this comprehensive guide to implement subscription plan changes in your application:Understand Plan Change Requirements
- Which subscription products can be changed to which others
- What proration mode fits your business model
- How to handle failed plan changes gracefully
- Which webhook events to track for state management
Choose Your Proration Strategy
- prorated_immediately
- difference_immediately
- full_immediately
- do_not_bill
- Calculates exact prorated amount based on remaining cycle time
- Charges a prorated amount based on unused time remaining in the cycle
- Provides transparent billing to customers
Implement the Change Plan API
prorated_immediately, full_immediately, difference_immediately, or do_not_bill.prevent_change: Keep subscription on current plan until payment succeedsapply_change(default): Apply plan change immediately regardless of payment outcome
- Tidak disediakan /
null— diskon yang ada denganpreserve_on_plan_change=truedipertahankan jika berlaku untuk produk baru. [](array kosong) — menghapus semua diskon yang ada dari langganan.["CODE_A", "CODE_B", ...]— menggantikan diskon yang ada dengan set baru ini.
discount_codes untuk integrasi baru. Bidang ini masih berfungsi untuk kompatibilitas ke belakang, tetapi tidak dapat digabungkan dengan discount_codes dalam permintaan yang sama.immediately(default): Terapkan segera perubahan paketnext_billing_date: Jadwalkan perubahan untuk tanggal penagihan berikutnya. Pelanggan mempertahankan paket mereka saat ini hingga periode penagihan berakhir.
next_billing_date untuk penurunan versi sehingga pelanggan tetap mendapatkan manfaat paket mereka saat ini hingga akhir periode penagihan.Handle Webhook Events
subscription.active: Perubahan paket berhasil, langganan diperbaruisubscription.plan_changed: Paket langganan berubah (peningkatan/penurunan versi/pembaruan addon)subscription.on_hold: Biaya perubahan paket gagal, langganan dijedapayment.succeeded: Biaya langsung untuk perubahan paket berhasilpayment.failed: Biaya langsung gagal
Update Your Application State
- Berikan/cabut fitur berdasarkan paket baru
- Perbarui dasbor pelanggan dengan detail paket baru
- Kirim email konfirmasi tentang perubahan paket
- Catat perubahan penagihan untuk tujuan audit
Test and Monitor
- Uji semua mode proratasi dengan berbeda skenario
- Verifikasi penanganan webhook berfungsi dengan benar
- Monitor tingkat keberhasilan perubahan paket
- Siapkan peringatan untuk perubahan paket yang gagal
Pratinjau Perubahan Paket
Sebelum melakukan perubahan paket, gunakan Preview API untuk menunjukkan kepada pelanggan berapa tepatnya yang akan mereka bayar:- Node.js SDK
- Python SDK
API Perubahan Paket
Gunakan API Perubahan Paket untuk memodifikasi produk, kuantitas, dan perilaku proratasi untuk langganan aktif.Contoh cepat memulai
- Node.js SDK
- Python SDK
- Go SDK
- HTTP
invoice_id dan payment_id hanya dikembalikan ketika biaya langsung dan/atau faktur dibuat selama perubahan paket. Selalu andalkan acara webhook (misalnya, payment.succeeded, subscription.plan_changed) untuk mengonfirmasi hasil.Mengelola Addon
Saat mengubah paket langganan, Anda juga dapat memodifikasi addon:Menerapkan Kode Diskon
Anda dapat menerapkan satu atau lebih kode diskon tambahan saat mengubah paket langganan (maks 20, diterapkan dalam urutan array). Ini berguna untuk menawarkan harga promosi pada peningkatan atau migrasi.- Node.js SDK
- Python SDK
- HTTP
Perilaku diskon pada perubahan paket
Nilai discount_codes | Perilaku |
|---|---|
Tidak disediakan / null | Diskon yang ada dengan preserve_on_plan_change=true secara otomatis dipertahankan jika berlaku untuk produk baru. |
[] (array kosong) | Semua diskon yang ada dihapus dari langganan. |
["CODE_A", "CODE_B", ...] | Menggantikan diskon yang ada dengan set tambahan ini, divalidasi dan diterapkan dalam urutan array. |
discount_code di endpoint ini dihapus tetapi masih berfungsi untuk kompatibilitas ke belakang — integrasi yang ada tidak perlu mengubah segera. Tidak dapat digabungkan dengan discount_codes dalam permintaan yang sama. Migrasikan ke bentuk array saat nyaman.Mode Prorasi
Pilih cara untuk menagih pelanggan saat mengubah paket:prorated_immediately
- Menagih perbedaan parsial dalam siklus saat ini
- Jika dalam percobaan, langsung menagih dan beralih ke paket baru sekarang
- Penurunan versi: dapat menghasilkan kredit prorated yang diterapkan ke pembaruan mendatang
full_immediately
- Menagih jumlah penuh dari paket baru secara langsung
- Mengabaikan waktu yang tersisa dari paket lama
difference_immediately diterapkan pada ruang lingkup langganan dan berbeda dari hak Penagihan Berbasis Kredit. Mereka secara otomatis diaplikasikan pada pembaruan di masa mendatang dari langganan yang sama dan tidak dapat dipindahtangankan antara langganan.difference_immediately
- Peningkatan: langsung menagih perbedaan harga antara paket lama dan baru
- Penurunan versi: tambahkan nilai yang tersisa sebagai kredit internal pada langganan dan terapkan secara otomatis saat pembaruan
do_not_bill
- Tidak ada biaya atau kredit yang dihitung
- Pelanggan beralih ke paket baru segera tanpa penyesuaian penagihan
- Siklus penagihan tetap tidak berubah
- Terbaik untuk migrasi sopan santun, perpindahan paket gratis, atau menyerap perbedaan biaya
| Fitur | prorated_immediately | difference_immediately | full_immediately | do_not_bill |
|---|---|---|---|---|
| Biaya upgrade | Perbedaan sesuai prorated untuk sisa hari | Perbedaan harga penuh antara paket | Harga penuh paket baru | Tidak ada biaya |
| Kredit downgrade | Kredit prorated untuk sisa hari | Perbedaan harga penuh sebagai kredit | Tidak ada kredit | Tidak ada kredit |
| Siklus penagihan | Direset menjadi hari ini | Direset menjadi hari ini | Direset menjadi hari ini | Tidak berubah |
| Perilaku percobaan | Akhiri percobaan, kenakan biaya segera | Akhiri percobaan, kenakan biaya segera | Akhiri percobaan, kenakan biaya penuh | Akhiri percobaan, tidak ada biaya |
| Terbaik untuk | Penagihan berbasis waktu adil | Matematika upgrade/downgrade sederhana | Mereset siklus penagihan | Migrasi gratis atau peralihan bersahabat |
| Kompleksitas | Sedang (penghitungan hari) | Rendah (pengurangan sederhana) | Rendah (biaya penuh) | Tidak ada |
Contoh skenario
Gunakan angka kanonik ini secara konsisten:- Paket saat ini: Basic di $30/bulan
- Target peningkatan: Pro di $80/bulan
- Target penurunan (dari Pro): Starter di $20/bulan
- Siklus penagihan: 30 hari, dimulai pada 1 Januari
- Perubahan paket terjadi pada 16 Januari (15 hari tersisa, 15 hari digunakan)
Upgrade: Basic ($30) → Pro ($80) with prorated_immediately
Upgrade: Basic ($30) → Pro ($80) with prorated_immediately
Downgrade: Pro ($80) → Starter ($20) with prorated_immediately
Downgrade: Pro ($80) → Starter ($20) with prorated_immediately
Upgrade: Basic ($30) → Pro ($80) with difference_immediately
Upgrade: Basic ($30) → Pro ($80) with difference_immediately
Downgrade: Pro ($80) → Starter ($20) with difference_immediately
Downgrade: Pro ($80) → Starter ($20) with difference_immediately
Upgrade: Basic ($30) → Pro ($80) with full_immediately
Upgrade: Basic ($30) → Pro ($80) with full_immediately
Mid-cycle upgrade with add-ons using prorated_immediately
Mid-cycle upgrade with add-ons using prorated_immediately
Bagaimana setiap mode memproses penagihan
Penanganan Kegagalan Pembayaran
Kontrol apa yang terjadi ketika pembayaran perubahan paket gagal menggunakan parameteron_payment_failure.
Mode Kegagalan Pembayaran
- prevent_change (Recommended for critical upgrades)
- apply_change (Default)
- Perubahan paket ditandai sebagai “pending”
- Pelanggan mempertahankan akses ke paket mereka saat ini
- Langganan berpindah ke status
activehanya setelah pembayaran berhasil - Berguna ketika Anda ingin memastikan pembayaran sebelum memberikan fitur peningkatan
on_payment_failure menggunakan pengaturan default tingkat bisnis Anda yang dikonfigurasi di dasbor.Kapan Menggunakan Setiap Mode
| Skenario | Mode yang Direkomendasikan | Alasan |
|---|---|---|
| Meningkatkan ke fitur premium | prevent_change | Pastikan pembayaran sebelum memberikan akses |
| Peningkatan jumlah (lebih banyak kursi) | prevent_change | Mencegah penggunaan tanpa pembayaran |
| Menurunkan paket | apply_change | Pelanggan mengurangi pengeluaran |
| Pelanggan perusahaan terpercaya | apply_change | Risiko lebih rendah dari ketidakpembayaran |
| Konversi percobaan ke berbayar | prevent_change | Momen pembayaran kritis |
Default Bisnis & Koleksi
Daripada memasukkan parameter prorated pada setiap perubahan paket, Anda dapat menetapkan perilaku default untuk upgrade & downgrade sekali di tingkat bisnis. Default ini berlaku untuk semua perubahan paket portal pelanggan, dan dapat ditimpa sesuai koleksi produk. Ada default terpisah untuk upgrade dan downgrade:| Pengaturan | Bidang (upgrade / downgrade) | Default (upgrade) | Default (downgrade) |
|---|---|---|---|
| Kapan paket baru dimulai | effective_at_on_upgrade / effective_at_on_downgrade | immediately | next_billing_date |
| Bagaimana cara pelanggan dikenakan biaya | proration_billing_mode_on_upgrade / proration_billing_mode_on_downgrade | difference_immediately | difference_immediately |
| Jika pembayaran pelanggan gagal | on_payment_failure | apply_change | apply_change |
Urutan Resolusi
Untuk setiap perubahan paket, setiap pengaturan diselesaikan dalam urutan ini:Menangani Webhooks
Lacak status langganan melalui webhooks untuk mengonfirmasi perubahan paket dan pembayaran.Jenis Peristiwa untuk Ditangani
subscription.active: langganan diaktifkansubscription.plan_changed: paket langganan berubah (perubahan upgrade/downgrade/addon)subscription.on_hold: pembayaran gagal, langganan dihentikansubscription.renewed: perpanjangan berhasilpayment.succeeded: pembayaran untuk perubahan paket atau perpanjangan berhasilpayment.failed: pembayaran gagal
Verifikasi Tanda Tangan dan Tangani Intent
- Next.js Route Handler
- Express.js
Praktik Terbaik
Ikuti rekomendasi ini untuk perubahan paket langganan yang andal:Strategi Perubahan Paket
- Uji secara menyeluruh: Selalu uji perubahan paket dalam mode uji sebelum produksi
- Pilih proration dengan hati-hati: Pilih mode proration yang paling sesuai dengan model bisnis Anda
- Tangani kegagalan dengan baik: Terapkan penanganan kesalahan dan logika coba ulang yang tepat
- Pantau tingkat keberhasilan: Lacak tingkat keberhasilan/kegagalan perubahan paket dan selidiki masalah
Implementasi Webhook
- Verifikasi tanda tangan: Selalu validasi tanda tangan webhook untuk memastikan keaslian
- Terapkan idempotensi: Tangani duplikasi peristiwa webhook dengan baik
- Proses secara asinkron: Jangan memblokir respon webhook dengan operasi berat
- Catat semuanya: Pertahankan catatan rinci untuk debugging dan audit
Pengalaman Pengguna
- Komunikasikan dengan jelas: Informasikan kepada pelanggan tentang perubahan dan waktu penagihan
- Berikan konfirmasi: Kirim konfirmasi email untuk perubahan paket yang berhasil
- Tangani kasus tepi: Pertimbangkan periode percobaan, perhitungan prorated, dan pembayaran yang gagal
- Perbarui UI segera: Refleksikan perubahan paket di antarmuka aplikasi Anda
Masalah Umum dan Solusi
Selesaikan masalah-masalah umum yang dihadapi selama perubahan paket langganan:Charge created but subscription not updated
Charge created but subscription not updated
- Pemrosesan webhook gagal atau tertunda
- Status aplikasi tidak diperbarui setelah menerima webhooks
- Masalah transaksi database selama pembaruan status
- Terapkan penanganan webhook yang andal dengan logika coba ulang
- Gunakan operasi idempoten untuk pembaruan status
- Tambahkan pemantauan untuk mendeteksi dan memberi tahu jika ada peristiwa webhook yang terlewatkan
- Verifikasi endpoint webhook dapat diakses dan merespon dengan benar
Credits not applied after downgrade
Credits not applied after downgrade
- Ekspektasi mode proration: Downgrade memberi kredit perbedaan harga paket penuh dengan
difference_immediately, sedangkanprorated_immediatelymembuat kredit prorated berdasarkan sisa waktu dalam siklus - Kredit bersifat spesifik untuk langganan dan tidak berpindah antar langganan
- Saldo kredit tidak terlihat di dasbor pelanggan
- Gunakan
difference_immediatelyuntuk downgrade jika Anda menginginkan kredit otomatis - Jelaskan kepada pelanggan bahwa kredit berlaku untuk perpanjangan langganan yang sama di masa depan
- Terapkan portal pelanggan untuk menunjukkan saldo kredit
- Periksa pratinjau faktur berikutnya untuk melihat kredit yang diterapkan
Webhook signature verification fails
Webhook signature verification fails
- Kunci rahasia webhook salah
- Badan permintaan mentah diubah sebelum verifikasi tanda tangan
- Algoritma verifikasi tanda tangan salah
- Verifikasi Anda menggunakan
DODO_WEBHOOK_SECRETyang benar dari dasbor - Baca badan permintaan mentah sebelum middleware parsing JSON
- Gunakan perpustakaan verifikasi webhook standar untuk platform Anda
- Uji verifikasi tanda tangan webhook di lingkungan pengembangan
Plan change fails with 422 error
Plan change fails with 422 error
- ID langganan atau produk tidak valid
- Langganan tidak dalam keadaan aktif
- Parameter yang diperlukan hilang
- Produk tidak tersedia untuk perubahan paket
- Verifikasi langganan ada dan aktif
- Periksa ID produk valid dan tersedia
- Pastikan semua parameter yang diperlukan disediakan
- Tinjau dokumentasi API untuk persyaratan parameter
Immediate charge fails during plan change
Immediate charge fails during plan change
- Dana tidak mencukupi pada metode pembayaran pelanggan
- Metode pembayaran kadaluwarsa atau tidak valid
- Bank menolak transaksi
- Deteksi penipuan memblokir biaya
- Tangani acara webhook
payment.faileddengan tepat - Beritahu pelanggan untuk memperbarui metode pembayaran
- Terapkan logika coba ulang untuk kegagalan sementara
- Pertimbangkan mengizinkan perubahan paket dengan biaya langsung yang gagal
Subscription on hold after plan change
Subscription on hold after plan change
on_holdApa yang terjadi:
Ketika biaya perubahan paket gagal, langganan secara otomatis ditempatkan di status on_hold. Langganan tidak akan diperpanjang secara otomatis hingga metode pembayaran diperbarui.Solusi: Perbarui metode pembayaran untuk mengaktifkan kembali langgananUntuk mengaktifkan kembali langganan dari status on_hold setelah perubahan paket gagal:- Perbarui metode pembayaran menggunakan API Perbarui Metode Pembayaran
- Pembuatan biaya otomatis: API secara otomatis membuat biaya untuk sisa tagihan
- Pembuatan faktur: Faktur dihasilkan untuk biaya tersebut
- Pemrosesan pembayaran: Pembayaran diproses menggunakan metode pembayaran baru
- Reaktivasi: Setelah pembayaran berhasil, langganan diaktifkan kembali ke status
active
subscription.on_hold: Langganan ditangguhkan (diterima saat biaya perubahan paket gagal)payment.succeeded: Pembayaran untuk sisa tagihan berhasil (setelah memperbarui metode pembayaran)subscription.active: Langganan diaktifkan kembali setelah pembayaran berhasil
- Beritahu pelanggan segera ketika biaya perubahan paket gagal
- Berikan instruksi yang jelas tentang cara memperbarui metode pembayaran mereka
- Pantau acara webhook untuk melacak status reaktivasi
- Pertimbangkan mengimplementasikan logika coba ulang otomatis untuk kegagalan pembayaran sementara
Update Payment Method API Reference
Menguji Implementasi Anda
Ikuti langkah-langkah ini untuk menguji implementasi perubahan paket langganan Anda secara menyeluruh:Set up test environment
- Gunakan kunci API uji dan produk uji
- Buat langganan uji dengan berbagai jenis paket
- Konfigurasikan endpoint webhook uji
- Siapkan pemantauan dan pencatatan
Test different proration modes
- Uji
prorated_immediatelydengan berbagai posisi siklus penagihan - Uji
difference_immediatelyuntuk upgrade dan downgrade - Uji
full_immediatelyuntuk mereset siklus penagihan - Uji
do_not_billuntuk peralihan paket tanpa biaya/kredit - Verifikasi perhitungan kredit benar
Test webhook handling
- Verifikasi semua peristiwa webhook terkait diterima
- Uji verifikasi tanda tangan webhook
- Tangani duplikasi peristiwa webhook dengan baik
- Uji skenario kegagalan pemrosesan webhook
Test error scenarios
- Uji dengan ID langganan tidak valid
- Uji dengan metode pembayaran kadaluarsa
- Uji kegagalan jaringan dan waktu habis
- Uji dengan dana tidak mencukupi
Penanganan Kesalahan
Tangani kesalahan API umum dengan baik dalam implementasi Anda:Kode Status HTTP
200 OK
200 OK
400 Bad Request
400 Bad Request
401 Unauthorized
401 Unauthorized
404 Not Found
404 Not Found
422 Unprocessable Entity
422 Unprocessable Entity
500 Internal Server Error
500 Internal Server Error
Format Respons Kesalahan
Langkah berikutnya
- Tinjau API Perubahan Paket
- Eksplorasi Penagihan Berbasis Kredit
- Terapkan peringatan untuk
subscription.on_hold - Lihat Panduan Integrasi Webhook kami