Skip to main content

Prerequisites

Before you start, you need:
  • A Dodo Payments merchant account
  • An API key from Developer → API Keys in the dashboard, stored in DODO_PAYMENTS_API_KEY
  • A webhook secret from Developer → Webhooks, stored in DODO_PAYMENTS_WEBHOOK_KEY
  • At least one subscription product created under Products
For more details, see Integration Guide Prerequisites.

API Integration

Checkout Sessions

Create a subscription by building a checkout session with your subscription product. The customer authorizes a payment method and the subscription activates when they complete checkout.
Bạn có thể kết hợp một subscription product với các one-time product trong cùng một checkout session. Điều này hỗ trợ phí thiết lập, gói phần cứng đi kèm SaaS và các trường hợp sử dụng tương tự. Xem Checkout Sessions để biết ví dụ.Bạn cũng có thể bán hai hoặc nhiều subscription product trong một checkout. Customer thanh toán một lần và nhận một subscription độc lập cho mỗi product, mỗi subscription có billing cycle riêng. Cart như vậy không thể chứa one-time product. Xem Multi-Subscription Cart.

API Response

Response bao gồm một checkout_url:
Chuyển customer đến URL này. Customer sẽ authorize payment method và subscription được kích hoạt.

Webhooks

Webhook thông báo cho server của bạn khi các subscription event xảy ra. Thiết lập endpoint trong Developer → Webhooks trên dashboard. Để thiết lập webhook endpoint, xem Webhooks.

Subscription Event Types

Theo dõi các event này để quản lý subscription lifecycle:
  1. subscription.active — Subscription được kích hoạt
  2. subscription.updated — Một field trên subscription đã thay đổi
  3. subscription.on_hold — Charge gia hạn hoặc charge thay đổi plan thất bại
  4. subscription.failed — Tạo subscription thất bại (terminal; customer phải subscribe lại)
  5. subscription.renewed — Recurring charge thành công
  6. subscription.past_due — Gia hạn thất bại và grace period bắt đầu; customer vẫn giữ quyền truy cập cho đến past_due_ends_at
  7. subscription.plan_changed — Plan được upgrade, downgrade hoặc thay đổi
  8. subscription.cancelled — Subscription đã bị cancel
  9. subscription.expired — Subscription đã đến cuối term
Đây là các event cốt lõi. Để xem danh sách đầy đủ, bao gồm paused, unpaused và update_payment_method, xem Subscription Webhooks.
Sử dụng subscription.updated để nhận thông báo real-time về mọi thay đổi subscription, giúp đồng bộ state của application mà không cần polling API.

Payment Scenarios

Successful Payment Flow Chuỗi webhook phụ thuộc vào việc subscription có trial hay không. Immediate billing (0 trial days):
  1. subscription.active: mandate được authorize và subscription được kích hoạt.
  2. payment.succeeded: xác nhận charge đầu tiên. Dự kiến event này xuất hiện trong 2–10 phút sau checkout.
With a trial period:
  1. At trial start (checkout): subscription.active được phát sau khi payment method được authorize. Chưa có recurring charge nào được thực hiện. Charge thực tế đầu tiên được trì hoãn đến khi trial kết thúc.
  2. At trial end: recurring amount được charge và bạn nhận payment.succeeded cùng với subscription.renewed.
Every subsequent renewal:
  • subscription.renewed: được phát ở mỗi billing cycle khi payment gia hạn được khấu trừ, luôn đi kèm payment.succeeded. Event này cũng chứa next_billing_date đã cập nhật.
Bất cứ khi nào tiền thực sự được khấu trừ cho subscription product, bạn sẽ nhận subscription.renewed và payment.succeeded. Sử dụng subscription.renewed (thay vì chỉ dùng payment.succeeded) làm tín hiệu để gia hạn quyền truy cập cho cycle tiếp theo.
Payment Failure Scenarios
  1. Subscription Failure
  • subscription.failed - Tạo subscription thất bại do không thể tạo mandate.
  • payment.failed - Cho biết payment thất bại.
  1. Subscription On Hold
  • subscription.on_hold - Subscription bị đặt on hold do payment gia hạn thất bại hoặc charge thay đổi plan thất bại. Nếu business của bạn có grace period, lần gia hạn thất bại trước tiên sẽ chuyển subscription sang past_due (subscription.past_due), và chỉ chuyển sang on_hold (hoặc cancelled, tùy theo cài đặt grace period) khi grace period kết thúc. Xem Subscription States.
  • Khi subscription chuyển sang on hold, subscription sẽ không tự động renew cho đến khi payment method được cập nhật.
