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.

RASP Callbacks

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.

Malware Callbacks

Callbacks are also triggered when an APK linked to an application transitions between malware states:

Callback type Description
MALWARE_DETECTED An APK linked to the application was classified as malware.
MALWARE_REMOVED An APK previously classified as malware was unlinked from the application, or is not classified as malware anymore.
MALWARE_HEALED The application no longer has any malware-classified APK of a specific malware type linked, having had at least one before.

A callback is dispatched only when the malware type is BANKER.

Like RASP callbacks, malware callbacks are replayed on a Client ID update: the platform replays all previously recorded malware detection, removal, and healed events for the device, subject to the same BANKER-only dispatch filter described above.

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 iap_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 iap_app_type_callback_config (app_type_id, url, retry_attempts, retry_backoff)
VALUES (
    (SELECT id FROM iap_app_type WHERE source_package_name = 'com.example.app'),
    'https://custom-system.example.com/webhook',
    3,
    'PT2S'
);

Authentication

Callbacks can be secured using mutual TLS (mTLS). Authentication is configured by storing a JSON document in the authentication column of the iap_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 INAPPPROTECTION_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
event.type string Callback type: DEVICE_SECURITY_VIOLATED, DEVICE_SECURITY_RESTORED, MALWARE_DETECTED, MALWARE_REMOVED or MALWARE_HEALED
event.info.type string Name of the flag that changed for DEVICE_SECURITY_VIOLATED / DEVICE_SECURITY_RESTORED callbacks, malware type for malware callbacks (always BANKER)
event.info.name String Application name (present only for malware callbacks)
event.info.packageName String Application package name (present only for malware callbacks)
event.info.apkSignature String Application signature (present only for malware callbacks)
event.info.installation.timestamp long Unix timestamp in seconds of first detection of an application installation (present only for malware callbacks)
event.info.installation.installer string Identification of the installer (present only for malware callbacks)
event.timestamp long Unix epoch timestamp in seconds when the flag change was detected
device.appPackageName string Package name of the mobile application
device.audienceGroupId string Distinguishes users from different customer systems (e.g. RETAIL, CORPORATE)
device.clientDeviceId string Customer-assigned device ID
device.clientId string Customer-assigned client ID
device.deviceId string (UUID) System-assigned device ID
device.timestampFirstSeen long Unix epoch timestamp in seconds when the device was first registered
device.timestampLastSeen long Unix epoch timestamp in seconds of the most recent activity
device.sourcePackageName string Package name of the source application
device.sourceInstaller string Package name of the installer that distributed the source application
device.deviceInfo.os string Operating system name (e.g. android, huawei, ios, mac_os, tv_os)
device.deviceInfo.platform string Platform identifier: android or apple
device.deviceInfo.brand string Device manufacturer brand
device.deviceInfo.model string Device model identifier
device.deviceInfo.versionSdkInt integer Operating system version
device.deviceInfo.versionSecurityPatch string Security patch level of the operating system
device.deviceInfo.versionRelease string The user-visible version string
device.deviceInfo.versionIncremental string The value used by the underlying source control to represent the device firmware build
device.deviceInfo.tags string Tags describing the operating system build
device.flags[].name string Name of the flag associated with the device.
device.flags[].score integer Risk score associated with the flag
device.flags[].timestamp long Unix epoch timestamp in seconds when the flag was detected
device.malware[].type string Type of the detected malware (always BANKER). Present only for malware callbacks, empty otherwise
device.malware[].name string Application name of the malware APK
device.malware[].packageName string Package name of the malware APK
device.malware[].apkSignature string SHA-256 digest of the malware APK
device.malware[].installation.timestamp long Unix epoch timestamp in seconds when the malware APK was first linked to the application
device.malware[].installation.installer string Package name of the installer that distributed the malware APK, if known
device.highestApkThreat.name string Name of the highest evaluated threat level for the application’s linked APK (e.g. MALWARE, DANGEROUS), omitted if not evaluated
device.highestApkThreat.score integer Score of device.highestApkThreat.name
device.highestDeviceThreat.name string Name of the highest-scoring flag currently assigned to the device.
device.highestDeviceThreat.score integer Score of device.highestDeviceThreat.name

The device.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: RASP Callback

{
  "event": {
    "info": {
      "type": "ROOTED"
    },
    "type": "DEVICE_SECURITY_VIOLATED",
    "timestamp": 1745490600
  },
  "device": {
    "appPackageName": "com.wultra.trader",
    "audienceGroupId": "RETAIL",
    "clientDeviceId": "device-abc",
    "clientId": "user-123",
    "deviceId": "f3a1c2e4-0000-0000-0000-000000000001",
    "timestampFirstSeen": 1735689600,
    "timestampLastSeen": 1745490600,
    "sourcePackageName": "com.wultra.test",
    "sourceInstaller": "com.google.android.packageinstaller",
    "deviceInfo": {
      "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": 1745490600
      },
      {
        "name": "DEVELOPER_MODE",
        "score": 70,
        "timestamp": 1745490300
      }
    ],
    "malware": [],
    "highestApkThreat": {
      "name": "SAFE",
      "score": 0
    },
    "highestDeviceThreat": {
      "name": "ROOTED",
      "score": 90
    }
  }
}

Example: Malware Callback

{
  "event": {
    "info": {
      "name": "CoinBase",
      "type": "BANKER",
      "packageName": "net.bhldc.kuxz",
      "apkSignature": "54eeef11a8197e686b7827e180b0e8d8fee4882ae4af67828dd7e11140d708ac",
      "installation": {
        "installer": "com.google.android.packageinstaller",
        "timestamp": 1785640763
      }
    },
    "type": "MALWARE_DETECTED",
    "timestamp": 1785640766
  },
  "device": {
    "appPackageName": "com.wultra.test.bank",
    "audienceGroupId": "RETAIL",
    "clientDeviceId": "167662723c2ace97",
    "clientId": "user-123",
    "deviceId": "226d7c8d-4abe-442b-acd1-e6c440598785",
    "timestampLastSeen": 1785640763,
    "timestampFirstSeen": 1785640722,
    "sourcePackageName": "cz.csob.smart",
    "sourceInstaller": "com.android.vending",
    "deviceInfo": {
      "os": "android",
      "tags": "release-keys",
      "brand": "Redmi",
      "model": "23108RN04Y",
      "platform": "android",
      "versionSdkInt": 35,
      "versionRelease": "15",
      "versionIncremental": "OS2.0.210.0.VGPEUXM",
      "versionSecurityPatch": "2026-05-01"
    },
    "malware": [
      {
        "name": "CoinBase",
        "type": "BANKER",
        "packageName": "net.bhldc.kuxz",
        "apkSignature": "54eeef11a8197e686b7827e180b0e8d8fee4882ae4af67828dd7e11140d708ac",
        "installation": {
          "installer": "com.google.android.packageinstaller",
          "timestamp": 1785640763
        }
      }
    ],
    "flags": [
      {
        "name": "ROOTED",
        "score": 90,
        "timestamp": 1745490600
      },
      {
        "name": "DEVELOPER_MODE",
        "score": 70,
        "timestamp": 1745490300
      }
    ],
    "highestApkThreat": {
      "name": "MALWARE",
      "score": 100
    },
    "highestDeviceThreat": {
      "name": "ROOTED",
      "score": 90
    }
  }
}
Last updated on Aug 13, 2026 (05:46) Edit on Github Send Feedback

develop

In-App Protection