> ## Documentation Index
> Fetch the complete documentation index at: https://docs.authsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting started with rules

> Learn how Authsignal rules enable risk-based authentication and how to implement them in your app.

Authsignal's rules engine transforms static authentication flows into intelligent, risk-based security systems. Rules determine when and how to challenge users based on contextual factors.

Rules are conditional statements that evaluate the context of each action to make intelligent security decisions. While actions define what users are doing, rules determine when and how to challenge them based on risk factors, device characteristics, user behavior, and custom business data.

## Creating a rule

To create a rule, navigate to your action (e.g., withdraw-funds) and click the Rules tab. Then click "Create rule" and provide a name and description.

## Core components of a rule

When you create a rule in Authsignal, you're defining the logic that determines when additional security measures are required. Here's what a rule contains:

### 1. Conditions

Define the criteria that will trigger the rule using various data points, for example:

* **Device characteristics:** New devices, device count
* **IP/Network data:** Anonymous IPs, country codes, impossible travel detection
* **Custom data points:** Your business-specific data like transaction amounts, account tiers

### 2. Outcomes

When a rule's conditions are met, it can override the action's default outcome with any of the four available action outcomes (`ALLOW`, `CHALLENGE`, `REVIEW`, or `BLOCK`). This allows you to apply outcomes dynamically based on risk assessment rather than using a static default.

<Frame>
  <img src="https://mintcdn.com/authsignal-23/U9XmxdPe4AWAeEuC/images/docs/actions-rules/rules-outcomes.png?fit=max&auto=format&n=U9XmxdPe4AWAeEuC&q=85&s=8a3b6ed13697501258b6d0826f576493" alt="Rule outcomes" width="3024" height="1588" data-path="images/docs/actions-rules/rules-outcomes.png" />
</Frame>

## Rule priority

When multiple rules are defined for an action, they are evaluated in priority order. Each rule is assigned a priority number, with lower numbers indicating higher priority.

<Frame>
  <img src="https://mintcdn.com/authsignal-23/ZlgxBxfjPDzU477P/images/docs/rules/rule-priority.png?fit=max&auto=format&n=ZlgxBxfjPDzU477P&q=85&s=7949f1f55ecd5326b1353bd3ade1b41e" alt="Rule priority ordering" width="1197" height="359" data-path="images/docs/rules/rule-priority.png" />
</Frame>

All rules are evaluated against the action's context, and if multiple rules match, the highest-priority rule's outcome is used. If no rules match, the action's default outcome is used.

You can reorder rules by dragging them in the rules list to adjust their priority. Place your most specific or highest-risk rules at the top to ensure they take precedence over broader rules.

<Info>
  For example, if you have a "High risk" rule (priority 1) that challenges transactions above \$10,000, and a "Low risk" rule (priority 2) that challenges transactions above \$1,000, a \$15,000 transaction will match both rules, but the "High risk" rule's outcome will be used because it has a higher priority.
</Info>

## Using rules with actions

Rules work seamlessly with your existing action tracking. When you track an action, Authsignal evaluates all applicable rules and returns the appropriate outcome.

