Change Plan API
Plan Change Preview
Integration Guide
サブスクリプションのアップグレードまたはダウングレードとは?
顧客のサブスクリプションプランを変更して、異なるティア間で移動させたり、seat-based products の数量を調整したり、新しい product に移行したりできます。API は、選択した billing mode に基づいて日割り計算と請求を自動的に行います。プラン変更を使用するタイミング
- 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
- 現在のサイクルの未使用部分を、残り時間に応じて日割りでクレジットします
- その後、新しいプランの full サイクルを請求します。新しいプランの料金が日割りになることはありません
- 正味の請求額 = 新しいサイクル全額 −(残りの割合 × 古いサイクル全額)
Implement the Change Plan API
prorated_immediately、full_immediately、difference_immediately、または do_not_bill。nullを送信する、または空の配列を送信すると、既存のアドオンがすべて削除されます。保持するには、現在のアドオンを含めてください。prevent_change:支払いが成功するまで現在のプランでサブスクリプションを維持apply_change(デフォルト):支払い結果にかかわらず、直ちにプラン変更を適用
allow_plan_change_via_payment_link capability(Settings → Subscriptions → Collect Plan Change Payments by Payment Link)、effective_at: immediately、および on_payment_failure: prevent_change が必要です。Collecting Payment via a Checkout Linkを参照してください。Preview routeでは無視されます。subscription_id、payment_id、status が追加されます。collect_via_payment_link: true が必要です。指定しない場合、リクエストは 422 で失敗します。支払い後の顧客のリダイレクトを参照してください。409 を返します。保留中の Payment Link の置き換えを参照してください。preview route では無視されます。- 未指定 /
null— 新しい product に適用可能な場合、preserve_on_plan_change=trueを含む既存の discounts は保持されます。 [](空の array) — サブスクリプションから既存の discounts をすべて削除します。["CODE_A", "CODE_B", ...]— 既存の discounts をこの stacked set に置き換えます。
discount_codes を使用してください。この field は backward compatibility のため引き続き動作しますが、同じリクエストで discount_codes と併用できません。immediately(デフォルト):プラン変更を直ちに適用next_billing_date:次回の billing date に変更を予約。billing period が終了するまで顧客は現在のプランを保持します。顧客が billing period の終了まで現在のプランの benefits を利用できるよう、downgrade にはこれを使用してください。
Handle Webhook Events
subscription.active:プラン変更成功、subscription updatedsubscription.plan_changed:サブスクリプションのプラン変更(upgrade/downgrade/addon update)subscription.on_hold:プラン変更の charge に失敗、renewals stoppedpayment.succeeded:プラン変更の即時 charge に成功payment.failed:即時 charge に失敗
Update Your Application State
- 新しいプランに基づいて features を付与/取り消し
- 新しいプランの詳細で customer dashboard を更新
- プラン変更の確認メールを送信
- audit purposes のため billing changes を記録
Test and Monitor
- さまざまな scenarios で全 proration modes をテスト
- webhook handling が正しく機能することを確認
- プラン変更の成功率を監視
- 失敗したプラン変更の alerts を設定
プラン変更のプレビュー
プラン変更を確定する前に、Preview API を使用して顧客に請求額を正確に表示します:- Node.js SDK
- Python SDK
immediate_charge.summary では、customer_credits は、customer_credits_currency で示される顧客の credit balance の純変動です。これは顧客の credit wallet の通貨であり、subscription currency です。summary の currency とは異なる場合があります。summary の値は total_amount と tax に適用されます。たとえば、USD subscription を INR で支払う顧客には、USD の credits が表示されます。Change Plan API
Change Plan API を使用して、active subscription の product、quantity、proration behavior を変更します。クイックスタートの例
- Node.js SDK
- Python SDK
- Go SDK
- HTTP
200 OK が直ちに返されます。これは charge が実際に settle する前です。body(ChangePlanResponse)の内容は、変更の回収方法によって異なります:
collect_via_payment_link request の場合、顧客が支払いを完了するまでサブスクリプションは現在のプランに留まります。webhook(payment.succeeded、payment.failed、subscription.plan_changed)で結果を確認するか、GET /subscriptions/{subscription_id} を使用してサブスクリプションを再読み込みしてください。payment-link case についてはリンクが未払いの間の動作を参照してください。Checkout Link による支払いの回収
デフォルトでは、即時のプラン変更によってサブスクリプションの保存済み payment method に直接請求されます。代わりにcollect_via_payment_link: true を設定すると、顧客を hosted checkout page に移動できます。保存済み payment method がない場合や、顧客に新しい価格を明示的に確認してもらいたい場合に便利です。
Requirements
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)では checkout page は不要です。- request で
on_payment_failure: prevent_changeを設定する。明示的なapply_changeは422で失敗します。
collect_via_payment_link は、上記の要件を満たす限り、charge が発生するすべての即時変更(downgrade を含む)に適用されます。payment_link とその他の checkout fields は null で返され、変更は直ちに適用されます。これは 422 ではありません。link を要求する前に、Preview Plan Change を呼び出して金額を確認してください。
- Node.js SDK
- Python SDK
- HTTP
Link が未払いの間の動作
- サブスクリプションは現在のプランに留まります。
product_id、recurring_pre_tax_amount、next_billing_dateは、link が支払われるまで変更されません。 - link が pending の間、追加の
change-planrequest は409 PendingPlanChangeExistsで拒否されます。保留中の変更を置き換えるには、新しい request にcancel_older_payment_link: trueを指定してください。保留中の Payment Link の置き換えを参照してください。 - declined payment の後に再試行するには、
change-planを再度呼び出して新しい link を取得します。 - link が一度も支払われない場合、
expires_on後に機能しなくなります。その後まもなく、サブスクリプションは自動的に新しい plan-change request を受け付けられる状態になります。 - scheduled change がすでに存在し、それを
cancel_scheduled_change_plan: trueで置き換えた場合、link が未払いの間は元の schedule が維持され、link の支払い時(新しいプランを適用する同一 transaction 内)にのみキャンセルされます。
支払い後の顧客のリダイレクト
顧客が link の支払い後にサイトへ戻るようにするには、return_url を設定します:
return_url に移動します:
return_url には collect_via_payment_link: true が必要です。指定しない場合、request は 422 で失敗します。
保留中の Payment Link の置き換え
顧客が支払わずに checkout を離れた場合、次のchange-plan request で cancel_older_payment_link: true を設定します。Dodo Payments は未払いの link をキャンセルし、新しいプラン変更で保留中の変更を置き換えます。キャンセルされた link は、すでに開いている checkout page であっても支払いを受け付けなくなります。
change-plan request は独自の invoice を発行します。置き換えられたプラン変更とその invoice はキャンセルされます。保留中のプラン変更がない場合、cancel_older_payment_link は効果がありません。
Addons の管理
サブスクリプションプランの変更時に、addons も変更できます:Discount Codes の適用
サブスクリプションプランの変更時に、1つ以上の stacked discount codes を適用します(最大20個、array の順序で適用):- Node.js SDK
- Python SDK
- HTTP
Plan Change 時の Discount Behavior
discount_code field は非推奨ですが、backward compatibility のため引き続き動作します。既存の integrations はすぐに変更する必要はありません。同じ request で discount_codes と併用できません。都合のよいタイミングで array form に移行してください。Proration Modes
プラン変更時に顧客へ請求する方法を選択します:prorated_immediately
- 現在の cycle の未使用部分(base plan、quantity、add-ons)を、残り時間に応じて prorate し、credit します
- その後、新しい plan、quantity、add-ons のfull cycle を請求します。charge 自体は prorate されません
- Net immediate charge =(新しい full cycle)−(残りの割合 × 古い full cycle)
- credit が新しい cycle の charge を超える場合(downgrade でよく発生)、差額は subscription-scoped credit として将来の renewals に使用されます
- trial 中の場合は直ちに請求し、現在新しいプランに切り替えます
full_immediately
- 新しいプランの全額を直ちに請求します
- 古いプランの残り時間を無視します。現在の cycle に対する credit はありません
prorated_immediately によって作成された credits と、difference_immediately を使用した downgrades によって作成された credits は subscription-scoped であり、Credit-Based Billing entitlements とは異なります。これらは同じ subscription の将来の renewals に自動的に適用され、subscriptions 間で transfer できません。difference_immediately
- Upgrade:古いプランと新しいプランの price difference を直ちに請求
- Downgrade:残りの value を subscription の internal credit として追加し、renewals に自動適用
do_not_bill
- charges または credits は計算されません
- billing adjustment なしで、顧客は直ちに新しいプランへ切り替わります
- Billing cycle は変更されません
- courtesy migrations、free plan switches、または cost differences の吸収に最適
Example Scenarios
次の canonical numbers を一貫して使用します:- Current 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
各モードの Billing 処理
Payment Failures の処理
on_payment_failure parameter を使用して、プラン変更の支払いに失敗した場合の動作を制御します。
Payment Failure Modes
- prevent_change (Recommended for critical upgrades)
- apply_change (Default)
- Plan change は「pending」としてマークされます
- 顧客は現在のプランへの access を維持します
- 支払い成功後にのみ、サブスクリプションは
activestate に移行します - upgraded features を付与する前に支払いを確実にしたい場合に有用です
on_payment_failure parameter は dashboard で設定された business-level default setting を使用します。各モードの使用場面
Business & Collection Defaults
Settings → Subscriptions の business level で、upgrade と downgrade の default behavior を設定します。これらの 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 changed(upgrade/downgrade/addon changes)subscription.on_hold:charge failed、renewals stoppedsubscription.renewed:renewal succeededpayment.succeeded:plan change または renewal の payment succeededpayment.failed:payment failed
Signatures の検証と Intents の処理
- Next.js Route Handler
- Express.js
Best Practices
Plan Change Strategy
- 十分にテストする:production 前に必ず test mode で plan changes をテスト
- proration を慎重に選択する:business model に合った proration mode を選択
- failures を適切に処理する:適切な error handling と retry logic を実装
- 成功率を監視する:plan change の成功/失敗率を追跡し、問題を調査
Webhook Implementation
- signatures を検証する:authenticity を保証するため、常に webhook signatures を検証
- idempotency を実装する:重複した webhook events を適切に処理
- asynchronously 処理する:重い operations で 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 を直ちに更新する:アプリケーション interface に plan changes を反映
Common Issues and Solutions
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 にアクセスでき、正しく応答していることを確認
Credits not applied after downgrade
Credits not applied after downgrade
- Proration mode の想定:downgrades は
difference_immediatelyで full plan price difference を credit します。一方prorated_immediatelyは古い cycle の未使用時間を credit し、新しいプランの full cycle を請求するため、その credit が新しいプラン価格を超えた場合にのみ credit balance が残ります - Credits は subscription-specific で、subscriptions 間で transfer されない
- Customer dashboard に credit balance が表示されない
- automatic credits が必要な downgrade には
difference_immediatelyを使用 - credits は同じ subscription の将来の 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_PAYMENTS_WEBHOOK_KEYを使用していることを確認 - 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 を declined
- fraud detection が charge を block
payment.failedwebhook events を適切に処理- 顧客に payment method の更新を通知
- temporary 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 を再有効化しますfailed plan change の後、on_hold state から subscription を再有効化するには:- payment method を更新:Update Payment Method API を使用
- Automatic charge creation:API が残りの dues に対する charge を自動作成
- Invoice generation:charge の invoice を生成
- Payment processing:新しい payment method で payment を処理
- Reactivation:payment 成功後、subscription を
activestate に再有効化
subscription.on_hold:Subscription placed on hold(plan change charge の失敗時に受信)payment.succeeded:remaining dues の payment succeeded(payment method 更新後)subscription.active:successful payment 後に subscription reactivated
- plan change charge の失敗時に顧客へ直ちに通知
- payment method の更新方法について明確な instructions を提供
- reactivation status を追跡するため webhook events を監視
- temporary payment failures に対する automatic retry logic の実装を検討
Update Payment Method API Reference
実装のテスト
subscription plan change implementation を十分にテストします: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をテスト - no-charge/no-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
payment_id、payment_link、client_secret、expires_on を含む ChangePlanResponse です。4つすべて nullable であるため、通常の off-session change では body は {} として serialize されます。成功した collect_via_payment_link request では checkout handles が返されます。Checkout Link による支払いの回収を参照してください。on_payment_failure=prevent_change の場合、plan change は payment が成功するまで pending のままです。400 Bad Request
400 Bad Request
409 Conflict
409 Conflict
PendingPlanChangeExists)があります。scheduled change の場合は、新しいものを送信する前に DELETE /subscriptions/{subscription_id}/change-plan/scheduled でキャンセルしてください。pending payment-link change の場合は、新しい request に cancel_older_payment_link: true を指定して置き換えてください。保留中の Payment Link の置き換えを参照してください。cancel_older_payment_link: true を指定した場合、409 は顧客が以前の link を現在支払っている(PLAN_CHANGE_PAYMENT_IN_PROGRESS)か、すでに支払い済み(PLAN_CHANGE_PAYMENT_ALREADY_COMPLETED)であることを意味します。422 Unprocessable Entity
422 Unprocessable Entity
collect_via_payment_link の対象外です。business で capability が有効になっていない、effective_at が immediately ではない、または on_payment_failure が prevent_change ではありません。Requirementsを参照してください。存在しない、またはアカウントに属していない subscription ID は、NOT_FOUND code とともに 404 を返します。500 Internal Server Error
500 Internal Server Error
Error Response Format
Errors はcode と human-readable な message を含む JSON body を返します:
Next Steps
- Change Plan API を確認
- Credit-Based Billing を詳しく確認
subscription.on_holdの alerts を実装- Webhook Integration Guide を確認