MambuPy Cookbook
Tip
This guide offers a complete collection of recipes and practical examples for working with MambuPy. It covers everything from initial installation and setup to advanced operations with the Mambu API. Whether you’re starting with integration or looking to implement specific functions, you’ll find clear code examples and detailed explanations for each key aspect of the library.
Installation of MambuPy
MambuPy works on Python >3.8
Installation using pip
pip install MambuPy
Similarly, MambuPy covers other aspects for interacting with Mambu. There is an ORM module with SQLAlchemy mappings for querying a backup of Mambu’s database dump. However, you may not want to install that feature. You may access this features by installing:
pip install MambuPy[full]
There are other optional dependencies you can isntall, mostly for developing MambuPy
pip install MambuPy[dev,devtools,doc]
Installation using uv
uv pip install MambuPy
Configuration of MambuPy
There are four ways to configure MambuPy, listed here in order of priority (highest to lowest)
1. Environment Variables
Environment variables have the highest priority and will override any other configuration:
export MAMBU_API_URL=yourtenant.sandbox.mambu.com
export MAMBU_API_USER=yourapiuser
export MAMBU_API_PWD=your_secret_password
2. Configuration via RC File
MambuPy will search for RC files in this order, overwriting values as it finds consecutive files containing the same configuration variables:
In the system’s global directory:
/etc/mambupy.rcIn the user’s home directory:
~/.mambupy.rc(this is a hidden file in your account’s$HOMEdirectory)
The RC file must have the following format:
[API]
apiurl=yourtenant.sandbox.mambu.com
apiuser=yourapiuser
apipwd=your_secret_password
# comments can be included
# and there may be more configurations not mentioned here
# See mambuconfig documentation for more details
If a variable value exists in /etc/mambupy.rc, and then another
value for the same variable exists in ~/.mambupy.rc, the value
from the latter file is used. In any other case, both files complement
each other.
3. Configuration via Code
If no environment variables or RC files are found, you can use values for these variables programmatically using MambuPy’s configuration module:
from mambupy import mambuconfig
# Basic configuration
mambuconfig.apiurl = "yourtenant.sandbox.mambu.com"
mambuconfig.apiuser = "yourapiuser"
mambuconfig.apipwd = "your_secret_password"
Note
Configuration priority order:
Code configuration (using
mambuconfig)Environment variables (
MAMBU_*).mambupy.rcfile in HOME directorymambupy.rcfile in/etc
Warning
- SECURITY NOTE: When using multiple configuration methods, ensure
credentials are properly protected in all storage locations. For the file in
/etc, it’s recommended to set restrictive permissions (600) and root ownership. For code configurations, ensure proper versioning, or no versioning, of credentials that must remain private.
Basic Recipes
1. Working with Clients (MambuClient)
Clients in Mambu represent individual persons. Here are some usage examples:
from mambupy.api.mambuclient import MambuClient
# Get a specific client by ID
client = MambuClient.get("0512N0025") # detailsLevel="BASIC" by default
# Read basic client information
print(f"Name: {client.firstName} {client.lastName}")
print(f"ID: {client.id}")
print(f"State: {client.state}")
# MambuPy entity properties can also be accessed using dictionary-style interface:
print(f"Name: {client['firstName']} {client['lastName']}")
print(f"ID: {client['id']}")
print(f"State: {client['state']}")
# You can get the same entity using its Mambu encodedKey:
client = MambuClient.get("8a099a673f1f25a0013f1fd0a1c318a5")
# Get all client details, including custom fields:
client = MambuClient.get("24N12345", detailsLevel="FULL")
print(f"ID: {client.id}")
print(f"Addresses: {client.addresses}") # list of MambuAddress VOs
print(f"ID Documents: {client.idDocuments}") # list of MambuIDDocument VOs
print(f"A custom fields group: {client._customfields_integrante}") # as they come from Mambu
print(f"Another custom fields group: {client._datoscrediticios_integrante}")
# MambuPy extracts each field,
# and converts it to a MambuPy object and sets it as an entity property:
print(
f"One of the fields from _customfields_integrante group:
{client.Actividad_economica_Clients}"
) # MambuEntityCF VO
# Get multiple clients with filters
clients = MambuClient.get_all(
limit=50, # Results limit
offset=0, # Page start
filters={
"firstName": "JOSEFA",
"state": "ACTIVE"
}
)
for client in clients:
print(f"Client {client.id}: {client.firstName} {client.lastName}")
# Search clients with advanced search
clients = MambuClient.search(
filterCriteria=[
{"field": "firstName", "operator": "EQUALS", "value": "JOSEFA"}
]
)
Note
About pagination: if you don’t send a limit argument, BY
DEFAULT MambuPy will handle downloading ALL entities that match the
criteria (and there could be MANY) by properly paginating Mambu
requests in chunks given by the apipagination config
(default=50). BE CAREFUL with resource usage in these cases!
2. Working with Groups (MambuGroup)
Groups allow grouping clients and managing group loans. Usage examples:
from mambupy.api.mambuclient import MambuClient
from mambupy.api.mambugroup import MambuGroup
# Get a specific group by ID
group = MambuGroup.get("24G23446")
# View group information
print(f"Group name: {group.groupName}")
print(f"ID: {group.id}")
# Get multiple groups with filters
groups = MambuGroup.get_all(
limit=20,
offset=0,
filters={
"creditOfficerUsername": "a.alas"
}
)
for group in groups:
print(f"Group: {group.groupName}")
print(f"Status: {group.loanCycle}")
# To get details like group members,
# the group must be instantiated using detailsLevel="FULL"
group = MambuGroup.get("25G54321", detailsLevel="FULL")
members = group.groupMembers
for member in members: # MambuClient instances still need to be instantiated one by one
client = MambuClient.get(member.clientKey)
print(f"Member {client.id}: {client.firstName} {client.lastName}")
3. Working with Loans (MambuLoan)
Loans represent loan accounts. Usage examples:
from mambupy.api.mambuloan import MambuLoan
# Get a specific loan by ID
loan = MambuLoan.get("54321")
# View basic loan information
print(f"Loan ID: {loan.id}")
print(f"Status: {loan.accountState}")
# MambuPy automatically converts data types obtained via REST:
print(f"Disbursement date: {loan.disbursementDetails.disbursementDate}") # datetime object
print(f"Amount: {loan.loanAmount}") # float
# Get multiple loans with filters
loans = MambuLoan.get_all(
limit=100,
offset=0,
filters={
"accountState": "ACTIVE_IN_ARREARS",
"creditOfficerUsername": "a.alas",
}
)
for loan in loans:
print(f"Loan ID: {loan.id}")
print(f"Amount: {loan.loanAmount}")
print(f"Status: {loan.accountState}")
# Get the loan holder (can be client or group)
holder = loan.get_accountHolder() # instantiates a MambuPy entity
if loan.accountHolderType == 'GROUP':
print(f"Holder (Group) {holder.id}: {holder.groupName}")
else:
print(f"Holder (Client) {holder.id}: {holder.firstName} {holder.lastName}")
# Get payment schedule
loan.get_schedule() # loan.schedule property doesn't exist before this
installments = loan.schedule
for installment in installments:
print(f"Installment: {installment.number}")
print(f"Status: {installment.state}")
print(f"Due date: {installment.dueDate}")
print(f"Principal paid: {installment.principal['amount']['paid']}")
# Get transactions
loan.get_transactions() # loan.transactions property doesn't exist before this
transactions = loan.transactions
for transaction in transactions:
print(f"Transaction: {transaction.id}")
print(f"Type: {transaction.type}")
print(f"Date: {transaction.valueDate}")
print(f"Amount: {transaction.amount}")
4. Working with Branches, Centres and Users
Branches, centres and users are important organizational elements in Mambu. Here are some examples of how to work with them:
MambuBranch
from mambupy.api.mambubranch import MambuBranch
# Get a specific branch
branch = MambuBranch.get("CCAZ")
print(f"Branch: {branch.name}")
print(f"State: {branch.state}")
# Get all branches
branches = MambuBranch.get_all()
for branch in branches:
print(f"ID: {branch.id}, Name: {branch.name}")
MambuCentre
from mambupy.api.mambucentre import MambuCentre
# Get a specific unit
centre = MambuCentre.get("TribeAZ-1")
print(f"Unit: {centre.name}")
print(f"Branch: {centre.assignedBranchKey}")
# Get all units
centres = MambuCentre.get_all()
for centre in centres:
print(f"ID: {centre.id}, Name: {centre.name}")
# Get units belonging to a specific branch:
centres = MambuCentre.get_all(
filters={
"branchId": "CCAZ",
}
)
MambuUser
from mambupy.api.mambuuser import MambuUser
# Get a specific user
user = MambuUser.get("a.alas", detailsLevel="FULL")
print(f"User: {user.firstName} {user.lastName}")
print(f"Role: {user.role}") # role doesn't come with detailsLevel "BASIC"
# instantiate user's role in a MambuRole entity,
# replacing the role property with the instantiated object:
user.get_role()
print(f"Role: {user.role}") # MambuRole object
# Get all users from a specific branch
users = MambuUser.get_all(
filters={"branchId": "CCAZ"}
) # BEWARE of missing limit parameter!
# MambuPy will download by pages according to mambuconfig.apipagination config
# but without a limit, it will make as many requests as needed
# to exhaust all entities from Mambu
Assignments and Relationships
from mambupy.api.mambuclient import MambuClient
from mambupy.api.mambugroup import MambuGroup
from mambupy.api.mambuloan import MambuLoan
# Check client assignments
client = MambuClient.get("0512N0025")
# Branch
print(f"Assigned branch: {client.assignedBranchKey}")
# instantiate the branch assigned to the client:
client.get_assignedBranch()
print(f"Assigned branch: {client.assignedBranch}") # MambuBranch object
# Centre
print(f"Assigned centre: {client.assignedCentreKey}")
# instantiate the centre assigned to the client:
client.get_assignedCentre()
print(f"Assigned centre: {client.assignedCentre}") # MambuCentre object
# NOTE: if an entity doesn't have an assignment level, e.g. user,
# MambuPy would raise an exception
# Also works with Groups
group = MambuGroup.get("24G23446")
print(f"Assigned officer: {group.assignedUserKey}")
# instantiate the user assigned to the group
group.get_assignedUser()
print(f"Assigned officer: {group.assignedUser}") # MambuUser object
# And also works with Loans
loan = MambuLoan.get("54321")
print(f"Assigned branch: {loan.assignedBranchKey}")
print(f"Assigned centre: {loan.assignedCentreKey}")
print(f"Assigned officer: {loan.assignedUserKey}")
loan.get_assignedBranch()
loan.get_assignedCentre()
loan.get_assignedUser()
Note
These get_assigned* methods create properties in the object and
contain the complete instance of the related entity. It’s more
efficient than creating instances manually, avoiding the need to
remember the property with the related encodedKey, and allows
direct access to all attributes of the related object.
Important
Assignments are crucial for hierarchical organization in Mambu. A client must always be assigned to a branch and can be assigned to a centre and a credit officer. The same applies to groups. These assignments are automatically inherited by the loan accounts of the client or group owner of the account.
5. Advanced Searches
Examples of more complex searches. See more information about their usage in the Mambu API documentation:
from mambupy.api.mambugroup import MambuGroup
from mambupy.api.mambuloan import MambuLoan
# Search loans by specific criteria
loans = MambuLoan.search(
filterCriteria=[
{"field": "accountState", "operator": "EQUALS", "value": "ACTIVE_IN_ARREARS"},
{"field": "amount", "operator": "MORE_THAN", "value": 750000}
],
limit=20
) # here we are limiting the maximum results, no matter how many there are in
# Mambu, it will only bring 20. You can use this argument along with offset to
# paginate on your own. If you omit the limit parameter, MambuPy will handle
# this bringing ALL entities that meet the criteria in chunks of
# mambuconfig.apipagination, which may delay an excessive time to load, or even
# fill your computer's RAM after a while
6. Exception Handling
MambuPy maintains an exception handling scheme for most error conditions. While this handling decision is opinionated, the exception structure maintains consistency regarding the meaning of thrown exceptions, and also responds to the library’s objective of abstracting low-level details of the way it communicates with the Mambu API, including details such as format (json), protocol (HTTP), and therefore also response codes.
Note
An exception from Mambu whose response includes an
errorCodeis handled asMambuError. AllerrorCodeshandled by Mambu are documented here. See more information in the Mambu API documentation.An exception derived from the inability to contact the Mambu API is handled as
MambuCommError. AMambuCommErroris a type ofMambuError.Any other exception thrown directly by MambuPy is handled as
MambuPyError. All exceptions thrown by MambuPy, includingMambuErrorand thereforeMambuCommErrorareMambuPyError.
Generic MambuPy error, in this case for sending an argument with an invalid type
from mambupy.api.mambuclient import MambuClient
clients = MambuClient.get_all(
limit=10,
offset="0" # offset parameter must be an int
)
Would throw the following exception
MambuPyError: offset must be integer
Tries to instantiate a client that doesn’t exist in Mambu:
from mambupy.api.mambuclient import MambuClient
client = MambuClient.get("I DONT EXIST")
Exception (note the errorCode: 301, and the response code also
included: 404)
MambuError: 301 (404) - INVALID_CLIENT_ID
log:
404 Client Error: for url: https://podemos.sandbox.mambu.com/api/clients/NOEXISTO?detailsLevel=BASIC on GET request: params {'detailsLevel': 'BASIC'}, data None, headers [('Accept', 'application/vnd.mambu.v2+json'))]
HTTPError, resp content: b'{"errors":[{"errorCode":301,"errorReason":"INVALID_CLIENT_ID"}]}'
Invalid credentials
mambuconfig.apipwd="BLAHBLAHBLAH" # assuming there's no environment variable or mambupy.rc file with this configuration set
client = MambuClient.get("0512N0025")
Exception (errorCode: 2, response code: 401)
MambuError: 2 (401) - INVALID_CREDENTIALS (credentials)
log:
401 Client Error: for url: https://podemos.sandbox.mambu.com/api/clients/0512N0025?detailsLevel=BASIC on GET request: params {'detailsLevel': 'BASIC'}, data None, headers [('Accept', 'application/vnd.mambu.v2+json')]
HTTPError, resp content: b'{"errors":[{"errorCode":2,"errorSource":"credentials","errorReason":"INVALID_CREDENTIALS"}]}'
Invalid URL
mambuconfig.apiurl="BLAHBLAHBLAH" # assuming there's no environment variable or mambupy.rc file with this configuration set
client = MambuClient.get("0512N0025")
Exception
MambuCommError: Unknown comm error with Mambu: HTTPSConnectionPool(host='BLAHBLAHBLAH', port=443): Max retries exceeded with url: /api/clients/0512N0025?detailsLevel=BASIC (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x706a6a2cb4d0>: Failed to resolve 'BLAHBLAHBLAH' ([Errno -2] Name or service not known)"))
log:
HTTPSConnectionPool(host='BLAHBLAHBLAH', port=443): Max retries exceeded with url: /api/clients/0512N0025?detailsLevel=BASIC (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x706a6a2cb4d0>: Failed to resolve 'BLAHBLAHBLAH' ([Errno -2] Name or service not known)")) Exception () on GET request: url https://BLAHBLAHBLAH/api/clients/0512N0025, params {'detailsLevel': 'BASIC'}, data None, headers [('Accept', 'application/vnd.mambu.v2+json')]
Note
By the way, MambuPy performs up to 5 retry attempts to contact Mambu in case of failure (response codes 429, 502, 503 or 504)
Next Recipes
Todo
Custom Fields Search
Entity Updates
Updating Custom Fields
Entity Creation
Approving, Disbursing, Paying and Closing a Loan Account
Account and Group Reassignment
Reassignment of Users with Assigned Accounts and Groups
Using an Entity with Different Authentication Credentials than the ones Configured by default
How to configure logging for MambuPy