---
title: Risk Predictors
description: PingOne supports multiple risk predictors, which are intended to identify possible fraudulent user behaviors based on these criteria:
component: pingone-api
page_id: pingone-api:protect:risk-predictors
canonical_url: https://developer.pingidentity.com/pingone-api/protect/risk-predictors.html
section_ids:
  risk-predictor-evaluations: Risk predictor evaluations
  assigning-admin-roles-and-permissions-to-this-service: Assigning admin roles and permissions to this service
  base-risk-predictor-data-model: Base risk predictor data model
  composite-risk-predictor-data-model: Composite risk predictor data model
  traffic-anomaly-risk-predictor-data-model: Traffic anomaly risk predictor data model
  velocity-risk-predictor-data-model: Velocity risk predictor data model
  risk-predictors-events-generated: Risk predictors events generated
  custom-risk-predictors: Custom risk predictors
  ip-range-custom-predictor-sample-request-body: IP Range custom predictor - sample request body
  string-matching-custom-predictor-sample-request-body: String Matching custom predictor - sample request body
  numeric-range-custom-predictor-sample-request-body: Numeric Range custom predictor - sample request body
  composite-risk-predictors: Composite risk predictors
  deleting-risk-predictors: Deleting risk predictors
---

# Risk Predictors

PingOne supports multiple risk predictors, which are intended to identify possible fraudulent user behaviors based on these criteria:

* **Anonymous network detection**

  Malicious actors typically use anonymous networks, such as unknown VPNs, Tor, and proxies to mask their IP address. PingOne Protect analyzes IP address data from a user's device to determine if the address is originating from any type of anonymous network. If so, the user can be prompted for step-up authentication or denied access. PingOne Protect also supports creating a whitelist of networks, ensuring that legitimate VPN users can access authorized resources.

* **IP velocity**

  IP Velocity tracks the number of distinct IPs used per user. The threshold of the number of IPs per user is based on a statistical learning of the organization's past behavior. The risk predictor learns the mean average number of distinct IPs per user per unit of time (hour), and the standard deviation. The Risk Predictor then calculates the low, medium, and high thresholds of the number of IPs per user for the organization.

* **IP reputation**

  IP addresses that have been involved in malicious activities, such as distributed denial-of-service (DDoS) attacks or spam activity, are considered risky. The more frequently they are used for malicious activities, the higher their risk score. If a user attempts to access an application that is associated with an IP address previously involved with suspicious activity, the probability of potentially risky behavior increases. PingOne Protect analyzes data from different intelligence sources to determine the probability an IP address is associated with malicious activity and to request stronger authentication to verify the user's identity. It also supports creating a whitelist of networks, ensuring that legitimate VPN users can access authorized resources.

* **User velocity**

  User Velocity tracks the number of distinct users per IP. The threshold of the number of users per IP is based on a statistical learning of the organization's past behavior. The risk predictor learns the mean average number of distinct users per IP per unit of time (hour), and the standard deviation. The Risk Predictor then calculates the low, medium, and high thresholds of the number of users per IP for the organization.

* **User-based risk behavior**

  The user-based risk behavior predictor compares a transaction with the typical behavior of the specific user. For example, if a user accesses an application that they rarely use, user-based risk behavior detects an anomaly. User-based risk behavior is a machine-learning model that continuously updates. The machine-learning model characterizes abnormal activity as low, medium, or high risk.

* **Geovelocity anomaly**

  Users frequently sign on to the same application from multiple locations throughout the day. However, a time lapse between the current sign-on location and the previous location that is shorter than the time it would take to travel between the two points could indicate potentially suspicious activity. PingOne Protect analyzes location data to calculate if travel time between two session locations is physically possible. If the elapsed time is calculated to be impossible, the user can be prompted with step-up authentication or denied access. It also supports creating a whitelist of networks, ensuring that legitimate VPN users can access authorized resources.

