Note
We are trialing a Discord server for developers building with Chargebee. Limited spots are open on a first-come basis. Join here if interested.
This is the official Java library for integrating with Chargebee.
- 📘 For a complete reference of available APIs, check out our API Documentation.
- 🧪 To explore and test API capabilities interactively, head over to our API Explorer.
The versioning scheme of this library is inspired by SemVer and the format is v{MAJOR}.{MINOR}.{PATCH}. For example, v4.0.0 and v3.0.0 are valid library versions.
The following table provides some details for each major version:
| Library major version | Status | Compatible API versions | Branch |
|---|---|---|---|
| v4 | Active | v2 | v4 |
| v3 | Active | v2 | v3 |
| v2 | Inactive | v2 and v1 | chargebee-v2 |
| v1 | Inactive | v1 | chargebee-v1 |
A couple of terms used in the above table are explained below:
- Status: The current development status for the library version. Beta versions are feature-complete but may have breaking changes. Active major versions are currently being maintained and continue to get backward-compatible changes. Inactive versions no longer receive any updates.
- Branch: The branch in this repository containing the source code for the latest release of the library version. Every version of the library has been tagged. You can check out the source code for any version using its tag.
🔴 Attention: The support for v3 will eventually be discontinued on December 31st 2026 and will no longer receive any further updates. We strongly recommend upgrading to v4 as soon as possible. See our migration guide for detailed upgrade instructions.
💡 Rest assured: Your existing v3 integrations will continue to function indefinitely. After December 31st 2026, v3 will no longer receive updates for new API features, but all current functionality will remain operational.
📘 Looking for v3 SDK documentation? Please refer to the
v3branch for v3 SDK usage and documentation.
Note: See the changelog for a history of changes.
- Java 1.8 or later.
The SDK provides a modern, immutable client with enhanced type safety and improved developer experience.
dependencies {
implementation("com.chargebee:chargebee-java:{MAJOR}.{MINOR}.{PATCH}")
}<dependency>
<groupId>com.chargebee</groupId>
<artifactId>chargebee-java</artifactId>
<version>{MAJOR}.{MINOR}.{PATCH}</version>
</dependency>You can find the JAR files for the library in the dist directory. To obtain the JAR files for a specific library version, check the dist directory within the source tree of the appropriate tag.
Alternatively, you can build the JAR files by following the steps below:
- Checkout the appropriate version of the library source code.
git checkout {tagname}For example, the following is valid:
git checkout v4.0.0- Clean and build using Maven.
mvn clean packageimport com.chargebee.v4.client.ChargebeeClient;
ChargebeeClient client = ChargebeeClient.builder()
.apiKey("cb_test_...")
.siteName("acme")
.build();import com.chargebee.v4.services.CustomerService;
import com.chargebee.v4.models.customer.params.CustomerCreateParams;
import com.chargebee.v4.models.customer.params.CustomerListParams;
import com.chargebee.v4.models.customer.responses.CustomerCreateResponse;
import com.chargebee.v4.models.customer.responses.CustomerListResponse;
CustomerService customers = client.customers();
CustomerCreateResponse created = customers.create(
CustomerCreateParams.builder()
.firstName("Ada")
.lastName("Lovelace")
.email("ada@example.com")
.billingAddress(
CustomerCreateParams.BillingAddressParams.builder()
.line1("50 Market St")
.city("San Francisco")
.state("CA")
.zip("94105")
.country("US")
.build()
)
.build()
);
CustomerListResponse list = customers.list(
CustomerListParams.builder()
.limit(10)
.email().startsWith("ada@")
.build()
);import com.chargebee.v4.internal.RetryConfig;
ChargebeeClient client = ChargebeeClient.builder()
.apiKey("cb_test_...")
.siteName("acme")
.retry(
RetryConfig.builder()
.enabled(true)
.maxRetries(3)
.baseDelayMs(500)
.build()
)
.timeout(10000, 60000)
.debugLogging(true)
.build();import com.chargebee.v4.client.request.RequestOptions;
CustomerService scoped = client.customers().withOptions(
RequestOptions.builder()
.header("Idempotency-Key", "req-123")
.maxNetworkRetries(2)
.build()
);import java.util.concurrent.CompletableFuture;
import com.chargebee.v4.transport.Response;
CompletableFuture<Response> future = client.getAsync("/customers");
future.thenAccept(resp -> {
if (resp.isSuccessful()) {
System.out.println(resp.getBodyAsString());
}
});The library provides a comprehensive exception hierarchy with strongly-typed error enums to handle different types of errors that may occur during API operations.
All Chargebee exceptions extend from ChargebeeException, which is an unchecked exception:
ChargebeeException (unchecked - extends RuntimeException)
├── ConfigurationException (setup/config errors)
└── TransportException (runtime API errors)
├── NetworkException (DNS failures, connection refused)
├── TimeoutException (connect/read timeouts)
└── HttpException (HTTP status code errors: 4xx, 5xx)
├── ClientErrorException (4xx errors)
├── ServerErrorException (5xx errors)
└── APIException (Chargebee API errors)
├── InvalidRequestException (validation errors)
├── PaymentException (payment-related errors)
├── OperationFailedException (business logic errors)
├── BatchAPIException (batch operation errors)
└── UbbBatchIngestionInvalidRequestException (batch ingestion errors)
ChargebeeException: Base exception for all SDK errors - catch-all for any Chargebee SDK errorConfigurationException: Thrown when SDK configuration is invalid (missing API key, invalid URL, etc.)TransportException: Base exception for all transport-layer failures (network issues, timeouts, etc.)HttpException: Thrown for HTTP error status codes (4xx, 5xx) - contains status code and responseClientErrorException: HTTP 4xx client errors (bad request, unauthorized, not found, etc.)ServerErrorException: HTTP 5xx server errors (internal server error, service unavailable, etc.)APIException: Base exception for Chargebee API errors - includes error type, API error code, and parametersInvalidRequestException: Invalid parameters, missing required fields, or validation errors (type:invalid_request)PaymentException: Payment failures such as card declined, insufficient funds, etc. (type:payment)OperationFailedException: Business logic violations or state conflicts (type:operation_failed)BatchAPIException: Errors specific to batch API operationsUbbBatchIngestionInvalidRequestException: Errors specific to UBB batch ingestion operations
The SDK provides strongly-typed enums for error handling, making it easier to write type-safe error handling code:
Represents the type of error returned by the API:
import com.chargebee.v4.exceptions.ErrorType;
// Available values:
ErrorType.INVALID_REQUEST // Validation and request errors
ErrorType.PAYMENT // Payment-related errors
ErrorType.OPERATION_FAILED // Business logic errors
ErrorType.UNTYPED // Untyped errors
ErrorType._UNKNOWN // Unknown/new error types (forward compatibility)Each HTTP status code has its own enum with specific error codes:
| Enum | HTTP Status | Example Error Codes |
|---|---|---|
BadRequestApiErrorCode |
400 | DUPLICATE_ENTRY, INVALID_REQUEST, PAYMENT_PROCESSING_FAILED, PARAM_WRONG_VALUE |
UnauthorizedApiErrorCode |
401 | API_AUTHENTICATION_FAILED, BASIC_AUTHENTICATION_FAILED |
ForbiddenApiErrorCode |
403 | REQUEST_BLOCKED, API_AUTHORIZATION_FAILED |
NotFoundApiErrorCode |
404 | RESOURCE_NOT_FOUND, SITE_NOT_FOUND |
ConflictApiErrorCode |
409 | INVALID_STATE_FOR_REQUEST |
TooManyRequestsApiErrorCode |
429 | REQUEST_LIMIT_EXCEEDED, OPERATION_LIMIT_EXCEEDED |
InternalServerErrorApiErrorCode |
500 | INTERNAL_ERROR, INTERNAL_TEMPORARY_ERROR |
ServiceUnavailableApiErrorCode |
503 | SITE_NOT_READY, SITE_MIGRATING, SITE_UNDER_MAINTENANCE |
All enums include an _UNKNOWN value for forward compatibility when new error codes are added by the API.
import com.chargebee.v4.client.ChargebeeClient;
import com.chargebee.v4.exceptions.APIException;
import com.chargebee.v4.exceptions.PaymentException;
import com.chargebee.v4.exceptions.codes.ApiErrorCode;
import com.chargebee.v4.exceptions.codes.BadRequestApiErrorCode;
import com.chargebee.v4.models.customer.responses.CustomerCreateResponse;
import com.chargebee.v4.services.CustomerService;
import com.chargebee.v4.exceptions.*;
import com.chargebee.v4.models.customer.params.CustomerCreateParams;
CustomerService customers = client.customers();
try {
CustomerCreateResponse created = customers.create(
CustomerCreateParams.builder()
.email("invalid-email") // Invalid email format
.build()
);
} catch (InvalidRequestException e) {
// getApiErrorCode() returns a strongly-typed ApiErrorCode enum
ApiErrorCode errorCode = e.getApiErrorCode();
// Cast to specific enum based on HTTP status code
if (errorCode instanceof BadRequestApiErrorCode) {
BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;
if (code == BadRequestApiErrorCode.DUPLICATE_ENTRY) {
System.err.println("Resource already exists!");
} else if (code == BadRequestApiErrorCode.PARAM_WRONG_VALUE) {
System.err.println("Invalid parameter: " + e.getParams());
}
}
} catch (PaymentException e) {
ApiErrorCode errorCode = e.getApiErrorCode();
if (errorCode instanceof BadRequestApiErrorCode) {
BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;
if (code == BadRequestApiErrorCode.PAYMENT_PROCESSING_FAILED) {
System.err.println("Payment failed. Please try again.");
} else if (code == BadRequestApiErrorCode.PAYMENT_METHOD_NOT_PRESENT) {
System.err.println("No payment method on file.");
}
}
} catch (APIException e) {
// Handle other API errors
System.err.println("API error: " + e.getMessage());
System.err.println("Error type: " + e.getErrorType());
} catch (TransportException e) {
// Handle network/transport errors
System.err.println("Transport error: " + e.getMessage());
}try {
// API operation
} catch (APIException e) {
switch (e.getErrorType()) {
case INVALID_REQUEST:
System.err.println("Invalid request: " + e.getMessage());
break;
case PAYMENT:
System.err.println("Payment error: " + e.getMessage());
break;
case OPERATION_FAILED:
System.err.println("Operation failed: " + e.getMessage());
break;
default:
System.err.println("Unknown error type: " + e.getType());
}
}import com.chargebee.v4.exceptions.*;
import com.chargebee.v4.exceptions.codes.ApiErrorCode;
import com.chargebee.v4.exceptions.codes.BadRequestApiErrorCode;
try {
client.subscriptions().create(params);
} catch (APIException e) {
ApiErrorCode errorCode = e.getApiErrorCode();
// Check if it's a BadRequest error code
if (errorCode instanceof BadRequestApiErrorCode) {
BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;
switch (code) {
case DUPLICATE_ENTRY:
System.err.println("Resource already exists");
break;
case RESOURCE_LIMIT_EXHAUSTED:
System.err.println("Limit reached, please upgrade your plan");
break;
case PAYMENT_PROCESSING_FAILED:
System.err.println("Payment failed, please update payment method");
break;
case _UNKNOWN:
// Unknown error code - use raw value for logging
System.err.println("Unknown error code: " + e.getApiErrorCodeRaw());
break;
default:
System.err.println("Error: " + e.getMessage());
}
}
}try {
// API operation
} catch (APIException e) {
ErrorType errorType = e.getErrorType();
if (!errorType.isKnown()) {
// New error type added by API that SDK doesn't know about yet
System.err.println("New error type encountered: " + e.getType());
// Log for investigation, but handle gracefully
}
ApiErrorCode errorCode = e.getApiErrorCode();
if (errorCode != null && !errorCode.isKnown()) {
// New error code - handle gracefully using raw value
System.err.println("New error code: " + e.getApiErrorCodeRaw());
}
}import com.chargebee.v4.exceptions.ClientErrorException;
import com.chargebee.v4.exceptions.ServerErrorException;
import com.chargebee.v4.exceptions.HttpException;
try {
CustomerCreateResponse response = client.customers().create(params);
} catch (ClientErrorException e) {
// Handle 4xx client errors
if (e.isUnauthorized()) {
System.err.println("Authentication failed. Check your API key.");
} else if (e.isNotFound()) {
System.err.println("Resource not found.");
} else if (e.isTooManyRequests()) {
System.err.println("Rate limit exceeded. Retry after some time.");
} else {
System.err.println("Client error: " + e.getStatusCode());
}
} catch (ServerErrorException e) {
// Handle 5xx server errors (often retryable)
if (e.isRetryable()) {
System.err.println("Server error. Consider retrying: " + e.getMessage());
}
} catch (HttpException e) {
System.err.println("HTTP error: " + e.getStatusCode());
}
catch (Exception e) {
throw new RuntimeException(e);
}The APIException class provides typed access to all error response attributes:
| Attribute | Method | Description |
|---|---|---|
message |
getMessage() |
Descriptive error information (for developer consumption, not for end users) |
type |
getType() / getErrorType() |
Error type grouping: payment, invalid_request, operation_failed |
api_error_code |
getApiErrorCode() / getApiErrorCodeRaw() |
Strongly-typed enum (ApiErrorCode) or raw string for error handling |
param |
getParam() / getParams() |
Parameter name(s) if error is parameter-specific |
error_cause_id |
getErrorCauseId() |
Chargebee-defined code for standardizing errors across gateways |
try {
// API operation
} catch (APIException e) {
// Get HTTP status code
int statusCode = e.getStatusCode();
// Get error type as enum (type-safe)
ErrorType errorType = e.getErrorType();
// Get error type as raw string
String type = e.getType();
// Get API error code as typed enum
ApiErrorCode apiErrorCode = e.getApiErrorCode();
// Get API error code as raw string (for logging)
String apiErrorCodeRaw = e.getApiErrorCodeRaw();
// Get error message (for developer consumption)
String message = e.getMessage();
// Get parameter name(s) that caused the error
String param = e.getParam(); // Single param (convenience)
List<String> params = e.getParams(); // All params
// Get error cause ID (for gateway error standardization)
String errorCauseId = e.getErrorCauseId();
// Get full JSON response for debugging
String jsonResponse = e.getJsonResponse();
// Get full HTTP response object
Response response = e.getResponse();
System.err.println("Error details: " + e.toString());
}try {
// Payment operation
} catch (PaymentException e) {
// error_cause_id helps standardize errors across different payment gateways
String errorCauseId = e.getErrorCauseId();
if (errorCauseId != null) {
// Use error_cause_id for consistent handling across gateways
System.err.println("Gateway error cause: " + errorCauseId);
}
// Check the specific API error code using typed enum
ApiErrorCode errorCode = e.getApiErrorCode();
if (errorCode instanceof BadRequestApiErrorCode) {
BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;
if (code == BadRequestApiErrorCode.PAYMENT_PROCESSING_FAILED) {
// Handle payment failure
}
}
}import java.util.concurrent.CompletableFuture;
CompletableFuture<CustomerCreateResponse> futureCustomer = customers.create(params);
futureCustomer
.thenAccept(customer -> {
System.out.println("Customer created: " + customer.getCustomer().getId());
})
.exceptionally(throwable -> {
if (throwable.getCause() instanceof InvalidRequestException) {
InvalidRequestException e = (InvalidRequestException) throwable.getCause();
ApiErrorCode errorCode = e.getApiErrorCode();
if (errorCode instanceof BadRequestApiErrorCode) {
BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;
if (code == BadRequestApiErrorCode.DUPLICATE_ENTRY) {
System.err.println("Customer already exists");
}
} else {
System.err.println("Validation error: " + e.getMessage());
}
} else if (throwable.getCause() instanceof APIException) {
APIException e = (APIException) throwable.getCause();
System.err.println("API error: " + e.getApiErrorCodeRaw());
} else {
System.err.println("Unexpected error: " + throwable.getMessage());
}
return null;
});Chargebee's SDK includes built-in retry logic to handle temporary network issues and server-side errors. This feature is disabled by default but can be enabled when needed.
- Automatic retries for specific HTTP status codes: Retries are automatically triggered for status codes
500,502,503, and504. - Exponential backoff: Retry delays increase exponentially to prevent overwhelming the server.
- Rate limit management: If a
429 Too Many Requestsresponse is received with aRetry-Afterheader, the SDK waits for the specified duration before retrying.Note: Exponential backoff and max retries do not apply in this case.
- Customizable retry behavior: Retry logic can be configured using the
retryConfigparameter in the environment configuration.
You can enable and configure the retry logic by passing a retryConfig object when initializing the Chargebee environment:
import com.chargebee.Environment;
public class Sample {
public static void main(String[] args) throws Exception {
Environment.configure("{site}", "{site_api_key}");
Environment.defaultConfig().updateRetryConfig(
new com.chargebee.internal.RetryConfig(
true,
3,
500,
new java.util.HashSet<>(java.util.Arrays.asList(500))
)
);
// ... your Chargebee API operations ...
}
}
You can enable and configure the retry logic for rate-limit by passing a retryConfig object when initializing the Chargebee environment:
import com.chargebee.Environment;
public class Sample {
public static void main(String[] args) throws Exception {
Environment.configure("{site}", "{site_api_key}");
Environment.defaultConfig().updateRetryConfig(
new com.chargebee.internal.RetryConfig(
true,
3,
500,
new java.util.HashSet<>(java.util.Arrays.asList(429))
)
);
// ... your Chargebee API operations ...
}
}- Immutable
ChargebeeClientwith fluent builder - Direct property naming (e.g.,
.apiKey(),.siteName()) - Type-safe request models and responses
- Sync and async APIs with retry/backoff
- Per-request options and headers
- Enhanced error handling and debugging
- Java 8+
./gradlew build- Build project./gradlew test- Run tests
If you're using ProGuard or R8, add the following rules to prevent the SDK from being obfuscated:
# Chargebee SDK - preserve all public API classes and models
-keep class com.chargebee.v4.** { *; }
-keepclassmembers class com.chargebee.v4.** { *; }
# Keep all enum values
-keepclassmembers enum com.chargebee.v4.** { *; }
These rules ensure that reflection-based serialization/deserialization and the exception hierarchy work correctly at runtime.
You may contribute patches to any of the Active versions of this library. To do so, raise a PR against the respective branch.
If you find something amiss, you are welcome to create an issue.
- Migration Guide - Upgrade instructions between versions
The API documentation for the Java library can be found in our API reference.
See the LICENSE.