The Java SDK provides convenient and ergonomic access to the Dodo Payments REST API for applications written in Java. It utilizes Java-specific features like Optional, Stream, and CompletableFuture for modern Java development.
Installation
Maven
Add the dependency to your pom.xml:
< dependency >
< groupId > com.dodopayments.api </ groupId >
< artifactId > dodo-payments-java </ artifactId >
< version > 1.86.3 </ version >
</ dependency >
Gradle
Add the dependency to your build.gradle:
implementation ( "com.dodopayments.api:dodo-payments-java:1.86.3" )
Always use the latest SDK version to access the newest Dodo Payments features. Check Maven Central for the latest version.
The SDK supports Java 8 and all later versions, including Java 11, 17, and 21.
Quick Start
Initialize the client and create a checkout session:
import com.dodopayments.api.client.DodoPaymentsClient;
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient;
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionCreateParams;
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionRequest;
import com.dodopayments.api.models.checkoutsessions.ProductItemReq;
// Configure using environment variables (DODO_PAYMENTS_API_KEY, DODO_PAYMENTS_BASE_URL)
// Or system properties (dodopayments.apiKey, dodopayments.baseUrl)
DodoPaymentsClient client = DodoPaymentsOkHttpClient . fromEnv ();
CheckoutSessionRequest params = CheckoutSessionRequest . builder ()
. addProductCart ( ProductItemReq . builder ()
. productId ( "product_id" )
. quantity ( 1 )
. build ())
. build ();
CheckoutSessionResponse checkoutSessionResponse = client . checkoutSessions (). create (params);
System . out . println ( checkoutSessionResponse . sessionId ());
Always store your API keys securely using environment variables, system properties, or a secure configuration management system. Never hardcode them in your source code.
Core Features
Type Safety Strongly typed API with compile-time safety
Thread-Safe Safe for concurrent use in multi-threaded applications
Builder Pattern Intuitive builder pattern for constructing requests
Async Support CompletableFuture support for asynchronous operations
Configuration
Environment Variables
Configure using environment variables or system properties:
DODO_PAYMENTS_API_KEY = your_api_key_here
DODO_PAYMENTS_BASE_URL = https://live.dodopayments.com
// Automatically reads from environment variables
DodoPaymentsClient client = DodoPaymentsOkHttpClient . fromEnv ();
Manual Configuration
Configure manually with all options:
import java.time.Duration;
DodoPaymentsClient client = DodoPaymentsOkHttpClient . builder ()
. bearerToken ( "your_api_key_here" )
. baseUrl ( "https://live.dodopayments.com" )
. maxRetries ( 4 )
. timeout ( Duration . ofSeconds ( 30 ))
. responseValidation ( true )
. build ();
Test Mode
Configure for test/sandbox environment:
DodoPaymentsClient testClient = DodoPaymentsOkHttpClient . builder ()
. fromEnv ()
. testMode ()
. build ();
Common Operations
Create a Checkout Session
Generate a checkout session:
CheckoutSessionRequest params = CheckoutSessionRequest . builder ()
. addProductCart ( ProductItemReq . builder ()
. productId ( "prod_123" )
. quantity ( 1 )
. build ())
. returnUrl ( "https://yourdomain.com/return" )
. build ();
CheckoutSessionResponse session = client . checkoutSessions (). create (params);
System . out . println ( "Checkout URL: " + session . url ());
Manage Customers
Create and retrieve customer information:
import com.dodopayments.api.models.customers.Customer;
import com.dodopayments.api.models.customers.CustomerCreateParams;
// Create a customer
CustomerCreateParams createParams = CustomerCreateParams . builder ()
. email ( "customer@example.com" )
. name ( "John Doe" )
. putMetadata ( "user_id" , "12345" )
. build ();
Customer customer = client . customers (). create (createParams);
// Retrieve customer
Customer retrieved = client . customers (). retrieve ( "cus_123" );
System . out . println ( "Customer: " + retrieved . name () + " (" + retrieved . email () + ")" );
Handle Subscriptions
Create and manage recurring subscriptions:
import com.dodopayments.api.models.subscriptions. * ;
// Create a subscription
SubscriptionNewParams subscriptionParams = SubscriptionNewParams . builder ()
. customerId ( "cus_123" )
. productId ( "prod_456" )
. priceId ( "price_789" )
. build ();
Subscription subscription = client . subscriptions (). create (subscriptionParams);
// Charge subscription
SubscriptionChargeParams chargeParams = SubscriptionChargeParams . builder ()
. amount ( 1000 )
. build ();
SubscriptionChargeResponse chargeResponse = client . subscriptions ()
. charge ( subscription . id (), chargeParams);
Usage-Based Billing
Create and manage meters for tracking usage:
import com.dodopayments.api.models.meters. * ;
// Create API calls meter
MeterCreateParams apiMeterParams = MeterCreateParams . builder ()
. name ( "API Requests" )
. eventName ( "api_request" )
. aggregation ( "count" )
. putMetadata ( "category" , "api_usage" )
. build ();
Meter apiMeter = client . meters (). create (apiMeterParams);
System . out . println ( "Meter created: " + apiMeter . meterId ());
// List all meters
client . meters (). list ()
. autoPager ()
. forEach (m -> System . out . println ( "Meter: " + m . name () + " - " + m . aggregation ()));
Ingest Usage Events
Track custom events:
import com.dodopayments.api.models.usageevents. * ;
import java.time.OffsetDateTime;
// Ingest single event
UsageEventIngestParams singleEventParams = UsageEventIngestParams . builder ()
. addEvent ( UsageEventIngestParams . Event . builder ()
. eventId ( "api_call_" + System . currentTimeMillis ())
. customerId ( "cus_abc123" )
. eventName ( "api_request" )
. timestamp ( OffsetDateTime . now ())
. putMetadata ( "endpoint" , "/api/v1/users" )
. putMetadata ( "method" , "GET" )
. putMetadata ( "tokens_used" , "150" )
. build ())
. build ();
UsageEventIngestResponse response = client . usageEvents (). ingest (singleEventParams);
System . out . println ( "Processed: " + response . processedEvents ());
Batch Ingest Events
Ingest multiple events efficiently (max 1000 per request):
UsageEventIngestParams . Builder batchBuilder = UsageEventIngestParams . builder ();
for ( int i = 0 ; i < 100 ; i ++ ) {
batchBuilder . addEvent ( UsageEventIngestParams . Event . builder ()
. eventId ( "batch_event_" + i + "_" + System . currentTimeMillis ())
. customerId ( "cus_abc123" )
. eventName ( "video_transcode" )
. timestamp ( OffsetDateTime . now (). minusMinutes (i))
. putMetadata ( "video_id" , "video_" + i)
. putMetadata ( "duration_seconds" , String . valueOf ( 120 + i))
. build ());
}
UsageEventIngestResponse batchResponse = client . usageEvents (). ingest ( batchBuilder . build ());
System . out . println ( "Batch processed: " + batchResponse . processedEvents () + " events" );
Error Handling
Comprehensive error handling for different scenarios:
import com.dodopayments.api.errors. * ;
try {
Payment payment = client . payments (). retrieve ( "pay_invalid" );
} catch ( NotFoundException e ) {
System . err . println ( "Payment not found: " + e . getMessage ());
} catch ( UnauthorizedException e ) {
System . err . println ( "Authentication failed: " + e . getMessage ());
} catch ( PermissionDeniedException e ) {
System . err . println ( "Permission denied: " + e . getMessage ());
} catch ( BadRequestException e ) {
System . err . println ( "Invalid request: " + e . getMessage ());
} catch ( UnprocessableEntityException e ) {
System . err . println ( "Validation error: " + e . getMessage ());
} catch ( RateLimitException e ) {
System . err . println ( "Rate limit exceeded: " + e . getMessage ());
// SDK automatically retries with backoff
} catch ( InternalServerException e ) {
System . err . println ( "Server error: " + e . getMessage ());
} catch ( DodoPaymentsServiceException e ) {
System . err . println ( "API error: " + e . statusCode () + " - " + e . getMessage ());
}
The SDK automatically retries requests on connection errors, 408, 409, 429, and 5xx errors with exponential backoff.
Async Operations
Use CompletableFuture for asynchronous operations:
import java.util.concurrent.CompletableFuture;
CompletableFuture < CheckoutSessionResponse > future = client . async ()
. checkoutSessions ()
. create (params);
// Handle response asynchronously
future . thenAccept (response -> {
System . out . println ( "Session created: " + response . sessionId ());
}). exceptionally (ex -> {
System . err . println ( "Error: " + ex . getMessage ());
return null ;
});
Spring Boot Integration
Configuration Class
import com.dodopayments.api.client.DodoPaymentsClient;
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ Configuration
public class DodoPaymentsConfig {
@ Value ( "${dodo.api.key}" )
private String apiKey ;
@ Value ( "${dodo.environment:sandbox}" )
private String environment ;
@ Bean
public DodoPaymentsClient dodoPayments () {
return DodoPaymentsOkHttpClient . builder ()
. bearerToken (apiKey)
. baseUrl ( environment . equals ( "live" )
? "https://live.dodopayments.com"
: "https://sandbox.dodopayments.com" )
. build ();
}
}
Service Layer
import com.dodopayments.api.client.DodoPaymentsClient;
import com.dodopayments.api.models.checkoutsessions. * ;
import org.springframework.stereotype.Service;
@ Service
public class PaymentService {
private final DodoPaymentsClient client ;
public PaymentService ( DodoPaymentsClient client ) {
this . client = client;
}
public CheckoutSessionResponse createCheckout ( List < ProductItemReq > items ) {
CheckoutSessionRequest params = CheckoutSessionRequest . builder ()
. productCart (items)
. returnUrl ( "https://yourdomain.com/return" )
. build ();
return client . checkoutSessions (). create (params);
}
}
Resources
GitHub Repository View source code and contribute
API Reference Complete API documentation
Discord Community Get help and connect with developers
Report Issues Report bugs or request features
Support
Need help with the Java SDK?
Contributing
We welcome contributions! Check the contributing guidelines to get started.