Best Practice: Để đơn giản hóa việc triển khai, chúng tôi khuyến nghị chủ yếu theo dõi subscription event để quản lý subscription lifecycle.
Để xem hướng dẫn đầy đủ về cách đọc error_code/error_message, quyết định thời điểm retry và hiển thị lỗi cho customer, xem Handle Payment Failures.

subscription.failed vs. subscription.on_hold

Hai event này rất dễ bị nhầm lẫn, nhưng cần được xử lý theo những cách rất khác nhau:
subscription.failed là terminal. Không thể reactivate subscription. Customer phải tạo subscription mới. Không bao giờ cấp entitlements khi event này được phát.

Handling Subscription On Hold

Khi subscription chuyển sang state on_hold, bạn cần cập nhật payment method để reactivate subscription. Phần này giải thích thời điểm subscription chuyển sang on hold và cách xử lý.

When Subscriptions Go On Hold

Subscription được đặt on hold khi:
  • Renewal payment fails: Charge gia hạn tự động thất bại do không đủ tiền, thẻ hết hạn hoặc ngân hàng từ chối
  • Plan change charge fails: Charge ngay lập tức trong quá trình upgrade/downgrade plan thất bại
  • Payment method authorization fails: Không thể authorize payment method cho recurring charge
Subscription ở state on_hold sẽ không tự động renew. Bạn phải cập nhật payment method để reactivate subscription.

Reactivating Subscriptions from On Hold

Để reactivate subscription từ state on_hold, hãy sử dụng Update Payment Method API. API này tự động:
  1. Tạo charge cho các khoản còn nợ
  2. Tạo invoice cho charge
  3. Xử lý payment bằng payment method mới
  4. Reactivate subscription về state active khi payment thành công
1

Handle subscription.on_hold webhook

Khi nhận webhook subscription.on_hold, hãy cập nhật application state và thông báo cho customer:
2

Update payment method

Khi customer sẵn sàng cập nhật payment method, hãy gọi Update Payment Method API:
Bạn cũng có thể sử dụng payment method ID hiện có nếu customer đã lưu payment method:
3

Monitor webhook events

Sau khi cập nhật payment method, hãy theo dõi các webhook event sau:
  1. payment.succeeded - Charge cho các khoản còn nợ đã thành công
  2. subscription.active - Subscription đã được reactivate

Sample Subscription Event Payload


Changing Subscription Plans

Bạn có thể upgrade hoặc downgrade subscription plan bằng change plan API endpoint. API này cho phép bạn sửa product, quantity của subscription và xử lý proration.

Change Plan API Reference

Để biết thông tin chi tiết về việc thay đổi subscription plan, vui lòng tham khảo tài liệu Change Plan API của chúng tôi.

Proration Options

Khi thay đổi subscription plan, bạn có bốn tùy chọn để xử lý charge ngay lập tức:

1. prorated_immediately

  • Credit phần chưa sử dụng của billing cycle hiện tại, được tính theo thời gian còn lại. Credit bao gồm base plan, quantity và mọi add-on
  • Sau đó charge đầy đủ một cycle theo plan, quantity và add-on mới. Bản thân charge không bao giờ được prorate
  • Net immediate charge = (full new cycle) trừ (remaining fraction x full old cycle). Nếu credit lớn hơn, phần chênh lệch được giữ dưới dạng credit ở cấp subscription cho các lần renew trong tương lai
  • Trong trial period, tùy chọn này ngay lập tức chuyển user sang plan mới và charge customer ngay

2. full_immediately

  • Charge customer toàn bộ subscription amount của plan mới mà không credit cho cycle trước
  • Dù upgrade hay downgrade, customer đều trả toàn bộ giá plan mới từ đầu
  • Hữu ích khi bạn muốn charge toàn bộ amount bất kể còn bao nhiêu thời gian trong plan cũ

