Skip to content

Migration guide for v32

Michael Broshi edited this page Mar 26, 2026 · 2 revisions

Migration guide for v32

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 Java SDK specific changelog for v32 has the corresponding changes in the SDKs as well as SDK specific breaking changes.

V2 decimal fields use BigDecimal instead of String

The v32 release of stripe-java fixes V2 decimal field types to use BigDecimal instead of String. V2 API fields with format: decimal (such as percent_ownership on Account relationships) previously generated as String. They now generate as BigDecimal, matching the behavior that V1 decimal fields already had.

The SDK serializes BigDecimal values as JSON strings on the wire (e.g., "75.25" not 75.25), which is what the Stripe API expects.

No changes needed for V1 decimal fields

V1 decimal fields (like unit_amount_decimal on Price) already used BigDecimal. This change only affects V2 resources.

Setting V2 decimal params

Before:

AccountCreateParams params = AccountCreateParams.builder()
    .setIdentity(AccountCreateParams.Identity.builder()
        .setIndividual(AccountCreateParams.Identity.Individual.builder()
            .setRelationship(AccountCreateParams.Identity.Individual.Relationship.builder()
                .setPercentOwnership("75.25")  // was String
                .build())
            .build())
        .build())
    .build();

After:

import java.math.BigDecimal;

AccountCreateParams params = AccountCreateParams.builder()
    .setIdentity(AccountCreateParams.Identity.builder()
        .setIndividual(AccountCreateParams.Identity.Individual.builder()
            .setRelationship(AccountCreateParams.Identity.Individual.Relationship.builder()
                .setPercentOwnership(new BigDecimal("75.25"))  // now BigDecimal
                .build())
            .build())
        .build())
    .build();

Reading V2 decimal responses

Before:

String pctString = account.getIdentity().getIndividual().getRelationship().getPercentOwnership();
BigDecimal pct = new BigDouble(pctString);

After:

BigDecimal pct = account.getIdentity().getIndividual().getRelationship().getPercentOwnership();

Affected V2 fields

V1 decimal fields already used BigDecimal — only V2 fields are affected:

Resource Field
Account (com.stripe.model.v2.core) identity.individual.relationship.percentOwnership
AccountPerson (com.stripe.model.v2.core) relationship.percentOwnership
AccountCreateParams.Identity.Individual.Relationship percentOwnership
AccountUpdateParams.Identity.Individual.Relationship percentOwnership
AccountTokenCreateParams.Identity.Individual.Relationship percentOwnership
PersonCreateParams.Relationship percentOwnership
PersonUpdateParams.Relationship percentOwnership
PersonTokenCreateParams.Relationship percentOwnership

V2 Amount type consolidation

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 com.stripe.v2.Amount type. The fields (value and currency) are identical — only the type name and import path changed.

Before:

import com.stripe.model.v2.core.Account;
Account.Identity.BusinessDetails.AnnualRevenue.Amount amount =
    account.getIdentity().getBusinessDetails().getAnnualRevenue().getAmount();

After:

import com.stripe.v2.Amount;
Amount amount = account.getIdentity().getBusinessDetails().getAnnualRevenue().getAmount();
System.out.println(amount.getValue());    // long
System.out.println(amount.getCurrency()); // String, e.g. "usd"

Automatic-Module-Name changed from stripe.java to com.stripe

The Java module name was updated to follow standard Java naming conventions. Most users won't be affected, but if you use the Java Platform Module System (JPMS) and have a module-info.java file that references the Stripe module, update the requires directive:

Before:

module my.app {
    requires stripe.java;
}

After:

module my.app {
    requires com.stripe;
}

If you don't have a module-info.java file, no action is needed.

Here's the migration guide snippet:

V2 error handling now uses typed exceptions based on HTTP status code

What changed: V2 API calls now throw the same typed StripeException subclasses as V1. Previously, a 429 from a V2 endpoint threw a generic ApiException; now it throws a RateLimitException, matching V1 behavior.

Additionally, RateLimitException now extends StripeException directly instead of ApiException.

Who is affected: Anyone catching ApiException from V2 API calls, or catching ApiException to handle rate limits.

What to do:

If you catch RateLimitException via ApiException, catch it directly or update your catch to StripeException:

// Before: RateLimitException extended ApiException
try {
    client.v2().core().events().list(params);
} catch (ApiException e) {
    // This caught RateLimitException and generic API errors
}

// After: RateLimitException extends StripeException directly
try {
    client.v2().core().events().list(params);
} catch (RateLimitException e) {
    // Handle rate limiting specifically
} catch (ApiException e) {
    // Handle other API errors
}

If you were only catching ApiException from V2 calls and expecting all errors to be that type, note that V2 errors now throw typed exceptions (InvalidRequestException, AuthenticationException, RateLimitException, etc.) just like V1:

// Before: V2 errors were all generic ApiException
try {
    client.v2().core().events().list(params);
} catch (ApiException e) {
    // Caught everything
}

// After: V2 errors are now typed like V1
try {
    client.v2().core().events().list(params);
} catch (RateLimitException e) {
    // 429
} catch (InvalidRequestException e) {
    // 400, 404
} catch (AuthenticationException e) {
    // 401
} catch (StripeException e) {
    // Everything else
}

Clone this wiki locally