Skip to main content
The Java SDK gives Java applications typed access to the Dodo Payments REST API. It uses Java types throughout: Optional for fields that can be missing, Stream for iterating results, and CompletableFuture for asynchronous calls.

Installation

Maven

Add the dependency to your pom.xml:
pom.xml

Gradle

Add the dependency to your build.gradle.kts:
build.gradle.kts
SDK releases add support for API changes. To find the most recent version, check Maven Central.
The SDK requires Java 8 or later, so it also runs on Java 11, 17, and 21.

Quick Start

Create a client, then create a checkout session:
fromEnv() connects to live mode unless DODO_PAYMENTS_BASE_URL or dodopayments.baseUrl says otherwise. To use test mode, see Test Mode. A test mode API key works only in test mode.
Keep API keys in environment variables, system properties, or a secrets manager. Never hardcode them in your source code.

Core Features

Type Safety

Typed request and response classes for compile-time checks.

Shared Client

Create one client and reuse it across requests: it holds the connection and thread pools. Request and response objects are immutable.

Builder Pattern

Every request class has a builder, and toBuilder() makes a modified copy.

Async Support

client.async() returns a client whose methods return CompletableFuture.

Configuration

Environment Variables

fromEnv() reads these environment variables, or the matching system properties. System properties take precedence:
.env
The API key comes from DODO_PAYMENTS_API_KEY or dodopayments.apiKey. The webhook signing secret comes from DODO_PAYMENTS_WEBHOOK_KEY or dodopayments.webhookKey, and the base URL from DODO_PAYMENTS_BASE_URL or dodopayments.baseUrl. Create one client and reuse it, because each client has its own connection pool and thread pools. To verify a webhook, pass the raw request body and headers to client.webhooks().unwrap(UnwrapWebhookParams.builder().body(rawBody).headers(headers).build()), where headers is a com.dodopayments.api.core.http.Headers. It checks the signature with your webhook key and returns the parsed event, or throws DodoPaymentsWebhookException. Without headers, unwrap doesn’t verify the signature. client.webhooks().unsafeUnwrap(rawBody) parses the body without verifying it, so use it only for testing. See Webhooks.

Manual Configuration

Set each option on the builder:
By default, the client retries twice and times out after 1 minute. It retries connection errors and responses with status 408, 409, 429, or 500 and above. To override the timeout for one call, pass RequestOptions.builder().timeout(Duration.ofSeconds(30)).build() as the method’s second argument. responseValidation(true) checks that the whole response matches the expected types up front. Without it, the SDK throws DodoPaymentsInvalidDataException only when you read a property with an unexpected type.

Test Mode

To use test mode (https://test.dodopayments.com), call testMode() on the builder:

Common Operations

The examples in this section use the client from Quick Start.

Create a Checkout Session

Create a checkout session, then redirect the customer to the returned checkout URL:
checkoutUrl() returns an Optional<String>. Each checkout URL works once and expires after 24 hours. For every session option, see Checkout Sessions.

Manage Customers

Create a customer with an email address, name, and metadata, then retrieve it by ID:

Handle Subscriptions

Create a subscription with a payment link, then charge it if it’s an on-demand subscription.
POST /subscriptions (the SDK’s subscriptions().create() method) is deprecated. It still works for existing integrations, but new integrations should create subscriptions through a Checkout Session.
productPrice is in the smallest currency unit, such as cents for USD or paise for INR. To charge $25.00, pass 2500.
subscriptions().charge(...) is for on-demand subscriptions. Dodo Payments bills other subscriptions automatically on the product’s billing schedule.

Usage-Based Billing

Configure Meters

Create a meter that counts events, then list your meters. autoPager() iterates over every meter and fetches more pages as needed:

Ingest Usage Events

Send a usage event for a customer. Event metadata values are JsonValue objects:
The eventId is the idempotency key, so give each event a unique value. A timestamp more than 1 hour in the past or more than 5 minutes in the future is rejected.

Batch Ingest Events

Send up to 1,000 events in one request. This example uses the imports from the previous one:

Error Handling

The SDK throws unchecked exceptions. For an error status, it throws a subclass of DodoPaymentsServiceException, which has statusCode(), headers(), and body(). Catch the specific classes you want to handle before the base class:
Statuses without their own class, such as 409, throw UnexpectedStatusCodeException. Network failures throw DodoPaymentsIoException, and responses the SDK can’t interpret throw DodoPaymentsInvalidDataException. All of these extend DodoPaymentsException.
The SDK retries connection errors and responses with status 408, 409, 429, or 500 and above, twice by default, with exponential backoff.

Async Operations

Call async() on the client to get an asynchronous client. Its methods return a CompletableFuture:
To create an asynchronous client from the start, use DodoPaymentsOkHttpClientAsync.fromEnv().

Spring Boot Integration

Configuration Class

Register one client as a bean, and choose the environment from a property:

Service Layer

Inject the client into a service:

Resources

GitHub Repository

Source code, releases, and the full method list.

API Reference

Every endpoint, parameter, and response.

Discord Community

Ask questions and talk with other developers.

Report Issues

Report bugs or request features.

Support

For help with the Java SDK:

Contributing

To contribute, read the contributing guidelines.
Last modified on September 25, 2026