<Tabs>
  <Tab title="Custom UI">
    <CodeGroup>
      ```ts Node.js theme={null}
      // Track an action - rules are evaluated automatically
      const result = await authsignal.track({
        userId: "0272c312-e181-4cad-a494-43647b503a0a",
        action: "withdraw-funds",
        attributes: {
          deviceId: "555c17e1-3837-4f13-81bb-131e5597e168",
          ipAddress: "203.0.113.42",
          userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        }
      });

      // Handle the result based on rule evaluation
      if (result.state === "CHALLENGE_REQUIRED") {
        // Rule determined a challenge is needed
        return {
          token: result.token // For custom UI with SDKs
        };
      } else if (result.state === "ALLOW") {
        // Rule determined user is trusted
        return { success: true };
      } else if (result.state === "REVIEW") {
        // Rule determined manual review is needed
        return { 
          status: "under_review",
          message: "Your request is being reviewed"
        };
      } else if (result.state === "BLOCK") {
        // Rule determined this is high-risk
        return { 
          error: "This action has been blocked for security reasons"
        };
      }
      ```

      ```csharp C# theme={null}
      // Track an action - rules are evaluated automatically
      var request = new TrackRequest(
          UserId: "0272c312-e181-4cad-a494-43647b503a0a",
          Action: "withdraw-funds",
          Attributes: new TrackAttributes(
              DeviceId: "555c17e1-3837-4f13-81bb-131e5597e168",
              IpAddress: "203.0.113.42",
              UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
          )
      );

      var result = await authsignal.Track(request);

      // Handle the result based on rule evaluation
      if (result.State == "CHALLENGE_REQUIRED") 
      {
          // Rule determined a challenge is needed
          return new {
              Token = result.Token // For custom UI with SDKs
          };
      }
      else if (result.State == "ALLOW") 
      {
          // Rule determined user is trusted
          return new { Success = true };
      }
      else if (result.State == "REVIEW") 
      {
          // Rule determined manual review is needed
          return new { 
              Status = "under_review",
              Message = "Your request is being reviewed"
          };
      }
      else if (result.State == "BLOCK") 
      {
          // Rule determined this is high-risk
          return new { 
              Error = "This action has been blocked for security reasons"
          };
      }
      ```

      ```java Java theme={null}
      // Track an action - rules are evaluated automatically
      TrackRequest request = new TrackRequest();
      request.userId = "0272c312-e181-4cad-a494-43647b503a0a";
      request.action = "withdraw-funds";
      request.attributes = new TrackAttributes();
      request.attributes.deviceId = "555c17e1-3837-4f13-81bb-131e5597e168";
      request.attributes.ipAddress = "203.0.113.42";
      request.attributes.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";

      TrackResponse result = authsignal.track(request).get();

      // Handle the result based on rule evaluation
      if ("CHALLENGE_REQUIRED".equals(result.state)) {
          // Rule determined a challenge is needed
          Map<String, Object> response = new HashMap<>();
          response.put("token", result.token); // For custom UI with SDKs
          return response;
      } else if ("ALLOW".equals(result.state)) {
          // Rule determined user is trusted
          return Map.of("success", true);
      } else if ("REVIEW".equals(result.state)) {
          // Rule determined manual review is needed
          return Map.of(
              "status", "under_review",
              "message", "Your request is being reviewed"
          );
      } else if ("BLOCK".equals(result.state)) {
          // Rule determined this is high-risk
          return Map.of(
              "error", "This action has been blocked for security reasons"
          );
      }
      ```

      ```ruby Ruby theme={null}
      # Track an action - rules are evaluated automatically
      result = Authsignal.track({
        user_id: "0272c312-e181-4cad-a494-43647b503a0a",
        action: "withdraw-funds",
        attributes: {
          device_id: "555c17e1-3837-4f13-81bb-131e5597e168",
          ip_address: "203.0.113.42",
          user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        }
      })

      # Handle the result based on rule evaluation
      case result[:state]
      when "CHALLENGE_REQUIRED"
        # Rule determined a challenge is needed
        {
          token: result[:token] # For custom UI with SDKs
        }
      when "ALLOW"
        # Rule determined user is trusted
        { success: true }
      when "REVIEW"
        # Rule determined manual review is needed
        {
          status: "under_review",
          message: "Your request is being reviewed"
        }
      when "BLOCK"
        # Rule determined this is high-risk
        {
          error: "This action has been blocked for security reasons"
        }
      end
      ```

      ```python Python theme={null}
      # Track an action - rules are evaluated automatically
      result = authsignal.track(
          user_id="0272c312-e181-4cad-a494-43647b503a0a",
          action="withdraw-funds",
          attributes={
              "deviceId": "555c17e1-3837-4f13-81bb-131e5597e168",
              "ipAddress": "203.0.113.42",
              "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
          }
      )

      # Handle the result based on rule evaluation
      if result["state"] == "CHALLENGE_REQUIRED":
          # Rule determined a challenge is needed
          return {
              "token": result["token"]  # For custom UI with SDKs
          }
      elif result["state"] == "ALLOW":
          # Rule determined user is trusted
          return {"success": True}
      elif result["state"] == "REVIEW":
          # Rule determined manual review is needed
          return {
              "status": "under_review",
              "message": "Your request is being reviewed"
          }
      elif result["state"] == "BLOCK":
          # Rule determined this is high-risk
          return {
              "error": "This action has been blocked for security reasons"
          }
      ```

      ```php PHP theme={null}
      // Track an action - rules are evaluated automatically
      $result = Authsignal::track([
          'userId' => "0272c312-e181-4cad-a494-43647b503a0a",
          'action' => "withdraw-funds",
          'attributes' => [
              'deviceId' => "555c17e1-3837-4f13-81bb-131e5597e168",
              'ipAddress' => "203.0.113.42",
              'userAgent' => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
          ]
      ]);

      // Handle the result based on rule evaluation
      switch ($result["state"]) {
          case "CHALLENGE_REQUIRED":
              // Rule determined a challenge is needed
              return [
                  'token' => $result["token"] // For custom UI with SDKs
              ];
          case "ALLOW":
              // Rule determined user is trusted
              return ['success' => true];
          case "REVIEW":
              // Rule determined manual review is needed
              return [
                  'status' => "under_review",
                  'message' => "Your request is being reviewed"
              ];
          case "BLOCK":
              // Rule determined this is high-risk
              return [
                  'error' => "This action has been blocked for security reasons"
              ];
      }
      ```

      ```go Go theme={null}
      // Track an action - rules are evaluated automatically
      result, err := client.Track(
          TrackRequest{
              UserId: "0272c312-e181-4cad-a494-43647b503a0a",
              Action: "withdraw-funds",
              Attributes: &TrackAttributes{
                  DeviceId:  "555c17e1-3837-4f13-81bb-131e5597e168",
                  IpAddress: "203.0.113.42",
                  UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              },
          },
      )
      if err != nil {
          return err
      }

      // Handle the result based on rule evaluation
      switch result.State {
      case "CHALLENGE_REQUIRED":
          // Rule determined a challenge is needed
          return map[string]interface{}{
              "token": result.Token, // For custom UI with SDKs
          }
      case "ALLOW":
          // Rule determined user is trusted
          return map[string]interface{}{"success": true}
      case "REVIEW":
          // Rule determined manual review is needed
          return map[string]interface{}{
              "status":  "under_review",
              "message": "Your request is being reviewed",
          }
      case "BLOCK":
          // Rule determined this is high-risk
          return map[string]interface{}{
              "error": "This action has been blocked for security reasons",
          }
      }
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Pre-built UI">
    <CodeGroup>
      ```ts Node.js theme={null}
      // Track an action - rules are evaluated automatically
      const result = await authsignal.track({
        userId: "0272c312-e181-4cad-a494-43647b503a0a",
        action: "withdraw-funds",
        attributes: {
          deviceId: "555c17e1-3837-4f13-81bb-131e5597e168",
          ipAddress: "203.0.113.42",
          userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
          redirectUrl: "https://yourapp.com/callback"
        }
      });

      // Handle the result based on rule evaluation
      if (result.state === "CHALLENGE_REQUIRED") {
        // Rule determined a challenge is needed
        return {
          url: result.url // For pre-built UI
        };
      } else if (result.state === "ALLOW") {
        // Rule determined user is trusted
        return { success: true };
      } else if (result.state === "REVIEW") {
        // Rule determined manual review is needed
        return { 
          status: "under_review",
          message: "Your request is being reviewed"
        };
      } else if (result.state === "BLOCK") {
        // Rule determined this is high-risk
        return { 
          error: "This action has been blocked for security reasons"
        };
      }
      ```

      ```csharp C# theme={null}
      // Track an action - rules are evaluated automatically
      var request = new TrackRequest(
          UserId: "0272c312-e181-4cad-a494-43647b503a0a",
          Action: "withdraw-funds",
          Attributes: new TrackAttributes(
              DeviceId: "555c17e1-3837-4f13-81bb-131e5597e168",
              IpAddress: "203.0.113.42",
              UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              RedirectUrl: "https://yourapp.com/callback"
          )
      );

      var result = await authsignal.Track(request);

      // Handle the result based on rule evaluation
      if (result.State == "CHALLENGE_REQUIRED") 
      {
          // Rule determined a challenge is needed
          return new {
              Url = result.Url // For pre-built UI
          };
      }
      else if (result.State == "ALLOW") 
      {
          // Rule determined user is trusted
          return new { Success = true };
      }
      else if (result.State == "REVIEW") 
      {
          // Rule determined manual review is needed
          return new { 
              Status = "under_review",
              Message = "Your request is being reviewed"
          };
      }
      else if (result.State == "BLOCK") 
      {
          // Rule determined this is high-risk
          return new { 
              Error = "This action has been blocked for security reasons"
          };
      }
      ```

      ```java Java theme={null}
      // Track an action - rules are evaluated automatically
      TrackRequest request = new TrackRequest();
      request.userId = "0272c312-e181-4cad-a494-43647b503a0a";
      request.action = "withdraw-funds";
      request.attributes = new TrackAttributes();
      request.attributes.deviceId = "555c17e1-3837-4f13-81bb-131e5597e168";
      request.attributes.ipAddress = "203.0.113.42";
      request.attributes.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";
      request.attributes.redirectUrl = "https://yourapp.com/callback";

      TrackResponse result = authsignal.track(request).get();

      // Handle the result based on rule evaluation
      if ("CHALLENGE_REQUIRED".equals(result.state)) {
          // Rule determined a challenge is needed
          Map<String, Object> response = new HashMap<>();
          response.put("url", result.url); // For pre-built UI
          return response;
      } else if ("ALLOW".equals(result.state)) {
          // Rule determined user is trusted
          return Map.of("success", true);
      } else if ("REVIEW".equals(result.state)) {
          // Rule determined manual review is needed
          return Map.of(
              "status", "under_review",
              "message", "Your request is being reviewed"
          );
      } else if ("BLOCK".equals(result.state)) {
          // Rule determined this is high-risk
          return Map.of(
              "error", "This action has been blocked for security reasons"
          );
      }
      ```

      ```ruby Ruby theme={null}
      # Track an action - rules are evaluated automatically
      result = Authsignal.track({
        user_id: "0272c312-e181-4cad-a494-43647b503a0a",
        action: "withdraw-funds",
        attributes: {
          device_id: "555c17e1-3837-4f13-81bb-131e5597e168",
          ip_address: "203.0.113.42",
          user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
          redirect_url: "https://yourapp.com/callback"
        }
      })

      # Handle the result based on rule evaluation
      case result[:state]
      when "CHALLENGE_REQUIRED"
        # Rule determined a challenge is needed
        {
          url: result[:url] # For pre-built UI
        }
      when "ALLOW"
        # Rule determined user is trusted
        { success: true }
      when "REVIEW"
        # Rule determined manual review is needed
        {
          status: "under_review",
          message: "Your request is being reviewed"
        }
      when "BLOCK"
        # Rule determined this is high-risk
        {
          error: "This action has been blocked for security reasons"
        }
      end
      ```

      ```python Python theme={null}
      # Track an action - rules are evaluated automatically
      result = authsignal.track(
          user_id="0272c312-e181-4cad-a494-43647b503a0a",
          action="withdraw-funds",
          attributes={
              "deviceId": "555c17e1-3837-4f13-81bb-131e5597e168",
              "ipAddress": "203.0.113.42",
              "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              "redirectUrl": "https://yourapp.com/callback"
          }
      )

      # Handle the result based on rule evaluation
      if result["state"] == "CHALLENGE_REQUIRED":
          # Rule determined a challenge is needed
          return {
              "url": result["url"]  # For pre-built UI
          }
      elif result["state"] == "ALLOW":
          # Rule determined user is trusted
          return {"success": True}
      elif result["state"] == "REVIEW":
          # Rule determined manual review is needed
          return {
              "status": "under_review",
              "message": "Your request is being reviewed"
          }
      elif result["state"] == "BLOCK":
          # Rule determined this is high-risk
          return {
              "error": "This action has been blocked for security reasons"
          }
      ```

      ```php PHP theme={null}
      // Track an action - rules are evaluated automatically
      $result = Authsignal::track([
          'userId' => "0272c312-e181-4cad-a494-43647b503a0a",
          'action' => "withdraw-funds",
          'attributes' => [
              'deviceId' => "555c17e1-3837-4f13-81bb-131e5597e168",
              'ipAddress' => "203.0.113.42",
              'userAgent' => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              'redirectUrl' => "https://yourapp.com/callback"
          ]
      ]);

      // Handle the result based on rule evaluation
      switch ($result["state"]) {
          case "CHALLENGE_REQUIRED":
              // Rule determined a challenge is needed
              return [
                  'url' => $result["url"] // For pre-built UI
              ];
          case "ALLOW":
              // Rule determined user is trusted
              return ['success' => true];
          case "REVIEW":
              // Rule determined manual review is needed
              return [
                  'status' => "under_review",
                  'message' => "Your request is being reviewed"
              ];
          case "BLOCK":
              // Rule determined this is high-risk
              return [
                  'error' => "This action has been blocked for security reasons"
              ];
      }
      ```

      ```go Go theme={null}
      // Track an action - rules are evaluated automatically
      result, err := client.Track(
          TrackRequest{
              UserId: "0272c312-e181-4cad-a494-43647b503a0a",
              Action: "withdraw-funds",
              Attributes: &TrackAttributes{
                  DeviceId:    "555c17e1-3837-4f13-81bb-131e5597e168",
                  IpAddress:   "203.0.113.42",
                  UserAgent:   "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
                  RedirectUrl: "https://yourapp.com/callback",
              },
          },
      )
      if err != nil {
          return err
      }

      // Handle the result based on rule evaluation
      switch result.State {
      case "CHALLENGE_REQUIRED":
          // Rule determined a challenge is needed
          return map[string]interface{}{
              "url": result.Url, // For pre-built UI
          }
      case "ALLOW":
          // Rule determined user is trusted
          return map[string]interface{}{"success": true}
      case "REVIEW":
          // Rule determined manual review is needed
          return map[string]interface{}{
              "status":  "under_review",
              "message": "Your request is being reviewed",
          }
      case "BLOCK":
          // Rule determined this is high-risk
          return map[string]interface{}{
              "error": "This action has been blocked for security reasons",
          }
      }
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Creating a rule to challenge high-risk users

