Your ideas, our roadmap!

Your feedback directly influences what we build. Share a feature request, report a rough edge, or tell us what's working well. The more detail (and upvotes), the faster we can act on it.

Open

Embeddable Payment Elements (like Stripe Elements)

Right now, integrating a custom checkout with Dodo Payments means either redirecting to a hosted checkout page or building the entire payment UI from scratch against the raw API. This makes it hard to offer a seamless, on-page checkout experience without a lot of custom work (styling, validation, card tokenization, error states, 3DS handling, etc.). Request: Build a set of embeddable, pre-built UI components (similar to Stripe Elements) that let developers drop a secure, customizable payment form directly into their own checkout page, instead of redirecting to a hosted page. Why this matters: - Better conversion — in-page checkout typically converts better than redirect flows since users never leave the merchant's site. - Faster integration — a drop-in card/payment element (with built-in tokenization, validation, and error handling) would cut integration time from days to hours. - Branding control — merchants could theme/style the element to match their site instead of a generic hosted page. - Security by default — sensitive card data stays inside Dodo's iframe/component, so merchants get PCI scope reduction without building it themselves. Suggested scope (v1): - A JS SDK with a mountable PaymentElement (or similar) for card details - Built-in support for common payment methods available on Dodo (cards, wallets, etc.) - Client-side tokenization + a confirmPayment()-style method to finalize on the frontend - Theming/customization options (fonts, colors, border radius) to match brand - Framework wrappers (React/Vue) similar to @stripe/react-stripe-js This would put Dodo Payments on par with Stripe/Adyen/Braintree in terms of developer experience for custom checkouts, which is often a deciding factor for teams choosing a payment provider.

Preetham Rangu·13 days ago
Open

Scheduled plan change does not re-attach the new product's meter price — usage bills at the old plan's rate indefinitely

# Scheduled plan change effective_at=next_billing_date) does not re-attach the new product's meter price — usage bills at the old plan's rate indefinitely Business: petnow (test mode) Feature: Subscriptions / Change Plan (v1.93.0 "Change Plan on Next Billing Date") ## Summary When a plan change is scheduled effective_at: "next_billing_date", proration_billing_mode: "full_immediately" — the only mode the API accepts with that timing), the subscription's product_id switches at the boundary as expected, but the subscription's attached usage meter keeps the old product's price_per_unit. Every subsequent renewal invoice bills usage at the old plan's rate while naming the new product on the line item. An immediate change effective_at: "immediately") re-attaches pricing correctly, so the two paths reach the same product with different billing. ## Environment - Subscription: sub_0NgsRDIOYpACfNHqo5G3u (customer cus_0NgsRDHy8LQ6ZhbqXJLGC) - Two products sharing one meter mtr_0Nb6cXrBT6IZZ7Ka4nnBW, "Active pets", aggregation last(pet_count), fixed price $0 on both): - Petify Core (DEV) pdt_0Nb6cwDRX6Qft6tEpHruq — $0.50/unit - Petify Plus (DEV) pdt_0NkHvBH9Y6Se7Qu2rDtco — $0.75/unit ## Steps to reproduce (all timestamps 2026-08-06 UTC; reproduced twice on the same subscription) 1. Put the subscription on Plus via change_plan effective_at=immediately, proration_billing_mode=do_not_bill) → meters[0].price_per_unit = "75" ✓ 2. Schedule a downgrade: change_plan with product_id=, proration_billing_mode=full_immediately, effective_at=next_billing_date → scheduled_change created ✓ 3. Let the boundary pass. The change applies: product_id → Core ✓, but meters[0].price_per_unit stays "75" ✗ 4. Ingest usage events and let two further renewals invoice. ## Actual results | Invoice | Cycle | Line item as printed | Total | |---|---|---|---| | inv_0NkmV4TAoiYfHnlVjqDq4 pay_0NkmV7RQIUQEzPgxUpW1N, 04:38:50Z) | 1st cycle spent fully on Core | "Petify Core (DEV)" + "2222 pets x 0.75 USD" | $1,833.15 | | inv_0NkmwSWJL8XkFftGIgP1K pay_0NkmwVU7eJQFrh8T9Hs40, repro run) | 1st cycle on Core | "1000 pets x 0.75 USD" | $825.00 | | inv_0Nkn8VSKgIX3dSdsnkpqM pay_0Nkn8VbKwOFBZFSBzjqVk) | 2nd consecutive cycle on Core — no plan change anywhere near it | "4000 pets x 0.75 USD" | $3,300.00 | subscriptions.retrieve throughout shows product_id = pdt_0Nb6cwDRX6Qft6tEpHruq (Core) with meters[0].price_per_unit = "75". The state never self-corrects — a "only the transition cycle bills at the old price" interpretation is ruled out by the third invoice. Note the internal contradiction on the invoices themselves: the line names Petify Core while billing a unit price that does not exist anywhere on the Core product. ## Expected After the scheduled change takes effect, usage bills at the new product's meter price ($0.50). Your documentation supports this expectation: - Localized Pricing: "the new plan's price is resolved with the same rules as checkout … This holds everywhere a plan change can originate: the Change Plan API, the Customer Portal, and changes scheduled for the end of the billing period." - Changelog v1.93.0: customers "retain access to their current plan until the end of the billing period." ## Ruled out - Not a configuration issue. No Product Collection is in use, Customer Portal self-service is unused ("Allow Subscription Updates" off); all calls are merchant-API. Under identical settings, the immediate path re-prices correctly. - Not proration-related. Both products have a $0 fixed price; the discrepancy is the meter unit price itself. ## Impact Silent mis-billing on usage-based products after any scheduled plan change — overcharge on downgrades, undercharge on upgrades — invisible to the customer until the invoice arrives. ## Workaround we validated After the scheduled change applies, calling change_plan again with the same product and proration_billing_mode=do_not_bill, effective_at=immediately re-attaches the correct meter price (observed 75 → 50, billing anchor preserved). ## Questions 1. Is this intended behavior or a defect? If a defect, what is the fix timeline? 2. Will a fix retroactively repair subscriptions already in the inconsistent state product_id ≠ attached meter pricing)? 3. Until then, is the no-op immediate change_plan the recommended mitigation? ## Secondary report — product attribution disagrees across surfaces While investigating, we noticed the dashboard payment detail page attributed a payment made on a Core cycle to "Petify Plus" (it appears to render the subscription's current product at view time), while the invoice PDF pins the payment-time product, and the payment API object carries no product at all product_cart: null on subscription renewals). Three surfaces disagree about which product a payment was for — worth aligning, since it makes billing incidents like the above much harder for merchants to diagnose.

