Why generate Apache Fineract API clients from the OpenAPI spec
An integration team that calls Fineract's REST API from Java or another language should generate typed clients from the OpenAPI specification rather than hand-build HTTP calls, provided the team will keep those clients aligned with each release. A generated client gives every endpoint, request model and response model a compile-time shape, so a renamed field or changed parameter shows up as a build failure instead of a production error. The OpenAPI 3.0.3 specification that ships with Fineract is the source of truth for that shape, and it is the artifact your team should version and review, not the generated code alone.
Generation pays off most when several services or teams call Fineract, when the integration covers many endpoints, or when the same calls must be made from more than one language. Fineract is headless, so there is no vendor UI to hide API details from integrators: your integration code is the client. It is also multi-tenant, which means every request carries a Fineract-Platform-TenantId header, and a well-designed generated client should make that header a required, explicit setting rather than something each call site remembers. For a one-off script that calls two endpoints, hand-written HTTP is usually the cheaper choice.
Confirm which spec version matches the Fineract instance you run. The Fineract website lists 1.15.0 as the current stable release, and the 1.x line is the maintained platform, since Fineract CN was archived without an official release. A client is only as current as the spec it was generated from, so an upgrade to a newer Fineract release means regenerating, diffing the API surface and retesting calls that depend on changed fields. Plan that regeneration as a recurring task with an owner, because the release cadence is quarterly and the generated code will not update itself.
Which client generation path fits your team
This table compares three ways to consume the Fineract API: the prebuilt or self-built fineract-client.jar, generated clients for other languages, and hand-written thin wrappers. Read each row against your team profile, then check the maintenance and cross-cutting handling columns before you commit to a path.
| Decision factor | Java client (fineract-client.jar) | Generated client for other languages | Hand-written thin wrapper |
|---|---|---|---|
| Team profile | Java services that call Fineract from a JVM codebase | Teams in Python, Go, TypeScript or .NET with a spare tooling owner | Small teams calling a few endpoints, such as repayments or client lookups |
| Source of the client | Built from the OpenAPI 3.0.3 specification for each release you run | Generated from the same specification with an OpenAPI generator you choose | Written by hand against the endpoints your integration uses |
| Maintenance cost | Rebuild and retest on each Fineract upgrade; the client must match your target release | Regenerate, review generator output and retest on each release; generator version pinning matters | Lowest tooling effort, but every endpoint change needs a manual code update |
| Tenant header handling | Set the Fineract-Platform-TenantId header through client configuration, confirmed against your version | Depends on the generator; confirm that header parameters are emitted and can be set per request | Added explicitly in each call, so it is easy to get wrong in one place |
| Authentication | Supports the auth options the client exposes; confirm OAuth2 and basic auth settings for your release | Auth schemes depend on generator support; check token refresh and secret handling | Full control over token acquisition, refresh and secret storage |
| Batch calls | Confirm whether the generated models cover the batch request shape for your version | Batch request models come from the spec; test referenced-result handling in your language | You build the batch payload yourself, which suits teams that need precise control |
| Generator quality risk | Low for Java, since the client is the project's own build output | Medium: generators differ in handling of enums, nullable fields and polymorphic models | Not applicable, but you carry all parsing and error-handling code |
| Recommended check | Compile against your target release and run a smoke test on a non-production tenant | Diff generated code between releases and run contract tests before adoption | Keep a short list of covered endpoints and review it at each upgrade |
Steps to build and verify a Fineract client
This sequence takes a team from a pinned Fineract release to a generated client that has made a successful call against a non-production tenant. Each step ends with a check, so problems surface in the step that caused them.
Pin the Fineract release and spec version
Choose the Fineract release your client will target, using the release notes and the documentation for that version, and record the exact version in your build configuration. Fineract publishes official releases quarterly, so confirm which release is current when you start and which one your environments run. Your team owns this decision, and it should match the server version you intend to call. The step is done when the target version is written in a repository file that every build reads, and the people maintaining the client agree on it.
Obtain the OpenAPI specification from the repository
Check out the apache/fineract source at the tag or branch that matches your pinned release and locate the OpenAPI 3.0.3 specification in the project tree. Do not download it from an unrelated mirror or a copy in a blog post, because a specification from another version will generate a client that calls endpoints your server does not expose. Store the file under version control alongside the client build. The check is a diff between the stored specification and the tagged source, which should show no differences.
Build the Java client jar
Run the Fineract build for the client module so it produces fineract-client.jar from the pinned specification, using the build tooling the repository documents for that release. Your engineers run this on a build agent you control, and the output is an artifact you can publish to your internal artifact repository. Confirm the jar contains the API classes you expect for the endpoints you plan to use, such as the client and loan services. The step is complete when the build succeeds from a clean checkout and the jar's version matches the pinned release.
Generate a client in a second language
Feed the same pinned specification to an OpenAPI generator for the language your integration team uses, and choose the generator version deliberately because output differs between generator releases. Generate into a separate directory and commit the generator version and configuration with it. Review the generated models for the money, date and identifier types your code will depend on, since these are where mismatches cause silent errors. The check is that the generated client compiles, and that a regenerated client from an unchanged specification produces no diff.
Configure the tenant header and authentication
Set the Fineract-Platform-TenantId header on every request through your client's configuration, not on individual calls, so a missed header cannot reach the wrong tenant. Point the client at a non-production instance and replace the default development login before any call is made. The README's default development login is mifos with the password, and it must be changed for any real deployment. Your security team should confirm that credentials come from a secret store and that a request made without the header is rejected or sent to a tenant you expect.
Run a smoke test on a non-production tenant
Write a short test that authenticates, reads a stable resource such as office or product data, and then performs one write on a test record that you can remove or ignore. Run it against a non-production tenant with the header set explicitly. Compare the response fields with the specification to catch deserialization gaps early. The check passes when the read returns the tenant data you expect, the write appears only in the test tenant, and the same test fails cleanly when the tenant header is removed.
Keep the client aligned with each release
Record the pinned version, generator version and smoke test results in the repository, and repeat steps two through six when you move to a new Fineract release. Treat the regenerated diff as a change to review, because removed or renamed fields break callers at compile time or at runtime. Assign an owner for each upgrade and keep the smoke test in your pipeline. The step is complete when a release upgrade produces a reviewed diff, a passing smoke test and an updated record of the versions in use.
Keeping generated clients in step with each release
Fineract ships quarterly, and each release can change the API surface your generated client depends on. The cards below set out the main risks and the control that addresses each one, so the client stays matched to the server version you actually run.
Spec drift after quarterly releases
Fineract publishes official releases quarterly, at the end of each quarter, so the OpenAPI specification your client was generated from can fall behind the server within a few months. Pin the Fineract version in your build, record the spec file hash alongside the generated client, and regenerate only as a deliberate step tied to a named release. Ask the team that owns the client to show which release each generated artifact came from.
Breaking changes in request models
A renamed field, a changed enum value or a request body that gained a required property can compile cleanly and still fail at runtime or silently drop data. Diff the specification between the current and target releases before each upgrade, and list every changed schema that your code calls. Treat any removed or renamed property as a blocking item until the call site is updated and tested.
Regenerated code overwriting customizations
If your team edits generated sources or adds helper methods inside the generated package, the next regeneration erases that work. Keep wrappers, retry logic and mapping code in a separate module that depends on the generated jar, and never commit manual changes to generated directories. Confirm during code review that the generation step runs from a clean output directory.
End-of-life releases archived
The Fineract project archives end-of-life releases, so a client pinned to an old version may depend on a server line that no longer receives fixes. Check the release policy in the README before you choose a target version, and schedule client upgrades on the same timetable as server upgrades. Record the end-of-life date for each release you run in your platform register.
Clients built against a development spec
Generating a client from an unreleased or development branch of the specification ties your code to endpoints that may change before the release ships. Generate only from the specification bundled with a tagged release, and reject builds that point at a branch or a local working copy. Add a pipeline check that fails when the specification source does not match the version in your build file.
How client generation interacts with custom Fineract code
If your deployment uses only the endpoints in the published Fineract specification, the generated client matches the API you run. The output depends on the specification version you build from, so the main risk is version drift between the spec and the server. Confirm the release you run in production against the release you generated from before you publish a client.
- Match the spec to the server: Build the client from the specification that corresponds to the Fineract release in production, and record that pairing in your release notes.
- Regenerate on each release: When you move to a new release, regenerate the client, review the diff, and publish a new
fineract-client.jaronly after the review passes. - Keep generated code out of hand edits: Treat generated sources as build output so a later regeneration does not overwrite changes made by hand.
- Pin the generator and template versions: Changes in generator defaults can alter method names or model types even when the spec has not changed.
- Test the calls your applications make: Run the client against a non-production instance covering the loan, savings and client endpoints your applications use.
Check that the spec version, the server release and the client artifact version all match before any application team relies on the output.
Custom modules that add REST resources are not part of the core specification unless the document the generator reads includes them. Generation only creates client methods for endpoints present in its input, so custom endpoints may be missing from the output even when the server exposes them. Custom modules also ship with your own image, so their contracts can change without a Fineract release.
- Confirm the spec source: Find out whether your spec comes from the published Fineract document or from a build that includes your module. Only endpoints in the input become client methods.
- Choose a client structure: Some teams publish a second artifact for custom endpoints so core and custom code can version independently. Decide this before the first release, since changing the layout later affects every consumer.
- Version the module contract: Give custom endpoints their own version and changelog, because your module releases on your schedule.
- Regenerate on module changes: A change to a request or response model in your module requires regeneration even when no core release has happened.
- Check headers and security settings: Confirm the generated client sends the
Fineract-Platform-TenantIdheader and the authentication scheme your custom endpoints require. Defaults in the generated code may not match custom security configuration.
Before relying on the output, confirm with a test call that each custom endpoint appears in the generated client and behaves as the server documents it.
If your team edits the OpenAPI document by hand, adds or removes paths, or changes schemas for internal tooling, the generated client reflects your fork. Upstream changes then have to be merged into your edited document before they reach the client. The fork carries its own maintenance cost for as long as it exists, and that cost grows with every change you make to the document.
- Record every spec change: Keep modifications as reviewable patches or as a transformation step in the build, so the difference from upstream stays visible.
- Plan a merge at each release: Official Fineract releases are created quarterly, so plan spec reviews and patch reapplication on that cadence.
- Watch for silent drift: A hand-edited schema can make the client accept a field the server rejects, or reject one the server accepts.
- Remember that the document is not the API: Changing the spec does not change server behavior. A client built from an edited document can look correct while the server behaves differently.
- Assign an owner for the patch set: Name one person or team responsible for spec patches, and require a contract test run against the server before any merge.
Confirm that your spec differences match what the server returns by running contract tests against the running release before you publish the client.
Security considerations for generated clients
A generated client carries the same trust decisions as the server it calls. The cards below cover transport, credentials, authentication choice, secret handling and the supply chain of the generated jar, which together decide whether the client is safe to ship.
Enforce HTTPS only
Configure every generated client to call Fineract over HTTPS and reject plain HTTP base URLs in code review and configuration. On the server side, the Fineract documentation strongly encourages HTTPS only and documents SSL settings through environment variables such as FINERACT_SERVER_SSL_ENABLED. Check that the client trusts the certificate chain your internal certificate authority issues, and that certificate validation is never disabled in a test profile that could be promoted by mistake.
Replace default credentials
The Fineract README shows a default development login, and it must be changed for any real deployment. Generated clients often ship with sample usernames and passwords in example code or test configuration, so search the generated sources, the README of your client module and your CI variables for those defaults. Issue a dedicated service identity for each client application instead of reusing an administrator login.
Choose OAuth2 or basic authentication
Fineract supports OAuth2 and HTTP basic authentication, and the client configuration must match the one your deployment enforces. Basic authentication sends a long-lived credential on every call, so limit it to controlled back-office integrations and confirm which mode each client uses. Where OAuth2 is in place, configure the client to request short-lived tokens, refresh them through the library rather than storing them, and confirm the token endpoint with your identity team.
Keep tokens and tenant secrets out of code
Generated code is regenerated from the specification, so anything typed into it is copied into every release. Keep access tokens, client secrets, basic credentials and the tenant identifier values in your secrets manager or environment variables, and inject them at runtime. Fineract is multi-tenant and requests carry a Fineract-Platform-TenantId header, so set that header from configuration per environment and confirm that a client built for one tenant cannot reach another.
Scan the generated jar
Treat fineract-client.jar as a dependency you ship and scan it on every build. Run a software composition analysis tool against its transitive libraries, pin the versions it resolves, and record the scan result with the release. Compare the jar's version with the Fineract release you target, since the project publishes official releases quarterly and archives end-of-life releases, so a client built for an archived line should be regenerated or retired.
Questions buyers ask about Fineract client generation
How much effort does generating and maintaining Fineract API clients take?
Effort depends mostly on how many languages you generate for, how much of the API your applications call, and how much automation surrounds the generator. Building the first client is a one-time cost. Keeping it current is the recurring cost, because Fineract's README states that official releases are created quarterly, at the end of each quarter, so each release can change endpoints, request fields or response models. Costs rise with each additional language, with custom wrappers for authentication and tenant handling, and with the regression tests needed to show that a regenerated client still works. When you request a quote, ask which languages are in scope, which release versions are covered, who reviews specification changes, and whether regeneration sits in the fixed scope or in a retainer.
Can our in-house team generate and maintain Fineract clients themselves?
Yes, if the team has Java and build tooling experience and one person or group clearly owns the process. The generator is rarely the hard part. The harder work is a repeatable pipeline that regenerates clients from the OpenAPI specification for each release, runs tests against a live test tenant, and publishes artifacts that applications consume. In-house efforts usually struggle when the engineer who built the pipeline moves on, when nobody reviews breaking changes in the specification, or when there is no test environment with realistic data. Check whether your team can answer three questions: who reads the specification diff for each release, where generated code is versioned, and how a failed regeneration is rolled back. If those answers are clear, an internal build is a sound choice. If they are not, a partner can set up the pipeline and hand over a written runbook.
What does a client generation project need from our side?
The project needs access, decisions and a few named people. You will need a running Fineract instance on the release you intend to target, a non-production tenant with representative configuration, and a build system with a runner that can execute the generator and tests. Your team should decide which languages and API areas matter, which applications will consume the client, and how credentials for test environments are issued and stored. A product or operations owner should also agree on acceptance criteria, such as which loan and savings flows the regression suite must cover. Ask for a written list of these inputs before work starts. Most delays come from late access and unresolved decisions, so naming owners for each input early keeps the schedule predictable.
How long does a first Fineract client take to produce?
The honest answer depends on scope, and no reliable duration can be given without it. The main drivers are the number of API areas your applications need, the number of target languages, the packaging and naming conventions of your build system, and how much authentication and tenant handling you wrap around the generated code. A narrow client for one language covering loans and savings is a different job from a full multi-language set with tests. Readiness also matters: the time to get a running Fineract instance, a populated test tenant and working credentials often outlasts the generation itself. Ask any provider for a written scope listing the API areas, languages and acceptance tests, plus the inputs they need from you to begin. The Apache Fineract platform documentation is the reference for confirming the endpoints your release exposes.
How do we keep generated clients current across quarterly Fineract releases?
Treat each adopted release as a deliberate change, and use the specification diff as your change list. Fineract's README says official releases are created quarterly under the ASF release policy and that end-of-life releases are archived, so pin each client to one release and plan upgrades on a schedule. A practical cycle is to watch for new releases, regenerate against the new specification on a branch, compare the diff for removed or renamed endpoints and changed models, run regression tests against a test tenant on the new release, and then publish a new client version. Keep the previous client version available until dependent applications have moved. Align this cycle with your Fineract upgrade plan so the server and the clients change together, and record each review decision for audit purposes.
Does a generated Fineract client handle authentication and tenant headers?
Usually only in part, so confirm the behavior against the specification and the client you generate. A generator produces request methods and models from the API definition, but Fineract is multi-tenant: requests carry a Fineract-Platform-TenantId header, and the Fineract documentation describes OAuth2 and HTTP basic authentication. Those values are typically set at runtime, so keep them in a thin wrapper that reads tenant and credential values from configuration or a secrets store. The README's default development login must be changed for any real deployment, and HTTPS should be enforced for every environment that carries real data. Test the wrapper against a non-production tenant, and confirm that a missing tenant header fails with a clear error in your code rather than silently reaching the wrong tenant.
When is it worth bringing in a partner for Fineract client generation?
Bring in a partner when the number of languages, the release burden or the timeline would push other work off your team's plate. DeployOpen plans, implements, integrates, tests and supports self-hosted open-source platforms inside your own infrastructure. Most engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts, and ongoing regeneration, testing and upgrades can be covered by a retainer. A partner is also worth considering when no one in-house owns the Fineract API surface, or when a regulated environment needs documented change control for every client release. DeployOpen does not publish a price list, so the first step is a written scope covering the APIs, languages, target releases and test expectations. From that scope, you can compare a partner quote with the cost of building the same capability internally.
Official Apache Fineract sources for client builds
Use the official Apache Fineract sources as the authority for exact build steps, and treat this page as the decision guide that tells you what to check there. The Apache Fineract platform documentation is the first read for how the API is organized and how the project describes its client-facing surface. Note that the project's website lists 1.15.0 as the current stable release, and the 1.15.0 documentation was built on July 10, 2026. If your deployment runs a different release, the documentation version you read must match it, because endpoints, schemas and generator inputs can change between releases.
The apache/fineract repository on GitHub holds the source for the release you run, so it is where you confirm the location of the OpenAPI specification file and the build tasks that package fineract-client.jar. Do not assume the path from an older tutorial or from a different branch. Open the tag or release branch that matches your production version, locate the specification file there, and record its path and version in your build notes. The same check applies to the generator configuration and any templates the build references, since these determine the shape of the generated code.
The Apache Fineract website and the release notes for each version are the sources for release timing and end-of-life status. Fineract releases are created quarterly under the ASF release policy, and end-of-life releases are archived. Confirm with your client team which release the generated clients will target, and plan a regeneration and regression run each time you move to a new quarterly release. Ask your implementation partner to show, in writing, how they will pin the specification version and rerun generation when the upstream spec changes.
How DeployOpen works on this
DeployOpen plans, builds, documents and supports self-hosted open-source platforms inside your own infrastructure. For Fineract client generation, we start from the OpenAPI specification your release targets, agree the languages and build pipeline in writing, and hand over generated clients your team can regenerate on its own.
How we scope
- Confirm which Fineract release the generated clients must match before any generation work starts.
- List target languages, client packaging and the repositories or registries where clients will be published.
- Agree in writing whether the Java fineract-client.jar build is in scope, with each target language named separately.
- Engagements are fixed-scope, with deliverables and timelines agreed in writing before work begins.
How we build
- Build the client generation pipeline against the Fineract OpenAPI 3.0.3 specification for the agreed release.
- Compare the generated Java client with the endpoints your integrations call, and record any gaps.
- Run compile and smoke tests of each client against a Fineract instance in a non-production environment you control.
- Keep the generator configuration and templates under version control so each build is repeatable.
How we hand over
- Deliver the generator configuration, build scripts and client packages with documentation of how to run them.
- Document the regeneration steps your team follows when a new quarterly Fineract release is adopted.
- Walk your engineers through the diff review process used to spot breaking changes between specification versions.
- Record the decisions made on naming, authentication handling and error mapping so future changes have a reference.
How we support
- Ongoing support, upgrades and regeneration after each Fineract release are available as a retainer.
- Retainer scope, response expectations and the release cadence covered are written down before work starts.
- Confirm with your own team which clients are consumed in production and how changes are approved before release.
- Ask any provider, including DeployOpen, to state the test coverage and rollback steps for each client update.

