MambuPy for REST
REST module of MambuPy implements communication with Mambu using Mambu’s REST API.
V1 of MambuPy implements v1 of Mambu’s REST API. There’s work in progress to implement v2 of MambuPy, which will use Mambu’s REST API v2.
Basically, MambuPy REST is a set of classes in Python that uses requests module to communicate with Mambu’s REST API.
As all modules in MambuPy, REST module must be configured with a user with correct permissions with API access rights.
If you’re looking for MambuPy v2 REST developing status, documentation and design principles, please go here: MambuPy for REST V2
How MambuPy REST module works
Every MambuPy REST object inherits from a common class,
MambuPy.rest.mambustruct.MambuStruct
.
Also, there are two types of MambuPy REST objects: single entities, and iterable entities.
Single entities simply inherit from MambuStruct.
Iterable entities also inherit from MambuStruct but also implement the Iterator protocol.
Since everything is related to Mambu’s REST API, it all boils down to JSON objects. If translated to python, JSON objects are either: dictionaries or lists (either of which may recursively include more dictionaries, lists, and of course plain data)
Single entities from Mambu
When you get a single entity from Mambu (say Client, Group, Loan Account, etc.), you usually request a GET operation and Mambu responds with a corresponding JSON object, such as:
{
"encodedKey": "abcdef1234567890",
"id": "ABC432",
"creationDate": "2022-05-03T21:00:00-05:00",
"accountState": "ACTIVE",
"disbursementDetails": {
"encodedKey": "987654321fedcba",
"disbursementDate": "2022-05-04T12:00:05-05:00"
},
"_list_of_values_in_set_cf": [
{
"some_value": "12345.67",
"another": "TESTING1"
},
{
"some_value": "0.0",
"another": "TESTING2"
}
]
}
As you can observe, you can, if you wish, translate this as a Python dictionary, having some keys with string values, and having others with lists and dictionaries, which in turn may have more nested data structures:
d = {"encodedKey": "abcdef1234567890",
"id": "ABC432",
"creationDate": "2022-05-03T21:00:00-05:00",
"accountState": "ACTIVE",
"disbursementDetails": {
"encodedKey": "987654321fedcba",
"disbursementDate": "2022-05-04T12:00:05-05:00"
},
"_list_of_values_in_set_cf": [
{"some_value": "12345.67",
"another": "TESTING1"
},
{"some_value": "0.0",
"another": "TESTING2"}]}
The principal design decision we made on MambuPy is to directly exploit this feature and translate the JSON objects to Python objects.
The other important decision is that MambuPy translates the data from the JSON object directly to python’s native data. For example, when the data can be translated in to a floating point number, the resulting dictionary gets a floating point number as its value. The following are the the data types detected by MambuPy, directly translated as python’s native types:
int
, for instance"123"
is translated as123
float
,"123.45"
is translated as123.45
datetime.datetime
, it’s not a native type, but we consider it to be of really high value to convert it. There are some gotchas to consider when using datetime objects, as any developer using datetimes may know. Please refer to the corresponding section below.str
are the default case, every other case not being able to be converted to some of the previous types is left as is.
All else been given, the result of this conversion would result on the following dictionary:
d = {"encodedKey": "abcdef1234567890",
"id": "ABC432",
"creationDate": datetime(2022, 5, 3, 21, 0),
"accountState": "ACTIVE",
"disbursementDetails": {
"encodedKey": "987654321fedcba",
"disbursementDate": datetime(2022, 5, 4, 12, 0, 5)
},
"_list_of_values_in_set_cf": [
{"some_value": 12345.67,
"another": "TESTING1"
},
{"some_value": 0.0,
"another": "TESTING2"}]}
In essence, that would be the way MambuPy objects work, they store
this dictionary inside itselves (in a property named
MambuPy.rest.mambustruct.MambuStruct.attrs
). In fact, every
MambuPy object has dictionary-like behaviour, since this data is what
in essence conforms the entity in Mambu.
Several other methods, besides the dictionary-like ones, support this objects.
Every module at MambuPy.rest
has a single-entity class used
to instantiate single entities from Mambu.
When you wish to instantiate certain Mambu entity, you give the entity’s Mambu ID to its constructor. If the ID exists in Mambu, the object will be instantiated.
Iterable entities from Mambu
Iterable entities implement the Iterator protocol.
MambuPy.rest.mambustruct.MambuStructIterator
class enables
iteration. It implements the iterator.__next__()
method.
Several modules at MambuPy.rest
have iterable entities
classes used to instantiate iterable entities from Mambu. Its name is
usually the single-entity class, pluralized. This class implements the
iterator.__iter__()
method, which in turn returns a
MambuPy.rest.mambustruct.MambuStructIterator
object.
When you wish to instantiate several Mambu entities, you give several filters to its constructor. When requested, MambuPy converts the resulting list in a list of single-entity classes.
urlfuncs
MambuPy uses certain functions to build the URL to contact and request Mambu’s REST API.
MambuPy.mambuutil
holds a lot of functions that in
themselves call MambuPy.mambuutil.getmambuurl()
. The purpose
of this function is to build a str
with the URL to access
some Mambu’s API endpoint.
Each urlfunc function is named getSOMETHINGurl
. Its signature is usually:
def getSOMETHINGurl(idSOMETHING, *args, **kwargs)
idSOMETHING
refers to the ID of the SOMETHING
entity at Mambu
(there are some exceptions to this rule).
idSOMETHING
is generally (but not always) optional. When you do
not supply an entity’s id to certain Mambu’s REST API endpoint results
in a request whose response is a list (which as you may recall is
converted into the Iterable entities from Mambu)
kwargs
usually has the query parameters for the URL. This
parameters implement functionality as generic as offsets and limits
for certain endpoint, but also filters that the endpoint gives to
filter out entities from Mambu using the request URL.
The real trick with urlfuncs is that, every MambuPy’s REST class uses
one as default. For instance,
MambuPy.rest.mambuclient.MambuClient
uses
MambuPy.mambuutil.getclienturl()
, so you don’t usually
have to worry about them.
HOWEVER, power users of MambuPy’s REST module can tweak their default use to take advantage of certain endpoints. Let’s talk it through an example:
MambuPy.rest.mambuloan.MambuLoan
uses
MambuPy.mambuutil.getloansurl()
as default. This default
behaviour builds the following URL to request certain loan account
at Mambu:
GET /loans/LOAN_ID
Which will result in a single or iterable
MambuPy.rest.mambuloan.MambuLoan
. If you don’t provide a
specific LOAN_ID
, you will get several
MambuPy.rest.mambuloan.MambuLoans
, depending on the
additional filters you give to the kwargs
parameter.
However, you can change the default urlfunc that MambuLoan
accepts, changing it for example with
MambuPy.mambuutil.getgrouploansurl()
, building the following
URL:
GET /groups/GROUP_ID/loans
which will respond with the list of loan accounts
(MambuPy.rest.mambuloan.MambuLoans
) belonging to a certain
group.
So, using the same class, MambuLoan
, you get for free two
different endpoints, /loans/LOAN_ID
and
/groups/GROUP_ID/loans
, depending only on the urlfunc you pass to
MambuLoan's
constructor. Remember that not providing any urlfunc
will use getloansurl
as default.
The connect() method
Now that we know what we need: a dictionary-like object with
properties acquired from the response in JSON from Mambu, request done
using certain urlfunc,
MambuPy.rest.mambustruct.MambuStruct.connect()
glues all this
together following this recipe:
determine the type of request to do (basically the HTTP verb, which depends on certain data present on the object)
using the given urlfunc (which may be the default one for the object), make the corresponding request to Mambu
the resulting JSON is then preprocessed: if Mambu gave an error (say for an invalid Mambu ID), a
MambuPy.mambuutil.MambuError
is thrownif no error was thrown by Mambu,
MambuPy.rest.mambustruct.MambuStruct.init()
is called, which basically executes some custom preprocessing, converts the JSON to adict
and them some custom postprocessing may be executed
The MambuPy.rest.mambustruct.MambuStruct.connect()
also
catches comm errors. If for some reason Mambu is down,
MambuPy.mambuutil.MambuCommError
is thrown.
- The following are the methods involved in step 4:
MambuPy.rest.mambustruct.MambuStruct.convertDict2Attrs()
Pagination
Also, when retrieving several objects (when the JSON response is a
list
), Mambu has some restrictions on how many objects will
be retrieved
(MambuPy.mambuutil.OUT_OF_BOUNDS_PAGINATION_LIMIT_VALUE
),
which basically means pagination must be used. Well, if you like it
that way, you can paginate it yourself.
We thinked it in another manner. We believe this details should be (at
least optionally) omitted. So,
MambuPy.rest.mambustruct.MambuStruct.connect()
also has
default logic to make the pagination for you, and join every single
item you requested in a resulting big list with all the info you
need.
The pro: forget about managing pagination logic by yourself. The cons:
you may end up with some really BIG structures, and the number of the
requests made to Mambu may be of a considerable size too. See the
documentation for the limit argument on
MambuPy.rest.mambustruct.MambuStruct.__init__()
Configuration
As you may read at MambuPy.mambuconfig
, REST configuration
consists of the following options:
MambuPy.mambuconfig.apiurl
- the URL of the Mambu tenant you use.MambuPy.mambuconfig.apiuser
- a Mambu user with API permissionsMambuPy.mambuconfig.apipwd
- the password of the user
As MambuPy.mambuconfig
documentation tells, you can set
these on /etc/mambupyrc
, $HOME/.mambupy.rc
, on an ini-format style. Home directory RC
file overrides what /etc
file says.
You can also set the environment variables: MAMBUPY_APIRUL
,
MAMBUPY_APIUSER
and MAMBUPY_APIPWD
, which override what RC
files say.
datetime objects gotchas
As you may read at https://docs.python.org/3/library/datetime.html#aware-and-naive-objects, datetime objects may be aware or naive.
Aware datetime objects know about timezones and daylight saving time information. Naive objecst on the other hand do not.
The most simple use of datetime objects is when you use them as naive. Using the aware feature complicates things a little. On the flip side being able to differentiate time zones on datetime objects gives you the ability to make date and time equivalencies, specially when treating with dates and times across the world.
Mambu gives timezone information insied every datetime field it uses. MambuPy v1’s REST module on the other hand uses naive mode. v2 for MambuPy supports aware mode too.
Examples
Steps to instantiate a certain MambuEntity (a
MambuPy.rest.mambuclient.MambuClient
for example):
Get the Mambu’s entity ID, and the level of detail you wish to retrieve.
Import the correct module from MambuPy:
from MambuPy.rest import mambuclient
Instantiate the object you are retrieving:
client = mambuclient.MambuClient(entid="MY_CLIENT_ID")
Go to MambuPy.rest
for the complete API reference.
API Docs
The API documentation is hold at the docstrings of every file at the
MambuPy.rest
module.