- 21 Jan 2025
- 8 Minutes To Read
- Print
- DarkLight
- PDF
Audit Trail V2
- Updated On 21 Jan 2025
- 8 Minutes To Read
- Print
- DarkLight
- PDF
The Audit Trail capability tracks all activities that were performed in the Mambu Core Banking Engine via either the UI or the V1 and V2 API. Audit records are grouped per tenant. Audit records include who did what and when. You can search and filter through stored events using an API (example requests are provided below).
A key difference between Audit Trail and Activities is Audit Trail’s ability to track both changes to your system, as well as system access history, due to the support for not only write operations such as POST, PUT, DELETE, and PATCH; but also GET (read) operations. This provides more granular user activity tracking, which is not possible in Activities.
Some example use cases might be:
- Investigate suspicious activity or potential fraud.
- Detect actions performed by an unauthorized user.
- Monitor and gather data about specific activities or users.
- Track failed login attempts (e.g. brute force attack upon your system).
- Generate compliance and audit reports from audit data.
Use of Audit Trail requires API Consumers, which is an Early Access feature. For more information see Authentication below.
Audit Trail V2 release information
Audit Trail V2 includes some significant improvements over V1, and some changes which may break your current implementation. Before upgrading to the /v2/events
endpoints, please refer to the extensive documentation on this page and the items listed in Backwards Compatibility to ensure that your migration process is smooth.
Data retention
We start storing events from the point that the Audit Trail feature is enabled. By default, events in Production are stored for 5 years, but only 6 months in Sandbox. After this period, events are irreversibly deleted.
If you want to change the production retention period for Audit Trail, please contact your CSM.
Service quota
- Each tenant receives 1 request per second for the
/v2/events
endpoint. Requests above this amount will be throttled and an exception will be returned. Here is an example of an exception:
HTTP Status: 429
{"message": "Throttling: API request limit exceeded"}
- With one search request you can access up to 50,000 records. The default limit for search requests is 10,000 records.
- Each call to the API will scan a certain amount of bytes. Depending on your Audit Trail tier, you are entitled to a certain amount of bytes to scan per year. Upon breaching the limit, we will inform you about it.
- You can only retrieve up to 30 days of usage history per request to safeguard against using up your quota. For example, you can scan from 01/01/2025 -> 30/01/2025, and then from 31/01/2025 -> 28/02/2025.
- Depending on your Audit Trail tier, you are entitled to a certain amount of storage. Upon breaching the limit, we will inform you about it and discuss further steps - either to increase the tier or remove old data.
Authentication
To authenticate audit trail requests you must use an API key generated by an API consumer that has the Manage Audit Trail (MANAGE_AUDIT_TRAIL
) permission assigned to it. For more information, see API Consumers.
Headers
Other than the authentication header with the API key, you do not need to use any additional headers.
Supported operations
Base URL: https://TENANT_NAME.mambu.com/api
Action | Endpoint | Description |
---|---|---|
GET | /v2/events | Retrieve a list of events. |
GET | /v2/events/metadata | Get information on how much data has been scanned. |
Events requests
The following section shows sample requests using curl. For all examples, replace TENANT_NAME
with your actual tenant URL.
Sample request
Get all UI login activities for two days:
curl 'https://TENANT_NAME.mambu.com/api/v2/events?occurred_at\[gte\]=2025-01-03T00:00:00Z&occurred_at\[lte\]=2025-01-04T23:59:59Z&event_source\[eq\]=UI&resource\[eq\]=login' \
--header 'apikey: {apikey}'
{apikey}
is an API key from the Audit Trail API consumer. For more information, see Authentication above.
Sample response
{
"events": [
{
"occurred_at": "2024-01-03T07:04:39.278Z",
"response_code": 200,
"resource": "login",
"event_source": "UI",
"client_ip": "3.73.218.49",
"request_method": "POST",
"request_payload": "{\"username\":[\"johnsmith\"],\"loginType\":[\"onlineLogin\"]}",
"resource_fragment": "/servlet/login",
"request_uri": "/servlet/login",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"response_payload": "SUCCESS",
"username": "johnsmith"
},
... more events
],
"totalItemsCount": 10000,
"bytesScanned": 1492285679,
"hasMore": true,
"nextStartTime": "2025-01-04T00:03:13.000Z"
}
Pagination
All results are ordered by the occurred_at
timestamp field in ascending order.
From the sample response, there are two parameters which help with pagination. When you scan a certain period, you will receive 10,000 events by default, and up to 50,000. However, if for a given period there are more events than 10,000/50,000 then hasMore: true
will indicate that. To fetch the next batch of events, you have to provide the nextStartTime
value to the occurred_at[gte]
query parameter. Taking the previous response body, the query will look like this:
curl 'https://TENANT_NAME.mambu.com/api/v2/events?occurred_at\[gte\]=2025-01-04T00:03:13.000Z&occurred_at\[lte\]=2025-01-04T23:59:59Z&event_source\[eq\]=UI&resource\[eq\]=login' \
--header 'apikey: {apikey}'
Additional sample requests
Get API requests with failed authorization:
curl 'https://TENANT_NAME.mambu.com/api/v2/events?event_source\[eq\]=API&response_code\[eq\]=401&occurred_at\[gte\]=2024-02-01&occurred_at\[lte\]=2024-03-01' \
--header 'apikey: {apikey}'
See what changes were made in a given month to clients by user 'john':
curl 'https://TENANT_NAME.mambu.com/api/v2/events?event_source\[eq\]=UI&resource\[eq\]=clients&request_method\[eq\]=PUT&username\[eq\]=john&occurred_at\[gte\]=2024-02-01&occurred_at\[lte\]=2024-03-01' \
--header 'apikey: {apikey}'
Check who manually sent an SMS or an email:
curl 'https://TENANT_NAME.mambu.com/api/v2/events?event_source\[eq\]=UI&resource\[eq\]=notifications&request_method\[eq\]=POST&occurred_at\[gte\]=2024-02-01&occurred_at\[lte\]=2024-03-01' \
--header 'apikey: {apikey}'
Track administrative users' logins:
curl 'https://TENANT_NAME.mambu.com/api/v2/events?event_source\[eq\]=UI&resource\[eq\]=login&occurred_at\[gte\]=2024-02-01&occurred_at\[lte\]=2024-03-01&username\[in\]=admin1,admin2' \
--header 'apikey: {apikey}'
Parameters
The following parameters can be used to filter your requests:
Name | Description | Required |
---|---|---|
FIELD_NAME[OPERATOR]=FIELD_VALUE | A filter using a LHS bracket with an operator. There can be more than one filter used per request. For a list of field names, see Field Names below. For a list of available operators, see Operators below. | Search window is required. Field occurred_at should contain lt/lte and gt/gte values. |
limit | The number of events that will be returned. By default, this is 10,000 events. You can increase it up to 50,000 events. However, note that latency will be increased with more events that need to be returned. | No |
Field names
Event fields | Description | Supported operators |
---|---|---|
event_source | The events that are supposed to be audited fall within the following categories: API , UI . | eq , ne , in |
request_uri | The part of the request's URL after the base URL and up to the query string. | eq , ne , in , contains |
request_method | HTTP request method (GET , POST , PUT , etc). | eq , ne , in |
request_payload | The raw request data as a string, with sensitive information removed. For more information, see Security. Parameter may be empty. | eq , ne , in , contains |
user_agent | The value of HTTP user agent header. | eq , ne , in , contains |
resource | For API requests, this value is obtained from parsing the URL. For example for /api/clients the resulting value is "clients". | eq , ne , in , contains |
resource_fragment | For API requests this holds the request URI. For UI operations this holds the raw URL hash. | eq , ne , in , contains |
username | The user who carried out the action or the name of the API consumer (may be empty). | eq , ne , in , contains |
client_ip | IP address from http request or X_FORWARDED_FOR header if present. | eq , ne , in |
response_code | HTTP response code. | eq , ne , in , gt , gte , lt , lte |
occurred_at | The timestamp, in UTC, when the event has been generated (when creating queries on this field the provided values must be in ISO8601 standard). | gt , gte , lt , lte |
response_payload | The raw response payload with sensitive information removed (see details in note below). A response payload is not included with every record. | eq , ne , in , contains |
Operators
Operator | Description | Example |
---|---|---|
eq | Equals - exact match, applies to any type of fields. | username[eq]=demo@mambu.com |
ne | Not equals, applies to any type of fields. | username[ne]=demo@mambu.com |
gt | Greater than, applies to numeric or date fields. | occurred_at[gt]=2018-05-01 |
gte | Greater than or equal, applies to numeric or date fields. | occurred_at[gte]=2018-05-01 |
lt | Less than, applies to numeric or date fields. | occurred_at[lt]=2018-05-01 |
lte | Less than or equal, applies to numeric or date fields. | occurred_at[lte]=2018-05-01 |
in | Element in list (exact match), applies to any type of fields. | username[in]= user1@mambu.com,user2@mambu.com |
contains | Operator allows searching for specific substrings or variables within a field. It supports partial matches, making it possible to find results even if the exact value isn't provided. However, this operator does not support searching for multiple elements simultaneously. | request_payload[contains]= "provisionedThroughFederation" |
Error responses
- If
occurred_at
value is not provided:
{
"errors": [
{
"message": "occurred_at[gte] or occurred_at[gt] filter is required. occurred_at[lte] or occurred_at[lt] filter is required."
}
],
"status": 400
}
- If date value is incorrect:
{
"errors": [
{
"message": "Invalid value <invalid value> for occurred_at field. Must be a valid date in ISO8601 standard."
}
],
"status": 400
}
- If the incorrect filter is provided:
{
"errors": [
{
"message": "Invalid filter occurred_at, must use LHR brackets with an operator syntax"
}
],
"status": 400
}
- When
limit
exceeds the highest threshold:
{
"errors": [
{
"message": "Limit exceed. The maximum allowed limit is 50000."
}
],
"status": 400
}
- When the query time range exceeds the limit of 30 days:
{
"errors": [
{
"message": "The maximum allowed time range is 30 days."
}
],
"status": 400
}
Events Search Metadata endpoint
To track how much data has been scanned by each request, you can use the response payload’s bytesScanned
field in your metrics. Audit Trail tracks this information as well and it can be accessed via the /v2/events/metadata
API. A metadata query looks like this:
curl 'https://TENANT_NAME.mambu.com/api/v2/events/metadata' \
--header 'apikey: {apikey}'
Response:
{"tenantId":<TENANT_NAME>,"bytesScanned":108301221}
Search response time
Search metadata via the Audit Trail API becomes available in 15 minutes sequences. In other words, if you’ve search on 15:46:00 UTC, then metadata will be updated and available at 16:02:00. If you’ve searched at 16:14:00 UTC, then the metadata will be updated and available at 16:17:00. Otherwise, the response will contain the previous cached value.
Best practices
- Limit your scans to the smallest timeframes possible. The less data that needs to be scanned, the faster the response will be. Furthermore, you will spend less of your quota.
- Use
contains
(see Operators) with smaller timeframes. - Periodically pulling batches of all records (or a big subset) is possible, but not the recommended approach.
Security
For security reasons, the following information is removed from request payloads when using Audit Trail:
PASSWORD
PAGINATION_DETAILS
FETCHING_INFO
MOBILE_PHONE
EMAIL_ADDRESS
ADDRESSES
BIRTH_DATE
MOBILE_PHONE1
MOBILE_PHONE2
FIRST_NAME
LAST_NAME
HOME_PHONE
MIDDLE_NAME
NOTES
GROUP_NAME
ADDRESS_LINE_1
ADDRESS_LINE_2
ADDRESS_LATITUDE
ADDRESS_LONGITUDE
DESCRIPTION
TITLE
TEXT
ASSET_NAME
LOAN_NAME
NAME
POST_CODE
COUNTRY
REGION
GENDER
IBAN