Malwarelytics API
Malwarelytics is a mobile threat intelligence - a solution that protects mobile apps from various cybersecurity issues. Malwarelytics API connects the Malwarelytics data to your systems, such as anti-fraud solution or SIEM.
The Malwarelytics API consists of the following services:
- The Event Queue API handles use-cases related to managing a queue of security-related events with get or truncate commands.
- The Devices API handles use-cases related to managing a queue of security-related events with get or truncate commands.
Malwarelytics API is located on the following address:
https://api.malwarelytics.com/
The Malwarelytics API uses JSON format for every request and response. Use Content-Type: application/json
header when calling any of the APIs:
Content-Type: application/json
Swagger Documentation
Next to the documented APIs here on our developer portal, we also publish documentation in the Swagger format:
You can access all the links above with an integration role user, or with any of your Malwarelytics console users.
Authentication
Use Malwarelytics console or contact us to obtain HTTP basic credentials. Please note that for the call to Device API you can use standard console user with Member role or integration user with Integration role. The Event Queue API requires a user with the role Integration.
HTTP basic authentication is used to protect all API endpoints:
Authorization: Basic base64_encoded_username_colon_password_value
Error Handling
In the case of an error, all endpoints return the response in the following format:
{
"status": "ERROR",
"responseObject": {
"code": "${ERROR_CODE}",
"message": "${ERROR_MESSAGE}"
}
}
Attribute | Type | Description |
---|---|---|
status * |
String |
Always the ERROR string. |
responseObject.code * |
String |
Error code. |
responseObject.message * |
String |
Error message with more info about the issue. |
Failing the Basic Request Validation
If request validation fails on the syntactic level, the service will return 400 Bad Request
response with the following extended structure:
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_REQUEST",
"message": "Description of the request constraint violation."
}
}
Attribute | Type | Description |
---|---|---|
status * |
String |
Always the ERROR string. |
responseObject.code * |
String |
Error code, always the value ERROR_REQUEST . |
responseObject.message * |
String |
Information about the violation. |
Event Queue API
The architecture of Event Queue API is based on a simple principle of queued events. The aim is to let you know about all important events as soon as we know it. All important events generated by Malwarelytics are stored to a unique queue belonging to one corresponding origin application. Only a user with rights on this origin application can read or truncate the events.
The Event Queue API can be easily used for data ingests when integrating a Fraud Detection System (FDS). By knowing new malware infections or healed devices, the FDS behavior can be configured according to security requirements.
A queued event will be automatically evicted after 4 days from its creation.
get /api/v1/event-queue Get Events
The service returns events from the queue matching provided timestamp filter and paging criteria. The returned events are in ascending order.
Request
Query Params
Param | Type | Description |
---|---|---|
timestampFrom |
Long |
Unix timestamp in seconds from which to obtain the events, default: now minus one hour. |
timestampTo |
Long |
Unix timestamp in seconds to which to obtain the events, default: now. |
page |
Long |
Number of a page (starts from 0) to get, default = 0. |
size |
Long |
Size of a page (number of events), default = 500, maximum = 500. |
Response
On a successful call the API will return matching events.
{
"timestampFrom": 1627033204,
"timestampTo": 1627036804,
"timestampLast": 1627036801,
"numberOfElements": 1,
"page": 0,
"size": 500,
"totalElements": 1,
"totalPages": 1,
"log": [
{
"event": {
"type": "MALWARE_DETECTED",
"timestamp": 1627036801,
"info": {
"type": "BANKER",
"name": "Facebook",
"packageName": "bmdit.bmdit.bmdit",
"apkSignature": "428f3988b9be5304c644e5d17c74ea81d17fceb9ee11c6e2d5a3842c296a5b5f",
"installation": {
"timestamp": 1627036754,
"installer": "com.google.android.packageinstaller"
}
}
},
"device": {
"appPackageName": "com.wultra.trader",
"audienceGroupId": "Distinguishes users from different customer systems (RETAIL, CORPORATE, ...)",
"clientDeviceId": "4aaa7e6d-42ef-42b8-82e5-ad5dcfaaf509",
"clientId": "813dfc77-6c44-4640-bb42-0c8db686851b",
"deviceId": "a08771d4-7d46-4ef8-8b02-b4c0d93123d6",
"timestampFirstSeen": 1627035554,
"timestampLastSeen": 1627036754,
"sourcePackageName": "com.wultra.test",
"sourceInstaller": "com.google.android.packageinstaller",
"deviceInfo": {
"os": "android",
"platform": "android",
"brand": "SAMSUNG",
"model": "SM-G950F",
"modelName": "Galaxy S8",
"versionSdkInt": 28,
"versionSecurityPatch": "2019-08-01",
"versionRelease": "9",
"versionIncremental": "G950FXXS5DSH8",
"tags": "release-keys"
},
"malware": [
{
"type": "BANKER",
"name": "Facebook",
"packageName": "bmdit.bmdit.bmdit",
"apkSignature": "428f3988b9be5304c644e5d17c74ea81d17fceb9ee11c6e2d5a3842c296a5b5f",
"installation": {
"timestamp": 1627036754,
"installer": "com.google.android.packageinstaller"
}
}
],
"flags": [
{
"name": "ROOTED",
"timestamp": 1627035554
},
{
"name": "DEVELOPER_MODE",
"timestamp": 1627035554
},
{
"name": "NO_SCREEN_LOCK",
"timestamp": 1627035554
}
]
}
}
]
}
Attribute | Type | Description |
---|---|---|
timestampFrom * |
Long |
Unix timestamp in seconds from which to obtain the events, returned a value from the request. |
timestampTo * |
Long |
Unix timestamp in seconds to which to obtain the events, returned a value from the request. |
timestampLast |
Long |
Unix timestamp in seconds of the most latest returned event. |
numberOfElements * |
Long |
Actual number of returned events. |
page * |
Long |
Number of a page to get, returned a value from the request. |
size * |
Long |
Size of a page, returned a value from the request. |
totalElements * |
Long |
Number of all events matching the timestamp filter. |
totalPages * |
Long |
Number of all pages. |
log * |
Object[] |
Currently matching events. |
log[].event * |
Object |
Information about an event on a device. |
log[].event.type * |
String |
Type of the event. One of enum values: MALWARE_DETECTED, MALWARE_HEALED, MALWARE_REMOVED. |
log[].event.timestamp * |
Long |
Unix timestamp in seconds of the even. |
log[].event.info.type * |
String |
Type of the malware, enum value BANKER. |
log[].event.info.name |
String |
Application name. |
log[].event.info.packageName * |
String |
Application package name. |
log[].event.info.apkSignature * |
String |
Application signature. |
log[].event.info.installation * |
Object |
Information about an application installation. |
log[].event.info.installation.timestamp * |
Object |
Unix timestamp in seconds of first detection of an application installation. |
log[].event.info.installation.installer |
Object |
Identification of the installer. |
log[].device * |
Object |
Information about a device from the time when the event occurred. |
log[].device.appPackageName |
String |
Distinguishes application purposes or segmentation in one organization (com.wultra.bank, com.wultra.trader, …) |
log[].device.audienceGroupId |
String |
Distinguishes users from different customer systems (RETAIL, CORPORATE, …) |
log[].device.clientId |
String |
Client identification assigned by the source application. |
log[].device.clientDeviceId |
String |
Client device identification assigned by the source application. |
log[].device.deviceId * |
String |
Device identification assigned by Malwarelytics. |
log[].device.timestampFirstSeen * |
Long |
Unix timestamp in seconds of the first time the device has been seen. |
log[].device.timestampLastSeen * |
Long |
Unix timestamp in seconds of the last time the device has been seen. |
log[].device.sourcePackageName * |
String |
Identification of the source application integrating the Malwarelytics SDK. |
log[].device.sourceInstaller * |
String |
Identification of the installer of the application integrating the Malwarelytics SDK. |
log[].device.deviceInfo * |
Object |
Detail information about the device. |
log[].device.deviceInfo.os * |
String |
In the case of android one of enum values: android, huawei. In the case of apple one of enum values: iOS, macOS, tvOS. |
log[].device.deviceInfo.platform * |
String |
Type of the platform. One of enum values: android, apple. |
log[].device.deviceInfo.brand * |
String |
Brand of the device. |
log[].device.deviceInfo.model * |
String |
Model of the device. |
log[].device.deviceInfo.modelName * |
String |
Marketing name of the device model. |
log[].device.deviceInfo.versionIncremental * |
String |
The value used by the underlying source control to represent the device firmware build. |
log[].device.deviceInfo.versionSdkInt * |
Long |
Operating system version. |
log[].device.deviceInfo.versionSecurityPatch |
String |
Security patch level of the operating system. |
log[].device.deviceInfo.versionRelease * |
String |
The user-visible version string. |
log[].device.deviceInfo.tags |
String |
Tags describing the operating system build. |
log[].device.flags |
Object[] |
Information about insecure flags present on the device. |
log[].device.flags[].name |
String |
Name of the insecure flag. One of enum values: EMULATOR, JAILBROKEN, REPACKAGED_SOURCE, ROOTED, NO_BIOMETRY, NO_SCREEN_LOCK. |
log[].device.flags[].score |
String |
Score of the insecure flag. |
log[].device.flags[].timestamp |
Long |
Unix timestamp in seconds of the first time this flag was detected on the device |
log[].device.highestApkThreat |
Object |
Highest threat level among installed APKs. |
log[].device.highestApkThreat.name |
String |
Application threat level name. |
log[].device.highestApkThreat.score |
Long |
Application threat score. |
log[].device.highestDeviceThreat |
Object |
Highest device threat. |
log[].device.highestDeviceThreat.name |
String |
Device threat name. |
log[].device.highestDeviceThreat.score |
Long |
Device threat score. |
log[].device.malware[].type |
String |
Type of the malware. |
log[].device.malware[].name |
String |
Application name. |
log[].device.malware[].packageName |
String |
Application package name. |
log[].device.malware[].apkSignature |
String |
Application signature. |
log[].device.malware[].installation |
Object |
Information about this malware installation. |
log[].device.malware[].installation.timestamp |
Long |
Unix timestamp in seconds of first detection of this malware installation. |
log[].device.malware[].installation.installer |
String |
Identification of the installer. |
Invalid request data or query parameters were provided while calling the API.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Not readable request body"
}
}
Invalid username or password was provided while calling the API.
Error occurred while calling the internal service.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Unknown error occurred"
}
}
post /api/v1/event-queue/truncate Truncate Events
Truncates from the queue all events up to the provided timestamp. All events are automatically truncated after 4 days from the creation.
Request
Query Params
Param | Type | Description |
---|---|---|
timestampTo * |
Long |
Unix timestamp in seconds to which truncate the events to. |
Response
{
"status": "OK"
}
Devices API
The API returns information about devices and device details. The typical use-cases of such API are:
- Multi-accounting attack prevention
- Limiting the user device count
- Obtaining the threats on a given device
The mobile app developer does not have access to extended device details directly on the device, neither does the developer have access to the value of a raw device fingerprint that is used under the hood to identify the same devices. As a result, the developer must initialize the Malwarelytics SDK and use the deviceId
value during the server call.
One typical use-case is evaluating a device security policy during the user registration. The application sends the device ID value to the server with the registration call, and the service that is responsible uses the device ID to obtain detailed device information from the Malwarelytics API. The registration back-end service then uses the provided information about device to determine the eligibility, and to provide appropriate response to the client app.
The following diagram visualizes the process:
get /api/v1/devices/${deviceId} Get Device Information
The API obtains information about a given device. Besides the generic device information, it also returns a history of the user identifiers (client IDs) that were assigned to the device. This way, it is possible to determine (according to the internal rules you define) if the device has been “multi-accounted”.
Multi-accounting is a situation where an attacker pairs multiple victim accounts to the same device.
The information about the device details is obtained using the ${deviceId}
attribute which is available from the Malwarelytics SDK. Malwarelytics correctly re-attaches the same device when the ${deviceId}
changes based on the back-end device fingerprinting mechanics.
Request
Path Params
Param | Type | Description |
---|---|---|
deviceId |
UUID |
Identifier of the device obtained via the Malwarelytics SDK, sometimes referred to as avUid . |
Query Params
Each of the following flags requires additional data collection from our systems and therefore, it makes the response a bit slower. Therefore, for performance reasons, we recommend requesting only the data that your application needs to make appropriate decisions. This is also a good practice from the data protection perspective - you should only work with the data that are essential for your application.
Param | Type | Description |
---|---|---|
includeClientIdHistory |
boolean |
Specifies if clientIdHistory (list with the history of client IDs on the device) should be included in the response (default: false ). |
includeCustomEvents |
boolean |
Specifies if customEvents (list with the history of custom events on the device) should be included in the response (default: false ). |
includeDeviceInfo |
boolean |
Specifies if deviceInfo (attribute with a detailed information the mobile device) should be included in the response (default: false ). |
includeFlags |
boolean |
Specifies if flags (attribute with an information about security related flags) should be included in the response (default: false ). |
includeMalware |
boolean |
Specifies if malware (attribute with an information about malware on the device) should be included in the response (default: false ). |
Response
{
"clientId": "813dfc77-6c44-4640-bb42-0c8db686851b",
"deviceId": "a08771d4-7d46-4ef8-8b02-b4c0d93123d6",
"timestampFirstSeen": 1627035554,
"timestampLastSeen": 1627036754,
"sourcePackageName": "com.wultra.test",
"sourceInstaller": "com.google.android.packageinstaller",
"highestApkThreat": {
"name": "MALWARE",
"score": 100
},
"highestDeviceThreat": {
"name": "DEVELOPER_MODE",
"score": 70
},
"deviceInfo": {
"os": "android",
"platform": "android",
"brand": "SAMSUNG",
"model": "SM-G950F",
"modelName": "Galaxy S8",
"versionSdkInt": 28,
"versionSecurityPatch": "2019-08-01",
"versionRelease": "9",
"versionIncremental": "G950FXXS5DSH8",
"tags": "release-keys"
},
"malware": [
{
"type": "BANKER",
"name": "Facebook",
"packageName": "bmdit.bmdit.bmdit",
"apkSignature": "428f3988b9be5304c644e5d17c74ea81d17fceb9ee11c6e2d5a3842c296a5b5f",
"installation": {
"timestamp": 1627036754,
"installer": "com.google.android.packageinstaller"
}
}
],
"flags": [
{
"name": "ROOTED",
"timestamp": 1627035554
},
{
"name": "DEVELOPER_MODE",
"timestamp": 1627035554
},
{
"name": "NO_SCREEN_LOCK",
"timestamp": 1627035554
}
],
"clientIdHistory": [
{
"clientId": "813dfc77-6c44-4640-bb42-0c8db686851b",
"timestampCreated": 1627036754
},
{
"clientId": "1213dfc33-3ca8-167f-ffce-1d5d22268cba",
"timestampCreated": 1627033154
}
],
"customEvents": [
{
"name": "USER_REGISTERED",
"severity": "INFO",
"timestampCreated": 1627036754
},
{
"name": "GENERIC_EVENT",
"severity": "INFO",
"parameters": {
"key_1": "value",
"key_2": 123,
"key_nested": {
"key": "value"
}
},
"timestampCreated": 1627033154
}
]
}
Invalid request data or query parameters were provided while calling the API.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Not readable request body"
}
}
Invalid username or password was provided while calling the API.
Device with the specified deviceId
value has not been found.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Resource has not been found"
}
}
Error occurred while calling the internal service.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Unknown error occurred"
}
}
post /api/v1/devices/${deviceId}/events Add an Event to a Device
The API allows to add an event to the device. This could be helpful for example to track actions which should be limited to occurrences (e.g. to allow one account registration on a device).
Request
- Headers:
Content-Type: application/json
{
"name": "USER_REGISTERED",
"severity": "INFO",
"parameters": {
"key_1": "value",
"key_2": 123,
"key_nested": {
"key": "value"
}
}
}
Path Params
Param | Type | Description |
---|---|---|
deviceId |
UUID |
Identifier of the device obtained via the Malwarelytics SDK, sometimes referred to as avUid . |
Response
{
"status": "OK"
}
Invalid request data were provided while calling the API.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Not readable request body"
}
}
Invalid username or password was provided while calling the API.
Error occurred while calling the internal service.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Unknown error occurred"
}
}
get /api/v1/clients/${clientId}/devices Get Client Devices
For a given client ID (which is a value from your user ID space), this API call returns a basic information about the devices that our systems can see for the given client. You can then use the GET /api/v1/devices/${deviceId}
call to obtain extended details of each device, if needed.
Request
Path Params
Param | Type | Description |
---|---|---|
clientId |
String |
Identifier of the client. The value represents an identifier in your user space and it can be in any format (example uses UUID). |
Response
{
"clientId": "813dfc77-6c44-4640-bb42-0c8db686851b",
"devices": [
{
"deviceId": "a08771d4-7d46-4ef8-8b02-b4c0d93123d6",
"timestampFirstSeen": 1627035554,
"timestampLastSeen": 1627036754,
"sourcePackageName": "com.wultra.test",
"sourceInstaller": "com.google.android.packageinstaller",
"deviceInfo": {
"os": "android",
"platform": "android",
"brand": "SAMSUNG",
"model": "SM-G950F",
"modelName": "Galaxy S8",
"versionSdkInt": 28,
"versionSecurityPatch": "2019-08-01",
"versionRelease": "9",
"versionIncremental": "G950FXXS5DSH8",
"tags": "release-keys"
}
}
]
}
Invalid username or password was provided while calling the API.
Error occurred while calling the internal service.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Unknown error occurred"
}
}
Callback API
The following APIs serve for testing HTTP callback (aka webhooks). You can use e.g. webhook.site for testing it.
post /api/v1/callback/trigger-basic Trigger a Basic Callback
On a successful call the API will trigger a basic callback and return its result. The request body of the callback will be
{
"requestObject": {
"data": "value"
}
}
Request
- Headers:
Content-Type: application/json
{
"callbackUrl": "https://callback-test.malwarelytics.com/api/v1/endpoint"
}
Attribute | Type | Description |
---|---|---|
callbackUrl * |
String |
API url value for the HTTP callback. |
httpMethod |
String |
HTTP method used for the callback, default: POST. |
Response
On a successful call the API will return the callback result.
{
"status": "OK",
"responseObject": "response data"
}
Attribute | Type | Description |
---|---|---|
status * |
String |
Always the OK string. |
responseObject * |
String |
Response body from the callback. |
Invalid request data or query parameters were provided while calling the API.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Not readable request body"
}
}
Invalid username or password was provided while calling the API.
Error occurred while calling the internal service.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_GENERIC",
"message": "Unknown error occurred"
}
}