Skip to main content

Change Plan API

Full API docs for updating subscriptions.

Plan Change Preview

See charge amounts before changing plans.

Integration Guide

Step-by-step subscription setup.

サブスクリプションのアップグレードまたはダウングレードとは?

顧客のサブスクリプションプランを変更して、異なるティア間で移動させたり、seat-based products の数量を調整したり、新しい product に移行したりできます。API は、選択した billing mode に基づいて日割り計算と請求を自動的に行います。
Plan changes can trigger an immediate charge depending on the proration mode you choose.

プラン変更を使用するタイミング

  • 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
詳細な設定手順については、Integration Guideを参照してください。

Step-by-Step Implementation Guide

Follow this comprehensive guide to implement subscription plan changes in your application:
1

Understand Plan Change Requirements

Before implementing, determine:
  • 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
Test plan changes thoroughly in test mode before implementing in production.
2

Choose Your Proration Strategy

Select the billing approach that aligns with your business needs:
最適な用途:古いプランの未使用期間をクレジットとして付与したい SaaS applications。
  • 現在のサイクルの未使用部分を、残り時間に応じて日割りでクレジットします
  • その後、新しいプランの full サイクルを請求します。新しいプランの料金が日割りになることはありません
  • 正味の請求額 = 新しいサイクル全額 −(残りの割合 × 古いサイクル全額)
3

Implement the Change Plan API

Use the Change Plan API to modify subscription details:
string
必須
The ID of the active subscription to modify.
string
必須
The new product ID to change the subscription to.
integer
必須
Number of units for the new plan (for seat-based products).
string
必須
How to handle immediate billing: prorated_immediately, full_immediately, difference_immediately, or do_not_bill.
array
新しいプランのオプションアドオン。このフィールドを省略する、nullを送信する、または空の配列を送信すると、既存のアドオンがすべて削除されます。保持するには、現在のアドオンを含めてください。
string
Controls behavior when the plan change payment fails:
  • prevent_change: Keep subscription on current plan until payment succeeds
  • apply_change (default): Apply plan change immediately regardless of payment outcome
If not specified, uses the business-level default setting.
サブスクリプションに保存されている支払い方法で請求する代わりに、payment linkでプラン変更額を回収します。顧客はホスト型のcheckoutページで支払います。business に 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では無視されます。
array
新しいプランに適用する、任意の stacked discount codes(最大20個、arrayの順序で適用)。動作は渡す値によって異なります:
  • 未指定 / null — preserve_on_plan_change=true を持つ既存のdiscountsは、新しいproductに適用可能であれば保持されます。
  • [](空のarray) — サブスクリプションから既存のdiscountsをすべて削除します。
  • ["CODE_A", "CODE_B", ...] — 既存のdiscountsを、このstacked setに置き換えます。
string
非推奨
Deprecated — 新しいintegrationでは discount_codes を使用してください。このfieldは後方互換性のため引き続き動作しますが、同じrequestで discount_codes と組み合わせることはできません。
string
デフォルト:"immediately"
プラン変更を適用するタイミング:
  • immediately(デフォルト):プラン変更を直ちに適用
  • next_billing_date:次回の請求日に変更を適用。請求期間が終了するまで、顧客は現在のプランを保持します。顧客が請求期間の終了まで現在のプランのbenefitsを利用できるようにするため、ダウングレードではこれを使用してください。
4

Handle Webhook Events

プラン変更の結果を追跡するため、webhook handlingを設定します:
  • subscription.active:プラン変更成功、subscription updated
  • subscription.plan_changed:サブスクリプションプラン変更(アップグレード/ダウングレード/addon update)
  • subscription.on_hold:プラン変更の請求に失敗、更新を停止
  • payment.succeeded:プラン変更の即時請求に成功
  • payment.failed:即時請求に失敗
必ずwebhook signaturesを検証し、idempotentなevent processingを実装してください。
5

Update Your Application State

webhook eventsに基づいて、アプリケーションを更新します:
  • 新しいプランに基づいてfeaturesを付与/取り消し
  • 新しいプランのdetailsでcustomer dashboardを更新
  • プラン変更の確認メールを送信
  • audit purposesのためbilling changesを記録
6

Test and Monitor

実装を十分にテストします:
  • さまざまなシナリオですべてのproration modesをテスト
  • webhook handlingが正しく動作することを確認
  • プラン変更の成功率を監視
  • 失敗したプラン変更のalertを設定