Hansaem Woo·about 1 month ago
Open

Hosted checkout (Product Collection): switching plans does not update the displayed meter price — shows the other product's price_per_unit

Hello Dodo Payments team, On the hosted checkout for a Product Collection, the per-unit meter price displayed under the selected plan does not update when the customer switches plans — it keeps showing the price_per_unit of the collection's first product. The product configuration and the session data are both correct, so this appears to be a display-layer issue on the checkout page. ### Setup (Test Mode) Two usage-based subscription products that attach the same meter with different price_per_unit, grouped in one Product Collection: - Collection: pdc_0NkHvR1jUc2bTqx3jtTNa (products in this order) - Product 1: pdt_0Nb6cwDRX6Qft6tEpHruq "Petify (DEV)" — $0 fixed price + meter mtr_0Nb6cXrBT6IZZ7Ka4nnBW ("Active pets") at price_per_unit: 50 ($0.50/unit) - Product 2: pdt_0NkHvBH9Y6Se7Qu2rDtco "Petify PRO (DEV)" — $0 fixed price + the same meter at price_per_unit: 75 ($0.75/unit) ### Steps to reproduce 1. Create a checkout session with product_collection_id and an empty product_cart (our repro: session cks_0NkZ7frvtONN42VbaS3TB, 2026-08-03 ~04:00 UTC). 2. Open the checkout URL. The first product is pre-selected and its meter line reads "Active pets — $0.5 per pets" (correct for that product). 3. Select the second plan, "Petify PRO (DEV)". ### Actual behavior The expanded meter line under the now-selected PRO plan still reads "Active pets — $0.5 per pets" — the first product's price. The wrong value is introduced at render time, not in the data: - GET /products/pdt_0NkHvBH9Y6Se7Qu2rDtco returns price_per_unit: 75 - the checkout page's own server-rendered/embedded session payload contains "price_per_unit":75 for the PRO product A possibly relevant detail: both products attach the same meter_id, so a meter-keyed price lookup in the checkout UI would collide between the two plans. First noticed by a teammate in a regular Chrome session; afterwards reproduced deterministically in a separate environment. ### Expected behavior The meter price line always reflects the selected product's own price_per_unit (here $0.75 per unit when the PRO plan is selected). ### Impact Customers choosing the higher-priced plan are shown a per-unit price ~33% lower than what their subscription is configured to bill. Since this is the number the customer decides on, it is a billing-transparency problem even if the subscription itself bills the correct configured price afterwards. ### Related observation (happy to file separately) For the same collection, creating a session with product_cart: [{"product_id": "pdt_0NkHvBH9Y6Se7Qu2rDtco", "quantity": 1}] (session cks_0NkZ82TXQIRv5S2j95QrN) still renders with the collection's first product pre-selected — the cart's product seems to be ignored in collection mode. If that is by design, a documented way to pre-select a specific plan in a collection checkout would be useful. Observed in Test Mode only so far (we have not yet mirrored this collection in Live Mode). Could you confirm whether the display issue reproduces on your side? Happy to provide more details.