Let's walk through creating a practical rule that automatically challenges high-risk users while allowing trusted users to access your application seamlessly.

### 1. Create a rule

* Navigate to your `signIn` action and click the Rules tab
* Click **Create rule** and name it Challenge "high-risk" users
* Click Continue to proceed to rule configuration

### 2. Add conditions

We'll determine a user as 'high-risk' if they meet any of the following conditions:

* Are detected as being a bot
* Are on a new device
* Are using an anonymous IP address

To add these conditions:

* Click **Add feature** and then **Select feature**
* Choose the **Device** category and select **Device is new**
* Repeat for **Device is a bot** (Device category)
* Repeat for **IP is anonymous** (IP/Network category)

<Frame>
  <img src="https://mintcdn.com/authsignal-23/o0kRW78VfDNgNDjk/images/docs/learn/tracking-actions/creating-rules/select-feature.png?fit=max&auto=format&n=o0kRW78VfDNgNDjk&q=85&s=e8d3f3d83923867005a2e52fc9a32ef4" alt="Select feature" width="1241" height="843" data-path="images/docs/learn/tracking-actions/creating-rules/select-feature.png" />
</Frame>

* Change the conjunction logic from AND to OR so the rule triggers if any condition is met

<Frame>
  <img src="https://mintcdn.com/authsignal-23/o0kRW78VfDNgNDjk/images/docs/learn/tracking-actions/creating-rules/conditions.png?fit=max&auto=format&n=o0kRW78VfDNgNDjk&q=85&s=6613f2a33fbc7d026d96bcab58fbc469" alt="Conditions" width="1171" height="689" data-path="images/docs/learn/tracking-actions/creating-rules/conditions.png" />