これで、サブスクリプションのプラン変更実装をproductionで使用できる状態になりました。

プラン変更のPreview

プラン変更を確定する前に、Preview APIを使用して、顧客に請求される正確な金額を表示します:
Preview APIを使用してconfirmation dialogsを作成し、顧客がプラン変更を確定する前に請求される正確な金額を表示します。

Change Plan API

Change Plan APIを使用して、アクティブなサブスクリプションのproduct、quantity、proration behaviorを変更します。

Quick Start Examples

プラン変更に成功すると 200 OK が直ちに返されます。これは、実際に請求がsettledする前です。body(ChangePlanResponse)の内容は、変更の支払い方法によって異なります:
このresponseはrequestが受け付けられたことを確認するものであり、請求が成功したことを示すものではありません。通常の即時請求では、結果はcall直後にoff-sessionで確定します。collect_via_payment_link requestでは、顧客が支払いを完了するまでサブスクリプションは現在のプランに留まります。webhook(payment.succeeded、payment.failed、subscription.plan_changed)で結果を確認するか、GET /subscriptions/{subscription_id} を使用してsubscriptionを再読み込みしてください。payment-linkの場合は、What Happens While the Link Is Unpaidを参照してください。
即時請求に失敗すると、支払いが成功するまでsubscriptionが subscription.on_hold に移行する場合があります。

Checkout Linkによる支払いの回収

デフォルトでは、即時のプラン変更によって、subscriptionのsaved payment methodに直接請求されます。顧客をhosted checkout pageへ送るには collect_via_payment_link: true を設定します。saved payment methodがない場合や、顧客に新しい価格を明示的に確認してもらいたい場合に便利です。
これは、Settings → Subscriptions の Collect Plan Change Payments by Payment Link toggleを有効にし、Customer Portalのプラン変更flowをcheckout経由にします。

Requirements

collect_via_payment_link: true は、次の すべて を満たす場合にのみ成功します。それ以外の場合、requestは 422 で失敗します:
  • businessで allow_plan_change_via_payment_link capabilityが有効になっている(Settings → Subscriptions → Collect Plan Change Payments by Payment Link)。
  • effective_at が immediately(デフォルト)であること。scheduled change(next_billing_date)にcheckout pageは必要ありません。
  • effective on_payment_failure が prevent_change に解決されること。明示的に送信する必要はありません。business-level defaultがすでに prevent_change であれば、fieldを省略しても条件を満たします。明示的な apply_change は 422 で失敗します。
collect_via_payment_link は、上記の要件を満たす限り、ダウングレードを含む、請求が発生するすべての即時変更に適用されます。
変更の差額がゼロまたはクレジットになる場合、payment linkは発行されません。payment_link とその他のcheckout fieldsは null として返され、変更は直ちに適用されます。これは 422 ではありません。linkをrequestする前に、Preview Plan Changeを呼び出して金額を確認してください。
成功したrequestはcheckout handlesを返します:

Linkが未払いの間に発生すること

  • subscriptionはcurrent planに留まります。product_id、recurring_pre_tax_amount、next_billing_date は、linkの支払いが完了するまで変更されません。
  • linkがpendingの間は、追加の change-plan requestは 409 PendingPlanChangeExists で拒否されます。必要であれば、DELETE /subscriptions/{subscription_id}/change-plan/scheduled でscheduled changeをキャンセルできます。ただし、このendpointはpending payment-link changeをキャンセルしません。キャンセルされるのは、支払いが成功した場合または期限切れになった場合のみです。
  • 顧客は、decline後も同じcheckout sessionでカードを再試行できます。新しい change-plan callを行うことはretry pathではありません。
  • linkが支払われない場合、expires_on 後に機能しなくなります。その後まもなく、subscriptionは新しいplan-change requestを受け付けられる状態になります。
  • scheduled changeがすでに存在し、それを cancel_scheduled_change_plan: true で置き換えた場合、linkが未払いの間は元のscheduleが維持されます。linkの支払いが完了した時点でのみ、new planを適用する同一transaction内でキャンセルされます。
即時のpayment-link changeが発行されると、そのsubscriptionに対する以後のすべてのplan-change request(副作用のないpreviewを含む)が、linkの解決までブロックされます。顧客に直ちに支払ってもらう予定のないlinkは発行しないでください。

Addonsの管理

