Callbacks

The In-App Protection platform supports integration through HTTP callbacks. When a security-relevant state change is detected on a device, the Integration API sends an HTTP POST request to a pre-configured URL. This allows external systems to receive security events without active polling.

Callbacks are triggered when a set of critical security flags assigned to a device changes. Following flag types are currently classified as critical:

Flag Description
JAILBROKEN The device has been jailbroken (iOS)
ROOTED The device has been rooted (Android)
UNWANTED_APPS A potentially harmful application is installed

When any of the listed critical flags is assigned to a device, a DEVICE_SECURITY_VIOLATED callback type is sent. When any of the listed critical flags is unassigned from a device, a DEVICE_SECURITY_RESTORED callback type is sent. Note that DEVICE_SECURITY_RESTORED does not imply the device is fully secure — other critical flags may still be active. Each callback represents a single flag change. If multiple critical flags change simultaneously, a separate callback is generated for each individual change.

Additionally, when a Client ID is updated, the platform replays all previously recorded critical flag changes for the device. This ensures that the external system can associate the device’s security history with the updated user identity.

Configuration

Callback delivery is configured per application type. Each configuration entry defines a target endpoint and delivery behavior. Multiple entries can be defined for the same application type, in which case each configured endpoint receives its own HTTP POST request for every event.

Configuration is stored in the mlw_app_type_callback_config database table and must be managed directly at the database level.

Configuration Fields

Column Type Default Description
app_type_id integer   Identifier of the application type to which this configuration applies
url varchar(2048)   Destination URL for the HTTP POST
retry_attempts integer 3 Maximum number of retry attempts after a failed delivery
retry_backoff varchar(64) PT2S Delay between retry attempts, in ISO 8601 duration format (e.g., PT2S = 2 seconds)
authentication text   JSON-serialized authentication configuration (see below)

Example of Inserting a Callback Configuration

INSERT INTO mlw_app_type_callback_config (app_type_id, url, retry_attempts, retry_backoff)
VALUES (
    (SELECT id FROM mlw_app_type WHERE name = 'com.example.app'),
    'https://custom-system.example.com/webhook'
);

Authentication

Callbacks can be secured using mutual TLS (mTLS). Authentication is configured by storing a JSON document in the authentication column of the mlw_app_type_callback_config. The structure is as follows:

{
  "certificate": {
    "enabled": true,
    "useCustomKeyStore": true,
    "keyStoreLocation": "classpath:keystore.p12",
    "keyStoreContent": "<base64-encoded-keystore>",
    "keyStorePassword": "secret",
    "keyAlias": "client",
    "keyPassword": "secret",
    "useCustomTrustStore": true,
    "trustStoreLocation": "classpath:truststore.p12",
    "trustStoreContent": "<base64-encoded-truststore>",
    "trustStorePassword": "secret",
    "handshakeTimeout": "PT10S"
  }
}

Key and trust material can be provided either as a file location (keyStoreLocation, trustStoreLocation) or as base64-encoded content (keyStoreContent, trustStoreContent). If the authentication field is NULL or enabled is set to false, no authentication is applied.

The Web Client configuration used for callback delivery is cached for performance reasons. The cache is refreshed according to the MLW_CALLBACK_WEBCLIENT_REFRESHCACHEAFTER configuration, by default every 5 minutes. When updating the callback configuration, update also the timestamp_last_updated column.

Callback Request

HTTP Method and Headers

Callbacks are delivered as HTTP POST requests.

Header Description
Idempotency-Key A UUID uniquely identifying the callback request. Can be used by the recipient to deduplicate deliveries in at-least-once scenarios.
Content-Type application/json

Request Body

The request body is a JSON object with the following structure:

Field Type Description
type string Callback type: DEVICE_SECURITY_VIOLATED or DEVICE_SECURITY_RESTORED
flagName string Name of the flag that changed
timestamp long Unix epoch timestamp in milliseconds when the flag change was detected
application.appPackageName string Package name of the mobile application
application.clientDeviceId string Customer-assigned device ID
application.clientId string Customer-assigned client ID
application.deviceId string (UUID) System-assigned device ID
application.timestampFirstSeen long Unix epoch timestamp in milliseconds when the device was first registered
application.timestampLastSeen long Unix epoch timestamp in milliseconds of the most recent activity
application.sourcePackageName string Package name of the source application
application.sourceInstaller string Package name of the installer that distributed the source application
application.device.os string Operating system name (e.g. android, huawei, ios, mac_os, tv_os)
application.device.platform string Platform identifier: android or apple
application.device.brand string Device manufacturer brand
application.device.model string Device model identifier
application.device.versionSdkInt integer Operating system version
application.device.versionSecurityPatch string Security patch level of the operating system
application.device.versionRelease string The user-visible version string
application.device.versionIncremental string The value used by the underlying source control to represent the device firmware build
application.device.tags string Tags describing the operating system build
application.flags[].name string Name of the flag associated with the device
application.flags[].score integer Risk score associated with the flag
application.flags[].timestamp long Unix epoch timestamp in milliseconds when the flag was detected

The application.flags field represents all flags currently active on the device at the time of dispatching. When a callback is replayed (for example, after a client ID change), the flags reflect the active state at the time of replay, not at the time of the original event.

Example

{
  "type": "DEVICE_SECURITY_VIOLATED",
  "flagName": "ROOTED",
  "timestamp": 1745490600000,
  "application": {
    "appPackageName": "com.wultra.trader",
    "clientDeviceId": "device-abc",
    "clientId": "user-123",
    "deviceId": "f3a1c2e4-0000-0000-0000-000000000001",
    "timestampFirstSeen": 1735689600000,
    "timestampLastSeen": 1745490600000,
    "sourcePackageName": "com.wultra.test",
    "sourceInstaller": "com.google.android.packageinstaller",
    "device": {
      "os": "android",
      "platform": "android",
      "brand": "Samsung",
      "model": "SM-G950F",
      "versionSdkInt": 28,
      "versionSecurityPatch": "2019-08-01",
      "versionRelease": "9",
      "versionIncremental": "G950FXXS5DSH8",
      "tags": "release-keys"
    },
    "flags": [
      {
        "name": "ROOTED",
        "score": 90,
        "timestamp": 1745490600000
      },
      {
        "name": "DEVELOPER_MODE",
        "score": 70,
        "timestamp": 1745490300000
      }
    ]
  }
}
Last updated on Apr 30, 2026 (13:00) Edit on Github Send Feedback
Search

develop

In-App Protection