3. difference_immediately

  • Customer chỉ trả phần chênh lệch giữa giá plan cũ và plan mới
  • Amount không phụ thuộc vào thời điểm thay đổi trong cycle. Cùng một upgrade có chi phí như nhau vào ngày 1 và ngày 29
  • Khi upgrade, customer được charge phần chênh lệch ngay lập tức. Ví dụ, $30/month → $80/month = charge ngay $50
  • Khi downgrade, phần chênh lệch giá được lưu dưới dạng credit ở cấp subscription và tự động áp dụng cho các lần renew trong tương lai. Ví dụ, $50/month → $20/month = lưu credit $30

4. do_not_bill

  • Áp dụng thay đổi plan ngay lập tức nhưng không charge tại thời điểm thay đổi. Plan, quantity và add-on mới có thể được sử dụng ngay
  • Vì hiện tại không có charge, upgrade cho customer sử dụng plan cao hơn miễn phí trong phần còn lại của cycle hiện tại. Downgrade có hiệu lực ngay lập tức nhưng không có credit cho phần cycle chưa sử dụng mà customer đã thanh toán
  • Add-on được cấp thông qua do_not_bill không được credit trong lần thay đổi plan sau đó vì chúng chưa từng được bill. Thay đổi tiếp theo sẽ bill toàn bộ quantity add-on mới
  • Plan cập nhật (cùng quantity/add-on) được bill vào lần renewal tiếp theo theo lịch, và ngày billing ban đầu được giữ nguyên
Cả ba mode “charge now” đều reset billing cycle. prorated_immediately, difference_immediately và full_immediately chuyển next_billing_date của subscription sang ngày thay đổi. Chỉ do_not_bill giữ ngày renewal ban đầu nhưng không áp dụng immediate charge.

Behavior

  • Khi gọi API này, Dodo Payments ngay lập tức khởi tạo charge dựa trên proration option bạn đã chọn
  • Với prorated_immediately, credit cho phần chưa sử dụng của cycle hiện tại được tính trong mỗi lần thay đổi, cả upgrade lẫn downgrade. Nếu credit lớn hơn charge của cycle mới, phần còn lại được cộng vào credit balance của subscription. Các credit này chỉ dành cho subscription đó và chỉ được dùng để bù trừ các recurring payment trong tương lai của cùng subscription
  • Với difference_immediately, net luôn bằng chính xác phần chênh lệch giá. Đối với downgrade, phần dư được lưu thành credit ở cấp subscription, giống như prorated_immediately
  • Tùy chọn full_immediately bỏ qua việc tính credit và charge toàn bộ amount của plan mới
  • Tùy chọn do_not_bill áp dụng thay đổi ngay lập tức nhưng trì hoãn billing đến ngày renewal tiếp theo, ngày này được giữ nguyên
Chọn proration mode:
  • difference_immediately — customer trả phần chênh lệch giá. Đây là tùy chọn dễ dự đoán nhất; charge giống nhau bất kể thay đổi được thực hiện vào thời điểm nào trong cycle.
  • prorated_immediately — customer chỉ được credit cho thời gian chưa sử dụng trong cycle hiện tại. Charge thay đổi tùy theo thời điểm thay đổi trong cycle.
  • full_immediately — customer trả toàn bộ amount của plan mới. Không có credit cho cycle trước.
  • do_not_bill — hiện tại không charge. Plan mới được bill ở lần renewal tiếp theo. Đây là mode duy nhất giữ nguyên ngày billing ban đầu.

Charge Processing

  • Immediate charge được khởi tạo khi thay đổi plan thường hoàn tất xử lý trong chưa đầy 2 phút
  • Nếu immediate charge này thất bại vì bất kỳ lý do nào, subscription sẽ tự động được đặt on hold cho đến khi vấn đề được giải quyết

On-Demand Subscriptions

