JSON-RPC API
The JSON-RPC interface at /jsonrpc and /web/dataset/call_kw is the canonical BridgeERP RPC surface. It lets clients call any model method (create, write, search_read, custom action) directly, with full ORM semantics.

When to use JSON-RPC vs REST
Use REST for third-party integrations, public-facing apps, and partners who must not know your BridgeERP schema. Use JSON-RPC for internal BridgeERP-to-BridgeERP links, admin scripts, and anything where you want to call a custom model method without writing a REST wrapper.
Authentication
Two options: session cookie (web.session) or API key.
import xmlrpc.client
# JSON-RPC via xmlrpc helper, or use requests + JSON-RPC payload directly
import requests
base = 'https://microfinance.mybridgeerp.com'
db = 'microfinance.mybridgeerp.com'
login = 'integration@bridgeerp.com'
api_key = 'ak_8f72...'
# Authenticate
resp = requests.post(f'{base}/jsonrpc', json={
'jsonrpc': '2.0',
'method': 'call',
'params': {
'service': 'common',
'method': 'authenticate',
'args': [db, login, api_key, {}]
}
}).json()
uid = resp['result']
Calling model methods
Once authenticated, call any model method by name. The pattern is execute_kw(db, uid, password, model, method, args, kwargs).
# Search and read members
resp = requests.post(f'{base}/jsonrpc', json={
'jsonrpc': '2.0',
'method': 'call',
'params': {
'service': 'object',
'method': 'execute_kw',
'args': [
db, uid, api_key,
'mfi.member', 'search_read',
[[['state', '=', 'active']]], # domain
{'fields': ['name', 'phone', 'national_id'], 'limit': 50}
]
}
}).json()
members = resp['result']
# Create a loan
loan_id = requests.post(f'{base}/jsonrpc', json={
'jsonrpc': '2.0',
'method': 'call',
'params': {
'service': 'object',
'method': 'execute_kw',
'args': [
db, uid, api_key,
'mfi.loan', 'create',
[{
'member_id': 4827,
'product_id': 12,
'principal': 5000000,
'term_months': 12,
}]
]
}
}).json()['result']
# Call custom action
requests.post(f'{base}/jsonrpc', json={
'jsonrpc': '2.0',
'method': 'call',
'params': {
'service': 'object',
'method': 'execute_kw',
'args': [
db, uid, api_key,
'mfi.loan', 'action_approve',
[[loan_id]]
]
}
})
Most-called models
- mfi.member — members and KYC
- mfi.loan — loans
- mfi.loan.schedule — schedule lines
- mfi.loan.disbursement — disbursements
- mfi.loan.repayment — repayments
- mfi.savings.account — savings accounts
- mfi.savings.transaction — savings transactions
- mfi.aml.alert — AML alerts
- mfi.regulatory.return — regulatory returns
- account.move — accounting entries (for reconciliation)
Performance tips
- Always pass a fields list to search_read; never read every column
- Use create([list_of_dicts]) for bulk create — order of magnitude faster than N calls
- Use the with_context() pattern by passing context as kwarg to switch language, lang code, or skip computes
- For pagination prefer search with offset+limit and ordered by id, then read in batches
Worked scenarios
Scenario — Florence runs nightly delinquency tagging via JSON-RPC
| Character | Role |
|---|---|
| Florence Achieng | Credit Risk Analyst |
| Samuel Kibet | DevOps Engineer |
Timeline
- Day 1, 09:00: Samuel writes Python script using requests + JSON-RPC. (Script uses Florence's API key with credit_risk role.)
- Day 1, 14:00: Cron scheduled at 02:00 daily on a jump box. (Systemd timer mfi-delinquency.timer enabled.)
- Day 2, 02:00: Cron fires. (Script auths, search_read mfi.loan, computes tiers, writes back.)
- Day 2, 02:04: 8,431 loans tagged. (163 loans moved from tier 0 to tier 1; 22 to tier 2; 4 to tier 3.)
- Day 2, 08:00: Florence opens dashboard. (Tier-based pivot shows overnight delta; she actions tier 3 loans first.)
Outcome — Daily delinquency tiering automated without writing a custom REST endpoint. Performance: 8,431 loans tagged in 4 minutes (bulk write batches of 500).
Reference
Common JSON-RPC error codes
| Code | Message | Cause | Fix |
|---|---|---|---|
| 100 | BridgeERP Session Expired | Session cookie timed out | Re-authenticate |
| 200 | BridgeERP Server Error | Unhandled Python exception | Check the API Audit Log under Configuration → API / Integrations → API Logs |
| -32600 | Invalid Request | Malformed JSON-RPC payload | Validate JSON, check method/params |
| -32601 | Method not found | Wrong service or method name | Use 'object' service + execute_kw |
| -32602 | Invalid params | Wrong argument count or types | Match BridgeERP method signature exactly |
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| execute_kw returns 'access denied' on mfi.loan write. | Bound user lacks Loan Officer role. | Add the role at Settings > Users. |
| search_read returns empty list despite records existing. | Record rule filters them out for this user. | Check record rules on mfi.loan; may be branch-scoped. |
| Custom action throws 'AttributeError: action_approve'. | Module not installed on tenant or method renamed. | Confirm mfi_loan version; check method name with dir() via shell. |

