跳转到主要内容
Subscriptions let you sell ongoing access with automated renewals. Use flexible billing cycles, free trials, plan changes, and add‑ons to tailor pricing for each customer.

Upgrade & Downgrade

Control plan changes with proration and quantity updates.

On‑Demand Subscriptions

Authorize a mandate now and charge later with custom amounts.

Customer Portal

Let customers manage plans, billing, and cancellations.

Subscription Webhooks

React to lifecycle events like created, renewed, and canceled.

What Are Subscriptions?

Subscriptions are recurring products customers purchase on a schedule. They’re ideal for:
  • SaaS licenses: Apps, APIs, or platform access
  • Memberships: Communities, programs, or clubs
  • Digital content: Courses, media, or premium content
  • Support plans: SLAs, success packages, or maintenance

Key Benefits

  • Predictable revenue: Recurring billing with automated renewals
  • Flexible cycles: Monthly, annual, custom intervals, and trials
  • Plan agility: Proration for upgrades and downgrades
  • Add‑ons and seats: Attach optional, quantifiable upgrades
  • Seamless checkout: Hosted checkout and customer portal
  • Developer-first: Clear APIs for creation, changes, and usage tracking

Creating Subscriptions

Create subscription products in your Dodo Payments dashboard, then sell them through checkout or your API. Separating products from active subscriptions lets you version pricing, attach add‑ons, and track performance independently.

Subscription product creation

Configure the fields in the dashboard to define how your subscription sells, renews, and bills. The sections below map directly to what you see in the creation form.

Product details

  • Product Name (required): The display name shown in checkout, customer portal, and invoices.
  • Product Description (required): A clear value statement that appears in checkout and invoices.
  • Product Image (required): PNG/JPG/WebP up to 3 MB. Used on checkout and invoices.
  • Brand: Associate the product with a specific brand for theming and emails.
  • Tax Category (required): Choose the category (for example, SaaS) to determine tax rules.
Pick the most accurate tax category to ensure correct tax collection per region.

Pricing

  • Pricing Type: Choose Subscription (this guide). Alternatives are Single Payment and Usage Based Billing.
  • Price (required): Base recurring price with currency.
  • Discount Applicable (%): Optional percentage discount applied to the base price; reflected in checkout and invoices.
  • Repeat payment every (required): Interval for renewals, e.g., every 1 Month. Select the cadence (months or years) and quantity.
  • Subscription Period (required): Total term for which the subscription remains active (e.g., 10 Years). After this period ends, renewals stop unless extended.
  • Trial Period Days (required): Set trial length in days. Use 0 to disable trials. The first charge occurs automatically when the trial ends.
  • Select add‑on: Attach up to 10 add‑ons that customers can purchase alongside the base plan.
Changing pricing on an active product affects new purchases. Existing subscriptions follow your plan‑change and proration settings.
Add‑ons are ideal for quantifiable extras such as seats or storage. You can control allowed quantities and proration behavior when customers change them.

Advanced settings

  • Tax Inclusive Pricing: Display prices inclusive of applicable taxes. Final tax calculation still varies by customer location.
  • Generate license keys: Issue a unique key to each customer after purchase. See the License Keys guide.
  • Digital Product Delivery: Deliver files or content automatically after purchase. Learn more in Digital Product Delivery.
  • Metadata: Attach custom key–value pairs for internal tagging or client integrations. See Metadata.
Use metadata to store identifiers from your system (e.g., accountId) so you can reconcile events and invoices later.

Subscription Trials

Trials let customers access subscriptions without immediate payment. The first charge occurs automatically when the trial ends.

Configuring Trials

Set Trial Period Days in the product pricing section (use 0 to disable). You can override this when creating subscriptions:
// Via subscription creation
const subscription = await client.subscriptions.create({
  customer_id: 'cus_123',
  product_id: 'prod_monthly',
  trial_period_days: 14  // Overrides product's trial period
});

// Via checkout session
const session = await client.checkoutSessions.create({
  product_cart: [{ product_id: 'prod_monthly', quantity: 1 }],
  subscription_data: { trial_period_days: 14 }
});
The trial_period_days value must be between 0 and 10,000 days.

Detecting Trial Status

Currently, there is no direct field to detect trial status. The following is a workaround that requires querying payments, which is inefficient. We are working on a more efficient solution.
To determine if a subscription is in trial, retrieve the list of payments for the subscription. If there is exactly one payment with amount 0, the subscription is in trial period:
const subscription = await client.subscriptions.retrieve('sub_123');
const payments = await client.payments.list({
  subscription_id: subscription.subscription_id
});

