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
preserve_on_plan_change=trueと既存の割引を持っている場合、新しい製品に適用可能であれば既存の割引が保持されます。immediately(デフォルト): プラン変更をすぐに適用next_billing_date: 次の請求日に変更をスケジュールします。顧客は請求期間が終了するまで現在のプランを保持します。
next_billing_dateを使用して、顧客が請求期間終了まで現在のプランの特典を保持するようにします。Handle Webhook Events
subscription.active: プラン変更が成功し、サブスクリプションが更新されましたsubscription.plan_changed: サブスクリプションプランが変更された(アップグレード/ダウングレード/アドオン更新)subscription.on_hold: プラン変更の課金が失敗し、サブスクリプションが一時停止されましたpayment.succeeded: プラン変更の即時課金が成功しましたpayment.failed: 即時課金が失敗しました
Update Your Application State
- 新しいプランに基づいて機能を付与/取り消し
- 顧客のダッシュボードを新しいプランの詳細で更新
- プラン変更について確認のメールを送信
- 監査目的で請求変更を記録
プラン変更のプレビュー
プラン変更の確認前に、Preview APIを使用して顧客に正確な請求額を表示します。- Node.js SDK
- Python SDK
プラン変更API
Change Plan APIを使用して、アクティブなサブスクリプションの製品、数量、および料金比例の動作を修正します。クイックスタートの例
- Node.js SDK
- Python SDK
- Go SDK
- HTTP
invoice_id および payment_id などのフィールドは、プラン変更時に即時課金および/または請求書が作成された場合のみ返されます。結果を確認するために常にウェブフックイベント(例:payment.succeeded、subscription.plan_changed)に依存してください。アドオンの管理
サブスクリプションプランを変更する際に、アドオンを変更することもできます:割引コードの適用
サブスクリプションプランの変更時に割引コードを適用できます。これはアップグレードや移行時にプロモーション価格を提供するのに役立ちます。- Node.js SDK
- Python SDK
- HTTP
プラン変更における割引の動作
| シナリオ | 動作 |
|---|---|
discount_code 提供済み | 割引を検証して新しいプランに適用します。 |
コード未提供、既存の割引ありpreserve_on_plan_change=true | 新しい製品に適用可能であれば、既存の割引が自動的に保持されます。 |
| コード未提供、保持可能な割引なし | 新しいプランに割引は適用されません。 |
料金比例モード
プラン変更時に顧客に請求する方法を選択します:prorated_immediately
- 現在のサイクルでの差額を計算し課金
- 試用中の場合は即座に課金し、新プランに切り替え
- ダウングレード: 将来の更新に適用される比例クレジットを生成する可能性があります
full_immediately
- 新プランの全額を即座に課金
- 旧プランからの残り時間を無視
difference_immediately を使用したダウングレードによって作成されたクレジットはサブスクリプション範囲であり、クレジットベースの課金 利権とは異なります。それらは同じサブスクリプションの将来の更新に自動的に適用され、サブスクリプション間で転送できません。difference_immediately
- アップグレード: 旧プランと新プランの価格差を即座に課金
- ダウングレード: 残価を内部クレジットとしてサブスクリプションに追加し、更新時に自動適用
do_not_bill
- 課金やクレジットは計算されません
- 顧客は請求調整なしで即座に新プランに切り替わります
- 請求サイクルは変更されません
- 無料プランのスイッチや、コスト差の吸収に最適
| 機能 | prorated_immediately | difference_immediately | full_immediately | do_not_bill |
|---|---|---|---|---|
| アップグレード課金 | 残り日数の比例差額 | 新旧プラン間の全額 | 新プランの全額 | 課金なし |
| ダウングレードクレジット | 残り日数の比例クレジット | クレジットとしての全額差 | クレジットなし | クレジットなし |
| 請求サイクル | 変更なし | 変更なし | 今日にリセット | 変更なし |
| 試用動作 | 試用終了、即座に課金 | 試用終了、即座に課金 | 試用終了、全額課金 | 試用終了、課金なし |
| 最適 | 公平な時間ベースの課金 | 単純なアップグレード/ダウングレード数式 | 請求サイクルの再設定 | 無料移行、礼儀上の切り替え |
| 複雑さ | 中程度(日数計算) | 低(単純な差し引き) | 低(全額課金) | 無し |
シナリオの例
これらの標準数値を一貫して使用します:- 現在のプラン: ベーシックで月額$30
- アップグレード目標: プロで月額$80
- ダウングレード目標(プロから): スターターで月額$20
- 請求サイクル: 30日間、1月1日に開始
- プラン変更が1月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
各モードが請求を処理する方法
支払い失敗時の処理
プラン変更支払いが失敗した際の処理をon_payment_failureパラメータを使用して制御します。
支払い失敗モード
- prevent_change (Recommended for critical upgrades)
- apply_change (Default)
- プラン変更が”保留中”としてマークされる
- 顧客は現在のプランのアクセスを保持する
- 支払いが成功した後のみサブスクリプションは
active状態に移行する - アップグレード機能を提供する前に支払いを確保したい場合に有用
on_payment_failureパラメータは、ダッシュボードに設定されたビジネスレベルのデフォルト設定を使用します。各モードの使用タイミング
| シナリオ | 推奨モード | 理由 |
|---|---|---|
| プレミアム機能へのアップグレード | prevent_change | アクセスを許可する前に支払いを確保する |
| 数量増加(座席追加) | prevent_change | 支払いなしに利用を防ぐ |
| プランのダウングレード | apply_change | 顧客が支出を削減している |
| 信頼できる企業顧客 | apply_change | 不払いのリスクが低い |
| 試用から有料への変換 | prevent_change | 重要な支払いの瞬間 |
ウェブフックの処理
プラン変更と支払いを確認するためにウェブフックを通じてサブスクリプションの状態を追跡します。処理するイベントタイプ
subscription.active: サブスクリプションがアクティブになるsubscription.plan_changed: サブスクリプションプランが変更された(アップグレード/ダウングレード/アドオン変更)subscription.on_hold: 課金が失敗し、サブスクリプションが一時停止されるsubscription.renewed: 更新が成功するpayment.succeeded: プラン変更または更新の支払いが成功するpayment.failed: 支払いが失敗する
署名の確認とインテントの処理
- Next.js Route Handler
- Express.js
ベストプラクティス
信頼性のあるサブスクリプションプランの変更のために、以下の推奨事項に従ってください:プラン変更戦略
- 徹底的にテストする: 本稼働前に常にテストモードでプラン変更をテスト
- 慎重に料金比例を選択する: ビジネスモデルに合った料金比例モードを選択
- 失敗を優雅に処理する: 適切なエラーハンドリングと再試行ロジックを実装
- 成功率を監視する: プラン変更の成功/失敗率を追跡し、問題を調査
ウェブフックの実装
- 署名を確認する: 署名を常に確認してウェブフックの信憑性を確保
- 冪等性を実装する: 重複するウェブフックイベントを優雅に処理
- 非同期で処理する: ウェブフックの応答を重い処理でブロッキングしない
- すべてを記録する: デバッグと監査のために詳細なログを維持
ユーザーエクスペリエンス
- 明確に伝える: 顧客に請求変更とタイミングを通知
- 確認を提供する: プラン変更の成功に関する確認メールを送信
- エッジケースを処理する: 試用期間、料金比例、支払い失敗を考慮
- UIを即座に更新する: アプリケーションインタフェースにプラン変更を反映
共通の問題と解決策
サブスクリプションプラン変更中に遭遇する一般的な問題を解決します:Charge created but subscription not updated
Charge created but subscription not updated
- ウェブフック処理が失敗または遅延している
- ウェブフック受信後にアプリケーション状態が更新されていない
- 状態更新中のデータベーストランザクションの問題
- 再試行ロジックを用いた頑強なウェブフック処理を実装
- 状態更新のために冪等な操作を使用
- 見逃したウェブフックイベントを検出して警告するための監視を追加
- ウェブフックエンドポイントがアクセス可能で正しく応答していることを確認
Credits not applied after downgrade
Credits not applied after downgrade
- 料金比例モードの期待: ダウングレードは、
difference_immediatelyでプランの全価格差をクレジットするが、prorated_immediatelyはサイクルの残り時間に基づいて比例クレジットを作成します - クレジットはサブスクリプション毎であり、サブスクリプション間で転送されない
- クレジット残高が顧客ダッシュボードに表示されていない
- ダウングレード時に自動クレジットを希望する場合は
difference_immediatelyを使用 - クレジットは同じサブスクリプションの将来の更新に適用されることを顧客に説明
- クレジット残高を表示する顧客ポータルを実装
- 適用されたクレジットを確認するには、次の請求書プレビューをチェック
Webhook signature verification fails
Webhook signature verification fails
- 不正確なウェブフックシークレットキー
- 署名検証前に修正された生リクエストボディ
- 誤った署名検証アルゴリズム
- ダッシュボードから正しい
DODO_WEBHOOK_SECRETを使用していることを確認 - JSON解析ミドルウェアの前に生リクエストボディを参照する
- プラットフォーム用の標準ウェブフック検証ライブラリを使用
- 開発環境でウェブフック署名の検証をテスト
Plan change fails with 422 error
Plan change fails with 422 error
- 無効なサブスクリプションIDまたは製品ID
- サブスクリプションがアクティブ状態にない
- 必要なパラメーターの欠如
- プラン変更のための製品の利用不可
- サブスクリプションが存在しアクティブであることを確認
- 製品IDが有効で利用可能であることを確認
- 必要なすべてのパラメーターが提供されていることを確認
- パラメーター要件についてAPIドキュメントを参照
Immediate charge fails during plan change
Immediate charge fails during plan change
- 顧客の支払い方法に資金不足
- 支払い方法が期限切れまたは無効
- 銀行が取引を拒否
- 詐欺検出が課金をブロック
payment.failedウェブフックイベントを適切に処理- 顧客に支払い方法の更新を通知
- 一時的な失敗のために再試行ロジックを実装
- 即時課金失敗でもプラン変更を許可することを検討
Subscription on hold after plan change
Subscription on hold after plan change
on_hold状態に移行する何が起こるか:
プラン変更の課金に失敗すると、サブスクリプションは自動的にon_hold状態になります。支払い方法が更新されるまでサブスクリプションは自動更新されません。解決策: 支払い方法を更新してサブスクリプションを再有効化プラン変更が失敗した後、on_hold状態からサブスクリプションを再活性化するには:- 支払い方法の更新を行う:Update Payment Method APIを使用
- 自動課金の作成: APIは自動的に残りの債務の課金を作成
- インボイスの生成: 課金のためのインボイスが生成されます
- 支払いの処理: 新しい支払い方法を使用して支払いが処理されます
- 再活性化: 支払いが成功すると、サブスクリプションは
active状態に再活性化されます
subscription.on_hold: プラン変更の課金失敗時にサブスクリプションが保留になるpayment.succeeded: 支払い方法の更新後、残りの債務の支払いが成功subscription.active: 支払いが成功した後、サブスクリプションが再活性化
- プラン変更の課金が失敗したときに顧客に即時に通知
- 支払い方法を更新する方法について明確な指示を提供
- 再活性化の状態を追跡するためにウェブフックイベントを監視
- 一時的な支払い失敗のために自動再試行ロジックを実装を検討
Update Payment Method API Reference
実装のテスト
サブスクリプションプラン変更の実装を徹底的にテストするために次の手順に従います:Set up test environment
- テストAPIキーとテスト製品を使用
- 異なるプランタイプでテストサブスクリプションを作成
- テスト用ウェブフックエンドポイントを設定
- 監視とログ記録を設定
Test different proration modes
- 様々な請求サイクルのポジションで
prorated_immediatelyをテスト - アップグレードとダウングレードを対象に
difference_immediatelyをテスト - 請求サイクルをリセットするために
full_immediatelyをテスト - 無料プランの切り替えために
do_not_billをテスト - クレジット計算が正しいことを確認
Test webhook handling
- すべての関連するウェブフックイベントが受信されていることを確認
- ウェブフックの署名確認をテスト
- 重複するウェブフックイベントを優雅に処理
- ウェブフック処理失敗シナリオをテスト
エラーハンドリング
実装内で一般的なAPIエラーを優雅に処理する: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
エラーレスポンス形式
次のステップ
- プラン変更APIを確認
- クレジットベースの課金を探る
subscription.on_holdのアラートを実装- Webhook Integration Guideを参照