Risk Recommendation

Gets recommendations for handling user requests to perform sensitive actions (like login) based on real-time risk.

About client-facing steps

A journey is a sequence of steps that are executed when it's invoked by a client application (known as the "client"). Some steps require involvement from the client, such as to collect user input. Other steps, like validating a token, are executed in the backend by the Transmit journey engine alone.

When invoked, the journey begins executing the steps while the client waits for further instructions. When a journey reaches a client-facing step, the journey asks the client for the required input and then waits for the client to respond. The client presents their own UI if user interaction is required, and returns input to the journey. The journey then proceeds in a similar manner until it's completed.


This client-facing step is used to obtain risk recommendations so you can detect and respond to real-time risk. For example, this allows you to request additional verification when bots are detected during account opening or to step up authentication when a user is trying to login from a suspicious device or location.

Use this step before the user performs a sensitive action in order to detect risk and help you decide how to respond. It will instruct the client to trigger an action event using the SDK. Once triggered, the journey proceeds to the branch that corresponds to the recommendation (either trust, allow, challenge, or deny). If defined, an output variable will store the risk recommendation result. In addition to a recommendation itself (allow, trust, deny, or challenge), the result includes more details such as risk score, reasons, and device details. This data can be used in subsequent journey steps in the expression fields (e.g., account_protection_result.recommendation) or as a part of an interpolated string (e.g., You're using ${account_protection_result.context.browser_name}).

Risk recommendations are provided by Transmit's Detection and Response Services based on telemetry streamed by the client. It includes device, network, and other context data used to continuously assess risk. For Web, Detection and Response functionality is bundled with Orchestration in the same SDK. For mobile apps, use a dedicated SDK: Detection and Response SDK (iOS) or Detection and Response SDK (Android).

  • Make sure Detection and Response services are configured to work in the same region as other Transmit services.
  • For details on how to set up and initialize the Detection and Response SDK for mobile apps, see Steps 2 & 3 of Android quickstart or iOS quickstart .


Field Description
Action Type Action the user wants to perform, which will provided to the client to trigger an action event. This includes all action types listed here
Output Variable Name of the variable used to store the result data from the completed step, which can be used in subsequent journey steps. Default is account_protection_result.

The object has the structure that's described here. In addition to a recommendation itself (allow, trust, deny, or challenge), it includes more details such as risk score, reasons, and device details.
Error Behavior Determines the behavior in case an unexpected error occurs during the process. You can choose to either abort the journey (default) or handle errors using a dedicated error branch.


In our example, the user attempts to login with their credentials. This step obtains a risk recommendation for the login event and defines how to proceed with the journey. For example, proceed normally if Transmit returns 'allow' or 'trust', terminate if 'deny', or enforce a step-up authentication if 'challenge'.

When executed, this step sends a callback to the client with the IDO service response object. It will have the journeyStepId set to drsTriggerAction and the data will include the action_type set to login. The client uses the data received from the IDO SDK as an input for DRS SDK and triggers an action with the DRS SDK. Having received the action token from the DRS SDK, the client submits it to the journey using the IDO SDK call in order for the journey to fetch a recommendation and proceed accordingly.

async function handleRiskRecommendations(idoResponse) {
  const correlationId = idoResponse.data.correlation_id;
  const claimedUserId = idoResponse.data.user_id;
  const actionType = idoResponse.data.action_type;

  // Triggers an action event using the DRS SDK
  const { actionToken } = await window.tsPlatform.drs.triggerActionEvent(actionType, {

  const data = { action_token: actionToken };

  // Submits an action token to the journey using the IDO SDK
  await window.tsPlatform.ido.submitClientResponse(ClientResponseOptionType.ClientInput, data);
do {
    // Initializes the DRS SDK
    try TSAccountProtection.initializeSDK { result in
        switch result {
        case .success:
            guard let actionType = idoResponse.data["action_type"] as? String else { return }
            let correlationId = idoResponse.data["correlation_id"] as? String
            let claimedUserId = idoResponse.data["user_id"] as? String

            // Triggers an action event using the DRS SDK
            TSAccountProtection.triggerAction(actionType) { result in
                switch result {
                case .success(let response):
                    debugPrint("[DEBUG] DRS access token: \(response.actionToken)")

                    // Submits an action token to the journey using the IDO SDK
                    TSIdo.submitClientResponse(clientResponseOptionId: .clientInput,
                                               data: ["action_token": response.actionToken])
                case .failure(let error):
                    debugPrint("[DEBUG] Trigger action error: \(error)")
                    TSIdo.submitClientResponse(clientResponseOptionId: .fail)
        case .failure(let error):
            debugPrint("[DEBUG] Initialize DRS SDK error: \(error)")
} catch {
    debugPrint("[DEBUG] SDK Initialization error: \(error)")
data class DrsActionToken(val action_token: String)
private fun triggerActionAndSubmit(serviceResponse: TSIdoServiceResponse) {
    val actionType = (serviceResponse.data as JSONObject).optString(“action_type”)
    if (!action.isNullOrEmpty()) {
           // Triggers an action event using the DRS SDK
           TSAccountProtection.triggerAction(actionType, object :
               ITransmitSecurityTriggerActionEventCallback {
               override fun onResponse(transmitSecurityTriggerActionResponse: TransmitSecurityTriggerActionResponse) {
                   val token= transmitSecurityTriggerActionResponse.token();
                   // Submits an action token to the journey using the IDO SDK
                   TSIdo.submitClientResponse(TSIdoClientResponseOptionType.ClientInput.type, DrsActionToken(token), callback)
               override fun onFailed(error: TransmitSecurityAccountProtectionError) {
                   //TODO: Handle error