-
Notifications
You must be signed in to change notification settings - Fork 928
Migration guide for v21
This version uses API version 2026-03-25.dahlia. If the format of this API version looks new to you, see our new API release process.
Please review our API changelog for 2026-03-25.dahlia to understand all the breaking changes to the Stripe API, the reasons behind them and potential alternatives.
The Node SDK specific changelog for v21 has the corresponding changes in the SDKs as well as SDK specific breaking changes.
Node.js versions lower than 18 are no longer supported. The package now requires Node >= 18.
Action required: Upgrade to Node 18 or later before updating to the latest SDK version. For more information, see our language version support policy.
Note that this is the last major release that supports Node 18. Please make plans to update to at least Node 20 (and ideally Node 22 or higher) before September 2026.
The v21 release of stripe-node introduces native decimal type support for all decimal_string fields. All fields with format: decimal in the Stripe API (such as unit_amount_decimal, quantity_decimal, and fx_rate) now use Stripe.Decimal instead of string in both request parameters and response objects. This applies to V1 and V2 resources.
Stripe.Decimal is a vendored arbitrary-precision decimal type backed by BigInt. It has zero external dependencies.
If you read a decimal field from one Stripe object and pass it to another without manipulating it, no changes are needed — the Decimal value flows through transparently.
Before:
const session = await stripe.checkout.sessions.retrieve('cs_test_xxx');
const rate: string = session.currency_conversion.fx_rate;
const parsed = parseFloat(rate);After:
const session = await stripe.checkout.sessions.retrieve('cs_test_xxx');
const rate: Stripe.Decimal = session.currency_conversion.fx_rate;
// Convert to string
const rateStr: string = rate.toString();
// Convert to number (may lose precision for very large/small values)
const rateNum: number = rate.toNumber();Before:
const price = await stripe.prices.create({
unit_amount_decimal: '9.99',
currency: 'usd',
recurring: { interval: 'month' },
product: 'prod_xxx',
});After (CommonJS / TypeScript with esModuleInterop):
import Stripe from 'stripe';
const price = await stripe.prices.create({
unit_amount_decimal: Stripe.Decimal.from('9.99'),
currency: 'usd',
recurring: { interval: 'month' },
product: 'prod_xxx',
});After (ESM):
import Stripe, { Decimal } from 'stripe';
const price = await stripe.prices.create({
unit_amount_decimal: Decimal.from('9.99'),
currency: 'usd',
recurring: { interval: 'month' },
product: 'prod_xxx',
});Stripe.Decimal provides instance methods for basic arithmetic. add(), sub(), and mul() each take a single argument. div() additionally requires a precision (number of decimal places) and a rounding direction:
const a = Stripe.Decimal.from('10.50');
const b = Stripe.Decimal.from('3.25');
const sum = a.add(b); // 13.75
const diff = a.sub(b); // 7.25
const product = a.mul(b); // 34.125
const quotient = a.div(b, 6, 'half-up'); // 3.230769Every field below changes from string to Stripe.Decimal on both response objects and request params.
Billing
| Resource | Field |
|---|---|
Plan |
amount_decimal |
Plan |
tiers[].flat_amount_decimal |
Plan |
tiers[].unit_amount_decimal |
Price |
unit_amount_decimal |
Price |
tiers[].flat_amount_decimal |
Price |
tiers[].unit_amount_decimal |
Price |
currency_options[].unit_amount_decimal |
Price |
currency_options[].tiers[].flat_amount_decimal |
Price |
currency_options[].tiers[].unit_amount_decimal |
InvoiceItem |
quantity_decimal |
InvoiceItem |
pricing.unit_amount_decimal |
InvoiceLineItem |
quantity_decimal |
InvoiceLineItem |
pricing.unit_amount_decimal |
CreditNoteLineItem |
unit_amount_decimal |
Climate
| Resource | Field |
|---|---|
Climate.Order |
metric_tons |
Climate.Product |
metric_tons_available |
Checkout
| Resource | Field |
|---|---|
Checkout.Session |
currency_conversion.fx_rate |
Issuing
| Resource | Field |
|---|---|
Issuing.Authorization |
fleet.reported_breakdown.fuel.gross_amount_decimal |
Issuing.Authorization |
fleet.reported_breakdown.non_fuel.gross_amount_decimal |
Issuing.Authorization |
fleet.reported_breakdown.tax.local_amount_decimal |
Issuing.Authorization |
fleet.reported_breakdown.tax.national_amount_decimal |
Issuing.Authorization |
fuel.quantity_decimal |
Issuing.Authorization |
fuel.unit_cost_decimal |
Issuing.Transaction |
purchase_details.fleet.reported_breakdown.fuel.gross_amount_decimal |
Issuing.Transaction |
purchase_details.fleet.reported_breakdown.non_fuel.gross_amount_decimal |
Issuing.Transaction |
purchase_details.fleet.reported_breakdown.tax.local_amount_decimal |
Issuing.Transaction |
purchase_details.fleet.reported_breakdown.tax.national_amount_decimal |
Issuing.Transaction |
purchase_details.fuel.quantity_decimal |
Issuing.Transaction |
purchase_details.fuel.unit_cost_decimal |
V2
| Resource | Field |
|---|---|
V2.Core.Account |
identity.individuals[].relationship.percent_ownership |
V2.Core.AccountPerson |
relationship.percent_ownership |
Request-only decimal fields also change (e.g., price_data.unit_amount_decimal on Subscription, SubscriptionItem, SubscriptionSchedule, Quote, PaymentLink, Invoice line creation params).
The Decimal type uses BigInt internally. If your code uses BigInt literals directly (e.g., passing 100n to Decimal.from()), your tsconfig.json must target ES2020 or later. If you only construct decimals from strings (Decimal.from('9.99')), no tsconfig.json change is needed.
V2 resources previously generated a separate, per-field Amount class for every monetary amount property (e.g., OutboundPayment.Amount, AnnualRevenue.Amount). These duplicates have been replaced with a single shared Amount type. The fields (value and currency) are identical — only the type name and import path changed:
// Before
const amount: Stripe.V2.Core.Account.Identity.BusinessDetails.AnnualRevenue.Amount =
account.identity.business_details.annual_revenue.amount;
// After
const amount: Stripe.V2.Amount =
account.identity.business_details.annual_revenue.amount;
console.log(amount.value); // number
console.log(amount.currency); // string, e.g. "usd"