</Frame>

### 3. Set the outcome

* Set the rule outcome to `CHALLENGE` so high-risk users will be prompted for additional verification, then click **Save**.
* Return to the Rules page of your `signIn` action. You should see your new rule listed.

<Frame>
  <img src="https://mintcdn.com/authsignal-23/o0kRW78VfDNgNDjk/images/docs/learn/tracking-actions/creating-rules/rule-created.png?fit=max&auto=format&n=o0kRW78VfDNgNDjk&q=85&s=c9799031d6a568c9170d886565f257ac" alt="Rule created" width="985" height="192" data-path="images/docs/learn/tracking-actions/creating-rules/rule-created.png" />
</Frame>

### 4. Configure default action outcome

* Navigate to your action's **Settings** tab
* Change the default outcome to `ALLOW`
* Click **Save**

<Frame>
  <img src="https://mintcdn.com/authsignal-23/o0kRW78VfDNgNDjk/images/docs/learn/tracking-actions/creating-rules/default-outcome.png?fit=max&auto=format&n=o0kRW78VfDNgNDjk&q=85&s=ab3eb275d80192c3f527bd5ad0ff5c94" alt="Default outcome" width="1250" height="573" data-path="images/docs/learn/tracking-actions/creating-rules/default-outcome.png" />
</Frame>

