{"id":28254939,"url":"https://github.com/chargebee/chargebee-java","last_synced_at":"2026-06-15T11:00:35.953Z","repository":{"id":2929585,"uuid":"3940850","full_name":"chargebee/chargebee-java","owner":"chargebee","description":"Java library for the Chargebee API.","archived":false,"fork":false,"pushed_at":"2026-06-02T08:21:58.000Z","size":841633,"stargazers_count":33,"open_issues_count":19,"forks_count":28,"subscribers_count":40,"default_branch":"v4","last_synced_at":"2026-06-02T09:21:55.881Z","etag":null,"topics":["chargebee","java"],"latest_commit_sha":null,"homepage":"https://apidocs.chargebee.com/docs/api?lang=java","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chargebee.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2012-04-05T14:59:06.000Z","updated_at":"2026-06-02T08:20:43.000Z","dependencies_parsed_at":"2023-10-17T12:10:01.638Z","dependency_job_id":"12c03bff-bb8d-4a48-a6e9-9f763370a690","html_url":"https://github.com/chargebee/chargebee-java","commit_stats":null,"previous_names":[],"tags_count":278,"template":false,"template_full_name":null,"purl":"pkg:github/chargebee/chargebee-java","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chargebee%2Fchargebee-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chargebee%2Fchargebee-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chargebee%2Fchargebee-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chargebee%2Fchargebee-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chargebee","download_url":"https://codeload.github.com/chargebee/chargebee-java/tar.gz/refs/heads/v4","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chargebee%2Fchargebee-java/sbom","scorecard":{"id":274115,"data":{"date":"2025-08-11","repo":{"name":"github.com/chargebee/chargebee-java","commit":"45b76584f287b83084950d3cab434db4f558fec1"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/maven.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":5,"reason":"7 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":7,"reason":"binaries present in source code","details":["Warn: binary detected: dist/chargebee-java-3.34.0-javadoc.jar:1","Warn: binary detected: dist/chargebee-java-3.34.0-sources.jar:1","Warn: binary detected: dist/chargebee-java-3.34.0.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 2/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/maven.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/chargebee/chargebee-java/maven.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/maven.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/chargebee/chargebee-java/maven.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":5,"reason":"SAST tool is not run on all commits -- score normalized to 5","details":["Warn: 1 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T14:03:01.530Z","repository_id":2929585,"created_at":"2025-08-17T14:03:01.530Z","updated_at":"2025-08-17T14:03:01.530Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34357285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chargebee","java"],"created_at":"2025-05-19T20:16:31.116Z","updated_at":"2026-06-15T11:00:35.916Z","avatar_url":"https://github.com/chargebee.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Chargebee Java Client Library\n\n\u003e [!NOTE]\n\u003e [![Join Discord](https://img.shields.io/badge/Discord-Early%20Access-blue?logo=discord\u0026logoColor=white)](https://discord.gg/gpsNqnhDm2)\n\u003e\n\u003e We are trialing a Discord server for developers building with Chargebee. Limited spots are open on a first-come basis. Join [here](https://discord.gg/gpsNqnhDm2) if interested.\n\nThis is the official Java library for integrating with Chargebee.\n\n- 📘 For a complete reference of available APIs, check out our [API Documentation](https://apidocs.chargebee.com/docs/api/?lang=java).  \n- 🧪 To explore and test API capabilities interactively, head over to our [API Explorer](https://api-explorer.chargebee.com).\n\n## Library versions\n***\n\nThe versioning scheme of this library is inspired by [SemVer](https://semver.org/) and the format is `v{MAJOR}.{MINOR}.{PATCH}`. For example, `v4.0.0` and `v3.0.0` are valid library versions.\n\nThe following table provides some details for each major version:\n\n| Library major version | Status   | Compatible API versions                                                                                               | **Branch**        |\n|----------------------------|----------|-----------------------------------------------------------------------------------------------------------------------|---------------|\n| v4                         | Active   | [v2](https://apidocs.chargebee.com/docs/api/?lang=java) | `v4`      |\n| v3                         | Active   | [v2](https://apidocs.chargebee.com/docs/api/?lang=java) | `v3`|\n| v2                         | Inactive | [v2](https://apidocs.chargebee.com/docs/api/?lang=java) and [v1](https://apidocs.chargebee.com/docs/api/v1?lang=java) | `chargebee-v2`|\n| v1                         | Inactive | [v1](https://apidocs.chargebee.com/docs/api/v1?lang=java)                                                             | `chargebee-v1`|\n\nA couple of terms used in the above table are explained below:\n- **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.\n- **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](https://github.com/chargebee/chargebee-java/tags). You can check out the source code for any version using its tag.\n\n🔴 **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](https://github.com/chargebee/chargebee-java/wiki/Migration-guide-for-V4) for detailed upgrade instructions.\n\n\u003e 💡 **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.\n\n\u003e 📘 **Looking for v3 SDK documentation?** Please refer to the [`v3`](https://github.com/chargebee/chargebee-java/tree/v3) branch for v3 SDK usage and documentation.\n\n**Note:** See the [changelog](CHANGELOG.md) for a history of changes.\n\n## Install the library\n***\n\n### Requirement\n***\n* Java 1.8 or later.\n\n### Installation\n***\n\nThe SDK provides a modern, immutable client with enhanced type safety and improved developer experience.\n\n#### Gradle (Kotlin DSL)\n```kotlin\ndependencies {\n    implementation(\"com.chargebee:chargebee-java:{MAJOR}.{MINOR}.{PATCH}\")\n}\n```\n\n#### Maven\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.chargebee\u003c/groupId\u003e\n  \u003cartifactId\u003echargebee-java\u003c/artifactId\u003e\n  \u003cversion\u003e{MAJOR}.{MINOR}.{PATCH}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Dependencies\n\nThe Chargebee Java SDK uses [Gson](https://github.com/google/gson) `2.13.2` for JSON processing. Gson is declared as a regular dependency of the SDK and is therefore included transitively when the SDK is added to a project.\n\n#### Gson version conflicts\n\nProjects that already depend on a different version of Gson may encounter version conflicts. The build tool resolves a single version based on its dependency resolution strategy, which can lead to mismatches.\n\n**Gradle** selects the highest version by default. If the project uses an older Gson version, Gradle will resolve to the highest version (`2.13.2`) by default. To pin a specific version:\n\n```kotlin\nconfigurations.all {\n    resolutionStrategy {\n        force(\"com.google.code.gson:gson:2.13.2\")\n    }\n}\n```\n\n**Maven** uses the nearest-wins strategy, meaning a direct dependency declared in the project takes precedence over the SDK's transitive dependency. If an older version is declared directly, it will override the SDK's version. To align versions, either upgrade the direct dependency or use `\u003cdependencyManagement\u003e`:\n\n```xml\n\u003cdependencyManagement\u003e\n    \u003cdependencies\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003ecom.google.code.gson\u003c/groupId\u003e\n            \u003cartifactId\u003egson\u003c/artifactId\u003e\n            \u003cversion\u003e2.13.2\u003c/version\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n\u003c/dependencyManagement\u003e\n```\n\n**Minimum compatible Gson version**: `2.8.6`. The SDK relies on `JsonParser.parseString()`, which was introduced in Gson 2.8.6. Versions older than 2.8.6 will cause a `NoSuchMethodError` at runtime.\n\n**Recommended**: Gson `2.10.1` or later is recommended for best compatibility. Projects unable to upgrade should verify that the resolved Gson version is at least `2.8.6`.\n\n### Install JAR files\n***\n\n#### Obtain pre-built JAR files\n***\n\nYou can find the JAR files for the library in the [`dist`](dist) directory. To obtain the JAR files for a specific library version, check the `dist` directory within the source tree of the appropriate [tag](https://github.com/chargebee/chargebee-java/tags).\n\n#### Build JAR files\n***\n\nAlternatively, you can build the JAR files by following the steps below:\n\n1. Checkout the appropriate version of the library source code.\n```shell\ngit checkout {tagname}\n```\nFor example, the following is valid:\n```shell\ngit checkout v4.0.0\n```\n\n2. Clean and build using Maven.\n```shell\nmvn clean package\n```\n\n## Use the library\n***\n\n### Quick Start\n\n#### Create a client\n```java\nimport com.chargebee.v4.client.ChargebeeClient;\n\nChargebeeClient client = ChargebeeClient.builder()\n    .apiKey(\"cb_test_...\")\n    .siteName(\"acme\")\n    .build();\n```\n\n#### Create and list customers (sync)\n```java\nimport com.chargebee.v4.services.CustomerService;\nimport com.chargebee.v4.models.customer.params.CustomerCreateParams;\nimport com.chargebee.v4.models.customer.params.CustomerListParams;\nimport com.chargebee.v4.models.customer.responses.CustomerCreateResponse;\nimport com.chargebee.v4.models.customer.responses.CustomerListResponse;\n\nCustomerService customers = client.customers();\n\nCustomerCreateResponse created = customers.create(\n    CustomerCreateParams.builder()\n        .firstName(\"Ada\")\n        .lastName(\"Lovelace\")\n        .email(\"ada@example.com\")\n        .billingAddress(\n            CustomerCreateParams.BillingAddressParams.builder()\n                .line1(\"50 Market St\")\n                .city(\"San Francisco\")\n                .state(\"CA\")\n                .zip(\"94105\")\n                .country(\"US\")\n                .build()\n        )\n        .build()\n);\n\nCustomerListResponse list = customers.list(\n    CustomerListParams.builder()\n        .limit(10)\n        .email().startsWith(\"ada@\")\n        .build()\n);\n```\n\n#### Configure client with retries and timeouts\n```java\nimport com.chargebee.v4.internal.RetryConfig;\n\nChargebeeClient client = ChargebeeClient.builder()\n    .apiKey(\"cb_test_...\")\n    .siteName(\"acme\")\n    .retry(\n        RetryConfig.builder()\n            .enabled(true)\n            .maxRetries(3)\n            .baseDelayMs(500)\n            .build()\n    )\n    .timeout(10000, 60000)\n    .debugLogging(true)\n    .build();\n```\n\n#### Per-request options\n```java\nimport com.chargebee.v4.client.request.RequestOptions;\n\nCustomerService scoped = client.customers().withOptions(\n    RequestOptions.builder()\n        .header(\"Idempotency-Key\", \"req-123\")\n        .maxNetworkRetries(2)\n        .build()\n);\n```\n\n#### Async support\n```java\nimport java.util.concurrent.CompletableFuture;\nimport com.chargebee.v4.transport.Response;\n\nCompletableFuture\u003cResponse\u003e future = client.getAsync(\"/customers\");\nfuture.thenAccept(resp -\u003e {\n    if (resp.isSuccessful()) {\n        System.out.println(resp.getBodyAsString());\n    }\n});\n```\n\n### Dynamic map fields (`Map\u003cString, Object\u003e`)\n\nSome attributes are returned as `Map\u003cString, Object\u003e` for schema-less JSON (for example `HostedPage.getContent()`, `HostedPage.getCheckoutInfo()`, `Event.getContent()`, `meta_data`). Nested JSON objects become `Map`, and nested JSON arrays become `List`:\n\n```java\nMap\u003cString, Object\u003e content = client.hostedPages().retrieve(hostedPageId).getHostedPage().getContent();\n\n@SuppressWarnings(\"unchecked\")\nMap\u003cString, Object\u003e subscription = (Map\u003cString, Object\u003e) content.get(\"subscription\");\nString subscriptionId = (String) subscription.get(\"id\");\n```\n\nEvery model exposes a `fromJson(Map\u003cString, Object\u003e)` overload, so a nested entity can be converted into a typed model by passing the map directly—no JSON string round-trip needed:\n\n```java\nSubscription typedSubscription = Subscription.fromJson(subscription);\n```\n\n### Custom Field Filtering\n\nFilter list operations by custom fields using type-safe filters (`stringFilter()`, `numberFilter()`, `timestampFilter()`, `booleanFilter()`):\n\n```java\nCustomerListParams params = CustomerListParams.builder()\n    .customField(\"cf_plan_tier\").stringFilter().in(\"gold\", \"platinum\")\n    .customField(\"cf_is_vip\").booleanFilter().is(true)\n    .customField(\"cf_total_spent\").numberFilter().gte(5000L)\n    .build();\n\nCustomerListResponse response = client.customers().list(params);\n```\n\n### Exception Handling\n\nThe library provides a comprehensive exception hierarchy with **strongly-typed error enums** to handle different types of errors that may occur during API operations.\n\n#### Exception Hierarchy\n\nAll Chargebee exceptions extend from `ChargebeeException`, which is an unchecked exception:\n\n```\nChargebeeException (unchecked - extends RuntimeException)\n├── ConfigurationException (setup/config errors)\n└── TransportException (runtime API errors)\n      ├── NetworkException (DNS failures, connection refused)\n      ├── TimeoutException (connect/read timeouts)\n      └── HttpException (HTTP status code errors: 4xx, 5xx)\n            ├── ClientErrorException (4xx errors)\n            ├── ServerErrorException (5xx errors)\n            └── APIException (Chargebee API errors)\n                  ├── InvalidRequestException (validation errors)\n                  ├── PaymentException (payment-related errors)\n                  ├── OperationFailedException (business logic errors)\n                  ├── BatchAPIException (batch operation errors)\n                  └── UbbBatchIngestionInvalidRequestException (batch ingestion errors)\n```\n\n#### Exception Types\n\n- **`ChargebeeException`**: Base exception for all SDK errors - catch-all for any Chargebee SDK error\n- **`ConfigurationException`**: Thrown when SDK configuration is invalid (missing API key, invalid URL, etc.)\n- **`TransportException`**: Base exception for all transport-layer failures (network issues, timeouts, etc.)\n- **`HttpException`**: Thrown for HTTP error status codes (4xx, 5xx) - contains status code and response\n- **`ClientErrorException`**: HTTP 4xx client errors (bad request, unauthorized, not found, etc.)\n- **`ServerErrorException`**: HTTP 5xx server errors (internal server error, service unavailable, etc.)\n- **`APIException`**: Base exception for Chargebee API errors - includes error type, API error code, and parameters\n- **`InvalidRequestException`**: Invalid parameters, missing required fields, or validation errors (type: `invalid_request`)\n- **`PaymentException`**: Payment failures such as card declined, insufficient funds, etc. (type: `payment`)\n- **`OperationFailedException`**: Business logic violations or state conflicts (type: `operation_failed`)\n- **`BatchAPIException`**: Errors specific to batch API operations\n- **`UbbBatchIngestionInvalidRequestException`**: Errors specific to UBB batch ingestion operations\n\n#### Strongly-Typed Error Enums\n\nThe SDK provides strongly-typed enums for error handling, making it easier to write type-safe error handling code:\n\n##### ErrorType Enum\nRepresents the type of error returned by the API:\n```java\nimport com.chargebee.v4.exceptions.ErrorType;\n\n// Available values:\nErrorType.INVALID_REQUEST   // Validation and request errors\nErrorType.PAYMENT           // Payment-related errors  \nErrorType.OPERATION_FAILED  // Business logic errors\nErrorType.UNTYPED           // Untyped errors\nErrorType._UNKNOWN          // Unknown/new error types (forward compatibility)\n```\n\n##### Per-HTTP-Status API Error Code Enums\nEach HTTP status code has its own enum with specific error codes:\n\n| Enum | HTTP Status | Example Error Codes |\n|------|-------------|---------------------|\n| `BadRequestApiErrorCode` | 400 | `DUPLICATE_ENTRY`, `INVALID_REQUEST`, `PAYMENT_PROCESSING_FAILED`, `PARAM_WRONG_VALUE` |\n| `UnauthorizedApiErrorCode` | 401 | `API_AUTHENTICATION_FAILED`, `BASIC_AUTHENTICATION_FAILED` |\n| `ForbiddenApiErrorCode` | 403 | `REQUEST_BLOCKED`, `API_AUTHORIZATION_FAILED` |\n| `NotFoundApiErrorCode` | 404 | `RESOURCE_NOT_FOUND`, `SITE_NOT_FOUND` |\n| `ConflictApiErrorCode` | 409 | `INVALID_STATE_FOR_REQUEST` |\n| `TooManyRequestsApiErrorCode` | 429 | `REQUEST_LIMIT_EXCEEDED`, `OPERATION_LIMIT_EXCEEDED` |\n| `InternalServerErrorApiErrorCode` | 500 | `INTERNAL_ERROR`, `INTERNAL_TEMPORARY_ERROR` |\n| `ServiceUnavailableApiErrorCode` | 503 | `SITE_NOT_READY`, `SITE_MIGRATING`, `SITE_UNDER_MAINTENANCE` |\n\nAll enums include an `_UNKNOWN` value for forward compatibility when new error codes are added by the API.\n\n#### Exception Handling Examples\n\n##### Basic exception handling with enums\n```java\nimport com.chargebee.v4.client.ChargebeeClient;\nimport com.chargebee.v4.exceptions.APIException;\nimport com.chargebee.v4.exceptions.PaymentException;\nimport com.chargebee.v4.exceptions.codes.ApiErrorCode;\nimport com.chargebee.v4.exceptions.codes.BadRequestApiErrorCode;\nimport com.chargebee.v4.models.customer.responses.CustomerCreateResponse;\nimport com.chargebee.v4.services.CustomerService;\n\nimport com.chargebee.v4.exceptions.*;\nimport com.chargebee.v4.models.customer.params.CustomerCreateParams;\n\nCustomerService customers = client.customers();\n\ntry {\n    CustomerCreateResponse created = customers.create(\n        CustomerCreateParams.builder()\n            .email(\"invalid-email\")  // Invalid email format\n            .build()\n    );\n} catch (InvalidRequestException e) {\n    // getApiErrorCode() returns a strongly-typed ApiErrorCode enum\n    ApiErrorCode errorCode = e.getApiErrorCode();\n    \n    // Cast to specific enum based on HTTP status code\n    if (errorCode instanceof BadRequestApiErrorCode) {\n        BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;\n        if (code == BadRequestApiErrorCode.DUPLICATE_ENTRY) {\n            System.err.println(\"Resource already exists!\");\n        } else if (code == BadRequestApiErrorCode.PARAM_WRONG_VALUE) {\n            System.err.println(\"Invalid parameter: \" + e.getParams());\n        }\n    }\n} catch (PaymentException e) {\n    ApiErrorCode errorCode = e.getApiErrorCode();\n    \n    if (errorCode instanceof BadRequestApiErrorCode) {\n        BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;\n        if (code == BadRequestApiErrorCode.PAYMENT_PROCESSING_FAILED) {\n            System.err.println(\"Payment failed. Please try again.\");\n        } else if (code == BadRequestApiErrorCode.PAYMENT_METHOD_NOT_PRESENT) {\n            System.err.println(\"No payment method on file.\");\n        }\n    }\n} catch (APIException e) {\n    // Handle other API errors\n    System.err.println(\"API error: \" + e.getMessage());\n    System.err.println(\"Error type: \" + e.getErrorType());\n} catch (TransportException e) {\n    // Handle network/transport errors\n    System.err.println(\"Transport error: \" + e.getMessage());\n}\n```\n\n##### Using switch with ErrorType enum\n```java\ntry {\n    // API operation\n} catch (APIException e) {\n    switch (e.getErrorType()) {\n        case INVALID_REQUEST:\n            System.err.println(\"Invalid request: \" + e.getMessage());\n            break;\n        case PAYMENT:\n            System.err.println(\"Payment error: \" + e.getMessage());\n            break;\n        case OPERATION_FAILED:\n            System.err.println(\"Operation failed: \" + e.getMessage());\n            break;\n        default:\n            System.err.println(\"Unknown error type: \" + e.getType());\n    }\n}\n```\n\n##### Handling specific error codes\n```java\nimport com.chargebee.v4.exceptions.*;\nimport com.chargebee.v4.exceptions.codes.ApiErrorCode;\nimport com.chargebee.v4.exceptions.codes.BadRequestApiErrorCode;\n\ntry {\n        client.subscriptions().create(params);\n} catch (APIException e) {\n    ApiErrorCode errorCode = e.getApiErrorCode();\n    \n    // Check if it's a BadRequest error code\n    if (errorCode instanceof BadRequestApiErrorCode) {\n        BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;\n        switch (code) {\n            case DUPLICATE_ENTRY:\n                System.err.println(\"Resource already exists\");\n                break;\n            case RESOURCE_LIMIT_EXHAUSTED:\n                System.err.println(\"Limit reached, please upgrade your plan\");\n                break;\n            case PAYMENT_PROCESSING_FAILED:\n                System.err.println(\"Payment failed, please update payment method\");\n                break;\n            case _UNKNOWN:\n                // Unknown error code - use raw value for logging\n                System.err.println(\"Unknown error code: \" + e.getApiErrorCodeRaw());\n                break;\n            default:\n                System.err.println(\"Error: \" + e.getMessage());\n        }\n    }\n}\n```\n\n##### Checking for unknown error types (forward compatibility)\n```java\ntry {\n    // API operation\n} catch (APIException e) {\n    ErrorType errorType = e.getErrorType();\n    \n    if (!errorType.isKnown()) {\n        // New error type added by API that SDK doesn't know about yet\n        System.err.println(\"New error type encountered: \" + e.getType());\n        // Log for investigation, but handle gracefully\n    }\n    \n    ApiErrorCode errorCode = e.getApiErrorCode();\n    if (errorCode != null \u0026\u0026 !errorCode.isKnown()) {\n        // New error code - handle gracefully using raw value\n        System.err.println(\"New error code: \" + e.getApiErrorCodeRaw());\n    }\n}\n```\n\n##### Handling HTTP-level errors\n```java\nimport com.chargebee.v4.exceptions.ClientErrorException;\nimport com.chargebee.v4.exceptions.ServerErrorException;\nimport com.chargebee.v4.exceptions.HttpException;\n\ntry {\n    CustomerCreateResponse response = client.customers().create(params);\n} catch (ClientErrorException e) {\n    // Handle 4xx client errors\n    if (e.isUnauthorized()) {\n        System.err.println(\"Authentication failed. Check your API key.\");\n    } else if (e.isNotFound()) {\n        System.err.println(\"Resource not found.\");\n    } else if (e.isTooManyRequests()) {\n        System.err.println(\"Rate limit exceeded. Retry after some time.\");\n    } else {\n        System.err.println(\"Client error: \" + e.getStatusCode());\n    }\n} catch (ServerErrorException e) {\n    // Handle 5xx server errors (often retryable)\n    if (e.isRetryable()) {\n        System.err.println(\"Server error. Consider retrying: \" + e.getMessage());\n    }\n} catch (HttpException e) {\n    System.err.println(\"HTTP error: \" + e.getStatusCode());\n}\ncatch (Exception e) {\n    throw new RuntimeException(e);\n}\n```\n\n##### Error Response Attributes\n\nThe `APIException` class provides typed access to all error response attributes:\n\n| Attribute | Method | Description |\n|-----------|--------|-------------|\n| `message` | `getMessage()` | Descriptive error information (for developer consumption, not for end users) |\n| `type` | `getType()` / `getErrorType()` | Error type grouping: `payment`, `invalid_request`, `operation_failed` |\n| `api_error_code` | `getApiErrorCode()` / `getApiErrorCodeRaw()` | Strongly-typed enum (`ApiErrorCode`) or raw string for error handling |\n| `param` | `getParam()` / `getParams()` | Parameter name(s) if error is parameter-specific |\n| `error_cause_id` | `getErrorCauseId()` | Chargebee-defined code for standardizing errors across gateways |\n\n##### Extracting detailed error information\n```java\ntry {\n    // API operation\n} catch (APIException e) {\n    // Get HTTP status code\n    int statusCode = e.getStatusCode();\n    \n    // Get error type as enum (type-safe)\n    ErrorType errorType = e.getErrorType();\n    \n    // Get error type as raw string\n    String type = e.getType();\n    \n    // Get API error code as typed enum\n    ApiErrorCode apiErrorCode = e.getApiErrorCode();\n    \n    // Get API error code as raw string (for logging)\n    String apiErrorCodeRaw = e.getApiErrorCodeRaw();\n    \n    // Get error message (for developer consumption)\n    String message = e.getMessage();\n    \n    // Get parameter name(s) that caused the error\n    String param = e.getParam();           // Single param (convenience)\n    List\u003cString\u003e params = e.getParams();   // All params\n    \n    // Get error cause ID (for gateway error standardization)\n    String errorCauseId = e.getErrorCauseId();\n    \n    // Get full JSON response for debugging\n    String jsonResponse = e.getJsonResponse();\n    \n    // Get full HTTP response object\n    Response response = e.getResponse();\n    \n    System.err.println(\"Error details: \" + e.toString());\n}\n```\n\n##### Handling gateway errors with error_cause_id\n```java\ntry {\n    // Payment operation\n} catch (PaymentException e) {\n    // error_cause_id helps standardize errors across different payment gateways\n    String errorCauseId = e.getErrorCauseId();\n    \n    if (errorCauseId != null) {\n        // Use error_cause_id for consistent handling across gateways\n        System.err.println(\"Gateway error cause: \" + errorCauseId);\n        \n    }\n    \n    // Check the specific API error code using typed enum\n    ApiErrorCode errorCode = e.getApiErrorCode();\n    if (errorCode instanceof BadRequestApiErrorCode) {\n        BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;\n        if (code == BadRequestApiErrorCode.PAYMENT_PROCESSING_FAILED) {\n            // Handle payment failure\n        }\n    }\n}\n```\n\n##### Async exception handling\n\n\u003e **Important:** When using async methods, exceptions are wrapped in a `java.util.concurrent.CompletionException`.\n\u003e Unlike sync methods that throw `ChargebeeException` directly, async methods deliver errors through\n\u003e `CompletableFuture`'s `.exceptionally()` or `.handle()` callbacks, where the original exception is\n\u003e available via `throwable.getCause()`. Always unwrap the `CompletionException` to access the\n\u003e underlying `ChargebeeException` (e.g., `InvalidRequestException`, `APIException`).\n\n```java\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.CompletionException;\n\nCompletableFuture\u003cCustomerCreateResponse\u003e futureCustomer = customers.createAsync(params);\n\nfutureCustomer\n    .thenAccept(response -\u003e {\n        System.out.println(\"Customer created: \" + response.getCustomer().getId());\n    })\n    .exceptionally(throwable -\u003e {\n        // Unwrap CompletionException to get the actual ChargebeeException\n        Throwable cause = throwable instanceof CompletionException\n            ? throwable.getCause()\n            : throwable;\n\n        if (cause instanceof InvalidRequestException) {\n            InvalidRequestException e = (InvalidRequestException) cause;\n            ApiErrorCode errorCode = e.getApiErrorCode();\n\n            if (errorCode instanceof BadRequestApiErrorCode) {\n                BadRequestApiErrorCode code = (BadRequestApiErrorCode) errorCode;\n                if (code == BadRequestApiErrorCode.DUPLICATE_ENTRY) {\n                    System.err.println(\"Customer already exists\");\n                }\n            } else {\n                System.err.println(\"Validation error: \" + e.getMessage());\n            }\n        } else if (cause instanceof APIException) {\n            APIException e = (APIException) cause;\n            System.err.println(\"API error: \" + e.getApiErrorCodeRaw());\n        } else {\n            System.err.println(\"Unexpected error: \" + cause.getMessage());\n        }\n        return null;\n    });\n```\n\nIf you prefer blocking on the result, use a try-catch around `.join()` or `.get()`:\n\n```java\ntry {\n    CustomerCreateResponse response = customers.createAsync(params).join();\n    System.out.println(\"Customer created: \" + response.getCustomer().getId());\n} catch (CompletionException e) {\n    // Unwrap to get the original ChargebeeException\n    Throwable cause = e.getCause();\n    if (cause instanceof InvalidRequestException) {\n        System.err.println(\"Validation error: \" + cause.getMessage());\n    } else if (cause instanceof APIException) {\n        System.err.println(\"API error: \" + ((APIException) cause).getApiErrorCodeRaw());\n    } else {\n        throw e; // Re-throw unexpected errors\n    }\n}\n```\n\n### Retry Handling\n\nChargebee'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**.\n\n#### Key features include:\n\n- **Automatic retries for specific HTTP status codes**: Retries are automatically triggered for status codes `500`, `502`, `503`, and `504`.\n- **Exponential backoff**: Retry delays increase exponentially to prevent overwhelming the server.\n- **Rate limit management**: If a `429 Too Many Requests` response is received with a `Retry-After` header, the SDK waits for the specified duration before retrying.\n  \u003e *Note: Exponential backoff and max retries do not apply in this case.*\n- **Customizable retry behavior**: Retry logic can be configured using the `retryConfig` parameter in the environment configuration.\n\n#### Example: Customizing Retry Logic\n\nYou can enable and configure the retry logic by passing a `retryConfig` object when initializing the Chargebee environment:\n\n```java\nimport com.chargebee.Environment;\npublic class Sample {\n    public static void main(String[] args) throws Exception {\n        Environment.configure(\"{site}\", \"{site_api_key}\");\n        Environment.defaultConfig().updateRetryConfig(\n            new com.chargebee.internal.RetryConfig(\n                true,\n                3,\n                500,\n                new java.util.HashSet\u003c\u003e(java.util.Arrays.asList(500))\n            )\n        );\n        // ... your Chargebee API operations ...\n    }\n }\n \n```\n\n#### Example: Rate Limit retry logic\n\nYou can enable and configure the retry logic for rate-limit by passing a `retryConfig` object when initializing the Chargebee environment:\n\n```java\nimport com.chargebee.Environment;\npublic class Sample {\n    public static void main(String[] args) throws Exception {\n        Environment.configure(\"{site}\", \"{site_api_key}\");\n        Environment.defaultConfig().updateRetryConfig(\n            new com.chargebee.internal.RetryConfig(\n                true,\n                3,\n                500,\n                new java.util.HashSet\u003c\u003e(java.util.Arrays.asList(429))\n            )\n        );\n        // ... your Chargebee API operations ...\n    }\n }\n```\n\n## Features\n\n### SDK Features\n- Immutable `ChargebeeClient` with fluent builder\n- Direct property naming (e.g., `.apiKey()`, `.siteName()`)\n- Type-safe request models and responses\n- Dynamic `Map\u003cString, Object\u003e` fields deserialize nested JSON as maps and lists (see [Dynamic map fields](#dynamic-map-fields-mapstring-object))\n- Sync and async APIs with retry/backoff\n- Per-request options and headers\n- Enhanced error handling and debugging\n\n## Build \u0026 Test\n- Java 8+\n- `./gradlew build` - Build project\n- `./gradlew test` - Run tests\n\n## ProGuard / R8 Configuration\n\nIf you're using ProGuard or R8, add the following rules to prevent the SDK from being obfuscated:\n\n```proguard\n# Chargebee SDK - preserve all public API classes and models\n-keep class com.chargebee.v4.** { *; }\n-keepclassmembers class com.chargebee.v4.** { *; }\n\n# Keep all enum values\n-keepclassmembers enum com.chargebee.v4.** { *; }\n```\n\nThese rules ensure that reflection-based serialization/deserialization and the exception hierarchy work correctly at runtime.\n\n## Contribution\n***\nYou may contribute patches to any of the **Active** versions of this library. To do so, raise a PR against the [respective branch](#library-versions). \n\nIf you find something amiss, you are welcome to create an [issue](https://github.com/chargebee/chargebee-java/issues).\n\n## Documentation\n***\n\n- [Migration Guide](https://github.com/chargebee/chargebee-java/wiki/Migration-guide-for-V4) - Upgrade instructions between versions\n\nThe API documentation for the Java library can be found in our [API reference](https://apidocs.chargebee.com/docs/api?lang=java).\n\n## License\n***\n\nSee the [LICENSE](LICENSE).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchargebee%2Fchargebee-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchargebee%2Fchargebee-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchargebee%2Fchargebee-java/lists"}