REST API

The REST API at /api/v1/ is the recommended integration surface for third parties. It is OAuth-protected, OpenAPI-described, and built for predictable, idempotent operations.

API settings
API keys + webhooks under Configuration → API / Integrations.
At a glance — Base URL: https:///api/v1/. Auth: OAuth 2.0 client credentials. Content-Type: application/json. Pagination: cursor-based. Idempotency: via Idempotency-Key header on POSTs.

Design principles

  • Resources named in singular BridgeERP model form (members, loans, savings_accounts)
  • Identifiers are stable BridgeERP integer IDs; UUIDs available via aliasing if a consumer requires non-enumerable IDs
  • Timestamps in ISO 8601 UTC with Z suffix
  • Currency amounts as decimals in minor units (KES cents) to avoid float drift
  • All list endpoints support filter[field]=value query params and cursor pagination
  • All mutating endpoints accept Idempotency-Key for safe retry

Key endpoint groups

GroupEndpointMethods
Members/api/v1/membersGET, POST, PATCH
Loans/api/v1/loansGET, POST, PATCH
Loan schedules/api/v1/loans/{id}/scheduleGET
Disbursements/api/v1/loans/{id}/disbursementsGET, POST
Repayments/api/v1/loans/{id}/repaymentsGET, POST
Savings accounts/api/v1/savings_accountsGET, POST, PATCH
Savings transactions/api/v1/savings_accounts/{id}/transactionsGET, POST
Mobile money/api/v1/mobile_money/transactionsGET, POST
AML alerts/api/v1/aml/alertsGET, PATCH
Webhooks/api/v1/webhooksGET, POST, DELETE

Example: create a member

curl -X POST https://microfinance.mybridgeerp.com/api/v1/members \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 4c2a-jane-wambui-2026-03-15' \
  -d '{
    "name": "Jane Wambui Mwangi",
    "national_id": "22748561",
    "phone": "+254712345678",
    "branch_id": 3,
    "kyc": {
      "id_type": "national_id",
      "id_number": "22748561",
      "date_of_birth": "1988-07-12",
      "address": {
        "city": "Nairobi",
        "county": "Nairobi",
        "country": "KE"
      }
    }
  }'

# 201 Created
# {
#   "id": 4827,
#   "member_no": "M-0004827",
#   "name": "Jane Wambui Mwangi",
#   "state": "pending_kyc",
#   ...
# }

Example: create and disburse a loan

# 1. Create loan in draft
curl -X POST https://microfinance.mybridgeerp.com/api/v1/loans \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "member_id": 4827,
    "product_id": 12,
    "principal": 5000000,
    "term_months": 12,
    "purpose": "Working capital for tailoring shop"
  }'
# {"id": 9183, "state": "draft", ...}

# 2. Approve
curl -X PATCH https://microfinance.mybridgeerp.com/api/v1/loans/9183 \
  -H 'Authorization: Bearer <token>' \
  -d '{"action": "approve"}'

# 3. Disburse to M-Pesa
curl -X POST https://microfinance.mybridgeerp.com/api/v1/loans/9183/disbursements \
  -H 'Authorization: Bearer <token>' \
  -H 'Idempotency-Key: disburse-9183-2026-03-15' \
  -d '{
    "amount": 5000000,
    "channel": "mpesa_b2c",
    "msisdn": "+254712345678"
  }'
# {"id": 7211, "state": "sent", "provider_ref": "PBJ4S6X9DC"}

Error format

Errors follow RFC 7807 Problem Details for HTTP APIs.

{
  "type": "https://docs.mybridgeerp.com/errors/insufficient_balance",
  "title": "Insufficient agent float",
  "status": 409,
  "detail": "M-Pesa B2C float is KES 32,000 but disbursement requires KES 50,000.",
  "instance": "/api/v1/loans/9183/disbursements",
  "agent_id": "agent-nairobi-01",
  "available_float": 3200000
}

Worked scenarios

Scenario — KCB Bank integrates loan disbursement via REST

Setting: KCB Bank disburses Mwananchi SACCO loans via its corporate bulk-payments API. KCB needs to confirm each disbursement back to Mwananchi's MFI Suite tenant.

CharacterRole
Samuel KibetMwananchi CTO
Aisha HassanKCB Integration Lead
Peter OtienoMwananchi Operations

Timeline

  1. Day 1, 10:00: Samuel provisions OAuth client for KCB. (Client id svc_kcb_disbursement, scopes loans:read disbursements:write.)
  2. Day 1, 14:00: Aisha integrates against /api/v1/loans?filter[state]=ready_to_disburse. (KCB polls every 5 minutes, pulls eligible loans.)
  3. Day 2, 09:00: Mwananchi approves 47 loans totalling KES 12.4M. (Loans state=ready_to_disburse.)
  4. Day 2, 09:05: KCB pulls the list, issues bulk EFT. (Bulk reference KCB-BULK-2026-03-16-001.)
  5. Day 2, 09:20: KCB POSTs disbursement confirmations. (47 POST /api/v1/loans/{id}/disbursements with KCB ref.)
  6. Day 2, 09:21: MFI Suite books disbursements, fires loan.disbursed webhooks. (Loan state=active, schedule starts.)
  7. Day 2, 09:30: Peter sees 47 active loans in dashboard. (All linked to KCB references for reconciliation.)

Outcome — Daily disbursement batch automated end-to-end. Reconciliation between MFI Suite ledger and KCB bank statement is exact via the KCB ref captured in mfi.loan.disbursement.provider_ref.

Reference

Common request and response headers

HeaderDirectionPurpose
Authorization: Bearer RequestOAuth access token
Content-Type: application/jsonRequestJSON body
Idempotency-KeyRequestSafe retry for mutating endpoints (24h TTL)
If-Match: RequestOptimistic concurrency for PATCH
X-Request-IDRequest/ResponseEcho trace ID for debugging
ETagResponseOptimistic concurrency token
X-RateLimit-RemainingResponseRequests remaining in window
Retry-AfterResponse (429)Seconds to wait before retry
Deprecation, SunsetResponseEndpoint deprecation signals

Troubleshooting

SymptomLikely causeFix
POST /loans returns 422 with 'product_id required'.Forgot the loan product reference.Provide product_id matching a row from GET /api/v1/loan_products.
Repayment returns 200 but loan balance unchanged.Repayment booked to a different loan (wrong loan id in URL).Always cross-check the response payload's loan_id; never reuse stale URLs from cached lists.
Idempotency-Key returns cached response from yesterday.Key reused within 24h TTL window.Use unique idempotency keys per logical operation; encode date or sequence.

See also

Was this page helpful?