// Check if subscription is in trial
const isInTrial = payments.items.length === 1 && 
                  payments.items[0].total_amount === 0;

Updating Trial Period

Extend the trial by updating next_billing_date:
await client.subscriptions.update('sub_123', {
  next_billing_date: '2025-02-15T00:00:00Z'  // New trial end date
});
You cannot set next_billing_date to a past time. The date must be in the future.

Subscription Plan Changes

Plan changes let you upgrade or downgrade subscriptions, adjust quantities, or migrate to different products. Depending on the proration mode you select, a change may trigger an immediate charge, create credit, or apply no billing adjustment.
You can change subscription plans and update the next billing date directly from the Dodo Payments dashboard. This provides a quick way to adjust subscriptions for customer support requests, promotional upgrades, or plan migrations without making API calls.
Enable self-service plan changes: Want customers to upgrade or downgrade their own subscriptions via the Customer Portal? Add your subscription products to a Product Collection and enable “Allow Subscription Updates” in your Subscription Settings.

Product Collections

Group related products into collections to enable seamless upgrade/downgrade paths in the Customer Portal.

Proration Modes

Choose how customers are billed when changing plans:
Quick comparison of the four proration modes:
prorated_immediatelydifference_immediatelyfull_immediatelydo_not_bill
升级剩余天数的按比例收费收取价格差额的全额收取全新计划的全额无需收费 — 立即切换
降级剩余天数的按比例信用全额价格差作为信用无信用,全额收费无信用 — 立即切换
计费周期重置为今天重置为今天重置为今天保持不变
最佳用途公平的基于时间的计费简单的阶梯更改计费周期重置免费迁移或礼节性切换

prorated_immediately

Charges prorated amount based on remaining time in the current billing cycle. Best for fair billing that accounts for unused time.
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
});

difference_immediately

Charges the price difference immediately (upgrade) or adds credit for future renewals (downgrade). Best for simple upgrade/downgrade scenarios.
// Upgrade: charges $50 (difference between $30 and $80)
// Downgrade: credits remaining value, auto-applied to renewals
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
});
Credits from downgrades using difference_immediately are subscription-scoped and auto-applied to future renewals. They’re distinct from Credit-Based Billing entitlements.
When a customer downgrades with difference_immediately, the unused value becomes a subscription-scoped credit that automatically offsets future renewals:

full_immediately

Charges full new plan amount immediately, ignoring remaining time. Best for resetting billing cycles.
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_monthly',
  quantity: 1,
  proration_billing_mode: 'full_immediately'
});

do_not_bill

Switches to the new plan without any billing adjustment. No proration charges, no credits — the customer simply moves to the new plan. Best for courtesy migrations, free plan switches, or scenarios where you want to absorb the cost difference.
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new_plan',
  quantity: 1,
  proration_billing_mode: 'do_not_bill'
});
Scenario: Customer on Basic (30/month)upgradestoPro(30/month) upgrades to Pro (80/month) on day 16 of a 30-day cycle using prorated_immediately.
Unused credit from Basic = $30 × (15 remaining / 30 total) = $15.00
Prorated cost of Pro     = $80 × (15 remaining / 30 total) = $40.00
────────────────────────────────────────────────────────────────────
Immediate charge         = $40.00 − $15.00 = $25.00
下一次续订日期为2月15日(1月16日 + 30天):$80.00/月
For more detailed calculation examples and edge cases, see our full Upgrade & Downgrade Guide.
Scenario: Customer on Pro (80/month)downgradestoStarter(80/month) downgrades to Starter (20/month) using difference_immediately.
Credit = Old plan − New plan = $80 − $20 = $60.00
The $60 credit auto-applies to future renewals:
  • Renewal 1: 2020 − 20 (credit) = **0.00(0.00** (40 credit remaining)
  • Renewal 2: 2020 − 20 (credit) = **0.00(0.00** (20 credit remaining)
  • Renewal 3: 2020 − 20 (credit) = $0.00 (credit exhausted)
  • Renewal 4: $20.00 (full price)
Learn more about how credits are managed in the Upgrade & Downgrade Guide.

Changing Plans with Add-ons

Modify add-ons when changing plans. Add-ons are included in proration calculations:
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [{ addon_id: 'addon_extra_seats', quantity: 2 }]  // Add add-ons
  // addons: []  // Empty array removes all existing add-ons
});
Plan changes trigger immediate charges. Failed charges may move the subscription to on_hold status. Track changes via subscription.plan_changed webhook events.