サブスクリプションプランの変更時に、addonsも変更できます:
Addonsはproration calculationに含まれ、選択したproration modeに従って請求されます。

Discount Codesの適用

サブスクリプションプランの変更時に、1つ以上のstacked discount codesを適用します(最大20個、arrayの順序で適用):

プラン変更時のDiscount Behavior

このendpointの単数形 discount_code fieldはdeprecatedですが、後方互換性のため引き続き動作します。既存のintegrationsはすぐに変更する必要はありません。同じrequestで discount_codes と組み合わせることはできません。都合のよいタイミングでarray形式へ移行してください。
Preview Plan Change APIを discount_codes とともに使用して、プラン変更を確定する前に顧客へ節約額を正確に表示します。

Proration Modes

プラン変更時に顧客へどのように請求するかを選択します:

prorated_immediately

  • 現在のサイクルの未使用部分(base plan、quantity、add-ons)を残り時間に応じて日割りでクレジット
  • その後、新しいplan、quantity、add-onsのfull cycleを請求します。請求自体が日割りになることはありません
  • 正味の即時請求額 =(新しいサイクル全額)−(残りの割合 × 古いサイクル全額)
  • クレジットが新しいサイクルの請求額を超える場合(ダウングレードでよく発生)、差額はsubscription-scoped creditとして今後の更新に使用されます
  • trial中の場合は、直ちに請求して新しいプランへ切り替えます

full_immediately

  • 新しいプランの全額を直ちに請求
  • 古いプランの残り時間を無視し、現在のサイクルに対するクレジットは付与しません
prorated_immediatelyによって作成されたクレジットと、difference_immediatelyを使用したダウングレードによって作成されたクレジットは、subscription-scopedであり、Credit-Based Billing entitlementsとは異なります。これらは同じsubscriptionの今後の更新に自動的に適用され、subscription間でtransferすることはできません。

difference_immediately

  • アップグレード:古いプランと新しいプランの価格差を直ちに請求
  • ダウングレード:残りの価値をsubscriptionのinternal creditとして追加し、更新時に自動適用

do_not_bill

  • 請求もクレジット計算も行いません
  • 請求調整なしで、顧客を直ちに新しいプランへ切り替えます
  • billing cycleは変更されません
  • 好意による移行、無料プランへの切り替え、または料金差を事業者が負担する場合に最適

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日)

各ModeでのBilling処理

古いプランの未使用期間をクレジットしながら新しいプランのfull cycleを請求するには prorated_immediately を選択します。billingを再開するには full_immediately を選択します。シンプルなアップグレードとダウングレード時の自動クレジットには difference_immediately を使用します。請求調整なしでプランを切り替えるには do_not_bill を使用します。

Payment Failuresの処理

on_payment_failure parameterを使用して、プラン変更の支払いに失敗した場合の動作を制御します。

Payment Failure Modes

指定しない場合、on_payment_failure parameterはdashboardで設定されたbusiness-level default settingを使用します。

各Modeを使用するタイミング

Business & Collection Defaults

Settings → Subscriptions でbusiness levelのアップグレードおよびダウングレードの動作を設定します。これらのdefaultsは、すべてのcustomer-portal plan changesに適用され、product collectionごとにoverrideできます。 アップグレードとダウングレードには、それぞれ別のdefaultsがあります: Settings → Subscriptions でbusiness defaultsを設定し、各product collectionでcollection overridesを設定します。各collection fieldは独立しています。未設定のままにするとbusiness defaultを継承し、値を設定するとoverrideします。

Resolution Order

特定のプラン変更では、各settingが次の順序で解決されます:
Change Plan APIに明示的に渡された値が常に優先されます。businessおよびcollection defaultsは、明示的な値が指定されていない場合にのみ有効になります。これはcustomer portalから開始されるすべてのplan changesに該当します。
一般的な設定では、アップグレードを immediately + difference_immediately にして、顧客が差額を支払い、すぐにaccessできるようにします。ダウングレードは next_billing_date にして、サイクル終了まで顧客が現在のプランを維持できるようにします。

Webhooksの処理

webhooksを通じてsubscription stateを追跡し、プラン変更と支払いを確認します。

処理するEvent Types

  • subscription.active:subscription activated
  • subscription.plan_changed:subscription plan changed(upgrade/downgrade/addon changes)
  • subscription.on_hold:charge failed、renewals stopped
  • subscription.renewed:renewal succeeded
  • payment.succeeded:plan changeまたはrenewalのpayment succeeded
  • payment.failed:payment failed