Hansaem Woo·about 2 months ago
Open

Subscription references a payment method ID missing from the customer’s payment methods list

Hello Dodo Payments Support, We found an apparent inconsistency between a subscription’s payment_method_id and the customer’s saved payment methods in Test Mode. ### Steps to reproduce 1. Create and pay for a subscription using a test card. 2. Cancel the subscription. 3. Create a new subscription for the same customer. 4. Manually enter the same card details again instead of selecting the saved card: - same card number - same expiration date - same CVV 5. Retrieve the new subscription and the customer’s payment methods. It appears Dodo recognizes and deduplicates the same physical card, so it does not create another entry in the customer payment methods list. However, the new subscription receives a different payment_method_id. ### Customer cus_0Nit5PNSWnwbGgdhx4axM ### Subscriptions [ { "subscription_id": "sub_0NjJ5ZzTvDYx0LfQ7g6xI", "status": "active", "payment_method_id": "pm_AGUnSlI1V3f5smOg8vl2", "created_at": "2026-07-16T11:59:54.850786Z", "next_billing_date": "2027-07-16T12:00:09.877212Z", "customer_id": "cus_0Nit5PNSWnwbGgdhx4axM" }, { "subscription_id": "sub_0Nit5dA8lhUEHkRNh72Nn", "status": "cancelled", "payment_method_id": "pm_gPZpWXKk4eSuzuXi9fu5", "created_at": "2026-07-10T14:44:34.167194Z", "next_billing_date": "2027-07-16T06:13:35.337024Z", "customer_id": "cus_0Nit5PNSWnwbGgdhx4axM" }, { "subscription_id": "sub_0Nit5POGOGvsoWzevyVhX", "status": "failed", "payment_method_id": null, "created_at": "2026-07-10T14:43:24.043795Z", "next_billing_date": "2026-07-10T14:43:24.043795Z", "customer_id": "cus_0Nit5PNSWnwbGgdhx4axM" } ] The active subscription references: pm_AGUnSlI1V3f5smOg8vl2 ### Customer payment methods response GET /customers/cus_0Nit5PNSWnwbGgdhx4axM/payment-methods returns: [ { "payment_method_id": "pm_gPZpWXKk4eSuzuXi9fu5", "payment_method": "card", "payment_method_type": "credit", "recurring_enabled": true, "last_used_at": "2026-07-10T14:44:49.850Z", "card": { "card_network": "visa", "card_type": "credit", "last4_digits": "4242", "expiry_month": "12", "expiry_year": "2034" } } ] Therefore, the active subscription references pm_AGUnSlI1V3f5smOg8vl2, but that ID is absent from the customer’s payment methods list. ### Impact Our UI cannot determine which saved payment method is currently used by the active subscription. Comparing payment method IDs produces no match, and Dodo does not expose an endpoint to retrieve payment method details directly by ID. ### Expected behavior We would expect one of the following: 1. The active subscription to reference the existing canonical customer payment method ID, or 2. The new payment method ID to appear in the customer payment methods list, or 3. An API field/endpoint that maps a subscription payment method ID to its canonical customer payment method. Could you confirm whether this behavior is expected and recommend the correct way to identify the customer payment method currently used by a subscription?

Need_To_Check
Andrii Mierlinov·about 2 months ago