Previewing Plan Changes

Before committing to a plan change, preview the exact charge and resulting subscription:
const preview = await client.subscriptions.previewChangePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
});

// Show customer the charge before confirming
console.log('You will be charged:', preview.immediate_charge.summary);

Preview Change Plan API

Preview plan changes before committing to them.

Subscription States

订阅在其生命周期中会经历一组定义的状态。本表提供每个状态的参考,其原因,以及您可以如何(或是否)恢复它。
状态含义可恢复?恢复路径 / 下一步
pending订阅正在创建或处理等待 subscription.active(或 subscription.failed
active订阅处于活动状态并会自动续订无需操作
on_hold续订付款(或计划更改费用)失败;订阅已暂停更新支付方式以重新激活 - 自动通过支付重试扣款,或手动通过更新支付方式API
cancelled订阅已取消且不会续订仅可重新购买客户需开始新订阅;扣款可以提示重新购买
failed订阅创建失败(初始授权或付款未成功)否 — 终态客户需使用有效的支付方式创建新订阅
expired订阅已到期如果需要,客户需启动新订阅
on_holdfailed 经常被混淆。on_hold 是一个可恢复的状态,针对的是已激活的订阅,其续订失败。failed 是一个终态,仅发生在初始订阅创建失败时,无法重新激活。

状态机

暂停状态

订阅进入 on_hold 状态时:
  • 续订付款失败(资金不足、卡片过期等)
  • 计划更改费用失败
  • 支付方式授权失败
订阅处于 on_hold 状态时,不会自动续订。您必须更新支付方式以重新激活订阅。

从暂停状态重新激活

要从 on_hold 状态重新激活订阅,更新支付方式。这会自动:
  1. 为未付金额创建扣款
  2. 生成发票
  3. 使用新支付方式处理付款
  4. 成功付款后将订阅重新激活到 active 状态
// Reactivate subscription from on_hold
const response = await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'new',
  return_url: 'https://example.com/return'
});

// For on_hold subscriptions, a charge is automatically created
if (response.payment_id) {
  console.log('Charge created:', response.payment_id);
  // Redirect customer to response.payment_link to complete payment
  // Monitor webhooks for payment.succeeded and subscription.active
}
成功更新 on_hold 状态订阅的支付方式后,您将收到 payment.succeeded 随后是 subscription.active 的 Webhook 事件。

按转换发送的 Webhook 事件

每次转换都会发出一个 Webhook,因此您可以在无需轮询的情况下驱动授权逻辑:
转换事件
订阅激活subscription.active
续订成功subscription.renewed
续订失败 → 暂停subscription.on_hold
创建失败subscription.failed
计划升级/降级subscription.plan_changed
已取消subscription.cancelled
期限结束subscription.expired
任一字段更改subscription.updated

Subscription Webhook Payloads

查看订阅生命周期事件的完整负载架构。

API 管理

使用 POST /subscriptions 从产品中以编程方式创建订阅,带有可选的试用期和附加组件。

API Reference

查看创建订阅的 API。
使用 PATCH /subscriptions/{id} 更新数量、在下一个计费日期取消或修改元数据。

API Reference

了解如何更新订阅详细信息。
使用比例分配控制更改活动产品和数量。

API Reference

查看计划更改选项。
对于按需订阅,按需收取特定金额。

API Reference

收取按需订阅费用。
使用 GET /subscriptions 列出所有订阅,使用 GET /subscriptions/{id} 检索一个订阅。

API Reference

浏览列表和检索 API。
获取按量计费或混合定价模型的记录使用情况。

API Reference

查看使用历史 API。
更新订阅的支付方式。对于活动订阅,这会更新未来续订的支付方式。对于处于 on_hold 状态的订阅,这会通过为剩余金额创建扣款来重新激活订阅。当生成新的支付方式链接(New 请求类型)时,您可以传递 allowed_payment_method_types 来限制客户在该页面上看到的支付方式。客户永远不会看到列表中没有的方法,虽然包括一种方法并不保证它会出现(可用性仍然取决于客户位置和您的业务设置等因素)。

API Reference

了解如何更新支付方式并重新激活订阅。

常见使用案例

  • SaaS 和 API:提供分级访问及增加席位或用量的附加组件
  • 内容和媒体:每月访问,带有入门试用
  • B2B 支持计划:年度合同,带有高级支持附加组件
  • 工具和插件:许可证密钥和版本发布

集成示例

结帐会话(订阅)

