{"id":28837639,"url":"https://github.com/recurly/recurly-client-java","last_synced_at":"2026-02-06T22:04:35.697Z","repository":{"id":37833867,"uuid":"154865813","full_name":"recurly/recurly-client-java","owner":"recurly","description":"Java library for Recurly's V3 API ","archived":false,"fork":false,"pushed_at":"2025-12-12T21:02:11.000Z","size":2190,"stargazers_count":32,"open_issues_count":9,"forks_count":5,"subscribers_count":28,"default_branch":"v3-v2021-02-25","last_synced_at":"2026-02-03T10:17:33.950Z","etag":null,"topics":["java","recurly"],"latest_commit_sha":null,"homepage":"https://developers.recurly.com","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/recurly.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2018-10-26T16:49:55.000Z","updated_at":"2025-12-12T21:02:14.000Z","dependencies_parsed_at":"2023-11-07T16:35:20.569Z","dependency_job_id":"5bedae66-423f-4003-8348-fd79c2f4420d","html_url":"https://github.com/recurly/recurly-client-java","commit_stats":null,"previous_names":[],"tags_count":113,"template":false,"template_full_name":null,"purl":"pkg:github/recurly/recurly-client-java","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recurly%2Frecurly-client-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recurly%2Frecurly-client-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recurly%2Frecurly-client-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recurly%2Frecurly-client-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/recurly","download_url":"https://codeload.github.com/recurly/recurly-client-java/tar.gz/refs/heads/v3-v2021-02-25","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recurly%2Frecurly-client-java/sbom","scorecard":{"id":767326,"data":{"date":"2025-08-11","repo":{"name":"github.com/recurly/recurly-client-java","commit":"3e9770a71905a6cc7bee63eb5d8a348c3e6298c3"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.8,"checks":[{"name":"Code-Review","score":5,"reason":"Found 10/20 approved changesets -- score normalized to 5","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":"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":"Maintained","score":10,"reason":"15 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:18","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:19","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/codeql.yml:1","Warn: no topLevel permission defined: .github/workflows/pr-review.yml:1","Warn: no topLevel permission defined: .github/workflows/semgrep.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":"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":"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":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"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":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"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":"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/ci.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/recurly/recurly-client-java/ci.yml/v3-v2021-02-25?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/recurly/recurly-client-java/ci.yml/v3-v2021-02-25?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/recurly/recurly-client-java/codeql.yml/v3-v2021-02-25?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/recurly/recurly-client-java/codeql.yml/v3-v2021-02-25?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/recurly/recurly-client-java/codeql.yml/v3-v2021-02-25?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/recurly/recurly-client-java/codeql.yml/v3-v2021-02-25?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr-review.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/recurly/recurly-client-java/pr-review.yml/v3-v2021-02-25?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/semgrep.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/recurly/recurly-client-java/semgrep.yml/v3-v2021-02-25?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/semgrep.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/recurly/recurly-client-java/semgrep.yml/v3-v2021-02-25?enable=pin","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party 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":"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":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-2qp4-g3q3-f92w","Warn: Project is vulnerable to: GHSA-cqj8-47ch-rvvq"],"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":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (20) 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-23T01:11:43.445Z","repository_id":37833867,"created_at":"2025-08-23T01:11:43.445Z","updated_at":"2025-08-23T01:11:43.445Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29178578,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T20:14:21.878Z","status":"ssl_error","status_checked_at":"2026-02-06T20:14:21.443Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["java","recurly"],"created_at":"2025-06-19T12:42:17.533Z","updated_at":"2026-02-06T22:04:35.691Z","avatar_url":"https://github.com/recurly.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Recurly\n\n[![Maven Central](https://img.shields.io/static/v1?label=Maven%20Central\u0026message=recurly\u0026color=purple)](https://search.maven.org/artifact/com.recurly.v3/api-client)\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)\n\nThis repository houses the official java client for Recurly's V3 API.\n\n\u003e *Note*:\n\u003e If you were looking for a V2 client, we recommend the [open source KillBilling library](https://github.com/killbilling/recurly-java-library/).\n\nDocumentation for the HTTP API and example code can be found\n[on our Developer Portal](https://developers.recurly.com/api/v2019-10-10/).\n\n## Getting Started\n\n### Installing\n\nAs a Maven dependency:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.recurly.v3\u003c/groupId\u003e\n  \u003cartifactId\u003eapi-client\u003c/artifactId\u003e\n  \u003cversion\u003e5.12.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nGradle:\n\n```groovy\nimplementation 'com.recurly.v3:api-client:5.12.0'\n```\n\nYou can find further release and distribution details on\n[Maven Central](https://search.maven.org/artifact/com.recurly.v3/api-client/)\n\n\u003e *Note*: We try to follow [semantic versioning](https://semver.org/) and will only apply breaking changes to major versions.\n\n### Creating a client\n\nClient instances provide one place where every operation on the Recurly API can be found (rather than\nhaving them spread out amongst classes). A new client can be initialized with its constructor. It only requires\nan API key which can be obtained on the [API Credentials Page](https://app.recurly.com/go/integrations/api_keys).\n\n```java\nimport com.recurly.v3.Client;\nimport com.recurly.v3.resources.Subscription;\n\nString apiKey = \"83749879bbde395b5fe0cc1a5abf8e5\";\nfinal Client client = new Client(apiKey);\nfinal Subscription sub = client.getSubscription(\"uuid-abcd123456\");\n```\n\nTo access Recurly API in Europe, you will need to specify the EU Region in the `ClientOptions`:\n```java\nimport com.recurly.v3.Client;\nimport com.recurly.v3.resources.Subscription;\n\nString apiKey = \"83749879bbde395b5fe0cc1a5abf8e5\";\nfinal ClientOptions options = new ClientOptions();\noptions.setRegion(ClientOptions.Regions.EU);\nfinal Client client = new Client(apiKey, options);\nfinal Subscription sub = client.getSubscription(\"uuid-abcd123456\");\n```\n\n### Operations\n\nEvery operation that can be performed against the API has a corresponding method in the `Client` class.\n\n### Pagination\n\nPagination is accomplished using the `Pager\u003c\u003e` object. A pager is created by the `list*` operations of the client.\n`Pager` implements [`Iterable`](https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html), so it exposes\na `forEach` method and can be used with enhanced for loops and lambdas:\n\n```java\nPager\u003cAccount\u003e accounts = client.listAccounts(new QueryParams());\n\n// For loop\nfor (Account account : accounts) {\n    System.out.println(account.getCode());\n}\n\n// Lambda\naccounts.forEach(account -\u003e System.out.println(account.getCode()));\n```\n\nNote that the `Pager` implementation of `forEach` fetches the next page automatically. For more control over the\nfetching of the next page, it is possible to use the `getNextPage()` and `hasMore()` methods directly. In order\nto work with the `List` of data directly, it is accessible via the `getData()` method. We recommend using this\ninterface for writing scripts that iterate over many pages. This allows you to catch exceptions and safely retry\nwithout double processing or missing some elements:\n\n```java\nPager\u003cAccount\u003e accounts = client.listAccounts(new QueryParams());\n\nwhile (accounts.hasMore()) {\n    System.out.println(\"Fetching next page...\");\n    accounts.getNextPage();\n    for (Account acct : accounts.getData()) {\n        System.out.println(acct.getCode());\n    }\n}\n```\n\n#### Query Parameters\n\nEvery `List*` endpoint accepts a number of query parameters that allow you to sort or filter the results.\nThese can be set using the `QueryParams` object. This object contains the union of all parameters across every endpoint, and thus it's up to the programmer to determine which parameters are supported by the endpoint. You can find this list by looking at the `QUERY PARAMETERS` section of the endpoint's docs. For an example, see [list_account](https://developers.recurly.com/api/latest#operation/list_accounts).\n\n```java\nQueryParams params = new QueryParams();\nparams.setBeginTime(new DateTime(2020, 1, 1, 0, 0)); // midnight, Jan 1, 2020 UTC\nparams.setEndTime(new DateTime(2020, 6, 1, 0, 0)); // midnight, June 1, 2020 UTC\nparams.setSort(\"created_at\"); // sort by `created_at` property\nparams.setOrder(\"asc\"); // \"ascending\" order\nparams.setSubscriber(new Boolean(true)); // must be a subscriber\nparams.setLimit(200); // Fetch 200 records per page\nPager\u003cAccount\u003e accounts = client.listAccounts(params);\n\nfor (Account acct : accounts) {\n    System.out.println(acct.getCode());\n}\n```\n\n#### Additional Pager Methods\n\nIn addition to the methods to facilitate pagination, the Pager class provides 2 helper methods:\n\n1. getFirst\n2. getCount\n\n##### First\n\nThe Pager's `getFirst` method can be used to fetch only the first resource from the endpoint for the given QueryParams.\n\n```java\nQueryParams params = new QueryParams();\nparams.setBeginTime(new DateTime(2020, 1, 1, 0, 0));\nPager\u003cAccount\u003e accounts = client.listAccounts(params);\n// Get the first Account created in 2020 UTC\nAccount account = accounts.getFirst();\nSystem.out.println(account.getCode());\n```\n\n##### Count\n\nThe Pager's `getCount` method will return the total number of resources that are available at the requested endpoint for the given QueryParams.\n\n```java\nDateTime beginTime = new DateTime(2020, 1, 1, 0, 0);\nQueryParams params = new QueryParams();\nparams.setBeginTime(beginTime);\nPager\u003cAccount\u003e accounts = client.listAccounts(params);\nint total = accounts.getCount();\nSystem.out.println(\"There are \" + total + \" accounts since \" + beginTime);\n```\n\n### Creating Resources\n\nEvery `create*` and `update*` method on the client takes a `Request` object that forms the request. This allows you\nto create requests in a type-safe manner. Request types are not necessarily 1-to-1 mappings of response types.\n\n```java\nimport com.recurly.v3.requests.AccountCreate;\nimport com.recurly.v3.requests.Address;\nimport com.recurly.v3.resources.Account;\n\nfinal AccountCreate accountReq = new AccountCreate();\nfinal Address address = new Address();\n\naccountReq.setCode(\"myaccountcode\");\naccountReq.setFirstName(\"Aaron\");\naccountReq.setLastName(\"Du Monde\");\n\naddress.setStreet1(\"900 Camp St.\");\naddress.setCity(\"New Orleans\");\naddress.setRegion(\"LA\");\naddress.setCountry(\"US\");\naddress.setPostalCode(\"70115\");\n\naccountReq.setAddress(address);\n\n// createAccount takes an AccountCreate object and returns an Account object\nfinal Account account = client.createAccount(accountReq);\nSystem.out.println(account.getAddress().getCity()); // New Orleans\n```\n\n### Error Handling\n\nThis library throws two types of unchecked exceptions. They both subclass from `RecurlyException`:\n\n1. `ApiException`\n2. `NetworkException`\n\n`ApiException` is thrown when the Recurly API responds with an error. Each endpoint in the reference documentation describes\nthe types of errors it may return. These errors generally mean that something was wrong with the request. There are a number\nof subclasses to `ApiException` which are derived from the error responses `type` json key. A common scenario might be\na `ValidationException`:\n\n```java\nimport com.recurly.v3.requests.AccountCreate;\nimport com.recurly.v3.exception.ValidationException;\nimport com.recurly.v3.ApiException;\n\ntry {\n    final AccountCreate accountReq = new AccountCreate();\n    accountReq.setCode(\"myaccountcode\");\n\n    final Account account = client.createAccount(accountReq);\n} catch (ValidationException e) {\n    // Here we have a validation error and might want to\n    // pass this information back to the user to fix\n    System.out.println(\"Validation Error: \" + e.getError().getMessage());\n} catch (ApiException e) {\n    // Use the base ApiException to catch a generic error from the API\n    System.out.println(\"Unexpected Recurly Error: \" + e.getError().getMessage());\n}\n```\n\n`NetworkException`s don't come from Recurly's servers, but instead are triggered by some problem related to the network.\nDepending on the context, you can often automatically retry these calls. GETs are always safe to retry but be careful\nabout automatically re-trying any other call that might mutate state on the server side as we cannot guarantee that it\nwill not be executed twice.\n\n```java\nimport com.recurly.v3.resources.Account;\nimport com.recurly.v3.NetworkException;\n\ntry {\n    final Account account = client.getAccount(\"code-myaccountcode\");\n} catch (NetworkException e) {\n    // You may want to find out the root cause\n    System.out.println(e.getCause().getCause());\n} \n```\n## Support\n\nLooking for help? Please contact [support@recurly.com](mailto:support@recurly.com) or visit\n[support.recurly.com](https://support.recurly.com).\n\nIt's also acceptable to post a question, problem, or request as a GitHub issue on this repository and the developers\nwill try to get back to you in a timely manner.\n\n### Contributing\n\nPlease see our [Contributing Guide](CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frecurly%2Frecurly-client-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frecurly%2Frecurly-client-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frecurly%2Frecurly-client-java/lists"}