business logicはsubscription eventsを基に実行し、confirmationとreconciliationにはpayment eventsを使用します。

Signaturesの検証とIntentsの処理

詳細なpayload schemasについては、Subscription webhook payloadsおよびPayment webhook payloadsを参照してください。

Best Practices

Plan Change Strategy

  • 十分にテストする:production前に必ずtest modeでプラン変更をテストする
  • prorationを慎重に選択する:business modelに合ったproration modeを選択する
  • failureを適切に処理する:適切なerror handlingとretry logicを実装する
  • 成功率を監視する:プラン変更の成功率/失敗率を追跡し、問題を調査する

Webhook Implementation

  • signaturesを検証する:authenticityを確保するため、必ずwebhook signaturesを検証する
  • idempotencyを実装する:重複するwebhook eventsを適切に処理する
  • 非同期で処理する:重い処理でwebhook responsesをブロックしない
  • すべてを記録する:debuggingとaudit purposesのため、詳細なlogsを維持する

User Experience

  • 明確に伝える:billing changesとタイミングを顧客に知らせる
  • confirmationsを提供する:プラン変更成功時にconfirmation emailsを送信する
  • edge casesを処理する:trial periods、prorations、failed paymentsを考慮する
  • UIを直ちに更新する:アプリケーションinterfaceにプラン変更を反映する

よくある問題と解決策

サブスクリプションのプラン変更中に発生する一般的な問題を解決します:
Symptoms:API callは成功するが、subscriptionが古いプランのままCommon causes:
  • Webhook processingが失敗または遅延した
  • webhook受信後にapplication stateが更新されていない
  • state update中のdatabase transaction issues
Solutions:
  • retry logicを使用したwebhook handlingを実装する
  • state updatesにidempotent operationsを使用する
  • missed webhook eventsを検出してalertするmonitoringを追加する
  • webhook endpointにaccessでき、正しく応答していることを確認する
Symptoms:顧客がダウングレードしたが、credit balanceが表示されないCommon causes:
  • Proration modeの想定:ダウングレードでは difference_immediately によりfull plan price differenceがクレジットされます。一方 prorated_immediately では、古いcycleの未使用期間がクレジットされ、その後新しいplanのfull cycleが請求されます。そのため、credit balanceが残るのはそのクレジットが新しいplan priceを超える場合のみです
  • Creditsはsubscription-specificであり、subscription間でtransferされない
  • Credit balanceがcustomer dashboardに表示されない
Solutions:
  • 自動creditsが必要なダウングレードには difference_immediately を使用する
  • creditsは同じsubscriptionのfuture renewalsに適用されることを顧客に説明する
  • credit balancesを表示するcustomer portalを実装する
  • next invoice previewで適用されたcreditsを確認する
Symptoms:invalid signatureによりWebhook eventsが拒否されるCommon causes:
  • webhook secret keyが正しくない
  • signature verification前にraw request bodyが変更された
  • signature verification algorithmが間違っている
Solutions:
  • dashboardの正しい DODO_PAYMENTS_WEBHOOK_KEY を使用していることを確認する
  • JSON parsing middlewareの前にraw request bodyを読み取る
  • platform向けのstandard webhook verification libraryを使用する
  • development environmentでwebhook signature verificationをテストする
Symptoms:APIが422 Unprocessable Entity errorを返すCommon causes:
  • subscription IDまたはproduct IDが無効
  • subscriptionがactive stateではない
  • required parametersが不足
  • productがplan changesに利用できない
Solutions:
  • subscriptionが存在し、activeであることを確認する
  • product IDが有効で利用可能であることを確認する
  • required parametersがすべて提供されていることを確認する
  • parameter requirementsについてAPI documentationを確認する
Symptoms:プラン変更が開始されたが、即時請求に失敗するCommon causes:
  • 顧客のpayment methodの残高不足
  • payment methodの期限切れまたは無効
  • bankがtransactionを拒否
  • fraud detectionがchargeをブロック
Solutions:
  • payment.failed webhook eventsを適切に処理する
  • 顧客にpayment methodの更新を通知する
  • 一時的なfailuresにretry logicを実装する
  • failed immediate chargesでもplan changesを許可することを検討する