This ensures users who don't trigger the high-risk rule can proceed without challenge.

### 5. Update your track call

Now that you have created the rule, you'll need to update your track action call to include some additional fields: `deviceId`, `ipAddress`, and `userAgent`.

<Tabs>
  <Tab title="Custom UI">
    <CodeGroup>
      ```ts Node.js theme={null}
      const request = {
        userId: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
        action: "signIn",
        attributes: {
          deviceId: "555c17e1-3837-4f13-81bb-131e5597e168", // From __as_aid cookie if using Authsignal Web SDK
          userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
          ipAddress: "203.0.113.42"
        }
      };

      const response = await authsignal.track(request);

      // Handle the response
      if (response.state === "CHALLENGE_REQUIRED") {
        // Use token with client SDK
        return { token: response.token };
      } else if (response.state === "ALLOW") {
        // User is trusted, proceed
        return { success: true };
      }
      ```

      ```csharp C# theme={null}
      var request = new TrackRequest(
          UserId: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
          Action: "signIn",
          Attributes: new TrackAttributes(
              DeviceId: "555c17e1-3837-4f13-81bb-131e5597e168", // From __as_aid cookie if using Authsignal Web SDK
              UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              IpAddress: "203.0.113.42"
          )
      );

      var response = await authsignal.Track(request);

      // Handle the response
      if (response.State == "CHALLENGE_REQUIRED") 
      {
          // Use token with client SDK
          return new { Token = response.Token };
      }
      else if (response.State == "ALLOW") 
      {
          // User is trusted, proceed
          return new { Success = true };
      }
      ```

      ```java Java theme={null}
      TrackRequest request = new TrackRequest();
      request.userId = "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833";
      request.action = "signIn";
      request.attributes = new TrackAttributes();
      request.attributes.deviceId = "555c17e1-3837-4f13-81bb-131e5597e168"; // From __as_aid cookie if using Authsignal Web SDK
      request.attributes.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";
      request.attributes.ipAddress = "203.0.113.42";

      TrackResponse response = authsignal.track(request).get();

      // Handle the response
      if ("CHALLENGE_REQUIRED".equals(response.state)) {
          // Use token with client SDK
          return Map.of("token", response.token);
      } else if ("ALLOW".equals(response.state)) {
          // User is trusted, proceed
          return Map.of("success", true);
      }
      ```

      ```ruby Ruby theme={null}
      response = Authsignal.track({
        user_id: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
        action: "signIn",
        attributes: {
          device_id: "555c17e1-3837-4f13-81bb-131e5597e168", # From __as_aid cookie if using Authsignal Web SDK
          user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
          ip_address: "203.0.113.42"
        }
      })

      # Handle the response
      case response[:state]
      when "CHALLENGE_REQUIRED"
        # Use token with client SDK
        { token: response[:token] }
      when "ALLOW"
        # User is trusted, proceed
        { success: true }
      end
      ```

      ```python Python theme={null}
      response = authsignal.track(
          user_id="dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
          action="signIn",
          attributes={
              "deviceId": "555c17e1-3837-4f13-81bb-131e5597e168",  # From __as_aid cookie if using Authsignal Web SDK
              "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              "ipAddress": "203.0.113.42"
          }
      )

      # Handle the response
      if response["state"] == "CHALLENGE_REQUIRED":
          # Use token with client SDK
          return {"token": response["token"]}
      elif response["state"] == "ALLOW":
          # User is trusted, proceed
          return {"success": True}
      ```

      ```php PHP theme={null}
      $response = Authsignal::track([
          'userId' => "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
          'action' => "signIn",
          'attributes' => [
              'deviceId' => "555c17e1-3837-4f13-81bb-131e5597e168", // From __as_aid cookie if using Authsignal Web SDK
              'userAgent' => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              'ipAddress' => "203.0.113.42"
          ]
      ]);

      // Handle the response
      switch ($response["state"]) {
          case "CHALLENGE_REQUIRED":
              // Use token with client SDK
              return ['token' => $response["token"]];
          case "ALLOW":
              // User is trusted, proceed
              return ['success' => true];
      }
      ```

      ```go Go theme={null}
      response, err := client.Track(
          TrackRequest{
              UserId: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
              Action: "signIn",
              Attributes: &TrackAttributes{
                  DeviceId:  "<device-id>", // From __as_aid cookie if using Authsignal Web SDK
                  UserAgent: "<user-agent>",
                  IpAddress: "<ip-address>",
              },
          },
      )
      if err != nil {
          return err
      }

      // Handle the response
      switch response.State {
      case "CHALLENGE_REQUIRED":
          // Use token with client SDK
          return map[string]interface{}{"token": response.Token}
      case "ALLOW":
          // User is trusted, proceed
          return map[string]interface{}{"success": true}
      }
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Pre-built UI">
    <CodeGroup>
      ```ts Node.js theme={null}
      const request = {
        userId: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
        action: "signIn",
        attributes: {
          deviceId: "555c17e1-3837-4f13-81bb-131e5597e168", // From __as_aid cookie if using Authsignal Web SDK
          userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
          ipAddress: "203.0.113.42",
          redirectUrl: "https://yourapp.com/callback"
        }
      };

      const response = await authsignal.track(request);

      // Handle the response
      if (response.state === "CHALLENGE_REQUIRED") {
        // Redirect to pre-built UI
        return { url: response.url };
      } else if (response.state === "ALLOW") {
        // User is trusted, proceed
        return { success: true };
      }
      ```

      ```csharp C# theme={null}
      var request = new TrackRequest(
          UserId: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
          Action: "signIn",
          Attributes: new TrackAttributes(
              DeviceId: "555c17e1-3837-4f13-81bb-131e5597e168", // From __as_aid cookie if using Authsignal Web SDK
              UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              IpAddress: "203.0.113.42",
              RedirectUrl: "https://yourapp.com/callback"
          )
      );

      var response = await authsignal.Track(request);

      // Handle the response
      if (response.State == "CHALLENGE_REQUIRED") 
      {
          // Redirect to pre-built UI
          return new { Url = response.Url };
      }
      else if (response.State == "ALLOW") 
      {
          // User is trusted, proceed
          return new { Success = true };
      }
      ```

      ```java Java theme={null}
      TrackRequest request = new TrackRequest();
      request.userId = "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833";
      request.action = "signIn";
      request.attributes = new TrackAttributes();
      request.attributes.deviceId = "555c17e1-3837-4f13-81bb-131e5597e168"; // From __as_aid cookie if using Authsignal Web SDK
      request.attributes.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";
      request.attributes.ipAddress = "203.0.113.42";
      request.attributes.redirectUrl = "https://yourapp.com/callback";

      TrackResponse response = authsignal.track(request).get();

      // Handle the response
      if ("CHALLENGE_REQUIRED".equals(response.state)) {
          // Redirect to pre-built UI
          return Map.of("url", response.url);
      } else if ("ALLOW".equals(response.state)) {
          // User is trusted, proceed
          return Map.of("success", true);
      }
      ```

      ```ruby Ruby theme={null}
      response = Authsignal.track({
        user_id: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
        action: "signIn",
        attributes: {
          device_id: "555c17e1-3837-4f13-81bb-131e5597e168", # From __as_aid cookie if using Authsignal Web SDK
          user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
          ip_address: "203.0.113.42",
          redirect_url: "https://yourapp.com/callback"
        }
      })

      # Handle the response
      case response[:state]
      when "CHALLENGE_REQUIRED"
        # Redirect to pre-built UI
        { url: response[:url] }
      when "ALLOW"
        # User is trusted, proceed
        { success: true }
      end
      ```

      ```python Python theme={null}
      response = authsignal.track(
          user_id="dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
          action="signIn",
          attributes={
              "deviceId": "555c17e1-3837-4f13-81bb-131e5597e168",  # From __as_aid cookie if using Authsignal Web SDK
              "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              "ipAddress": "203.0.113.42",
              "redirectUrl": "https://yourapp.com/callback"
          }
      )

      # Handle the response
      if response["state"] == "CHALLENGE_REQUIRED":
          # Redirect to pre-built UI
          return {"url": response["url"]}
      elif response["state"] == "ALLOW":
          # User is trusted, proceed
          return {"success": True}
      ```

      ```php PHP theme={null}
      $response = Authsignal::track([
          'userId' => "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
          'action' => "signIn",
          'attributes' => [
              'deviceId' => "555c17e1-3837-4f13-81bb-131e5597e168", // From __as_aid cookie if using Authsignal Web SDK
              'userAgent' => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
              'ipAddress' => "203.0.113.42",
              'redirectUrl' => "https://yourapp.com/callback"
          ]
      ]);

      // Handle the response
      switch ($response["state"]) {
          case "CHALLENGE_REQUIRED":
              // Redirect to pre-built UI
              return ['url' => $response["url"]];
          case "ALLOW":
              // User is trusted, proceed
              return ['success' => true];
      }
      ```

      ```go Go theme={null}
      response, err := client.Track(
          TrackRequest{
              UserId: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
              Action: "signIn",
              Attributes: &TrackAttributes{
                  DeviceId:    "<device-id>", // From __as_aid cookie if using Authsignal Web SDK
                  UserAgent:   "<user-agent>",
                  IpAddress:   "<ip-address>",
                  RedirectUrl: "https://yourapp.com/callback",
              },
          },
      )
      if err != nil {
          return err
      }

      // Handle the response
      switch response.State {
      case "CHALLENGE_REQUIRED":
          // Redirect to pre-built UI
          return map[string]interface{}{"url": response.Url}
      case "ALLOW":
          // User is trusted, proceed
          return map[string]interface{}{"success": true}
      }
      ```
    </CodeGroup>
  </Tab>
</Tabs>

<Info>
  Note: When using the Authsignal Web SDK, you can obtain the deviceId from the `__as_aid` cookie that's automatically created on the client side.
</Info>