* **User location anomaly**

  User Location Anomaly detects a user's login location and checks it against previously saved authentication locations. If an authentication attempt occurs at a location whose distance from the user's expected location is greater than the radius you defined, it is considered medium or high risk, depending on the extent of the deviation from the defined radius.

* **Bot detection**

  Analyzes multiple device and user behavior factors to detect non-human behavior, automated frameworks, and recorders during attempts to register or authenticate. This type of predictor requires use of the Signals (Protect) SDK.

* **New device**

  New device predictors allow your risk policy to take into account the risk associated with users trying to access applications from unknown devices or devices that have not been used for sign-on in the recent past.

  |   |                                                                                                                                                                                                                                                                                                                                                                                                                                 |
  | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | + NOTE: If you plan to include a new device predictor in your risk evaluations, your authentication flow must provide information that can be used to identify individual devices. The best way to do this is to [implement the PingOne Signals (Protect) SDK](/pingone/native-sdks/v1/api/#pingone-protect-native-sdks) in your web and mobile applications. This can also be done by providing a persistent cookie as input.+ |

* **Suspicious device**

  Checks for suspicious settings or mismatches between browser, operating system, and hardware attributes in order to detect situations such as emulators, superuser permissions, virtual machines, mirroring applications, and devices that have been tampered with. This type of predictor requires use of the Signals (Protect) SDK.

* **Adversary-in-the-Middle (AitM)**

  Adversary-in-the-Middle is a variant of Man-in-the-Middle attacks. In AitM, a malicious actor uses a reverse proxy to position themselves between a user and an online service in order to obtain user credentials and session tokens. This type of attack circumvents the protection usually provided by OTP-based multi-factor authentication, and is a common technique in phishing attempts. The predictor checks the domain name that the user is trying to access in order to identify AitM attacks. The AitM predictor requires use of the Signals (Protect) SDK.

* **Email reputation**

  Detects the use of disposable email addresses during registration. You can add the predictor to your risk policies, and you can also define a specific course of action if the `result.recommendedAction` field in the risk evaluation response indicates the use of a disposable email address.

* **Traffic Anomaly**

  Intended for detection of traffic anomalies in terms of variables such as users, devices, and sessions, the Traffic Anomaly predictor will eventually include a variety of rules, some of which you can select to enable or disable. Currently, the predictor detects situations where there are a large number of risk evaluations requested for a single user within a short period of time, and optionally can also detect situations where the number of users per device during a given period is suspicious. When this predictor returns a value of High, it is recommended that you deny access because the suspicious activity is likely due to malicious behavior.

* **PingID Device Trust**

  The PingID Device Trust predictor checks if a device is trusted by validating the trust created during the installation of the PingID Device Trust agent. Requires use of the Signals (Protect) SDK and that the agent be installed on user computers.

* **Custom risk predictors**

  You can create custom predictors to assign high, medium, or low risk level based on external data that you provide or data that is accessible via the PingOne API but not included in the out-of-the-box predictor types.

In addition to the standard risk predictors, each of which represents a single risk factor, you can create composite risk predictors for situations where you are interested in combining a number of risk factors into a single predictor. For example, a situation where you are concerned about the use of an anonymous network only in cases where a user location anomaly is also reported.

## Risk predictor evaluations

The `evaluatedPredictors` property in the policy set identifies the list of predictors (by ID) to be evaluated. If there is not enough data to assess a predictor level, the evaluation result does not assign any level to the predictor. In these cases, the response returns a `Not enough information to assess risk score` message.

When a predictor is added to a policy, regardless of the predictor weight, the predictor is evaluated when the policy is evaluated and its output appears in the `details` section of the risk service response. If you set the risk predictor's weight to 0, this predictor is evaluated but its risk assessment is not taken into account when calculating the risk score. Conversely, if the predictor is not added to the `evaluatedPredictors` property, or it was removed from the policy before evaluation, then the predictor is not evaluated and its output does not appear in the `details` section of the response.

## Assigning admin roles and permissions to this service

Admin role assignments determine access to PingOne APIs. When assigning admin roles to this service, refer to [PingOne Permissions by Service](../platform/reference/roles-and-permissions-in-pingone/permissions-by-service.html) for the service-specific permissions.

You can also choose to assign admin roles based on particular service resources. Refer to [PingOne Permissions by Resource](../platform/reference/roles-and-permissions-in-pingone/permissions-by-resource.html) when assigning admin roles per service resources.

Admin assignments to roles are set by:

* [Automatic assignment for some roles](../platform/roles/predefined-roles.html#automatic-role-assignment).

* [Group Role Assignments](../platform/group-role-assignments/group-role-assignments.html).

* [User Role Assignments](../platform/users/user-role-assignments.html).

Refer to [Roles Management](../platform/roles.html) for more information.

## Base risk predictor data model

| Property                          | Type    | Required?         | Mutable?  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| --------------------------------- | ------- | ----------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `activationAt`                    | Date    | Optional          | Mutable   | For New Device predictors, you can use the `activationAt` parameter to specify a date on which the learning process for the predictor should be restarted. This can be used in conjunction with the fallback setting (`default.result.level`) to force strong authentication when moving the predictor to production. The date should be in the form yyyy-mm-dd. Note that activation date uses UTC time.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `compactName`                     | String  | Required          | Immutable | A unique name for the predictor. The value must be alpha-numeric (case-sensitive), with no special characters or spaces. This name is used in the API both for policy configuration, and in the Risk Evaluation response (under `details`).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `createdAt`                       | Date    | N/A               | Read-only | The date the risk predictor was created (format ISO-8061).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `default`                         | Object  | Optional          | Mutable   | Contains the default values used for a new risk predictor.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `default.result`                  | Object  | Optional          | Mutable   | Contains the result assigned to the predictor if the predictor could not be calculated during the risk evaluation. If this field is not provided, and the predictor could not be calculated during risk evaluation:\* If the predictor is used in an override, the override is skipped.\* In a weighted policy, the predictor will have a weight of 0.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `default.result.level`            | String  | Optional          | Mutable   | The default result level. Options are `HIGH`, `MEDIUM`, and `LOW`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `default.result.type`             | String  | N/A               | Read-only | The default result type. Options are `VALUE`, indicating any custom attribute that's defined.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `default.score`                   | Integer | N/A               | Read-only | The score assigned to the risk predictor in a new policy by default.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `default.weight`                  | Integer | N/A               | Read-only | The weight assigned to the risk predictor in a new policy by default.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `description`                     | String  | Optional          | Mutable   | The description of the risk predictor. Maximum length is 1024 characters.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `detect`                          | String  | Optional/Required | Immutable | Used only for New Device, Suspicious Device, and PingID Device Trust predictors. These predictor types all use the value DEVICE for `type`. The `detect` field is used to specify the kind of devices you are trying to detect. The possible values are NEW\_DEVICE, SUSPICIOUS\_DEVICE, and PINGID\_TRUSTED\_DEVICE.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `includeRepeatedEventsWithoutSdk` | Boolean | Optional          | Mutable   | Relevant only for Bot Detection predictors. Set the value of `includeRepeatedEventsWithoutSdk` to `true` to expand the range of bot activity that PingOne Protect can detect.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `name`                            | String  | Required          | Mutable   | A unique, friendly name for the predictor. The `name` value is case (and space) sensitive. The API does not allow two predictors with the exact same name. However, the API does not restrict creating predictors with names such as `my name` and `My Name`. This name is displayed in the Risk Policies UI, when the admin is asked to define the overrides and weights.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `licensed`                        | Boolean | N/A               | Read-only | Indicates whether the environment has the license required for the predictor.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `shouldDetectCompromisedAccount`  | Boolean | Optional          | Mutable   | Relevant only for the User-based Risk Behavior predictor. Set `shouldDetectCompromisedAccount` to `true` if you want PingOne to attempt to detect compromised user accounts and take this into account when calculating the risk level for this predictor.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `shouldValidatePayloadSignature`  | Boolean | Optional          | Mutable   | Relevant only for Suspicious Device predictors. If `shouldValidatePayloadSignature` is set to `true`, then any risk policies that include this predictor will require that the Signals SDK payload be provided as a signed JWT whose signature will be verified before proceeding with risk evaluation. You instruct the Signals SDK to provide the payload as a signed JWT by using the `universalDeviceIdentification` flag during initialization of the SDK, or by selecting the relevant setting for the `skrisk` component in DaVinci flows.                                                                                                                                                                                                                                                                                                                                         |
| `type`                            | String  | Required          | Immutable | Any one of the following values: `ADVERSARY_IN_THE_MIDDLE`, `ANONYMOUS_NETWORK`, `BOT`, `COMPOSITE`, `DEVICE`, `EMAIL_REPUTATION`, `GEO_VELOCITY`, `IP_REPUTATION`, `MAP`, `TRAFFIC_ANOMALY`, `USER_LOCATION_ANOMALY`, `USER_RISK_BEHAVIOR`, `VELOCITY`. Note that the New Device, Suspicious Device, and PingID Device Trust predictors all use the type `DEVICE`. To differentiate between them, you use the `detect` field. For `COMPOSITE`, refer also to the [Composite risk predictor data model](#composite-risk-predictor-data-model) below. For `MAP`, refer also to [Custom risk predictors](#custom-risk-predictors) below. For `VELOCITY`, refer also to [Velocity risk predictor data model](#velocity-risk-predictor-data-model) below. For `TRAFFIC_ANOMALY`, refer also to [Traffic anomaly risk predictor data model](#traffic-anomaly-risk-predictor-data-model) below. |
| `updatedAt`                       | Date    | N/A               | Read-only | The date the risk predictor set was updated (format ISO-8061).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `whiteList`                       | List\[] | Optional          | Mutable   | For the `geoVelocity`, `ipReputation`, and `anonymousNetwork` predictors, use `whiteList` to specify IP addresses (CIDRs) that should be ignored by the predictor (usually because these are IPs you know are legitimate). The list can include IPs in IPv4 format and IPs in IPv6 format. For the `ADVERSARY_IN_THE_MIDDLE` predictor, use `whiteList` to specify the legitimate domains that your users will access for your restricted resources.                                                                                                                                                                                                                                                                                                                                                                                                                                      |

## Composite risk predictor data model

| Property                   | Type   | Required? | Mutable? | Description                                                                                                                                                                       |
| -------------------------- | ------ | --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `compositions`             | Array  | Required  | Mutable  | Contains the objects that specify the conditions to test and the risk level that should be assigned if the conditions are met. The array can contain a maximum of three elements. |
| `compositions[].condition` | Object | Required  | Mutable  | Specifies the set of conditions that are to be tested.                                                                                                                            |
| `compositions[].level`     | String | Required  | Mutable  | The risk level that should be assigned if the specified conditions are met. Can be `HIGH`, `MEDIUM`, or `LOW`.                                                                    |

## Traffic anomaly risk predictor data model

| Property                        | Type    | Required? | Mutable? | Description                                                                                                                                                    |
| ------------------------------- | ------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rules`                         | Array   | Required  | Mutable  | Collection of rules to use for this traffic anomaly predictor.                                                                                                 |
| `rules[].enabled`               | Boolean | Required  | Mutable  | Set to `true` to use the defined rule in the predictor.                                                                                                        |
| `rules[].interval`              | Object  | Required  | Mutable  | Object that contains the fields used to define the timeframe to consider. The timeframe can be between 1 hour and 14 days.                                     |
| `rules[].interval.unit`         | String  | Required  | Mutable  | The time unit for defining the timeframe for tracking number of users on the device - can be `DAY` or `HOUR`                                                   |
| \`rules\[].interval.quantity \` | Integer | Required  | Mutable  | The number of days or hours for the timeframe for tracking number of users on the device.                                                                      |
| `rules[].threshold`             | Object  | Required  | Mutable  | Object that contains the fields used to define the risk thresholds.                                                                                            |
| `rules[].threshold.medium`      | Integer | Required  | Mutable  | Number of users during the defined timeframe that will be considered Medium risk.                                                                              |
| `rules[].threshold.high`        | Integer | Required  | Mutable  | Number of users during the defined timeframe that will be considered High risk.                                                                                |
| `rules[].type`                  | String  | Required  | Mutable  | The type of rule. Currently the only valid value is `UNIQUE_USERS_PER_DEVICE` - for tracking the number of unique users for a device over a defined timeframe. |

## Velocity risk predictor data model

| Property                 | Type    | Required? | Mutable? | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ------------------------ | ------- | --------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `by`                     | List    | Optional  | Mutable  | An ordered list of JSON parameters for the values to aggregate. For example, `${event.ip},${event.user.id}`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `of`                     | String  | Optional  | Mutable  | A JSON pointer for the value to aggregate. For example `${event.ip}` or `${event.user.id}`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `threshold`              | Object  | Optional  | Mutable  | Contains information about the calculated threshold used.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `threshold.high`         | Integer | Optional  | Mutable  | The value calculated for the high threshold. If the IP was accessed by more than the `high` number of users during the past hour, the IP is flagged as a `HIGH` `userVelocityByIp.level`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `threshold.medium`       | Integer | Optional  | Mutable  | The value calculated for the medium threshold. If the IP was accessed by more than the `medium` number of users during the past hour, the IP is flagged as a `MEDIUM` `userVelocityByIp.level`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `threshold.source`       | String  | Optional  | Mutable  | The source used to calculate the threshold. This can be:\* `MIN_NOT_REACHED`. If the measure is less than `every.minSample`, the threshold isn't calculated. Instead, a value of `LOW` is automatically assigned.\* `CALCULATED`. Indicates the threshold was calculated.\* `ENVIRONMENT_FALLBACK`. Indicates a global threshold calculated for the entire environment is used. The global threshold is used when the `userVelocityByIp.threshold` couldn't be calculated for the user, generally due to a lack of past transactions for the risk predictor to use for the threshold calculation.\* `DEFAULT_FALLBACK`. Indicates the default threshold defined for the predictor (in `threshold.medium` or `threshold.high`) is used. The default threshold is used when `ENVIRONMENT_FALLBACK` (the global threshold) could not be calculated, generally due to a lack of past transactions for the risk predictor to use for the global threshold calculation. |
| `threshold.calculatedAt` | Date    | Optional  | Mutable  | The timestamp for the calculated threshold.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `threshold.expiresAt`    | Date    | Optional  | Mutable  | Indicates when the threshold will be recalculated. The recalculation will happen before this time.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `velocity.distinctCount` | Integer | Required  | Mutable  | The distinct count during a specified number of seconds. The duration is set using the `velocity.during` property. Applicable only for IP velocity predictors that have `measure=DISTINCT_COUNT` set.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `velocity.during`        | Integer | Required  | Mutable  | The number of seconds for the `DISTINCT_COUNT` duration. Applicable only for IP velocity predictors that have `measure=DISTINCT_COUNT` set.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

## Risk predictors events generated

Refer to [Audit Reporting Events](/pingone/platform/v1/api/#audit-reporting-events) for the events generated.

## Custom risk predictors

You can define three types of custom risk predictors:

* IP Range - for custom handling of IP-related risks

* String Matching - definition of risk levels associated with different values of custom input provided as a string

* Numeric Range - definition of risk levels associated with different values of custom input provided as a number

While different fields are used for defining these three types of conditions, the basic JSON structure for the body of the request is similar for all types:

* The top-level field `type` must be set to MAP.

* The conditions are contained inside objects called `map.high`, `map.medium`, and `map.low`. You do not have to include all three levels, you just have to include at least one of these objects. If you include more than one level, for example, `map.high` and `map.medium`, each must refer to the same variable, for example, `${details.country}`.

* The `contains` field in the condition can use any of the following as the variable whose value is being checked:

  * Any field in the `details` object (refer to [Risk Evaluations](#risk-evaluations))

  * Any field in the `event` object (refer to [Risk Evaluations](#risk-evaluations))

  * Any custom attribute added to the `event` object simply by adding the attribute to the `event` object in the body of a risk evaluation request

|   |                                                                                                                                                                                                          |
| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | When referencing the `details` object, the variable cannot be of the form `details.<predictorCompactName>.<attribute name>` if the predictor being referenced is itself a custom or composite predictor. |

### IP Range custom predictor - sample request body

```none
{
  "name": "Device IP - custom",
  "compactName": "deviceIpCustom",
  "map": {
    "high": {
        "ipRange": [
            "1.1.1.1/5",
            "2.2.2.2/8"
        ],
    "contains": "${event.ip}"
    }
  },
  "type": "MAP",
  "default": {
    "result": {
      "level": "MEDIUM"
    }
  }
}
```

### String Matching custom predictor - sample request body

```none
{
  "name": "Device country - custom",
  "compactName": "deviceCountryCustom",
  "map": {
    "high": {
        "list": [
            "Iran",
            "Syria"
        ],
    "contains": "${details.country}"
    },
    "medium": {
        "list": [
            "Ethiopia",
            "Russia"
        ],
    "contains": "${details.country}"
    }
  },
  "type": "MAP",
  "default": {
    "result": {
      "level": "MEDIUM"
    }
  }
}
```

|   |                                                                                    |
| - | ---------------------------------------------------------------------------------- |
|   | **Note:** For a string matching custom predictor, you can define up to 50 strings. |

### Numeric Range custom predictor - sample request body

```none
{
  "name": "Device Network Location",
  "compactName": "deviceNetworkLocation",
  "map": {
    "high": {
      "between": {
        "minScore": 804672,
        "maxScore": 12742000
      },
      "contains": "${details.device.estimatedDistance}"
    },
    "medium": {
      "between": {
        "minScore": 321869,
        "maxScore": 804672
      },
      "contains": "${details.device.estimatedDistance}"
    },
    "low": {
      "between": {
        "minScore": 0,
        "maxScore": 321869
      },
      "contains": "${details.device.estimatedDistance}"
    }
  },
  "type": "MAP",
  "default": {
    "result": {
      "level": "LOW"
    }
  }
}
```

## Composite risk predictors

The JSON content below shows the body of a request for creating a composite predictor.

Details to note about the content of the request body:

* `type` must be set to COMPOSITE.

* Each of the objects in the `compositions` array contain a `condition` object, which is use to specify the set of conditions to test, and the `level` field, which specifies the risk level that should be assigned if the conditions are met.

* The `compositions` array can contain a maximum of three elements.

* The specific predictor comparisons to carry out should use the `${details.*.level}` format to specify the predictor to use. The string between `details` and `level` should be the compact name of the predictor.

* In addition to standard and custom predictors, you can include the following risk factors in composite predictors: country (`${details.country}`), state (`${details.state}`), IP range (`${event.ip}`), IP domain organization (`${details.ipAddressReputation.domain.organization}`), ISP (`${details.ipAddressReputation.domain.isp}`), target resource (`${event.targetResource.name}`), user ID (`${event.user.id}`), and user name (`${event.user.name}`). When creating conditions with these risk factors, you can use the following comparisons:

  * `equals`

  * `notEquals`

  * `contains` - to check if a value is in a defined list or in an IP range

  * `notContains` - to check if a value is not included in a defined list or in an IP range

  * `startsWith` - to check if a value begins with the specified string. Can be used with ISP, IP domain organization, user ID, and user name.

  * `endsWith` - to check if a value ends with the specified string. Can be used with ISP, IP domain organization, user ID, and user name.

  * `containsIgnoreCase` - to check if a value contains the specified substring, not case-sensitive. Can only be used for user ID and user name.

* In your composite predictors you can also include conditions that check what user groups the user belongs to. For user groups conditions, the comparisons to use are `contains` and `notContains`.

* Use `${details.counters.predictorLevels.high}`, `${details.counters.predictorLevels.medium}`, and `${details.counters.predictorLevels.low}` to specify criteria relating to the number of predictors in a policy that yield a high, medium, or low risk result. For criteria of this type, use the relational terms `equals`, `greater`, `lower`, `greaterEquals`, `lowerEquals`.

* Within `condition` objects, use `or` for the array of conditions if it is enough for any of the conditions to be true, and `and` if all the criteria must be true. If none of the criteria can be true, construct an `or` array, then enclose it in a `not` object.\
  \
  Example of `or`:

```none
"compositions": [
  {
    "condition": {
      "or": [
        {
          "equals": 3,
          "value": "${details.counters.predictorLevels.high}",
          "type": "VALUE_COMPARISON"
        },
        {
          "equals": "HIGH",
          "value": "${details.anonymousNetwork.level}",
          "type": "VALUE_COMPARISON"
        },
        {
          "type": "STRING_LIST",
          "list": [
            "Italy",
            "Germany"
          ],
          "notContains": "${details.country}"
        }
      ]
    },
    "level": "HIGH"
  }
]
[source]
```

Example of `not`:

```none
"compositions": [
  {
    "condition": {
      "not": {
        "or": [
          {
            "value": "${details.counters.predictorLevels.high}",
            "equals": 3,
            "type": "VALUE_COMPARISON"
          },
          {
            "value": "${details.anonymousNetwork.level}",
            "equals": "high",
            "type": "VALUE_COMPARISON"
          },
          {
            "list": [
              "ITALY",
              "GERMANY"
            ],
            "notContains": "${details.country}",
            "type": "STRING_LIST"
          }
        ]
      }
    },
    "level": "HIGH"
  }
]
[source]
```

Full composite predictor example:

```none
{
    "name": "Composite - anonymous network and country",
    "compactName": "compositeAnonymousAndCountry",
    "licensed": true,
    "compositions": [
        {
            "condition": {
                "or": [
                    {
                        "equals": 3,
                        "value": "${details.counters.predictorLevels.high}",
                        "type": "VALUE_COMPARISON"
                    },
                    {
                        "equals": "HIGH",
                        "value": "${details.anonymousNetwork.level}",
                        "type": "VALUE_COMPARISON"
                    },
                    {
                        "type": "STRING_LIST",
                        "list": [
                            "Italy",
                            "Germany"
                        ],
                        "notContains": "${details.country}"
                    }
                ]
            },
            "level": "HIGH"
        },
        {
            "condition": {
                "and": [
                    {
                        "equals": "HIGH",
                        "value": "${details.userLocationAnomaly.level}",
                        "type": "VALUE_COMPARISON"
                    }
                ]
            },
            "level": "MEDIUM"
        }
    ],
    "type": "COMPOSITE",
    "default": {
        "weight": 5,
        "score": 50,
        "result": {
            "level": "LOW",
            "type": "VALUE"
        }
    }
}
```

## Deleting risk predictors

|   |                                                                                                                                                                                                                                                                                                                       |
| - | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Risk predictors that are referenced in an existing risk policy cannot be deleted. To delete the predictor, you must either delete the associated risk policy first or remove the usage of the predictor in the risk policy. Similarly, you cannot delete a predictor that is currently used in a composite predictor. |