Symptoms:プラン変更の請求に失敗し、subscriptionが on_hold stateに移行するWhat happens: プラン変更の請求に失敗すると、subscriptionは自動的に on_hold stateになります。payment methodが更新されるまで、subscriptionは自動的にrenewされません。Solution:payment methodを更新してsubscriptionをreactivateしますプラン変更の失敗後、 on_hold stateのsubscriptionをreactivateするには:
  1. payment methodを更新:Update Payment Method APIを使用
  2. Automatic charge creation:APIが残りの未払い額に対するchargeを自動作成
  3. Invoice generation:chargeのinvoiceを生成
  4. Payment processing:新しいpayment methodでpaymentを処理
  5. Reactivation:payment成功後、subscriptionを active stateへreactivate
監視するWebhook events:
  • subscription.on_hold:Subscription placed on hold(plan change charge fails時に受信)
  • payment.succeeded:Payment for remaining dues succeeded(payment method更新後)
  • subscription.active:Payment成功後にsubscription reactivated
Best practices:
  • plan change chargeが失敗したら直ちに顧客へ通知する
  • payment methodの更新方法を明確に案内する
  • reactivation statusを追跡するためwebhook eventsを監視する
  • 一時的なpayment failuresに対するautomatic retry logicの実装を検討する

Update Payment Method API Reference

payment methodsの更新とsubscriptionsのreactivationに関する完全なAPI documentationを確認してください。

実装のテスト

サブスクリプションのプラン変更実装を十分にテストします:
1

Set up test environment

  • test API keysとtest productsを使用する
  • 異なるplan typesでtest subscriptionsを作成する
  • test webhook endpointを設定する
  • monitoringとloggingを設定する
2

Test different proration modes

  • さまざまなbilling cycle positionsで prorated_immediately をテストする
  • アップグレードとダウングレードで difference_immediately をテストする
  • billing cyclesをリセットするため full_immediately をテストする
  • no-charge/no-credit plan switchesで do_not_bill をテストする
  • credit calculationsが正しいことを確認する
3

Test webhook handling

  • 関連するすべてのwebhook eventsが受信されることを確認する
  • webhook signature verificationをテストする
  • duplicate webhook eventsを適切に処理する
  • webhook processing failure scenariosをテストする
4

Test error scenarios

  • invalid subscription IDsでテストする
  • expired payment methodsでテストする
  • network failuresとtimeoutsをテストする
  • insufficient fundsでテストする
5

Monitor in production

  • failed plan changesのalertを設定する
  • webhook processing timesを監視する
  • plan change success ratesを追跡する
  • plan change issuesに関するcustomer support ticketsを確認する

Error Handling

実装で一般的なAPI errorsを適切に処理します:

HTTP Status Codes

Plan change requestは正常に処理されました。response bodyは payment_id、payment_link、client_secret、expires_on を含む ChangePlanResponse です。4つすべてがnullableであるため、通常のoff-session changeではbodyは {} としてserializeされます。成功した collect_via_payment_link requestでは値が設定され、checkout handlesが返されます。Collecting Payment via a Checkout Linkを参照してください。on_payment_failure=prevent_change の場合、payment成功までplan changeはpendingのままです。
Request parametersが無効です。required fieldsがすべて提供され、正しい形式であることを確認してください。
API keyが無効または不足しています。DODO_PAYMENTS_API_KEY が正しく、適切なpermissionsを持っていることを確認してください。
このsubscriptionにはpending plan changeがすでに存在します(PendingPlanChangeExists)。scheduled changeの場合は、新しいものをsubmitする前に DELETE /subscriptions/{subscription_id}/change-plan/scheduled でキャンセルしてください。pending payment-link changeにはcancel endpointがありません。顧客が支払うかlinkの期限が切れると、subscriptionは新しいplan-change requestを受け付けます。
subscriptionがinactiveまたはon-demandであるか、requestが collect_via_payment_link の対象外です。businessでcapabilityが有効になっていない、effective_at が immediately ではない、または on_payment_failure が prevent_change ではない可能性があります。Requirementsを参照してください。存在しない、またはaccountに属していないsubscription IDには、NOT_FOUND codeを含む 404 が返されます。
Server errorが発生しました。短時間待ってからrequestをretryしてください。

Error Response Format

Errorsは、 code と、人間が読める message を含むJSON bodyを返します:
完全な一覧については、Error Codesを参照してください。

Next Steps

最終更新日 2026年9月26日