Appearance
REST API Overview
Apache Fineract exposes a REST API over HTTPS. Every feature in the system - loans, clients, savings accounts, accounting, reports, configuration - is accessible via this API. The web UI (Mifos X) is itself an API client and uses the same endpoints.
This page covers the conventions that apply to every API call.
Base URL
All endpoints are under:
https://your-instance.finecko.com/fineract-provider/api/v1/Replace your-instance.finecko.com with your actual Finecko instance URL.
Required Headers
Every request needs two headers:
bash
Fineract-Platform-TenantId: default
Authorization: Basic <base64(username:password)>Fineract-Platform-TenantId - identifies which tenant's database to use. Without this header, the request is rejected with a 401. Use the tenant identifier provided at onboarding (typically default for single-tenant deployments).
Authorization - HTTP Basic Auth. Encode username:password in Base64:
bash
# Generate the header value
echo -n 'mifos:password' | base64
# → bWlmb3M6cGFzc3dvcmQ=
# Use in a request
curl https://your-instance.finecko.com/fineract-provider/api/v1/offices \
-H "Fineract-Platform-TenantId: default" \
-H "Authorization: Basic bWlmb3M6cGFzc3dvcmQ="The -H "Authorization: Basic $(echo -n 'user:pass' | base64)" shorthand works in bash and is used throughout these docs.
Authentication
Fineract uses HTTP Basic Authentication. Credentials are validated on every request - there are no sessions or tokens to manage.
Getting a credential key via the authentication endpoint:
bash
curl -X POST \
https://your-instance.finecko.com/fineract-provider/api/v1/authentication \
-H "Fineract-Platform-TenantId: default" \
-H "Content-Type: application/json" \
-d '{"username": "mifos", "password": "password"}'Response:
json
{
"username": "mifos",
"userId": 1,
"base64EncodedAuthenticationKey": "bWlmb3M6cGFzc3dvcmQ=",
"authenticated": true,
"officeId": 1,
"officeName": "Head Office",
"roles": [...],
"permissions": [...]
}The base64EncodedAuthenticationKey is the same value you would compute manually - it is provided for convenience and can be passed directly as the Authorization: Basic value.
Service accounts: For integrations, create a dedicated user account with only the permissions the integration requires. Avoid using the admin account for API integrations. See User Management for how to create service accounts and assign minimal permissions.
Request Conventions
Content type: All write requests (POST, PUT) must include Content-Type: application/json.
Date fields: Every date field in a request body requires two companion fields: dateFormat and locale. The format string uses Java's DateTimeFormatter pattern syntax. The locale is a BCP 47 language tag.
json
{
"activationDate": "15 March 2024",
"dateFormat": "dd MMMM yyyy",
"locale": "en"
}Common date formats:
| Format string | Example |
|---|---|
dd MMMM yyyy | 15 March 2024 |
yyyy-MM-dd | 2024-03-15 |
dd/MM/yyyy | 15/03/2024 |
Use the same format string and locale consistently within a request. Mismatched formats are a frequent source of 400 errors.
Decimal values: Monetary amounts are sent as plain JSON numbers. Fineract applies the rounding mode configured for the tenant (default: half-even, ROUND_HALF_EVEN).
Response Conventions
Success responses:
GETrequests return the resource object or an array of objectsPOST(create) requests return{ "resourceId": <id> }- the ID of the created resourcePUT(update) requests return{ "resourceId": <id>, "changes": { ... } }- the ID and the fields that changedDELETErequests return{ "resourceId": <id> }
Listing responses return the array directly (not wrapped in a pagination envelope for most endpoints):
json
[
{ "id": 1, "name": "Head Office", ... },
{ "id": 2, "name": "Nairobi Branch", ... }
]Some endpoints return richer envelopes with pageItems and totalFilteredRecords - see Pagination below.
Pagination
Endpoints that can return large result sets support offset-based pagination via query parameters:
| Parameter | Description |
|---|---|
offset | Number of records to skip (default: 0) |
limit | Maximum records to return (default varies by endpoint, often 200) |
orderBy | Field to sort by |
sortOrder | ASC or DESC |
Example - list clients with pagination:
bash
curl "https://your-instance.finecko.com/fineract-provider/api/v1/clients?offset=0&limit=50&orderBy=id&sortOrder=ASC" \
-H "Fineract-Platform-TenantId: default" \
-H "Authorization: Basic $(echo -n 'mifos:password' | base64)"Paginated responses return:
json
{
"totalFilteredRecords": 1240,
"pageItems": [ { ... }, { ... } ]
}Use totalFilteredRecords to calculate the total number of pages.
Filtering
Most listing endpoints accept search query parameters to filter results. Common filters:
bash
# Filter clients by office
/clients?officeId=2
# Filter loans by status
/loans?loanStatus=300 # 300 = active
# Filter by external ID
/clients?externalId=CUST-1001
# Search clients by name
/clients?sqlSearch=firstname%20like%20%27Amara%25%27The sqlSearch parameter accepts SQL-style WHERE clause fragments. Use with care - always URL-encode the value.
Idempotency
Fineract supports idempotency keys on write requests to prevent duplicate operations on retries. Pass the key in the request header:
bash
curl -X POST \
https://your-instance.finecko.com/fineract-provider/api/v1/loans/1/transactions?command=repayment \
-H "Fineract-Platform-TenantId: default" \
-H "Authorization: Basic $(echo -n 'mifos:password' | base64)" \
-H "Idempotency-Key: txn-20240315-001" \
-H "Content-Type: application/json" \
-d '{ ... }'If the same request is submitted again with the same Idempotency-Key, Fineract returns the original response without creating a duplicate transaction. Idempotency keys expire after a configured period. The header name defaults to Idempotency-Key and is configurable via FINERACT_IDEMPOTENCY_KEY_HEADER_NAME.
Error Handling
Fineract returns structured error responses with HTTP status codes and a body describing the problem.
400 Bad Request
Validation failure. The response body identifies the specific field(s) that failed:
json
{
"developerMessage": "The request was invalid.",
"httpStatusCode": "400",
"defaultUserMessage": "Validation errors exist.",
"userMessageGlobalisationCode": "validation.msg.validation.errors.exist",
"errors": [
{
"developerMessage": "The parameter 'dateFormat' cannot be blank.",
"defaultUserMessage": "The parameter 'dateFormat' cannot be blank.",
"parameterName": "dateFormat",
"value": null
}
]
}Common causes: missing required fields, incorrect date format, invalid enum values, referencing an entity that does not exist.
401 Unauthorized
Authentication failed or the tenant header is missing. Check credentials and the Fineract-Platform-TenantId header.
403 Forbidden
The authenticated user does not have permission for the requested action. Check the user's roles and permissions. See User Management for permission configuration.
404 Not Found
The requested resource does not exist in this tenant. Verify the resource ID and that you are using the correct Fineract-Platform-TenantId.
500 Internal Server Error
A server-side error. The response body typically contains a developerMessage with details. Contact Finecko support with the full request and response if the error persists.
The Swagger UI
An interactive API reference is available at:
https://your-instance.finecko.com/fineract-provider/api/v1/swagger-ui/index.htmlThe Swagger UI lists every endpoint, shows the expected request body schema, and allows you to make live API calls directly from the browser. It is the most complete reference for specific endpoint parameters and response shapes.
To authenticate in Swagger UI:
- Click "Authorize" at the top right
- Enter your
Fineract-Platform-TenantIdvalue in thetenantidfield - Enter your username and password in the HTTP Basic Auth fields
Common Operations Reference
Offices
bash
GET /offices # List all offices
POST /offices # Create an office
GET /offices/{id} # Get office details
PUT /offices/{id} # Update an officeClients
bash
GET /clients # List clients (supports pagination and filters)
POST /clients # Create a client
GET /clients/{id} # Get client details
PUT /clients/{id} # Update a client
POST /clients/{id}?command=activate # Activate a pending clientLoans
bash
GET /loans # List loans
POST /loans # Submit a loan application
GET /loans/{id} # Get loan details
POST /loans/{id}?command=approve # Approve a loan
POST /loans/{id}?command=disburse # Disburse a loan
POST /loans/{id}/transactions?command=repayment # Post a repaymentSavings
bash
GET /savingsaccounts # List savings accounts
POST /savingsaccounts # Open a savings account
POST /savingsaccounts/{id}?command=approve # Approve
POST /savingsaccounts/{id}?command=activate # Activate
POST /savingsaccounts/{id}/transactions?command=deposit # Deposit
POST /savingsaccounts/{id}/transactions?command=withdrawal # WithdrawalUsers and Roles
bash
GET /users # List users
POST /users # Create a user
PUT /users/{id} # Update a user (including password change)
GET /roles # List roles
POST /roles # Create a role
PUT /roles/{id}/permissions # Update role permissionsReports
bash
GET /reports # List available reports
GET /runreports/{report-name} # Run a reportUse the Swagger UI for the full parameter reference for each endpoint.