创建结帐会话时,请包含您的订阅产品和可选的附加组件:
const session = await client.checkoutSessions.create({
  product_cart: [
    {
      product_id: 'prod_subscription',
      quantity: 1
    }
  ]
});

具有比例分配的计划更改

升级或降级订阅并控制比例分配行为:
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
});

在下一个计费日期取消

安排在当前计费周期结束时生效的取消:
await client.subscriptions.update('sub_123', {
  cancel_at_next_billing_date: true
});

按需订阅

创建按需订阅,并在需要时收取费用:
const onDemand = await client.subscriptions.create({
  customer_id: 'cus_123',
  product_id: 'prod_on_demand',
  on_demand: true
});

await client.subscriptions.charge(onDemand.id, {
  amount: 4900,
  currency: 'USD',
  description: 'Extra usage for September'
});

更新活动订阅的支付方式

更新活动订阅的支付方式:
// Update with new payment method
const response = await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'new',
  return_url: 'https://example.com/return'
});

// Or use existing payment method
await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'existing',
  payment_method_id: 'pm_abc123'
});

从暂停状态重新激活订阅

重新激活由于未付款而处于暂停状态的订阅:
// Update payment method - automatically creates charge for remaining dues
const response = await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'new',
  return_url: 'https://example.com/return'
});

if (response.payment_id) {
  // Charge created for remaining dues
  // Redirect customer to response.payment_link
  // Monitor webhooks: payment.succeeded → subscription.active
}

具有 RBI 合规授权的订阅

UPI 和印度卡订阅在 RBI(印度储备银行)法规下运行,具有特定的授权要求:

授权限制

授权类型和金额取决于您的订阅的定期收费:
  • 费用低于授权下限(默认 ₹15,000): 我们为下限金额创建按需授权。根据您的订阅频率按期收取订阅金额,最高可达授权限额。
  • 费用达到或超过授权下限: 我们为精确订阅金额创建订阅授权(或按需授权)。
授权下限可根据商家或请求通过 mandate_min_amount_inr_paise (INR paise)进行配置。银行登记的金额为 max(mandate_floor, billing_amount) - 因此,下限实际上成为每次计费较低时面向客户的授权上限。 有关 RBI 合规授权和印度支付方式可配置授权下限的详细信息,请参阅印度支付方式页面。

升级和降级注意事项

重要: 升级或降级订阅时,要仔细考虑授权限额:
  • 如果升级/降级导致的收费金额超过 ₹15,000 并超出现有按需付款限额,交易将可能失败。
  • 在这种情况下,客户可能需要更新其支付方式或再次更改订阅以建立具有正确限额的新授权。

高值收费的授权

对于达到或超过 ₹15,000 的订阅费用:
  • 客户将被其银行提示授权交易。
  • 如果客户未能授权交易,交易将失败,订阅将被暂停。

48 小时处理延迟

处理时间表: 印度卡和 UPI 订阅的定期扣费遵循特有的处理模式:
  • 根据您的订阅频率,在计划日期发起收费。
  • 从付款发起后48 小时起,客户帐户的实际扣款才会发生。
  • 此 48 小时窗口可能会根据银行的 API 响应延长 2-3 小时

授权取消窗口

在 48 小时的处理窗口:
  • 客户可以通过他们的银行应用取消授权。
  • 如果客户在此期间取消授权,订阅将保持活动(这是印度卡和 UPI 自动支付订阅特有的边缘情况)。
  • 但是,实际扣款可能会失败,在这种情况下,我们将把订阅置为暂停状态。
边缘情况处理: 如果您在发起扣款后立即向客户提供优惠、积分或订阅使用,您需要在应用中妥善处理此 48 小时的窗口。请考虑:
  • 在付款确认前推迟优惠激活
  • 实施宽限期或临时访问
  • 监控订阅状态以应对授权取消
  • 在应用逻辑中处理订阅暂停状态
监控订阅 Webhooks 以跟踪付款状态更改,并处理在 48 小时窗口期间取消授权的边缘情况。

最佳实践

  • 从明确的层级开始:2-3 个计划,各具明显区别
  • 传达定价信息:显示总计、比例分配和下次续订
  • 谨慎使用试用期:通过引导转化,而不仅仅是时间
  • 利用附加组件:保持基础计划简单,并追加销售额外功能
  • 测试更改:在测试模式下验证计划更改和分配
订阅是可灵活用于创建定期收入的基础。开始简单,彻底测试,并根据采用、流失和扩展指标进行迭代。
最后修改于 2026年6月18日