IDs
Every resource ID is exposed as a string.- Treat IDs as opaque. Do not parse them as integers in your client code; future versions may switch to UUIDs.
- Pass them back exactly as received.
- Path params accept the same string format:
GET /v1/customers/42.
"productId": 1). Responses always come back as strings. One
deliberate exception: customerId on
POST /v1/loans carries the customer’s externalId
(a string), not the numeric LMS id — see below.
externalIds
Every customer and loan also carries a partner-suppliedexternalId —
a string you choose (account number, MSISDN, your own UUID, a wallet
transaction reference). The LMS enforces uniqueness across customers
on one externalId space and across loans on another.
externalIds are the primary integration key — drive your
integration off the identifiers you already store and skip the mapping
back to numeric LMS ids. Prefer the externalId form everywhere you can.
Where externalIds work
Two distinct namespaces
- A customer externalId identifies a person/account.
- A loan externalId identifies one specific loan.
customerExternalId for customer-scoped filters,
customer_external_id on customer resource paths,
loan_external_id on loan-scoped paths (single-loan reads and the
whole repayment family). A loan list filtered by
customerExternalId returns N loans; a single-loan path like
/loans/external/{loan_external_id} or
/loans/external/{loan_external_id}/repayments/... targets one
specific loan.
Limitations
PUT /v1/loans/{loan_id}(update) and thewriteoffendpoint are numeric-id only. The wallet-rollback hot path (undo-disbursal → undo-approval → delete) is fully externalId-addressable.
Errors
- Unknown externalId on a path lookup →
404 not_foundfrom the upstream LMS. - Unknown externalId on a query filter (
?externalId=,?customerExternalId=) → empty page (total: 0, items: []), preserving the list response shape.
Dates
All dates on the wire are ISO-8601YYYY-MM-DD strings.

