A REST and JSON API for the whole lending lifecycle: clients, loans, repayments, accounting and reports, with scoped tokens, safe retries and clear limits.
/api/v1Everything your team does in the Credit Watch screens can be done through the API, so you can connect your own app, core banking system, payment channels or data warehouse to one ledger.
| Base URL | https://creditwatch.online/api/v1 |
| Format | JSON requests and responses. Send Accept: application/json. |
| Authentication | Bearer token in the Authorization header. |
| Company data | Every call runs as your company. A token can never read another company's records. |
| Versioning | The version is in the path. Breaking changes ship as a new version, and we tell you before anything you use changes. |
From a new account to your first successful call in about five minutes.
# List active clients, 20 per page curl "https://creditwatch.online/api/v1/client?status=active&limit=20" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json"
const res = await fetch("https://creditwatch.online/api/v1/client?status=active&limit=20", { headers: { Authorization: "Bearer YOUR_TOKEN", Accept: "application/json", }, }); const clients = await res.json(); console.log(clients);
<?php
$ch = curl_init("https://creditwatch.online/api/v1/client?status=active&limit=20");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer YOUR_TOKEN",
"Accept: application/json",
],
]);
$clients = json_decode(curl_exec($ch), true);
curl_close($ch);import requests r = requests.get( "https://creditwatch.online/api/v1/client", params={"status": "active", "limit": 20}, headers={"Authorization": "Bearer YOUR_TOKEN", "Accept": "application/json"}, ) print(r.json())
[
{
"current_page": 1,
"per_page": 20,
"total": 134,
"data": [
{
"id": 482,
"name": "Mary Banda",
"gender": "female",
"mobile": "260971234567",
"email": "mary@example.com",
"external_id": "CRM-10482",
"status": "active",
"branch": "Lusaka Main",
"staff": "Joseph Mwale"
}
]
}
]
Every request carries a bearer token. Tokens belong to your company, carry only the scopes you gave them, and can be revoked at any time.
Created in Company Settings, API Integrations. Good for scripts, back-office tools and getting started.
For server-to-server integrations and apps. Your system requests short-lived access tokens from the token endpoint.
/oauth/tokenAuthorization: Bearer YOUR_TOKEN Accept: application/json Content-Type: application/json
A token can only do what its scopes allow. Give each integration the smallest set that works.
| Scope | What it allows |
|---|---|
loans:read | View loans, applications, schedules and balances |
loans:write | Create, approve, disburse and write off loans |
repayments:read | View repayments and transactions |
repayments:write | Record and reverse repayments |
clients:read | View clients |
clients:write | Create and update clients |
accounting:read | View the chart of accounts, journal entries and reports |
accounting:write | Post journal entries |
reports:read | Run reports |
tradefinance:read | View trade finance facilities, invoices and advances |
tradefinance:write | Submit invoices and request drawdowns |
loans:read and repayments:read. A payments reconciler needs repayments:write. A BI tool needs reports:read.Most integrations follow this path. Each step is one call, and the loan is always in a known state.
POST /client/storePOST /loan/calculatorPOST /loan/storePOST /loan/{id}/approve_loanPOST /loan/{id}/disburse_loanPOST /loan/{id}/repayment/storecurl -X POST https://creditwatch.online/api/v1/client/store \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" \ -d first_name=Mary \ -d last_name=Banda \ -d gender=female \ -d dob=1990-04-12 \ -d branch_id=1 \ -d created_date=2026-10-15 \ -d mobile=260971234567
# Required fields include: client_id, loan_product_id, fund_id, loan_purpose_id, # applied_amount, loan_term, repayment_frequency, repayment_frequency_type, # interest_rate, expected_disbursement_date, loan_officer_id curl -X POST https://creditwatch.online/api/v1/loan/store \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" \ -H "Idempotency-Key: 6f1c0d52-9b7e-4c1a-8d3e-5a2b7c9e1f40" \ -d client_id=482 \ -d loan_product_id=3 \ -d applied_amount=5000 \ -d loan_term=6 \ -d repayment_frequency=1 \ -d repayment_frequency_type=months \ -d interest_rate=3 \ -d expected_disbursement_date=2026-10-20
# Approve curl -X POST https://creditwatch.online/api/v1/loan/910/approve_loan \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Idempotency-Key: a31b6c10-2d8f-4f0e-9a64-7d5c3e8b1a22" # Disburse curl -X POST https://creditwatch.online/api/v1/loan/910/disburse_loan \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Idempotency-Key: 0c9d4e77-61aa-43b8-b2f1-9e3a5d7c4b10"
curl -X POST https://creditwatch.online/api/v1/loan/910/repayment/store \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" \ -H "Idempotency-Key: mobile-money-TX88213" \ -d amount=1250.00 \ -d date=2026-11-05 \ -d payment_type_id=2 \ -d receipt=TX88213
await fetch("https://creditwatch.online/api/v1/loan/910/repayment/store", { method: "POST", headers: { Authorization: "Bearer YOUR_TOKEN", Accept: "application/json", "Idempotency-Key": "mobile-money-TX88213", "Content-Type": "application/json", }, body: JSON.stringify({ amount: 1250.0, date: "2026-11-05", payment_type_id: 2, receipt: "TX88213" }), });
import requests requests.post( "https://creditwatch.online/api/v1/loan/910/repayment/store", headers={ "Authorization": "Bearer YOUR_TOKEN", "Accept": "application/json", "Idempotency-Key": "mobile-money-TX88213", }, json={"amount": 1250.0, "date": "2026-11-05", "payment_type_id": 2, "receipt": "TX88213"}, )
The calls most integrations use, grouped by area. Paths are relative to /api/v1. The full reference, including every field, is shared with your team when you get access.
clients:read, clients:write| GET/client | List clients. Filter with status and branch_id, page with limit. |
| GET/client/{id}/show | One client with their details. |
| POST/client/store | Create a client. |
| POST/client/{id}/update | Update a client. |
| POST/client/{id}/change_status | Activate, deactivate or otherwise change a client's status. |
| POST/client/{id}/client_identification/store | Add an ID document to a client. |
| POST/client/{id}/client_next_of_kin/store | Add next of kin. |
| POST/client/{id}/file/store | Attach a document or file. |
loans:read, loans:write| GET/loan | List loans. |
| GET/loan/{id}/show | One loan with its terms, status and balances. |
| POST/loan/calculator | Work out a repayment schedule without creating a loan. |
| POST/loan/store | Create a loan. Supports Idempotency-Key. |
| POST/loan/{id}/approve_loan | Approve a loan. Supports Idempotency-Key. |
| POST/loan/{id}/reject_loan | Reject a loan. |
| POST/loan/{id}/disburse_loan | Disburse an approved loan. Supports Idempotency-Key. |
| GET/loan/{id}/schedule/show | The repayment schedule. |
| POST/loan/{id}/charge/store | Add a charge to a loan. Supports Idempotency-Key. |
| POST/loan/{id}/waive_interest | Waive interest. Supports Idempotency-Key. |
| POST/loan/{id}/write_off_loan | Write a loan off. Supports Idempotency-Key. |
| POST/loan/{id}/change_loan_officer | Reassign the loan officer. |
loans:write| POST/loan-applications | Submit an application. Supports Idempotency-Key. |
| GET/loan-applications/{id} | Check the status of an application. |
repayments:read, repayments:write| POST/loan/{id}/repayment/store | Record a repayment (amount, date, payment_type_id). Supports Idempotency-Key. |
| POST/loan/repayment/{id}/update | Correct a repayment. Supports Idempotency-Key. |
| GET/loan/repayment/{id}/reverse | Reverse a repayment. |
loans:write| POST/loan-migrations | Import one loan with its history. Supports Idempotency-Key. |
| POST/loan-migrations/batch | Import many loans in one request. Supports Idempotency-Key. |
loans:read, loans:write| GET/loan/product | List loan products. |
| GET/loan/product/{id}/show | One product with its limits and rules. |
| POST/loan/product/store | Create a product. |
| POST/loan/product/{id}/update | Update a product. |
accounting:read, accounting:write| GET/accounting/chart_of_account | The chart of accounts. |
| GET/accounting/journal_entry | List journal entries. |
| POST/accounting/journal_entry/store | Post a journal entry. Supports Idempotency-Key. |
| GET/accounting/trial_balance | Trial balance. |
| GET/accounting/ledger | General ledger. |
| GET/accounting/balance_sheet | Balance sheet. |
| GET/accounting/income_statement | Income statement. |
| GET/accounting/cash_flow | Cash flow. |
reports:read| GET/report/loan/arrears | Loans in arrears. |
| GET/report/loan/portfolio_at_risk | Portfolio at risk. |
| GET/report/loan/collection_sheet | Collection sheet. |
| GET/report/loan/repayment | Repayments in a period. |
| GET/report/loan/expected_repayment | Repayments expected in a period. |
| GET/report/loan/disbursement | Disbursements in a period. |
tradefinance:read, tradefinance:write| GET/trade-finance/facilities | List facilities. |
| GET/trade-finance/facilities/{id} | One facility with its limits. |
| POST/trade-finance/facilities/{id}/invoices | Submit an invoice against a facility. |
| POST/trade-finance/facilities/{id}/advances | Request an advance. |
| GET/trade-finance/invoices | List invoices. |
| GET/trade-finance/advances/{id} | One advance. |
by area| GET/branch | List branches. |
| GET/currency | Currencies. |
| GET/payment_type | Payment types, for repayments and disbursements. |
| GET/communication/campaign | Messaging campaigns. |
| GET/communication/log | Messages sent. |
Predictable conventions, so your client code stays small.
List calls return a page of results. Ask for a page size with limit (default 20) and move through pages with page. The response includes current_page, per_page and total.
List calls accept filters such as status and branch_id. Dates use YYYY-MM-DD.
| Code | Meaning |
|---|---|
200 | The request worked. |
400 | Validation failed. The body lists each field that needs fixing. |
401 | The token is missing, expired or revoked. |
403 | The token does not have the scope, or the user may not do this. |
404 | That record does not exist in your company. |
409 | A request with the same Idempotency-Key is still running. |
429 | You are over the rate limit. Wait for the time in Retry-After. |
{
"success": false,
"errors": {
"amount": ["The amount field is required."],
"payment_type_id": ["The payment type id field is required."]
}
}
Networks fail. When a request that moves money times out, you need to retry without paying someone twice. Add an Idempotency-Key header and we make sure the action runs once.
409, so you know to wait and try again.Limits keep the platform fast for everyone. The default is 120 requests per minute for each token, and we can raise it for busy integrations.
X-RateLimit-Limit: 120 X-RateLimit-Remaining: 117 # when you go over HTTP/1.1 429 Too Many Requests Retry-After: 23 { "message": "Too many requests. Slow down." }
Read X-RateLimit-Remaining to pace yourself, and on a 429 wait for Retry-After seconds before you try again. For bulk loads, use the batch migration endpoint instead of many single calls.
Common ways teams use the API, and where we help.
Quote with the calculator, submit an application, then show status and schedules. Your app owns the experience, Credit Watch owns the loan.
Post each mobile-money or bank payment as a repayment using the provider reference as the Idempotency-Key, so duplicates are harmless.
Push journal entries to your ledger and pull trial balance and statements on a schedule.
Pull arrears, portfolio-at-risk, disbursement and repayment reports into your analytics tools each night.
Import open loans and history with the batch migration endpoint, then reconcile balances with our team.
Payment providers call back into the platform to confirm repayments. For events to your own systems, we set up notifications with you during implementation.
Test safely first, then switch to production with a short checklist.
Ask us for a sandbox company with sample products and clients. Your tokens and data there are separate from production.
Create production tokens in your live company, with narrower scopes than you used while building.
What your risk and security teams will ask about.
Talk to people who know the platform and the lending behind it.
Create an account, make your first call today, and tell us what you want to build.
Get started for free Talk to our team