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

Currency amount renders reversed in RTL locales on hosted checkout

Summary On the hosted checkout page, the amount in the Show order details bar renders reversed in right-to-left locales. A $59.00 product displays as 00.95$, and a $57.00 product displays as 00.75$. The underlying DOM text is correct ($59.00). Only the visual order is wrong. ## Screenshots !Hosted checkout in Hebrew showing 00.95$ instead of $59.00 !Order details bar showing 00.75$ instead of $57.00 ## Steps to reproduce 1. Create a checkout session for any product, e.g. pdt_0NqUl9MraypWZDfcldkmu ($59.00 every 3 months) 2. Open the checkout URL with browser language he-IL, or create the session with customization.force_language: "he" 3. Look at the order details bar at the top of the page Expected: $59.00 Actual: 00.95$ ## Cause The amount is not LTR-isolated inside the RTL layout. $ and . are neutral characters, so the numeric runs reorder against the RTL base direction. ## Suggested fix Wrap money amounts in , or apply unicode-bidi: isolate; direction: ltr to the amount element. This applies to every RTL locale, not only Hebrew. ## Scope The rest of the Hebrew page renders correctly, including the card number placeholder and the PCI DSS badge. The issue is isolated to the amount in the order details bar. ## Impact Reported by SecretJobs (bus_0NfojPM6FjM9SErFgo8j6), who sell mostly into Israel and create sessions with force_language: "he". Customers reach the hosted page when their embedded checkout fails to load, so they see an incorrect price at the moment of payment. Seen 25 Oct 2026, test mode, Chrome at phone width. Chatwoot ticket 34860.

Venkatesh·7 days ago
Open

Arabic checkout: card number and expiry render right-to-left on mobile

Summary On a checkout with force_language: "ar", the numeric card fields are mirrored along with the rest of the page. Card number groups and the expiry date render right-to-left, which makes them read incorrectly to the customer. Numeric input such as card numbers, expiry dates and CVC should stay left-to-right even inside an RTL layout. This is standard RTL practice and every other checkout handles it this way. ## Impact Reported by Eytan Fishman (withyouchat.com), using the Overlay SDK on mobile. Payments do process successfully, so this is visual only, but it is not cosmetic. The expiry field renders as 31 / 04 where the customer entered 04 / 31. That is not a valid MM/YY value, so the customer is shown what looks like an invalid date on a field they just filled in correctly. On a payment form that directly undermines trust at the point of payment. The card number is affected the same way, with the groups reversed so the last block appears first. ## Reproduction 1. Create a checkout session with customization.force_language set to "ar". 2. Open it on a mobile device using the Overlay SDK. 3. Enter a card number and an expiry date. 4. Observe that both render reversed. ## Expected The page mirrors for Arabic, but the card number, expiry and CVC inputs keep left-to-right direction and ordering. ## Actual Card number groups and the expiry date are mirrored along with the layout. Entering 04 / 31 displays as 31 / 04. ## Note The merchant was initially asked to raise this on the feature requests board, but could not post there ("You don't have access to post on this board"), and reasonably pushed back that this is a bug rather than a feature request. Filing it on their behalf.

Venkatesh·15 days ago
Open

Invoice stays unpaid after a later payment attempt on the same invoice succeeds

Summary When a subscription renewal fails and the customer retries, every attempt in that billing cycle shares the same invoice. If a later attempt succeeds, the invoice is not marked paid. It stays in an unpaid state, so merchants see a leftover unpaid invoice for a cycle that was in fact collected. No duplicate invoice is created and the customer is not double charged. Only the invoice status is wrong. ## Impact Reported by Waveloop (Eran Kutner). Their finance view treats the unpaid invoice as an open debt against the customer, which creates duplicate revenue recognition and manual reconciliation every time a renewal fails and recovers. They report it happening consistently, not as a one-off. ## Reproduction 1. Let a subscription renewal fail (card declined). 2. Have the customer retry and complete the payment. 3. Observe the invoice for that cycle. It remains unpaid despite the successful charge. ## Live example Customer cus_0Nl4kJCXRTzPcpCerC1IP, subscription sub_0Nl4ketDQq7KlC9N0OYe1, billing cycle 18 Oct 2026. All three attempts share invoice inv_0Nq07l7H7jQenUO7d7ahA: | Time (UTC) | Payment ID | Status | | ---------- | --------------------------- | ------------------------- | | 10:55 | pay_0Nq07o8F4maPJUBjvCz1C | failed, CARD\_DECLINED | | 13:09 | pay_0Nq0XIgatqLcCLq7qntGp | requires\_payment\_method | | 13:39 | pay_0Nq0cx9GOTIsqP4ZaMTu6 | succeeded, 32084 ILS | 32084 ILS was collected once, at 13:39, against inv_0Nq07l7H7jQenUO7d7ahA. That invoice is still unpaid. The same pattern appears on this subscription's two earlier cycles: - 17 Sep, invoice inv_0NnpCl0sTcRtsowJHm5Hs: pay_0NnpClRus8mkBkRJEoQbk failed, pay_0NnrQ0phqzx48XUGXppq9 succeeded 31544 ILS - 17 Aug, invoice inv_0NlZrlP9r4knGEJlnHR8Z: pay_0NlZroPAsQZYLbNRCLCTV failed, pay_0Nlc57CR32GvEysaCZGME succeeded 30342 ILS ## Expected behaviour Once any payment attempt against an invoice succeeds, that invoice should be marked paid. ## Actual behaviour The invoice remains unpaid, apparently tracking the status of the first failed attempt rather than the successful one.

Venkatesh·15 days ago
Open

Prorated mid-cycle charge that keeps the existing renewal date

We sell a base subscription with add-ons (extra user and vehicle packs) that customers can add part-way through a billing period. On annual plans we need to charge for an addition right away and keep the customer's renewal date. Today every change-plan mode that charges now (prorated_immediately, difference_immediately, full_immediately) restarts the billing cycle from the moment of the change. do_not_bill keeps the renewal date but charges nothing until renewal. So a customer who adds a 5-user pack in month 4 of an annual plan either: - has their renewal date moved by four months and pays for a full new year on the spot, or - gets the pack free until renewal. Neither is what the customer expects. Most subscription billing systems handle this the same way: charge only for the time left in the period, and leave the renewal date alone. Request: a proration mode for change-plan (for example prorated_immediately_keep_cycle) that: 1. charges the prorated difference for the rest of the current period straight away, 2. keeps next_billing_date unchanged, and 3. puts that charge on the subscription's invoice and payment history. The same option in the plan-change preview endpoint would let us show customers the exact amount before they confirm. Support suggested a workaround: use do_not_bill, then take a separate one-click checkout payment on the saved card. With that, we would have to calculate the proration ourselves, and the charge would show up as a separate payment, not on the subscription invoice. It also creates a failure case where the plan change succeeds but the payment doesn't (or the other way round). A native mode would remove all of that. This would make mid-cycle add-on sales workable on annual plans for any merchant selling seats or usage packs.

stephen·1 month 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·3 months ago
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·2 months ago