On-demand subscription cho phép bạn charge customer linh hoạt, không chỉ theo lịch cố định. Tính năng này khả dụng cho mọi account.
To create an on-demand subscription: Để tạo on-demand subscription, sử dụng POST /checkouts API endpoint và thêm field subscription_data.on_demand vào request body. Điều này cho phép bạn authorize payment method mà không charge ngay lập tức hoặc đặt initial price tùy chỉnh.
POST /subscriptions đã deprecated. Tính năng này vẫn hoạt động với các integration hiện có, nhưng integration mới nên tạo on-demand subscription thông qua Checkout Session (POST /checkouts) cùng subscription_data.on_demand. Xem On-Demand Subscriptions Guide để biết flow hiện tại.
To charge an on-demand subscription: Đối với các charge tiếp theo, sử dụng endpoint POST /subscriptions//charge và chỉ định amount cần charge customer cho transaction đó.
Để xem hướng dẫn đầy đủ từng bước (bao gồm request/response example, safe retry policy và webhook handling), xem On-Demand Subscriptions Guide.

Key Things to Know About Subscription Billing

Đặt subscription period dài hơn payment frequency. Nếu subscription period bằng payment frequency (ví dụ: period = 1 month, frequency = 1 month), subscription chỉ có hiệu lực trong một cycle rồi chuyển sang expired thay vì renew. Đối với monthly plan liên tục, hãy đặt subscription period dài (ví dụ: 20 years) với monthly payment frequency.
Currency được khóa ở lần charge thành công đầu tiên. Luôn truyền rõ ràng billing_currency và billing_address.country khi tạo checkout. Nếu bỏ qua, các giá trị này được xác định từ IP của customer (Adaptive Currency), và khi subscription thực hiện charge đầu tiên, currency sẽ được cố định trong toàn bộ vòng đời. Customer đi du lịch sau đó cũng không thể chuyển đổi.
Trial thực hiện authorization $0, không phải charge. Khi subscription có trial, trial start tạo mandate authorization $0 để lưu card; charge thực tế đầu tiên xảy ra khi trial kết thúc. Trong payment list, subscription đang free trial hiển thị chính xác một payment với total_amount bằng 0. Paid trial thay vào đó sẽ charge trial_amount ngay từ đầu.
Subscription lifecycle: past_due = gia hạn thất bại và grace period đang diễn ra (customer vẫn giữ quyền truy cập). on_hold = gia hạn thất bại (có thể khôi phục: yêu cầu customer cập nhật payment method; dunning retry được áp dụng). expired = term kết thúc mà không renew và không thể reactivate. Customer phải subscribe lại. cancelled = kết thúc bởi customer hoặc merchant. Hầu hết lỗi gia hạn là issuer-side decline (không đủ tiền, thẻ bị từ chối), không phải lỗi của Dodo.
Thẻ Ấn Độ hoạt động trên RBI e-mandate. Off-session charge (charge gia hạn và charge thay đổi plan) có thể mất tối đa khoảng 48 giờ để settlement, và recurring auto-debit trên ₹15,000 yêu cầu customer authentication mới (do đó upgrade vượt giới hạn này không thể sử dụng mandate hiện tại). Khi một charge vẫn đang ở trạng thái processing, charge thứ hai trên cùng subscription sẽ thất bại với “Cannot create new charge as previous payment is not successful yet.” Thẻ ngoài Ấn Độ được xác nhận gần như ngay lập tức.
Subscription có minimum là $1.00 bằng USD. Checkout từ chối total thấp hơn với TOTAL_PAYMENT_AMOUNT_BELOW_MINIMUM_AMOUNT. Các currency khác ngoài USD, EUR và GBP cũng phải có giá trị ít nhất $1.00; xem Minimum Amounts. On-demand charge product_price thấp hơn 100 theo smallest currency unit sẽ bị từ chối với product_price: value out of range. Subscription product có giá chính xác $0 được cho phép; xem Card-Optional at Zero Price. Để authorize card mà không charge, hãy sử dụng on-demand mandate_only setup.

Create Subscription (Deprecated)

Legacy API để tạo subscription trực tiếp. Sử dụng Checkout Sessions cho integration mới

Change Subscription Plan

API reference để upgrade, downgrade hoặc thay đổi subscription plan với các proration option

Update Payment Method

API reference để cập nhật payment method và reactivate subscription đang on hold

Patch Subscription

API reference để cập nhật subscription detail và configuration
Lần sửa đổi cuối 8 tháng 10, 2026