Skip to main content
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:
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:
build.gradle.kts
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:
.env
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

Configure Meters

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.