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
allow_plan_change_via_payment_link機能(Settings → Subscriptions → Collect Plan Change Payments by Payment Link)が有効であり、effective_at: immediatelyおよびon_payment_failure: prevent_changeが必要です。Collecting Payment via a Checkout Linkを参照してください。プレビューrouteでは無視されます。- 指定なし /
null— 新しいproductに適用可能な場合、preserve_on_plan_change=trueを含む既存のdiscountsが保持されます。 [](空のarray) — サブスクリプションから既存のdiscountsをすべて削除します。["CODE_A", "CODE_B", ...]— 既存のdiscountsをこのstacked setに置き換えます。
discount_codesを優先してください。このfieldはbackward compatibilityのため引き続き動作しますが、同じrequestでdiscount_codesと併用することはできません。immediately(デフォルト):プラン変更を直ちに適用しますnext_billing_date:次回のbilling dateに変更をscheduleします。billing periodが終了するまで、顧客は現在のプランを維持します。
next_billing_dateを使用し、billing periodの終了まで顧客が現在のプランのbenefitsを維持できるようにします。Handle Webhook Events
subscription.active:プラン変更に成功し、subscriptionが更新されたsubscription.plan_changed:subscription planが変更された(upgrade/downgrade/addon update)subscription.on_hold:プラン変更のchargeに失敗し、renewalsが停止されたpayment.succeeded:プラン変更の即時chargeに成功したpayment.failed:即時chargeに失敗した
Update Your Application State
- 新しいplanに基づいてfeaturesを付与/取り消す
- 新しいplanの詳細でcustomer dashboardを更新する
- plan changesについてconfirmation emailsを送信する
- audit purposesのためbilling changesをlogに記録する
Test and Monitor
- さまざまなscenarioですべてのproration modesをテストする
- webhook handlingが正しく動作することを確認する
- plan change success ratesを監視する
- failed plan changesのalertsを設定する
プラン変更のプレビュー
プラン変更を確定する前に、Preview APIを使用して、顧客に請求される正確な金額を表示します。- Node.js SDK
- Python SDK
Change Plan API
Change Plan APIを使用して、active subscriptionのproduct、quantity、proration behaviorを変更します。クイックスタートの例
- Node.js SDK
- Python SDK
- Go SDK
- HTTP
200 OKが直ちに返されます。body(ChangePlanResponse)の内容は、変更の回収方法によって異なります。
collect_via_payment_link requestでは、結果は後から非同期に確定します。responseで渡されるのはcheckout linkだけで、subscriptionは現在のplanにとどまり、顧客が実際にlinkでpaymentを完了するまで結果は分かりません。いずれの場合も、このresponseから結果を推測しないでください。webhook(payment.succeeded、payment.failed、subscription.plan_changed)で確認するか、GET /subscriptions/{subscription_id}でsubscriptionを再読み込みしてください。payment-linkの場合の詳細はWhat Happens While the Link Is Unpaidを参照してください。Checkout LinkによるPaymentの回収
デフォルトでは、即時のplan changeによってsubscriptionの保存済み支払い方法に直接chargeされます。collect_via_payment_link: trueを設定すると、代わりに顧客をhosted checkout pageへ誘導できます。off-sessionでchargeできる保存済み支払い方法がない場合や、顧客に新しい価格を明示的に確認してもらいたい場合に便利です。
要件
collect_via_payment_link: trueが成功するには、次のすべてを満たす必要があります。満たさない場合、requestは422で失敗します。
- businessで
allow_plan_change_via_payment_linkcapabilityが有効になっている(Settings → Subscriptions → Collect Plan Change Payments by Payment Link)。 effective_atがimmediately(デフォルト)であること。scheduled change(next_billing_date)では、適用されるまでchargeされないためcheckout pageは不要です。- effectiveな
on_payment_failureがprevent_changeに解決されること。明示的に送る必要はありません。business-level default(下記のBusiness & Collection Defaultsを参照)がすでにprevent_changeであれば、fieldを省略してもこの条件を満たします。明示的なapply_change、または解決されたdefaultがapply_changeの場合は422で失敗します。
collect_via_payment_linkはupgradeに限定されません。上記の要件を満たし、chargeが発生する即時変更であれば、downgradeを含めて適用されます。proration_billing_mode: do_not_bill、または今cycleの合計がたまたまゼロになる別のmode)は、checkout pageに表示するものがありません。payment linkは発行されず、payment_linkなどはnullとして返され、変更はcollect_via_payment_linkなしの場合と同じく直ちに適用されます。これは422ではありません。このflagは回収すべき正の金額がある場合にのみ有効です。明確なupgrade以外のplan changesに一般的にcollect_via_payment_linkを設定する場合は、まずPreview Plan Changeを呼び出し、previewされた金額を回収する価値がある場合にのみlinkを要求してください。
- Node.js SDK
- Python SDK
- HTTP
Linkが未払いの間に発生すること
- subscriptionは現在のplanにとどまります。
product_id、recurring_pre_tax_amount、next_billing_dateは、linkが支払われるまで変更されません。 - linkがpendingの間、同じsubscriptionへの追加の
change-planrequestは409 PendingPlanChangeExistsで拒否されます。必要に応じてDELETE /subscriptions/{subscription_id}/change-plan/scheduledでscheduled changeをcancelできますが、このendpointではpending payment-link changeはcancelできません。cancelされるのは、paymentの成功またはexpiryによってのみです。 - decline後も、顧客は同じcheckout sessionでカードを再試行できます。新しい
change-plancallはretry pathではありません。 - linkが一度も支払われない場合、
expires_on後に機能しなくなり、その少し後にsubscriptionは新しいplan-change requestを受け付けられる状態になります。 - scheduled change(
next_billing_date)がすでに存在し、それをcancel_scheduled_change_plan: trueで置き換えた場合、linkが未払いの間は元のscheduleが維持されます。linkの支払いが完了した時点で、新しいplanを適用するtransaction内でのみcancelされます。
Addonsの管理
subscription plansを変更する際、addonsも変更できます。Discount Codesの適用
subscription plansの変更時に、1つ以上のstacked discount codes(最大20個、arrayの順序で適用)を適用できます。upgradeやmigrationにpromotional pricingを提供する場合に便利です。- Node.js SDK
- Python SDK
- HTTP
Plan change時のDiscountの動作
discount_code fieldは非推奨ですが、backward compatibilityのため引き続き動作します。既存のintegrationsですぐに変更する必要はありません。同じrequestでdiscount_codesと併用することはできません。都合のよいタイミングでarray形式へ移行してください。Proration modes
plansの変更時に顧客へどのようにbillするかを選択します。prorated_immediately
- 現在のcycleにおける差額の一部をchargeする
- trial中の場合は直ちにchargeし、今すぐ新しいplanに切り替える
- Downgrade:prorated creditが発生し、今後のrenewalsに適用される場合がある
full_immediately
- 新しいplanの全額を直ちにchargeする
- 旧planの残り期間を無視する
difference_immediatelyを使用したdowngradeによって作成されるcreditsはsubscriptionにスコープされ、Credit-Based Billingのentitlementsとは別物です。同じsubscriptionの今後のrenewalsに自動適用され、subscription間でtransferすることはできません。difference_immediately
- Upgrade:旧planと新planの価格差を直ちにchargeする
- Downgrade:残りのvalueをsubscriptionへのinternal creditとして追加し、renewalsに自動適用する
do_not_bill
- chargesもcreditsも計算しない
- billing adjustmentなしで、顧客を直ちに新しいplanへ切り替える
- billing cycleは変更しない
- courtesy migrations、free plan switches、またはcost differencesの吸収に最適
シナリオ例
次のcanonical numbersを一貫して使用します。- 現在のplan:Basic、$30/month
- Upgrade target:Pro、$80/month
- Downgrade target(Proから):Starter、$20/month
- Billing cycle:30 days、January 1に開始
- Plan changeはJanuary 16に発生(残り15日、使用済み15日)
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
各modeでのbilling処理
Payment Failuresの処理
on_payment_failure parameterを使用して、plan change paymentが失敗した場合の動作を制御します。
Payment Failure Modes
- prevent_change (Recommended for critical upgrades)
- apply_change (Default)
- Plan changeは「pending」としてmarkされる
- 顧客は現在のplanへのaccessを維持する
- subscriptionはpayment成功後にのみ
activestateへ移行する - upgraded featuresを付与する前にpaymentを確実に受け取りたい場合に有用
on_payment_failure parameterはdashboardで設定されたbusiness-level default settingを使用します。各Modeの使用タイミング
Business & Collection Defaults
すべてのplan changeでproration parametersを渡す代わりに、default upgrade & downgrade behaviorをbusiness levelで一度設定できます。これらのdefaultsはすべてのcustomer-portal plan changesに適用され、product collectionごとにoverrideできます。 upgradeとdowngradeにはそれぞれ別のdefaultsがあります。Resolution order
指定されたplan changeでは、各settingが次の順序で解決されます。Webhooksの処理
webhooksでsubscription stateを追跡し、plan changesとpaymentsを確認します。処理するEvent types
subscription.active:subscriptionがactivatedsubscription.plan_changed:subscription planが変更された(upgrade/downgrade/addon changes)subscription.on_hold:chargeに失敗し、renewalsが停止されたsubscription.renewed:renewalに成功したpayment.succeeded:plan changeまたはrenewalのpaymentに成功したpayment.failed:paymentに失敗した
Signaturesの検証とIntentsの処理
- Next.js Route Handler
- Express.js
Best Practices
信頼性の高いsubscription plan changesのため、次の推奨事項に従ってください。Plan Change Strategy
- 十分にテストする:productionの前に、必ずtest modeでplan changesをテストする
- prorationを慎重に選択する:business modelに合うproration modeを選択する
- failuresを適切に処理する:適切なerror handlingとretry logicを実装する
- success ratesを監視する:plan changeのsuccess/failure ratesを追跡し、問題を調査する
Webhook Implementation
- signaturesを検証する:authenticityを確保するため、常にwebhook signaturesをvalidateする
- idempotencyを実装する:重複したwebhook eventsを適切に処理する
- 非同期で処理する:重い処理でwebhook responsesをblockしない
- すべてをlogに記録する:debuggingとaudit purposesのため詳細なlogsを保持する
User Experience
- 明確に伝える:billing changesとtimingを顧客に知らせる
- confirmationsを提供する:成功したplan changesについてemail confirmationsを送信する
- edge casesを処理する:trial periods、prorations、failed paymentsを考慮する
- UIを直ちに更新する:application interfaceにplan changesを反映する
よくある問題と解決策
subscription plan changes中に発生する一般的な問題を解決します。Charge created but subscription not updated
Charge created but subscription not updated
- Webhook processingに失敗した、または遅延した
- webhooks受信後にapplication stateが更新されていない
- state update中のdatabase transaction issues
- retry logicを備えた堅牢なwebhook handlingを実装する
- state updatesにidempotent operationsを使用する
- missed webhook eventsを検出してalertするmonitoringを追加する
- webhook endpointにaccessでき、正しくresponseしていることを確認する
Credits not applied after downgrade
Credits not applied after downgrade
- Proration modeの想定:downgradeでは
difference_immediatelyによりfull plan price differenceがcreditされる一方、prorated_immediatelyではcycleの残り時間に基づくprorated creditが作成される - Creditsはsubscription-specificで、subscription間でtransferされない
- Customer dashboardにcredit balanceが表示されない
- automatic creditsが必要なdowngradeには
difference_immediatelyを使用する - creditsは同じsubscriptionのfuture renewalsに適用されることを顧客に説明する
- credit balancesを表示するcustomer portalを実装する
- next invoice previewで適用されたcreditsを確認する
Webhook signature verification fails
Webhook signature verification fails
- webhook secret keyが正しくない
- signature verification前にraw request bodyが変更された
- signature verification algorithmが間違っている
- dashboardの正しい
DODO_WEBHOOK_SECRETを使用していることを確認する - JSON parsing middlewareの前にraw request bodyを読み取る
- platform用のstandard webhook verification libraryを使用する
- development environmentでwebhook signature verificationをテストする
Plan change fails with 422 error
Plan change fails with 422 error
- subscription IDまたはproduct IDが無効
- subscriptionがactive stateではない
- required parametersが不足している
- productがplan changesに利用できない
- subscriptionが存在し、activeであることを確認する
- product IDが有効で利用可能か確認する
- required parametersがすべて指定されていることを確認する
- parameter requirementsについてAPI documentationを確認する
Immediate charge fails during plan change
Immediate charge fails during plan change
- 顧客のpayment methodの残高不足
- payment methodの期限切れまたは無効
- bankがtransactionをdeclineした
- fraud detectionがchargeをblockした
payment.failedwebhook eventsを適切に処理する- 顧客にpayment methodの更新を通知する
- 一時的なfailuresに対するretry logicを実装する
- failed immediate chargesでもplan changesを許可することを検討する
Subscription on hold after plan change
Subscription on hold after plan change
on_hold stateへ移行するWhat happens:
plan change chargeに失敗すると、subscriptionは自動的にon_hold stateになります。payment methodが更新されるまで、subscriptionは自動renewされません。Solution:payment methodを更新してsubscriptionをreactivateするfailed plan change後、on_hold stateのsubscriptionをreactivateするには:- payment methodを更新する:Update Payment Method APIを使用します
- Automatic charge creation:APIが未払い残額へのchargeを自動作成します
- Invoice generation:chargeのinvoiceが生成されます
- Payment processing:新しいpayment methodでpaymentが処理されます
- Reactivation:payment成功後、subscriptionは
activestateにreactivateされます
subscription.on_hold:subscriptionがholdされる(plan change charge失敗時に受信)payment.succeeded:未払い残額のpaymentに成功(payment method更新後)subscription.active:payment成功後にsubscriptionがreactivateされた
- plan change charge失敗時に顧客へ直ちに通知する
- payment methodの更新方法を明確に案内する
- reactivation statusを追跡するためwebhook eventsを監視する
- 一時的なpayment failuresに対するautomatic retry logicの実装を検討する
Update Payment Method API Reference
実装のテスト
subscription plan changeの実装を十分にテストするには、次の手順に従います。Set up test environment
- test API keysとtest productsを使用する
- 異なるplan typesでtest subscriptionsを作成する
- test webhook endpointを設定する
- monitoringとloggingを設定する
Test different proration modes
- さまざまなbilling cycle positionsで
prorated_immediatelyをテストする - upgradesとdowngradesで
difference_immediatelyをテストする - billing cyclesをresetするため
full_immediatelyをテストする - chargeもcreditもないplan switchesで
do_not_billをテストする - credit calculationsが正しいことを確認する
Test webhook handling
- 関連するすべてのwebhook eventsが受信されることを確認する
- webhook signature verificationをテストする
- duplicate webhook eventsを適切に処理する
- webhook processing failure scenariosをテストする
Test error scenarios
- invalid subscription IDsでテストする
- expired payment methodsでテストする
- network failuresとtimeoutsをテストする
- insufficient fundsでテストする
Monitor in production
- failed plan changesのalertsを設定する
- webhook processing timesを監視する
- plan change success ratesを追跡する
- plan change issuesに関するcustomer support ticketsを確認する
Error Handling
実装では一般的なAPI errorsを適切に処理します。HTTP Status Codes
200 OK
200 OK
collect_via_payment_link requestの場合はcheckout handlesを返します。詳しくはCollecting Payment via a Checkout Linkを参照してください。on_payment_failure=prevent_changeの場合、paymentが成功するまでplan changeはpendingのままです。400 Bad Request
400 Bad Request
404 Not Found
404 Not Found
409 Conflict
409 Conflict
PendingPlanChangeExists)。scheduled changeの場合は、別のものをsubmitする前にDELETE /subscriptions/{subscription_id}/change-plan/scheduledでcancelしてください。pending payment-link changeにはcancel endpointがありません。顧客が支払うかlinkがexpiryすると、subscriptionは新しいplan-change requestを受け付けます。422 Unprocessable Entity
422 Unprocessable Entity
collect_via_payment_linkの対象外です。businessでcapabilityが有効になっていない、effective_atがimmediatelyではない、またはon_payment_failureがprevent_changeではありません。Requirementsを参照してください。500 Internal Server Error
500 Internal Server Error
Error Response Format
次のステップ
- Change Plan APIを確認する
- Credit-Based Billingを確認する
subscription.on_holdのalertsを実装する- Webhook Integration Guideを確認する