# DecisionRules Documentation

{% hint style="success" %}
Starting from version **1.20.0**, this documentation site supports multiple versions.

You can switch between versions using the version selector located in the top left corner of the page. Please ensure you are viewing the correct version of the documentation relevant to your needs.
{% endhint %}

### Agile Business Rule Engine for Every Industry

<figure><img src="https://cdn.prod.website-files.com/62038ffc9cd2db6132e3c782/6765552556400b759b7465bc_tab-minified.svg" alt=""><figcaption></figcaption></figure>

[DecisionRules](https://decisionrules.io/) is a lightweight business rules engine that lets you create, manage and deploy business rules. It is easy to use and allows to create the first rule in just a couple of minutes.

[Go to DecisionRules.io](https://decisionrules.io)

{% embed url="<https://youtu.be/TuEOn597ciw>" %}
DecisionRules intro
{% endembed %}

### What can you find in this documentation?

The documentation describes all the functionality you can find in the application. The descriptions are complemented by illustrative examples, so it is very easy to learn new skills!

### What you might like:

{% content-ref url="/pages/qENC7fm0pvACKnbT6FDe" %}
[API Introduction](/doc/api/api-introduction)
{% endcontent-ref %}

{% content-ref url="/pages/f7fAqW9SJXm1LHFNxN2p" %}
[Decision Table](/doc/rules/decision-table)
{% endcontent-ref %}

{% content-ref url="/spaces/-MN4F4-qybg8XDATvios/pages/-MgoeeBxNems\_FjTlY3T" %}
[Environment Variables](/doc/other-deployment-options/docker-and-on-premise/containers-environmental-variables)
{% endcontent-ref %}

### Learn basics in couple of minutes:

{% content-ref url="/pages/f7fAqW9SJXm1LHFNxN2p" %}
[Decision Table](/doc/rules/decision-table)
{% endcontent-ref %}

{% content-ref url="/pages/SkWeCmhUnTALgxD7McgV" %}
[Flow](/doc/rules/flow)
{% endcontent-ref %}

{% content-ref url="/pages/ZqDBKKMKpSYTyPxPCl9j" %}
[Decision Tree](/doc/rules/decision-tree)
{% endcontent-ref %}

### Most visited pages:

{% content-ref url="/pages/-ManB6dQvaV-fFix9Ks\_" %}
[Functions](/doc/rules/data-types-and-functions/operators/functions)
{% endcontent-ref %}

{% content-ref url="/pages/-MOcVILcb\_5ZDBDBsFeX" %}
[Simple Editor](/doc/rules/common-rule-features/input-and-output/simple-editor)
{% endcontent-ref %}

If you have any questions do not hesitate to contact us on: <mark style="color:purple;"><support@decisionrules.io></mark> or in term of sale support on <mark style="color:purple;"><sales@decisionrules.io></mark>


# API Introduction

Welcome to the section that deals with the [DecisionRules](https://decisionrules.io/) API. Here you can learn how to manage and use the API for the various functionalities we offer.

As far as rules are concerned, the solver API for rules and the Rule Flow and Management API are explained here. Furthermore, the data infrastructure is mentioned and described. Lastly, the solver API for Apache Kafka is described.

### How to setup an endpoint?

{% content-ref url="/pages/-MX\_hU6\_jnx5lznAByLk" %}
[Endpoint Settings](/doc/api/endpoints)
{% endcontent-ref %}

### What can you find in this space

{% content-ref url="/pages/-MQSqw9nnpqeCOmXYzmK" %}
[API Keys](/doc/api/api-keys)
{% endcontent-ref %}

{% content-ref url="/pages/-MN5N6X1Z6NeH4Hht5ye" %}
[Rule Solver API](/doc/api/rule-solver-api)
{% endcontent-ref %}

{% content-ref url="/pages/20voSVZXEFBa3K5HbcMe" %}
[Jobs API](/doc/api/jobs-api)
{% endcontent-ref %}

{% content-ref url="/pages/-Mj3V7IpLHGSWF6ZQqXB" %}
[Rule Flow Solver API (DEPRECATED)](/doc/api/archive/rule-flow-solver-api)
{% endcontent-ref %}

{% content-ref url="/pages/-Mhr2TXn2qhkf-92wVN9" %}
[Management API](/doc/api/management-api)
{% endcontent-ref %}

{% content-ref url="/pages/-MZrQbNZZ3V\_bfSLRvUP" %}
[Datacenters & Locations](/doc/api/geo-location)
{% endcontent-ref %}

{% content-ref url="/pages/ZdqcCdMRkI8pzsWPZ9aU" %}
[Apache Kafka Solver API](/doc/api/apache-kafka-solver-api)
{% endcontent-ref %}


# API Keys

API keys for using in your application.

## Three kinds of API Keys

API keys are an integral part of calling rules.

To use [Rule Solver](/doc/api/rule-solver-api) in your application, you need to have a solver API key.

To manage rules through our API in your application, you need to have a Management API key.

To get data about the rule solver activity for business intelligence, you need to have a BI API Key.

![](/files/-MhrBo44msPeriQZISCH)


# Solver API Keys

The DecisionRules Solver API Key is a specific type of API key used for accessing the Rule Solver API provided by DecisionRules.

To use [Rule Solver API](/doc/api/rule-solver-api) in your application, you need to have solver API keys.

{% hint style="info" %}

#### OAuth Solver API Authentication

Using the Solver API key is simple, but Enterprise clients often prefer OAuth with an external Identity provider. For detailed guidance on implementing **Enterprise OAuth**, please refer to our [OAuth documentation](/doc/api/api-keys/enterprise-oauth-m2m).
{% endhint %}

### Introduction

Here is a breakdown of what it is and its purpose:

* Purpose: The Solver API Key is essential for rule execution. It allows your application to send requests to DecisionRules to solve rules, such as decision tables, decision trees, or rule flows, and receive the calculated output data.
* Authentication: When making a call to the Rule Solver API, the Solver API Key is typically included in the authorization header (e.g., `Authorization: Bearer <Solver API Key>`) to authenticate the request and grant access to execute the rules within your space.
* Context: DecisionRules offers different types of API keys for various functionalities:
  * Solver API Key: Used for executing rules (solving).
  * Management API Key: Used for administrative actions like managing, creating, or updating rules via the API.
  * Business Intelligence (BI) API Key: Used to get analytical and reporting data about rule solver activity.

### Getting the Solver API key

You can find all your solver API keys on the API key page. On this page, you can copy, delete, or create a new solver API key.

To create a solver API key navigate: `Space -> API Keys -> Add API Key`

![](/files/rPimNc4ZijQ7sYSUgbj7)


# Management API keys

To manage rules through our [Management Solver API](/doc/api/management-api) in your application, you need to have a Management API key.

## Getting the management API key

You can find all your management API keys on the API key page. On this page, you can copy, delete, or create a new management API key.

### Go to the API key page

To create a management API key, sign in, then go to API Keys item in the sidebar menu.

![](/files/-MhrBo44msPeriQZISCH)

### Create a management API key

1. Go to API key page
2. Click on ![](/files/-MhrKTCP1Wri6X5PP9i9) the button. After that, a new Management API key will be created.


# BI API keys

To get data about the rule solver activity for business intelligence, you need to have a BI API Key.

## Getting the BI API key

You can find all your BI API Keys on the API Keys page. On this page, you can instantly copy, delete, or create a new BI API Key.

### Go to the API Keys page

To create a BI API Key, sign in and click the API Keys item in the sidebar menu.

![](/files/-MhrBo44msPeriQZISCH)

### Create a new BI API Key

1. Go to the API Keys page
2. In the BI API Keys section, click the Add BI API Key button.

{% hint style="danger" %}
Please note that anyone with access to a Business Intelligence API Key can also inherently access your Solver keys, as Audit Logs keep record of the Solver key used for the Solver invocation.
{% endhint %}


# Enterprise OAuth (M2M)

### Enterprise OAuth Integration: Solver API Key Security

Welcome to the DecisionRules Enterprise OAuth Setup Guide. This documentation outlines the steps required to secure and manage access to your Organization's **DecisionRules Solver API** using industry-standard OAuth 2.0 protocols.

#### Purpose

The DecisionRules Solver API processes sensitive business logic and requires machine-level security. To achieve this, we enforce the **OAuth 2.0 Client Credentials Grant Flow** (also known as Machine-to-Machine or M2M). This method ensures that all automated service calls are authenticated using secure, short-lived Access Tokens rather than static, long-lived API keys.

####

<table data-view="cards"><thead><tr><th></th></tr></thead><tbody><tr><td></td></tr><tr><td></td></tr></tbody></table>


# Custom Claims Format

### Creating the Custom Scope Claim for DecisionRules Solver API

To correctly set up the **OAuth M2M flow**, the Access Token must contain a custom scope claim that specifically identifies the organization, space, and target API (Solver) the client is authorized to access.

This claim ensures the token is restricted and valid only for the intended resources within your DecisionRules instance.

{% hint style="success" %}
First OAuth setup is done with the deployment with **DecisionRules Engineers.**&#x20;
{% endhint %}

#### Custom Scope Format

The required format for the custom scope claim is a colon-separated string that must start with `decisionrules`.

**The structure is as follows:**

$$\text{decisionrules}:\text{orgid}:\langle\text{Organization ID}\rangle:\text{spaceid}:\langle\text{Space ID}\rangle:\langle\text{scope}\rangle$$

**example:**

`decisionrules:orgid:12b057b4-865b-4545-81c4-8899d1da3537:spaceid:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver`

| **Component**       | **Description**                                                | **Example Value**                                                          |
| ------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `decisionrules`     | Mandatory prefix indicating the target service.                | `decisionrules`                                                            |
| `orgid`             | Fixed identifier for the Organization ID key.                  | `orgid`                                                                    |
| `<Organization ID>` | The unique identifier of your DecisionRules Organization.      | `12b057b4-865b-4545-81c4-8899d1da3537`                                     |
| `spaceid`           | Fixed identifier for the Space ID key.                         | `spaceid`                                                                  |
| `<Space ID>`        | The unique identifier of the Space within the Organization.    | `8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6`                                     |
| `scope`             | The specific API resource scope you are authorizing access to. | <p>Currently only supported scope is <code>solver</code> </p><p>      </p> |
|                     |                                                                |                                                                            |


# Organization Setup

### OAuth Setup for DecisionRules Organization

{% hint style="success" %}
First OAuth setup is done with the deployment with **DecisionRules Engineers.**&#x20;
{% endhint %}

For **OAuth Machine-to-Machine (M2M)** authentication to function within your DecisionRules Organization, you must configure the platform to correctly validate the JSON Web Tokens (JWTs) issued by your external **Identity Provider (IdP)**.

This setup transforms DecisionRules into a Resource Server that trusts tokens signed by your IdP, ensuring only authenticated machines from your ecosystem can access the Solver API.

**Navigate to:  `Organizations -> Select Organization -> Settings -> Enterprise Oauth API Settings`**

<figure><img src="/files/YU6S1XjfhpsU0kPeJsk1" alt=""><figcaption></figcaption></figure>

#### 1. OAuth Identity Provider

This setting tells DecisionRules which industry-standard IdP you are using. This selection helps ensure compatibility and may pre-fill standard endpoints.

* Options:
  * Azure: Refers to Azure Active Directory (now Microsoft Entra ID).
  * Okta: A major independent identity and access management provider.
  * Auth0: A popular, flexible identity platform (now part of Okta).

***

#### 2. JSON Web Key Sets URL

The JWKS URL is arguably the most critical component for token validation.

* What it is: JSON Web Key Set (JWKS) is a standardized JSON object that contains the public keys used by the Identity Provider to digitally sign the JWT Access Tokens it issues.
* What it means: When DecisionRules (the Resource Server) receives an Access Token from your client application, it must verify the token's signature. It does this by:
  1. Fetching the public keys from the JWKS URL.
  2. Finding the correct public key (typically by matching the `kid`—Key ID—in the token's header).
  3. Using that public key to cryptographically verify the token's signature.
* Purpose: This mechanism proves that the token was genuinely created and signed by the trusted Identity Provider and hasn't been tampered with. It also simplifies key management, as the IdP can rotate its private signing keys without requiring manual updates in DecisionRules—DecisionRules automatically fetches the updated public keys from this URL.
* Typical Format: `https://your-idp-domain.com/.well-known/jwks.json`

***

#### 3. Token Issurer (iss)

The `iss` claim in the JWT identifies the principal that issued the token.

* What it is: A case-sensitive string or URI representing the Identity Provider (Authorization Server) that generated and signed the Access Token.
* What it means: DecisionRules will check the `iss` claim inside every incoming Access Token. If the value does not exactly match the `ISS` value configured in the Organization settings, the token will be rejected. This is a crucial security check to ensure tokens are only accepted from your designated, trusted IdP.
* Example Value: `https://your-idp-domain.com/oauth2/default`

***

#### 4. Audience (aud)

The `aud` claim in the JWT identifies thee intended recipient of the token.

* What it is: A case-sensitive string or URI that represents the specific resource (API) the token is meant to be used for.
* What it means: DecisionRules (the Solver API) acts as the Audience. When the IdP issues the token to your machine client, it includes the API's unique identifier in the `aud` claim. DecisionRules checks this claim and will only accept a token if the configured `AUD` value is present in the token's audience list. This prevents a token issued for, say, a document API from being mistakenly used to access the DecisionRules Solver API.
* Example Value: `https://api.decisionrules.io` or a custom identifier configured in your IdP.


# Client App Authorization

To authorize your requests to the DecisionRules API using OAuth 2.0, you can include your generated access token directly in the `Authorization` header of your HTTP request.

***

#### Header Format

The `Authorization` header must be formatted as follows, using the prefix `oauth:` followed immediately by your access token:

`Authorization: oauth:<access_token>`

* `<access_token>`: Replace this placeholder with the actual OAuth 2.0 access token you received during the authorization process.

***

#### Example

If your access token is `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eW91ckFjY2Vzc1Rva2Vu`, the complete header would look like this:

| **Header**      | **Value**                                                         |
| --------------- | ----------------------------------------------------------------- |
| `Authorization` | `oauth:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eW91ckFjY2Vzc1Rva2Vu` |

This format is typically used when making calls to secure endpoints, ensuring that the request is properly authenticated.

```ara
curl --request POST \
  --url http://api.decisionrules.io/rule/solve/my-rule-alias/1 \
  --header 'Authorization: oauth:eyJ0eXAiOiJKV1QiLCJhbGc.....' \
  --header 'Content-Type: application/json' \
  --header 'X-Strategy: STANDARD' \
  --data '{
  "data": {
    "productType": "medium",
    "period": "year",
    "promoCode": "SUMMER SALE"
  }
}'
```

Would you like to see an example of an API call using this authorization method?


# Azure OAuth

### Azure AD OAuth 2.0 Client Credentials (M2M) Setup

This guide details the two-part setup required in **Microsoft Entra ID (Azure AD)** to use the OAuth Machine-to-Machine (M2M) flow for securing your DecisionRules Solver API Key.

### Part I: DecisionRules Resource Application Setup

The Resource Application represents the DecisionRules Solver API itself. This is where you define the custom scope that grants access to your specific Organization and Space.

#### Step 1: Register the DecisionRules Resource API

1. **Sign in** to the [Microsoft Entra admin center](https://www.google.com/search?q=https://entra.microsoft.com).
2. Navigate to **Identity** > **Applications** > **App registrations**.
3. Click **+ New registration**.
4. **Name:** Enter `DecisionRules Solver API Resource` (or similar).
5. **Supported account types:** Select your desired tenant option (e.g., `Accounts in this organizational directory only`).
6. Click **Register**.

#### Step 2: Define the Application ID URI (The AUD Claim)

This URI uniquely identifies the DecisionRules Resource API and will be used as the **Audience (AUD)** for validation.

1. From the new App Registration overview page, navigate to **Manage** > **Expose an API**.
2. Next to **Application ID URI**, click **Set**.
3. Accept the default URI format (e.g., `api://<Application (client) ID>`) or define your own (e.g., `https://decisionrules.io/solver-api`).
4. **RECORD THIS FULL URI.** This value is critical and must be provided to the DecisionRules platform during your Organization's OAuth setup.

#### Step 3: Create the Custom Scope

This scope embeds your specific Organization and Space identifiers, ensuring fine-grained authorization.

1. In the same **Expose an API** blade, scroll down to **Scopes defined by this API**.
2. Click **+ Add a scope**.
3. Configure the scope using your provided identifiers:

| Field                          | Value                                                                                                          |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| **Scope name**                 | `decisionrules:orgid:12b057b4-865b-4545-81c4-8899d1da3537:spaceid:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver` |
| **Who can consent?**           | Select **Admins only** (Recommended for M2M flow)                                                              |
| **Admin consent display name** | `Access DecisionRules Solver API for specific Org/Space`                                                       |
| **Admin consent description**  | `Allows machine clients to execute rules on the specified DecisionRules Organization and Space.`               |
| **State**                      | **Enabled**                                                                                                    |

4. Click **Add scope**.

### Part II: Client Application Setup

The Client Application represents your calling service (e.g., your ERP, microservice, or back-end automation). This application requests the token.

#### Step 1: Register the Client Application

1. Navigate back to **App registrations** and click **+ New registration**.
2. **Name:** Enter a name for your calling service (e.g., `My ERP Client Service`).
3. Click **Register**.
4. From the overview page, record the **Application (client) ID** (your **Client ID**) and the **Directory (tenant) ID** (your **Tenant ID**).

#### Step 2: Create Client Credentials

1. From the client's management menu, navigate to **Certificates & secrets**.
2. Click **+ New client secret**.
3. Add a description and set an appropriate expiration.
4. **IMMEDIATELY COPY AND SECURELY STORE THE SECRET VALUE.** You will not be able to retrieve it again. This is your **Client Secret**.

#### Step 3: Grant Application Permission and Admin Consent

You must grant the Client Application permission to use the custom scope defined in Part I.

1. From the client's management menu, navigate to **API permissions**.
2. Click **+ Add a permission**.
3. Select the **My APIs** tab.
4. Select the **DecisionRules Solver API Resource** you created in Part I.
5. Select **Application permissions** (for M2M/service-to-service calls).
6. Expand the permission and check the box next to your custom scope: `decisionrules:orgid:12b057b4-865b-4545-81c4-8899d1da3537:spaceid:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver`.
7. Click **Add permissions**.
8. Click the **Grant admin consent for \[Your Tenant]** button and confirm. The Status must show **"Granted"**.

### Final Step: Requesting the Access Token

Your client application must now use its credentials and the `.default` scope to request an Access Token that includes the granted custom permission.

| OAuth Parameter     | Source Value                                                                                                                                                                                                             |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`client_id`**     | Client Application ID (from Part II, Step 1)                                                                                                                                                                             |
| **`client_secret`** | Client Secret Value (from Part II, Step 2)                                                                                                                                                                               |
| **`grant_type`**    | `client_credentials` (Fixed value for M2M)                                                                                                                                                                               |
| **`scope`**         | <p><strong>example:</strong> <em>api://cdc128ef-09ca-46ca-a349-57c0c248cad7/.default</em></p><p><strong>Application ID URI</strong> (from Part I, Step 2) <strong>followed by</strong> <code>/.default</code>   <br></p> |

**Example Token Request:**

```ara
# Assuming the Application ID URI (AUD) from Part I is:
# RESOURCE_URI="api://cdc128ef-09ca-46ca-a349-57c0c248cad7"

CLIENT_ID="<Your Client Application ID>"
CLIENT_SECRET="<Your Client Secret Value>"
TENANT_ID="<Your Tenant ID>"
RESOURCE_URI="api://cdc128ef-09ca-46ca-a349-57c0c248cad7"

curl --location --request POST "[https://login.microsoftonline.com/$](https://login.microsoftonline.com/$){TENANT_ID}/oauth2/v2.0/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=${CLIENT_ID}" \
--data-urlencode "client_secret=${CLIENT_SECRET}" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "scope=${RESOURCE_URI}/.default"
```

**Example Response:**

```json
{
  "token_type": "Bearer",
  "expires_in": 3599,
  "ext_expires_in": 3599,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InJ0c0ZULWItN0x1
  WTdEVlllU05LY0lKN1ZuYyJ9.eyJhdWQiOiJjZGMxMjhlZi0wOWNhLTQ2Y2EtYTM0OS01N2MwYzI0
  OGNhZDciLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vOTY2MGFkMjYtOD
  k2ZC00NDM4LWEwMTMtZTNlZTIzYjU3YjdjL3YyLjAiLCJpYXQiOjE3NjM0NTg4NjAsIm5iZiI6MTc
  2MzQ1ODg2MCwiZXhwIjoxNzYzNDYyNzYwLCJhaW8iOiJrMkpnWUlqWWZsWFNjMnVMc0NwN3lvSWR3a
  WN2aThjWjMzMFZzWExPM3pxQkNnTmx6Yk1BIiwiYXpwIjoiMjk3NDkyNmEtMDgxOC00MDdiLWE4NmM
  tYjc2MTZjZTNhODFhIiwiYXpwYWNyIjoiMSIsIm9pZCI6ImE3NmFmMTQ1LWI4MGEtNGZkOS05Yzc2L
  WJmNTZmOGIzYjAwOSIsInJoIjoiMS5BUk1CSnExZ2xtMkpPRVNnRS1QdUk3VjdmTzhvd2MzS0NjcEd
  vMGxYd01KSXl0YzZBUUFUQVEuIiwicm9sZXMiOlsiU29sdmVyIiwiTWFuYWdlbWVudCIsImRlY2lza
  W9ucnVsZXM6b3JnSWQ6MTJiMDU3YjQtODY1Yi00NTQ1LTgxYzQtODg5OWQxZGEzNTM3OnNwYWNlSWQ
  6OGJhNmJhYzktMDhhOC1lNjQ4LThhMmMtMGIzOTkyYTliNGQ2OnNvbHZlciJdLCJzdWIiOiJhNzZhZ
  jE0NS1iODBhLTRmZDktOWM3Ni1iZjU2ZjhiM2IwMDkiLCJ0aWQiOiI5NjYwYWQyNi04OTZkLTQ0Mzgt
  YTAxMy1lM2VlMjNiNTdiN2MiLCJ1dGkiOiJEVEMxRzBpamhFU3oyZTNRa055WEFBIiwidmVyIjoiMi4
  wIiwieG1zX2Z0ZCI6IjdHd1NVVFZRRkpDWlRGQ0xJMTRLdVEzeHotSVNTWXR2M05FdVpBY3BsbmdCWl
  hWeWIzQmxibTl5ZEdndFpITnRjdyJ9.BouxeEV4SGFUq0Q9JvaxpZ-gxgUeyRw5Y8VDjAkMlNp3c-zX
  o65OOiulH8IK_Jdv1A28ZWAU-X3LEbvG_YifNjy9UnKrsnKMGvi8DmIN8ZoAsoUJTTfZD9CUEjxTjx1
  QwZc6njqGt8J-zfffGLvewMzNmijWaCdv81O8hDOYTV84xz2YSbIMvjZ65BZC4jnGunVmbgN9LXgQRQ
  xSncnOd2X8JDmG36YDknjlKyZUtSV8hE1kaAkApgQRvZKzaWFhqZoKotMcQRTnRhGuRbxHgIRKBI6KL
  R1fJTCVkywzDqTQdm84dJrERPp9Lg51EBeZPZ0Bqalg5RsNFWmqX0IA9Q"
}
```

**Example Decoded JWT Token Data:**

```jsonc
// JWT HEaders
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "rtsFT-b-7LuY7DVYeSNKcIJ7Vnc"
}

// Decoded Payload
{
  "aud": "cdc128ef-09ca-46ca-a349-57c0c248cad7",
  "iss": "https://login.microsoftonline.com/9660ad26-896d-4438-a013-e3ee23b57b7c/v2.0",
  "iat": 1763458860,
  "nbf": 1763458860,
  "exp": 1763462760,
  "aio": "k2JgYIjYflXSc2uLsCp7yoIdwicvi8cZ330VsXLO3zqBCgNlzbMA",
  "azp": "2974926a-0818-407b-a86c-b7616ce3a81a",
  "azpacr": "1",
  "oid": "a76af145-b80a-4fd9-9c76-bf56f8b3b009",
  "rh": "1.ARMBJq1glm2JOESgE-PuI7V7fO8owc3KCcpGo0lXwMJIytc6AQATAQ.",
  "roles": [
    "decisionrules:orgId:12b057b4-865b-4545-81c4-8899d1da3537:spaceId:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver"
  ],
  "sub": "a76af145-b80a-4fd9-9c76-bf56f8b3b009",
  "tid": "9660ad26-896d-4438-a013-e3ee23b57b7c",
  "uti": "DTC1G0ijhESz2e3QkNyXAA",
  "ver": "2.0",
  "xms_ftd": "7GwSUTVQFJCZTFCLI14KuQ3xz-ISSYtv3NEuZAcplngBZXVyb3Blbm9ydGgtZHNtcw"
}
```

The resulting Access Token will be valid and contain the necessary `roles` (scope) claim, allowing the client to access the DecisionRules Solver API.


# Okta OAuth

### Okta OAuth 2.0 Client Credentials (M2M) Setup

This guide details the two-part setup required in **Okta** to use the OAuth Machine-to-Machine (M2M) flow for securing your DecisionRules Solver API Key.

### Part I: DecisionRules Resource API (Custom Authorization Server)

The Resource API is defined by an Okta **Custom Authorization Server**, which mints the JWT Access Tokens and validates the custom scope.

#### Step 1: Create the Custom Authorization Server

1. **Sign in** to your Okta Admin Console.
2. Navigate to **Security** > **API**.
3. Select the **Authorization Servers** tab.
4. Click **Add Authorization Server**.
5. **Name:** Enter `DecisionRules Solver API` (or similar).
6. **Audience:** Enter a unique identifier for this server, such as: `https://decisionrules.io/solver-api`
   * **RECORD THIS VALUE.** This is your **Audience (AUD)** and will be the **Issuer (ISS)** URI when requesting tokens.
7. Click **Save**.

#### Step 2: Configure Claims

You must configure the Authorization Server to include a custom scope in the access token.

1. Stay in the new **DecisionRules Solver API** Authorization Server and navigate to the **Scopes** tab.
2. Click **Add Scope**.
3. Configure the scope using your provided identifiers:

| Field             | Value                                                                                                          |
| ----------------- | -------------------------------------------------------------------------------------------------------------- |
| **Name**          | `decisionrules:orgid:12b057b4-865b-4545-81c4-8899d1da3537:spaceid:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver` |
| **Display Name**  | `DecisionRules Solver Access`                                                                                  |
| **Description**   | `Allows machine clients to execute rules on the specified DecisionRules Organization and Space.`               |
| **Default Scope** | Leave unchecked.                                                                                               |
| **Consent**       | Select **No Consent Required**.                                                                                |

4. Click **Create**.

**Key URLs from Authorization Server:**

* **ISS (Issuer):** Found under the **Settings** tab (e.g., `https://{your-okta-domain}/oauth2/ausxxxxxxxxxx`)
* **JWKS URL:** Found under the **Settings** tab. DecisionRules requires this URL for token signature verification.

### Part II: Client Application Setup

The Client Application is the machine or service that will authenticate and request the access token.

#### Step 1: Create the Service Application

1. Navigate to **Applications** > **Applications** in the Okta Admin Console.
2. Click **Create App Integration**.
3. **Sign-in method:** Select **API Services** (or Service).
4. **Application Type:** Select **Client Credentials**.
5. Click **Next**.
6. **App integration name:** Enter a name for your calling service (e.g., `My ERP Client Service`).
7. Click **Save**.
8. From the **General** tab, record the following critical values:
   * **Client ID**
   * **Client Secret**

#### Step 2: Grant Client Access via an Access Policy

You must configure the Custom Authorization Server to allow the new Client Application to access the custom scope.

1. Navigate back to **Security** > **API** > **Authorization Servers** and select the **DecisionRules Solver API** server.
2. Go to the **Access Policies** tab.
3. If no policy exists, click **Add New Policy**.
   * **Policy Name:** E.g., `M2M Client Credentials Policy`.
   * **Assign to:** Set **The following clients** and add your **My ERP Client Service** application.
4. Within the new policy, click **Add Rule**.
   * **Rule Name:** E.g., `Client Credentials Grant`.
   * **If Grant Type is:** Check **Client Credentials**.
   * **If User is:** Set **The user assigned to the application**.
   * **THEN:** Ensure the **Access Token lifetime** is set (e.g., 3600 seconds/1 hour).
   * **Access Token with the following scopes:** Include the full custom scope: `decisionrules:orgid:12b057b4-865b-4545-81c4-8899d1da3537:spaceid:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver`.
5. Click **Create Rule**.

### Final Step: Requesting the Access Token

In the Okta Client Credentials flow, you explicitly request the custom scope name.

| OAuth Parameter        | Source Value                                                                                                                                                                                                                     |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Token Endpoint URL** | Authorization Server metadata (e.g., `https://{your-okta-domain}/oauth2/ausxxxxxxxxxx/v1/token`)                                                                                                                                 |
| **`client_id`**        | Client Application ID (from Part II, Step 1)                                                                                                                                                                                     |
| **`client_secret`**    | Client Secret Value (from Part II, Step 2)                                                                                                                                                                                       |
| **`grant_type`**       | `client_credentials` (Fixed value for M2M)                                                                                                                                                                                       |
| **`scope`**            | <p><strong>The full, specific custom scope name (from Part I, Step 2)</strong><br><br><strong>example:</strong> decisionrules:orgId:12b057b4-865b-4545-81c4-8899d1da3537:spaceId:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver</p> |

**Example Token Request:**

```ara
AUTH_SERVER_URL="https://{your-okta-domain}/oauth2/ausxxxxxxxxxx"

curl --location --request POST "${AUTH_SERVER_URL}/v1/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=<Your Client ID>" \
--data-urlencode "client_secret=<Your Client Secret>" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "scope=decisionrules:orgid:12b057b4-865b-4545-81c4-8899d1da3537:spaceid:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver"
```

**Example Response:**

```jsonc
// Some code
{
  "token_type": "Bearer",
  "expires_in": 3600,
  "access_token": "eyJraWQiOiJvNzI0LTVhZXV5X2hnZTd1bE1mYXU2Nk1OZEFDeENNcV9GWGEyc002VD
  M0IiwiYWxnIjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULlEtOTc5eWVlMzJydUkteEFvOVpKZkFyU
  3VzMnAwNXVsNFh1R0xGcjNhd0UiLCJpc3MiOiJodHRwczovL3RyaWFsLTM2OTc5ODUub2t0YS5jb20vb2F
  1dGgyL2F1c3g1NnJrd3ZmOXVDVUNjNjk3IiwiYXVkIjoiaHR0cHM6Ly9hcGkubXljb21wYW55LmNvbS9yZ
  XNvdXJjZS1hcHAiLCJpYXQiOjE3NjM0NTk2NDAsImV4cCI6MTc2MzQ2MzI0MCwiY2lkIjoiMG9heDU2dDV
  zY0JSMG90U3A2OTciLCJzY3AiOlsiZGVjaXNpb25ydWxlczpvcmdJZDoxMmIwNTdiNC04NjViLTQ1NDUtO
  DFjNC04ODk5ZDFkYTM1Mzc6c3BhY2VJZDo4YmE2YmFjOS0wOGE4LWU2NDgtOGEyYy0wYjM5OTJhOWI0ZDY
  6c29sdmVyIl0sInN1YiI6IjBvYXg1NnQ1c2NCUjBvdFNwNjk3In0.wo6RIZWNvl_H0u5ghTgwPX126vB-n
  aZzWiNhAISbgwXkIEeR142eQ47Ew-8iCVw24O6lQWiZS0eSUWxHZLpHD_cM-NIbGw-xuGc__VgFDa-mqu
  gWMLqXiRgGSKzQfZNl6b77TXtf6PRIrUwMveIdNwHWjqCaTXGyiw-Veu9tPZjdsvYNKwVwq-BVP0VWaeY
  tblyFmao7A2TexYA0W3FOU7L180tbWHKSh2L4yURz59l3evOVbRktCvCi8NNqFNtYTh2c9Z6KCRkMzmi2
  O9RDjKlFd_fu5F1uokkueJw-lqmOk1kNTJUBIDgOzw9APgWJOd41L7zFOLx9NNUMVmC53g",
  "scope": "decisionrules:orgId:12b057b4-865b-4545-81c4-8899d1da3537:spaceId:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver"
}
```

**Example Decoded Access Token Data:**

```jsonc
// Decoded headers
{
  "kid": "o724-5aeuy_hge7ulMfau66MNdACxCMq_FXa2sM6T34",
  "alg": "RS256"
}

// Decoded payload
{
  "ver": 1,
  "jti": "AT.Q-979yee32ruI-xAo9ZJfArSus2p05ul4XuGLFr3awE",
  "iss": "https://trial-3697985.okta.com/oauth2/ausx56rkwvf9uCUCc697",
  "aud": "https://api.mycompany.com/resource-app",
  "iat": 1763459640,
  "exp": 1763463240,
  "cid": "0oax56t5scBR0otSp697",
  "scp": [
    "decisionrules:orgId:12b057b4-865b-4545-81c4-8899d1da3537:spaceId:8ba6bac9-08a8-e648-8a2c-0b3992a9b4d6:solver"
  ],
  "sub": "0oax56t5scBR0otSp697"
}
```

The resulting Access Token will be a JWT containing the custom scope in the `scp` (scope) claim, which the DecisionRules Solver API will use to authorize the execution.


# Rule Solver API

Request and response from API solving.

The Rule Solver API is the most important API of DecisionRules. It allows you to send requests to solve rules (decision tables, decision trees, etc.) and obtain the output data. Below, you will find the specification of the single endpoint of this API.

{% hint style="success" %}
In version 1.16.0 and newer you can solve your ruleflow with **Rule Solver API** endpoint.

Rule flow Solver API endpoint is now deprecated.
{% endhint %}

### Swagger

You can check out these endpoints and call them right away using swagger.

**Swagger UI:** [https://api.decisionrules.io/api/solver/docs](https://api.decisionrules.io/api/solver/docs/)

**Swagger JSON File:** <https://api.decisionrules.io/api/solver/docs/json>

| Name                                            | Type   | Description                                                                                                                                                                                                |
| ----------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | string | Bearer \<Solver API Key>                                                                                                                                                                                   |
| Content-Type                                    | string | application/json                                                                                                                                                                                           |
| X-Strategy                                      | string | <p>Execution Strategy: STANDARD, FIRST\_MATCH, ARRAY or EVALUATE\_ALL</p><p><a href="/pages/-McxGhGLuMz7QidlmeeA">More in execution strategies</a></p>                                                     |
| X-Lookup-Method                                 | string | <p>Specifies the method to use:  LOOKUP\_EXISTS or LOOKUP\_VALUE<br><a href="/pages/-McxGhGLuMz7QidlmeeA">More in execution strategies</a></p>                                                             |
| X-Correlation-Id                                | string | Correlation ID, in case you would like to set it manually. If not present, correlation ID will be generated automatically. In any case, the correlation ID is returned in the same header of the response. |
| X-Audit                                         | string | Decides whether an audit of the solve should be created and saved. In case you want the audit to be created and saved, input "true".                                                                       |
| X-Audit-Ttl                                     | string | A number that dictates after how many days the audit will be deleted. Set to 14 days by default.                                                                                                           |

## Solve Rule

> This endpoint allows you to solve your rule while providing input data in JSON format. If the \`{version}\` parameter is omitted from the path, the last published version will be used automatically.

```json
{"openapi":"3.0.0","info":{"title":"DecisionRules Rule Solver API","version":"1.0.0"},"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Please insert: \"Bearer <SOLVER_API_KEY>\" into Authorization header."}}},"paths":{"/rule/solve/{ruleId}/{version}?":{"post":{"summary":"Solve Rule","description":"This endpoint allows you to solve your rule while providing input data in JSON format. If the `{version}` parameter is omitted from the path, the last published version will be used automatically.","parameters":[{"name":"ruleId","in":"path","required":true,"description":"Unique identifier for the rule that is common to all rule versions. Instead of rule ID, it is possible to use a rule alias.","schema":{"type":"string"}},{"name":"version","in":"path","required":false,"description":"Business rule version. If the parameter is not filled in, the last published version will be used automatically.","schema":{"type":"integer"}},{"name":"Authorization","in":"header","required":true,"description":"Bearer Solver_API_Key","schema":{"type":"string"}},{"name":"Content-Type","in":"header","required":false,"description":"The media type of the request body. Example: application/json.","schema":{"type":"string"}},{"name":"X-Strategy","in":"header","required":false,"description":"Defines the execution strategy. Possible values: STANDARD, ARRAY, FIRST_MATCH.","schema":{"type":"string","enum":["STANDARD","ARRAY","FIRST_MATCH"]}},{"name":"X-Correlation-Id","in":"header","required":false,"description":"Correlation ID, if you'd like to set it manually. If not present, it will be generated automatically and returned in the response.","schema":{"type":"string"}},{"name":"X-Audit","in":"header","required":false,"description":"Decides whether an audit of the solve should be created and saved. Use 'true' to enable auditing.","schema":{"type":"string","enum":["true","false"]}},{"name":"X-Audit-Ttl","in":"header","required":false,"description":"Number of days after which the audit will be deleted. Default is 14 days.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"Request body containing the input data and solver options.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"JSON object that describes the input json data."},"options":{"type":"object","description":"Object specifying solver options."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Authentication token missing","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="info" %}
For easy Rule Solver API calls go to Integrations -> Code Library. Note that the cURL code can be copy/pasted directly to Postman.
{% endhint %}

#### Request example

```http
URL
https://api.decisionrules.io/rule/solve/:ruleId/:version

Headers:
Content-Type: application/json
Authorization: Bearer DOZpz-h6xnOrKGIINlYvkd9hn41pRR3oG6cqH
```

{% hint style="info" %}
If you're using the **Regional Cloud** version of DecisionRules, read more about API calls [here](/doc/other-deployment-options/regional-cloud/region-specific-api-urls#making-api-calls-on-region-cloud-accounts).
{% endhint %}

{% hint style="info" %}
Note that you can use **rule alias** instead of rule ID to identify the rule. In that case, make sure that the rule alias is unique within the space, otherwise the request will fail.
{% endhint %}

{% hint style="info" %}
You must provide your own API Key after the `Bearer` keyword. Generate it in the [API Keys ](https://app.decisiongrid.io/api-keys)section of the app.
{% endhint %}

The body of the request needs to have the following structure.

```javascript
{
    "data": {
        // INPUT OBJECT
    }
}
```

For example, it may look as follows. Note that the object provided under the `data` key needs to correspond to the input model of the rule you wish to solve (see Rule Settings -> I/O Model).

```javascript
{
    "data": {
        "client": {
            "age": 18
        }
    }
}
```

### Simple Solve

Simple solve means that you send a single set of input data and the solver thus evaluates this single input. The response is an array of results (given e.g. by the individual rows of a decision table).

#### Rule

![](/files/n8zMXZ64r55iJmPZyh1a)

#### Simple Request

This is how the object sent under the `data` key could look for the given rule.

```json
{
  "client": {
    "age": 18
  },
  "productCount": {
    "accountsAndCards": 4,
    "Investments": 4
  },
  "portfolioAmount": 15000
}
```

#### Simple Response

And this would be the response. Suppose that only one row of the decision table was triggered and the output is therefore an array with a single output data object (corresponding to the outputs set on the triggered row).

```json
[
  {
    "totalProducts": 8,
    "amountPerProduct": 1875,
    "client": {
      "segment": "senior affluent"
    },
    "profitability": 1
  }
]
```

### Bulk Solve

On the other hand, DecisionRules also supports the bulk solve, which is a call to the solver where you include multiple sets of input data. Each set is evaluated individually, with no relation to any other, and the solver returns an array of the corresponding output objects.

#### Rule

![](/files/i0JBIKLWB9XXfpbAheZ2)

#### Bulk Request

This is how the JSON under the `data` key of a bulk request is structured. Instead of an input data object, you send an array of these objects.

```json
[
  {
    "product": {
      "id": "P1",
      "price": 400
    },
    "paymentMethod": {
      "debitCard": true,
      "creditCard": false,
      "cash": {}
    }
  },
  {
    "product": {
      "id": "P2",
      "price": 300
    },
    "paymentMethod": {
      "debitCard": true,
      "creditCard": {},
      "cash": {}
    }
  }
]
```

#### Bulk Response

And here is the response. The outer array corresponds to the array provided in the bulk input. The inner arrays specify the individual results, just as in the case of a simple solve. Thus, in the following example, you can see two elements of the outer array corresponding to the two input data objects sent over in our bulk request (as seen above). Each of these elements is an array which holds a single result (therefore, a single row of the decision table was triggered for both sets of input data).

```json
[
  [
    {
      "suplier": "Amazon",
      "amount": 400
    }
  ],
  [
    {
      "suplier": "Lenovo",
      "amount": 300
    }
  ]
]
```

### Options

As you might have noticed, the body of the request to the Rule Solver API takes an optional `options` object. This object allows to configure the solver. In general, the options are different for each type of rule. As of now, they are only used for decision tables.

If you are solving a **decision table**, you may configure the solver with the following options.

#### Included Condition Cols

Allows to specify condition columns that should be taken in account when solving the decision table. All other columns will be ignored. Columns are identified by the name of the input variable related to the respective column.

For example, the body of the request may look like this.

```javascript
{
    "data": {
        // INPUT OBJECT
    },
    "options": {
        "includedConditionCols": ["client.age","portfolioAmount"]
    }
}
```

With this configuration, only the columns related to `client.age` and `portfolioAmount` input variables will be evaluated.

#### Excluded Condition Cols

If you wish to exclude some columns, you can do that with this property. Columns are identified by the name of the input variable related to the respective column.

{% hint style="info" %}
Note that the `includedConditionCols` take precedence over `excludedConditionCols`. If you specify both included and excluded condition columns, the excluded columns will be therefore ignored. It is recommended to use just one of these properties.
{% endhint %}

The body of the request may look as follows.

```javascript
{
    "data": {
        // INPUT OBJECT
    },
    "options": {
        "excludedConditionCols": ["client.age","portfolioAmount"]
    }
}
```

With this setup, all columns except the `client.age` and `portfolioAmount` will be considered when solving of the decision table.

As of now, there are no other **options** supported; in particular, there are no options that would affect other types of rules. However, it is expected that these will be added in the future with the evolving capabilities of DecisionRules.


# Jobs API

The Jobs API is a secure REST API that manage jobs.

### Request authorization

{% hint style="info" %}
To authenticate your requests, you must use a Bearer token with a valid **Solver API key**.
{% endhint %}

For example:

```
Authorization: Bearer YOUR_SOLVER_API_KEY
```

## Start a new job.

> Starts a new asynchronous job for a specific Integration Flow.\
> The \`identifier\` is the unique ID of the Integration Flow, and \`version\` is its specific version.\
> This endpoint only accepts rules of type \`IntegrationFlow\`.<br>

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"servers":[{"url":"https://api.decisionrules.io/job"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"ApiKey"}},"schemas":{"JobStatus":{"type":"object","properties":{"state":{"$ref":"#/components/schemas/JobState"},"code":{"$ref":"#/components/schemas/JobStatusCode"},"message":{"type":"string","description":"A human-readable message for the status."}}},"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]},"JobStatusCode":{"type":"string","enum":["JOB_SUCCESS","JOB_ERROR","JOB_TIMEOUT","JOB_QUOTA_EXCEEDED","JOB_EXECUTION_ERROR","JOB_VALIDATION_ERROR","JOB_USER_CANCELED","JOB_SYSTEM_CANCELED","ZOMBIE_PROCESS","JOB_INITIALIZED","JOB_RUNNING","JOB_WAITING"]}}},"paths":{"/start/{identifier}/{version}":{"post":{"summary":"Start a new job.","description":"Starts a new asynchronous job for a specific Integration Flow.\nThe `identifier` is the unique ID of the Integration Flow, and `version` is its specific version.\nThis endpoint only accepts rules of type `IntegrationFlow`.\n","operationId":"startJob","parameters":[{"name":"identifier","in":"path","required":true,"description":"The unique identifier of the Integration Flow.","schema":{"type":"string"}},{"name":"version","in":"path","required":false,"description":"The specific version of the Integration Flow. If not provided, the latest published version is used.","schema":{"type":"string"}}],"requestBody":{"description":"Input data for the Integration Flow.","required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"A JSON object containing the input data for the job."}}}},"responses":{"200":{"description":"Job started successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string","description":"The ID of the newly created job."},"status":{"$ref":"#/components/schemas/JobStatus"}}}}}},"400":{"description":"Business error."},"401":{"description":"Unauthorized. Invalid or missing API key."}}}}}}
```

## Cancel a job.

> Attempts to cancel a specific job by its ID. The job must belong to the requesting space.

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"servers":[{"url":"https://api.decisionrules.io/job"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"ApiKey"}},"schemas":{"Job":{"type":"object","properties":{"jobId":{"type":"string"},"correlationId":{"type":"string"},"inputData":{"type":"object","additionalProperties":true},"output":{"type":"object","additionalProperties":true,"nullable":true},"ruleReference":{"$ref":"#/components/schemas/JobRuleReference"},"context":{"$ref":"#/components/schemas/JobContext"},"status":{"$ref":"#/components/schemas/JobStatus"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true},"apiKey":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"nullable":true}}},"JobRuleReference":{"type":"object","properties":{"baseId":{"type":"string","description":"The ID of the rule."},"version":{"type":"number","description":"The version of the rule."},"type":{"type":"string","description":"The type of the rule (e.g., IntegrationFlow)."}}},"JobContext":{"type":"object","properties":{"spaceId":{"type":"string"},"billingUserId":{"type":"string"},"executorUser":{"type":"object","nullable":true},"usedApiKeyId":{"type":"string","nullable":true}}},"JobStatus":{"type":"object","properties":{"state":{"$ref":"#/components/schemas/JobState"},"code":{"$ref":"#/components/schemas/JobStatusCode"},"message":{"type":"string","description":"A human-readable message for the status."}}},"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]},"JobStatusCode":{"type":"string","enum":["JOB_SUCCESS","JOB_ERROR","JOB_TIMEOUT","JOB_QUOTA_EXCEEDED","JOB_EXECUTION_ERROR","JOB_VALIDATION_ERROR","JOB_USER_CANCELED","JOB_SYSTEM_CANCELED","ZOMBIE_PROCESS","JOB_INITIALIZED","JOB_RUNNING","JOB_WAITING"]}}},"paths":{"/cancel/{jobId}":{"post":{"summary":"Cancel a job.","description":"Attempts to cancel a specific job by its ID. The job must belong to the requesting space.","operationId":"cancelJob","parameters":[{"name":"jobId","in":"path","required":true,"description":"The ID of the job to cancel.","schema":{"type":"string"}}],"responses":{"200":{"description":"Job canceled successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"Business error."},"401":{"description":"Unauthorized. Invalid or missing API key."}}}}}}
```

## Cancel all waiting jobs for a space.

> Cancels all jobs that are in a \`WAITING\` state for a specific space.

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"servers":[{"url":"https://api.decisionrules.io/job"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"ApiKey"}}},"paths":{"/cancelAll/space/{spaceId}":{"post":{"summary":"Cancel all waiting jobs for a space.","description":"Cancels all jobs that are in a `WAITING` state for a specific space.","operationId":"cancelAllWaitingJobsForSpace","parameters":[{"name":"spaceId","in":"path","required":true,"description":"The ID of the space.","schema":{"type":"string"}}],"responses":{"200":{"description":"The number of waiting jobs that were canceled.","content":{"application/json":{"schema":{"type":"object","properties":{"canceledCount":{"type":"number","description":"The total count of jobs that were canceled."}}}}}},"400":{"description":"Business error."},"401":{"description":"Unauthorized. Invalid or missing API key."}}}}}}
```

## Cancel all waiting jobs for a rule.

> Cancels all jobs that are in a \`WAITING\` state for a specific rule identifier and an optional version.

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"servers":[{"url":"https://api.decisionrules.io/job"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"ApiKey"}}},"paths":{"/cancelAll/rule/{identifier}/{version}":{"post":{"summary":"Cancel all waiting jobs for a rule.","description":"Cancels all jobs that are in a `WAITING` state for a specific rule identifier and an optional version.","operationId":"cancelAllWaitingJobsForRule","parameters":[{"name":"identifier","in":"path","required":true,"description":"The identifier of the rule.","schema":{"type":"string"}},{"name":"version","in":"path","required":false,"description":"The version of the rule. If not provided, jobs for all versions of the rule will be considered.","schema":{"type":"string"}}],"responses":{"200":{"description":"The number of waiting jobs that were canceled for the rule.","content":{"application/json":{"schema":{"type":"object","properties":{"canceledCount":{"type":"number","description":"The total count of jobs that were canceled."}}}}}},"400":{"description":"Bad request. Rule identifier or version is invalid."},"401":{"description":"Unauthorized. Invalid or missing API key."},"403":{"description":"Forbidden. Insufficient permissions to cancel jobs for this rule."}}}}}}
```

## Get job details.

> Retrieves detailed information about a specific job, including its status and output. The job must belong to the requesting space.

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"servers":[{"url":"https://api.decisionrules.io/job"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"ApiKey"}},"schemas":{"Job":{"type":"object","properties":{"jobId":{"type":"string"},"correlationId":{"type":"string"},"inputData":{"type":"object","additionalProperties":true},"output":{"type":"object","additionalProperties":true,"nullable":true},"ruleReference":{"$ref":"#/components/schemas/JobRuleReference"},"context":{"$ref":"#/components/schemas/JobContext"},"status":{"$ref":"#/components/schemas/JobStatus"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true},"apiKey":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"nullable":true}}},"JobRuleReference":{"type":"object","properties":{"baseId":{"type":"string","description":"The ID of the rule."},"version":{"type":"number","description":"The version of the rule."},"type":{"type":"string","description":"The type of the rule (e.g., IntegrationFlow)."}}},"JobContext":{"type":"object","properties":{"spaceId":{"type":"string"},"billingUserId":{"type":"string"},"executorUser":{"type":"object","nullable":true},"usedApiKeyId":{"type":"string","nullable":true}}},"JobStatus":{"type":"object","properties":{"state":{"$ref":"#/components/schemas/JobState"},"code":{"$ref":"#/components/schemas/JobStatusCode"},"message":{"type":"string","description":"A human-readable message for the status."}}},"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]},"JobStatusCode":{"type":"string","enum":["JOB_SUCCESS","JOB_ERROR","JOB_TIMEOUT","JOB_QUOTA_EXCEEDED","JOB_EXECUTION_ERROR","JOB_VALIDATION_ERROR","JOB_USER_CANCELED","JOB_SYSTEM_CANCELED","ZOMBIE_PROCESS","JOB_INITIALIZED","JOB_RUNNING","JOB_WAITING"]}}},"paths":{"/{jobId}":{"get":{"summary":"Get job details.","description":"Retrieves detailed information about a specific job, including its status and output. The job must belong to the requesting space.","operationId":"getJobsDetail","parameters":[{"name":"jobId","in":"path","required":true,"description":"The ID of the job to retrieve details for.","schema":{"type":"string"}}],"responses":{"200":{"description":"Job details retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"Business error."},"401":{"description":"Unauthorized. Invalid or missing API key."}}}}}}
```

## The JobState object

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"components":{"schemas":{"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]}}}}
```

## The JobStatusCode object

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"components":{"schemas":{"JobStatusCode":{"type":"string","enum":["JOB_SUCCESS","JOB_ERROR","JOB_TIMEOUT","JOB_QUOTA_EXCEEDED","JOB_EXECUTION_ERROR","JOB_VALIDATION_ERROR","JOB_USER_CANCELED","JOB_SYSTEM_CANCELED","ZOMBIE_PROCESS","JOB_INITIALIZED","JOB_RUNNING","JOB_WAITING"]}}}}
```

## The JobStatus object

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"components":{"schemas":{"JobStatus":{"type":"object","properties":{"state":{"$ref":"#/components/schemas/JobState"},"code":{"$ref":"#/components/schemas/JobStatusCode"},"message":{"type":"string","description":"A human-readable message for the status."}}},"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]},"JobStatusCode":{"type":"string","enum":["JOB_SUCCESS","JOB_ERROR","JOB_TIMEOUT","JOB_QUOTA_EXCEEDED","JOB_EXECUTION_ERROR","JOB_VALIDATION_ERROR","JOB_USER_CANCELED","JOB_SYSTEM_CANCELED","ZOMBIE_PROCESS","JOB_INITIALIZED","JOB_RUNNING","JOB_WAITING"]}}}}
```

## The JobRuleReference object

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"components":{"schemas":{"JobRuleReference":{"type":"object","properties":{"baseId":{"type":"string","description":"The ID of the rule."},"version":{"type":"number","description":"The version of the rule."},"type":{"type":"string","description":"The type of the rule (e.g., IntegrationFlow)."}}}}}}
```

## The Job object

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"components":{"schemas":{"Job":{"type":"object","properties":{"jobId":{"type":"string"},"correlationId":{"type":"string"},"inputData":{"type":"object","additionalProperties":true},"output":{"type":"object","additionalProperties":true,"nullable":true},"ruleReference":{"$ref":"#/components/schemas/JobRuleReference"},"context":{"$ref":"#/components/schemas/JobContext"},"status":{"$ref":"#/components/schemas/JobStatus"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true},"apiKey":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"nullable":true}}},"JobRuleReference":{"type":"object","properties":{"baseId":{"type":"string","description":"The ID of the rule."},"version":{"type":"number","description":"The version of the rule."},"type":{"type":"string","description":"The type of the rule (e.g., IntegrationFlow)."}}},"JobContext":{"type":"object","properties":{"spaceId":{"type":"string"},"billingUserId":{"type":"string"},"executorUser":{"type":"object","nullable":true},"usedApiKeyId":{"type":"string","nullable":true}}},"JobStatus":{"type":"object","properties":{"state":{"$ref":"#/components/schemas/JobState"},"code":{"$ref":"#/components/schemas/JobStatusCode"},"message":{"type":"string","description":"A human-readable message for the status."}}},"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]},"JobStatusCode":{"type":"string","enum":["JOB_SUCCESS","JOB_ERROR","JOB_TIMEOUT","JOB_QUOTA_EXCEEDED","JOB_EXECUTION_ERROR","JOB_VALIDATION_ERROR","JOB_USER_CANCELED","JOB_SYSTEM_CANCELED","ZOMBIE_PROCESS","JOB_INITIALIZED","JOB_RUNNING","JOB_WAITING"]}}}}
```

## The JobContext object

```json
{"openapi":"3.0.0","info":{"title":"Job API","version":"1.0.0"},"components":{"schemas":{"JobContext":{"type":"object","properties":{"spaceId":{"type":"string"},"billingUserId":{"type":"string"},"executorUser":{"type":"object","nullable":true},"usedApiKeyId":{"type":"string","nullable":true}}}}}}
```


# Rule Testing API

The Rule Testing API is a secure REST API that manage test runs.

### Request authorization

{% hint style="info" %}
To authenticate your requests, you must use a Bearer token with a valid **Solver API key**.
{% endhint %}

For example:

```
Authorization: Bearer YOUR_SOLVER_API_KEY
```

## Start a Test Run

> Starts a new test run job for the specified test suites or individual tests.  You must provide either an array of \`testSuiteIds\`, an array of \`testIds\`, or both.

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"servers":[{"url":"https://api.decisionrules.io/testRun"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"ApiKey"}},"schemas":{"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]}}},"paths":{"/start":{"post":{"summary":"Start a Test Run","description":"Starts a new test run job for the specified test suites or individual tests.  You must provide either an array of `testSuiteIds`, an array of `testIds`, or both.","operationId":"startTestRun","parameters":[{"name":"x-correlation-id","in":"header","required":false,"description":"A custom correlation ID to track the job execution. If not provided, a GUID will be automatically generated.","schema":{"type":"string"}}],"requestBody":{"description":"Input data specifying which test suites or test cases to run.","required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"testSuiteIds":{"type":"array","items":{"type":"string"},"description":"A list of Test Suite IDs to be executed."},"testIds":{"type":"array","items":{"type":"string"},"description":"A list of individual Test IDs to be executed."}}}}}},"responses":{"200":{"description":"The test run job has been successfully created and queued.","content":{"application/json":{"schema":{"type":"object","properties":{"testRunId":{"type":"string","description":"The ID of the newly created test run job."},"status":{"$ref":"#/components/schemas/JobState","description":"Initial status of the test run job (e.g., WAITING)."}}}}}},"400":{"description":"Business error. Missing parameters or rule resolution failed."},"401":{"description":"Unauthorized. Invalid or missing API key."}}}}}}
```

## Get Test Run Job

> Retrieves test run job details for a specific test run, including its overall execution state and timing context. The job must belong to the requesting space.

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"servers":[{"url":"https://api.decisionrules.io/testRun"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"ApiKey"}},"schemas":{"Job":{"type":"object","properties":{"jobId":{"type":"string"},"correlationId":{"type":"string"},"inputData":{"type":"object","additionalProperties":true},"output":{"type":"object","additionalProperties":true,"nullable":true},"status":{"$ref":"#/components/schemas/JobStatus"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true}}},"JobStatus":{"type":"object","properties":{"state":{"$ref":"#/components/schemas/JobState"},"code":{"type":"string"},"message":{"type":"string","description":"A human-readable message for the status."}}},"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]}}},"paths":{"/{testRunId}":{"get":{"summary":"Get Test Run Job","description":"Retrieves test run job details for a specific test run, including its overall execution state and timing context. The job must belong to the requesting space.","operationId":"getJobsDetail","parameters":[{"name":"testRunId","in":"path","required":true,"description":"The ID of the test run job to retrieve details for.","schema":{"type":"string"}}],"responses":{"200":{"description":"Job details retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"Business error."},"401":{"description":"Unauthorized. Invalid or missing API key."}}}}}}
```

## Get Test Run Results Detail

> Retrieves detailed information about a specific test run execution, including the evaluation status of individual tests and test suites.

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"servers":[{"url":"https://api.decisionrules.io/testRun"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"ApiKey"}},"schemas":{"TestRunRule":{"type":"object","required":["testSuiteRuns"],"properties":{"baseId":{"type":"string"},"baseType":{"$ref":"#/components/schemas/BaseType"},"status":{"$ref":"#/components/schemas/BaseStatus"},"ruleName":{"type":"string"},"ruleAlias":{"type":"string"},"ruleVersion":{"type":"number"},"testSuiteRuns":{"type":"array","items":{"$ref":"#/components/schemas/TestSuiteRun"},"description":"Array of test suites executed under this rule."}}},"BaseType":{"type":"string","enum":["decision-table","complex-rule","composition","decision-tree","workflow","integration-flow","lookup-table","ai-rule"]},"BaseStatus":{"type":"string","enum":["published","pending"]},"TestSuiteRun":{"type":"object","required":["testSuiteId","status","tests","jobId","createdAt"],"properties":{"id":{"type":"string"},"userId":{"type":"string"},"spaceId":{"type":"string"},"ruleAlias":{"type":"string"},"ruleVersion":{"type":"number"},"name":{"type":"string"},"testSuiteId":{"type":"string"},"status":{"$ref":"#/components/schemas/TestSuiteRunStatus"},"tests":{"type":"array","items":{"$ref":"#/components/schemas/TestExecution"}},"jobId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time"}}},"TestSuiteRunStatus":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELED","ERROR"]},"TestExecution":{"type":"object","required":["testId","name","strategy","input","expectedOutput","ignoredOutputs"],"properties":{"id":{"type":"string"},"testId":{"type":"string"},"name":{"type":"string"},"strategy":{"$ref":"#/components/schemas/SolverStrategyEnum"},"input":{"description":"Input payload for the test execution."},"expectedOutput":{"description":"The expected output."},"ignoredOutputs":{"type":"array","items":{"type":"string"},"description":"Array of object paths to ignore (e.g., \"object.property\")"},"sortedInputHash":{"type":"string"},"lastRunAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"resultStatus":{"$ref":"#/components/schemas/TestResultStatus"},"result":{"description":"Actual execution result payload."},"error":{"description":"Error details if the test failed or errored."}}},"SolverStrategyEnum":{"type":"string","enum":["STANDARD","ARRAY","FIRST_MATCH","EVALUATE_ALL"]},"TestResultStatus":{"type":"string","enum":["PASSED","FAILED","ERROR"]}}},"paths":{"/detail/{testRunId}":{"get":{"summary":"Get Test Run Results Detail","description":"Retrieves detailed information about a specific test run execution, including the evaluation status of individual tests and test suites.","operationId":"getTestRunDetail","parameters":[{"name":"testRunId","in":"path","required":true,"description":"The Test Run ID to retrieve results for.","schema":{"type":"string"}}],"responses":{"200":{"description":"Test run details retrieved successfully. Returns an array of evaluated rules, grouped by test suites and their nested test executions.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TestRunRule"}}}}},"400":{"description":"Business error."},"401":{"description":"Unauthorized. Invalid or missing API key."}}}}}}
```

## The TestRunRule object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"TestRunRule":{"type":"object","required":["testSuiteRuns"],"properties":{"baseId":{"type":"string"},"baseType":{"$ref":"#/components/schemas/BaseType"},"status":{"$ref":"#/components/schemas/BaseStatus"},"ruleName":{"type":"string"},"ruleAlias":{"type":"string"},"ruleVersion":{"type":"number"},"testSuiteRuns":{"type":"array","items":{"$ref":"#/components/schemas/TestSuiteRun"},"description":"Array of test suites executed under this rule."}}},"BaseType":{"type":"string","enum":["decision-table","complex-rule","composition","decision-tree","workflow","integration-flow","lookup-table","ai-rule"]},"BaseStatus":{"type":"string","enum":["published","pending"]},"TestSuiteRun":{"type":"object","required":["testSuiteId","status","tests","jobId","createdAt"],"properties":{"id":{"type":"string"},"userId":{"type":"string"},"spaceId":{"type":"string"},"ruleAlias":{"type":"string"},"ruleVersion":{"type":"number"},"name":{"type":"string"},"testSuiteId":{"type":"string"},"status":{"$ref":"#/components/schemas/TestSuiteRunStatus"},"tests":{"type":"array","items":{"$ref":"#/components/schemas/TestExecution"}},"jobId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time"}}},"TestSuiteRunStatus":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELED","ERROR"]},"TestExecution":{"type":"object","required":["testId","name","strategy","input","expectedOutput","ignoredOutputs"],"properties":{"id":{"type":"string"},"testId":{"type":"string"},"name":{"type":"string"},"strategy":{"$ref":"#/components/schemas/SolverStrategyEnum"},"input":{"description":"Input payload for the test execution."},"expectedOutput":{"description":"The expected output."},"ignoredOutputs":{"type":"array","items":{"type":"string"},"description":"Array of object paths to ignore (e.g., \"object.property\")"},"sortedInputHash":{"type":"string"},"lastRunAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"resultStatus":{"$ref":"#/components/schemas/TestResultStatus"},"result":{"description":"Actual execution result payload."},"error":{"description":"Error details if the test failed or errored."}}},"SolverStrategyEnum":{"type":"string","enum":["STANDARD","ARRAY","FIRST_MATCH","EVALUATE_ALL"]},"TestResultStatus":{"type":"string","enum":["PASSED","FAILED","ERROR"]}}}}
```

## The TestSuiteRun object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"TestSuiteRun":{"type":"object","required":["testSuiteId","status","tests","jobId","createdAt"],"properties":{"id":{"type":"string"},"userId":{"type":"string"},"spaceId":{"type":"string"},"ruleAlias":{"type":"string"},"ruleVersion":{"type":"number"},"name":{"type":"string"},"testSuiteId":{"type":"string"},"status":{"$ref":"#/components/schemas/TestSuiteRunStatus"},"tests":{"type":"array","items":{"$ref":"#/components/schemas/TestExecution"}},"jobId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time"}}},"TestSuiteRunStatus":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELED","ERROR"]},"TestExecution":{"type":"object","required":["testId","name","strategy","input","expectedOutput","ignoredOutputs"],"properties":{"id":{"type":"string"},"testId":{"type":"string"},"name":{"type":"string"},"strategy":{"$ref":"#/components/schemas/SolverStrategyEnum"},"input":{"description":"Input payload for the test execution."},"expectedOutput":{"description":"The expected output."},"ignoredOutputs":{"type":"array","items":{"type":"string"},"description":"Array of object paths to ignore (e.g., \"object.property\")"},"sortedInputHash":{"type":"string"},"lastRunAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"resultStatus":{"$ref":"#/components/schemas/TestResultStatus"},"result":{"description":"Actual execution result payload."},"error":{"description":"Error details if the test failed or errored."}}},"SolverStrategyEnum":{"type":"string","enum":["STANDARD","ARRAY","FIRST_MATCH","EVALUATE_ALL"]},"TestResultStatus":{"type":"string","enum":["PASSED","FAILED","ERROR"]}}}}
```

## The TestExecution object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"TestExecution":{"type":"object","required":["testId","name","strategy","input","expectedOutput","ignoredOutputs"],"properties":{"id":{"type":"string"},"testId":{"type":"string"},"name":{"type":"string"},"strategy":{"$ref":"#/components/schemas/SolverStrategyEnum"},"input":{"description":"Input payload for the test execution."},"expectedOutput":{"description":"The expected output."},"ignoredOutputs":{"type":"array","items":{"type":"string"},"description":"Array of object paths to ignore (e.g., \"object.property\")"},"sortedInputHash":{"type":"string"},"lastRunAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"resultStatus":{"$ref":"#/components/schemas/TestResultStatus"},"result":{"description":"Actual execution result payload."},"error":{"description":"Error details if the test failed or errored."}}},"SolverStrategyEnum":{"type":"string","enum":["STANDARD","ARRAY","FIRST_MATCH","EVALUATE_ALL"]},"TestResultStatus":{"type":"string","enum":["PASSED","FAILED","ERROR"]}}}}
```

## The BaseType object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"BaseType":{"type":"string","enum":["decision-table","complex-rule","composition","decision-tree","workflow","integration-flow","lookup-table","ai-rule"]}}}}
```

## The BaseStatus object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"BaseStatus":{"type":"string","enum":["published","pending"]}}}}
```

## The TestSuiteRunStatus object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"TestSuiteRunStatus":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELED","ERROR"]}}}}
```

## The TestResultStatus object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"TestResultStatus":{"type":"string","enum":["PASSED","FAILED","ERROR"]}}}}
```

## The SolverStrategyEnum object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"SolverStrategyEnum":{"type":"string","enum":["STANDARD","ARRAY","FIRST_MATCH","EVALUATE_ALL"]}}}}
```

## The JobState object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]}}}}
```

## The JobStatus object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"JobStatus":{"type":"object","properties":{"state":{"$ref":"#/components/schemas/JobState"},"code":{"type":"string"},"message":{"type":"string","description":"A human-readable message for the status."}}},"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]}}}}
```

## The Job object

```json
{"openapi":"3.0.0","info":{"title":"Rule Testing API","version":"1.0.0"},"components":{"schemas":{"Job":{"type":"object","properties":{"jobId":{"type":"string"},"correlationId":{"type":"string"},"inputData":{"type":"object","additionalProperties":true},"output":{"type":"object","additionalProperties":true,"nullable":true},"status":{"$ref":"#/components/schemas/JobStatus"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"claimedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true}}},"JobStatus":{"type":"object","properties":{"state":{"$ref":"#/components/schemas/JobState"},"code":{"type":"string"},"message":{"type":"string","description":"A human-readable message for the status."}}},"JobState":{"type":"string","enum":["WAITING","RUNNING","COMPLETED","CANCELING","CANCELED","ERROR"]}}}}
```


# Management API

The Management API is a secure REST API that provides read/write access to your rules and spaces.

API Request methods cheat sheet:&#x20;

{% hint style="info" %} <mark style="color:$success;">GET</mark> - Used to **retrieve resource representation/information** and not modify it in any way, e.g., get a JSON representaition of a rule with the GET RULES endpoint.

<mark style="color:orange;">POST</mark> - Used to **create new subordinate resources**, e.g., creating a new rule in a Space or Importing a rule into a Space.

<mark style="color:blue;">PUT</mark> - Used primarily to **update an existing resource (if the resource does not exist, then API may decide to create a new resource or not),** e.g., updating a Rule Flow

<mark style="color:purple;">PATCH</mark> - Used to **make a partial update** on a resource, e.g., add Tags to an existing rule.

<mark style="color:red;">DELETE</mark> - Used to **delete resources,** e.g., deleting rules.
{% endhint %}

{% hint style="success" %} <mark style="background-color:green;">**NEW in v1.16.0!**</mark> The Management API now fully support use of Rule Aliases when making requests.
{% endhint %}

{% hint style="info" %}
If you're using the **Regional Cloud** version of DecisionRules, read more about API calls [here](/doc/other-deployment-options/regional-cloud/region-specific-api-urls#making-api-calls-on-region-cloud-accounts).
{% endhint %}

## Swagger

You can check out these endpoints and call them right away using swagger.

**Swagger UI:** <https://api.decisionrules.io/api/docs/>

**Swagger JSON File:** <https://api.decisionrules.io/api/docs/json>

## Folder Paths

{% hint style="success" %} <mark style="background-color:green;">**NEW in v1.18.1**</mark> Some Management API Endpoints now support targetting by **Folder Path.**&#x20;
{% endhint %}

All Folder and select Rule endpoints now support targetting items by their folder path. Instead of having to provide the requests with Rule Aliases/IDs or Folder IDs users can now define the request target by leveraging the new **Folder Path functionality**.

#### Example:

To access **Calculation&#x20;**<mark style="color:orange;">**v2**</mark> (see image below), instead of appending it's rule ID to the request as a parameter you can now specify the ?path= query parameter.&#x20;

<figure><img src="/files/jysVLE7bLw7kGheNWZHN" alt="" width="216"><figcaption></figcaption></figure>

In this case to GET the rule the request would look like this:

```
https://api.decisionrules.io/api/rule?path=/Client/Important/Calculation&version=2
```

To access the entire "Important" Folder the request could now look like this:

```
https://api.decisionrules.io/api/folder?path=/Client/Important
```

{% hint style="warning" %}

* Request targets can be defined either by the ID **or** path, not both at the same time
* Folder Paths have to always begin with a slash "/"
* To target specific rule versions by path use the ?version= query parameter&#x20;
  {% endhint %}

## Rules

## Get rule

> Gets all of the information stored about the rule, including its content, version or input and output schemas. \
> \
> \- If the version is specified, gets the version irrespective of the rule status. \
> \- If the version is not specified, gets the latest published version.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Rule"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/rule/{identifier}/{version}?":{"get":{"tags":["Rule"],"summary":"Get rule","description":"Gets all of the information stored about the rule, including its content, version or input and output schemas. \n\n- If the version is specified, gets the version irrespective of the rule status. \n- If the version is not specified, gets the latest published version.","parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true,"description":"The ID or alias of the rule."},{"schema":{"type":"string"},"name":"version","in":"path","required":false,"description":"The version of the rule."},{"schema":{"type":"string"},"name":"path","in":"query","description":"The unique folder path leading to the rule. Use this OR the 'identifier' parameter.","required":false},{"schema":{"type":"integer"},"name":"version","in":"query","description":"Optional. The specific version of the business rule.","required":false},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="info" %}
You can target the rule using [Folder Path](https://docs.decisionrules.io/doc/api/management-api#folder-paths) instead of the :ruleId and :version parameters.
{% endhint %}

{% hint style="info" %}
Get rule might be useful when you wish to create a new version of a rule. To do so you may GET the rule, manually change the `"version"`attribute of the returned JSON object and then use said object with the POST Create rule method. This will result in a new version of the rule being created.
{% endhint %}

## Create rule

> Creates rule based on the body of the request. The body must be formatted according to the example below.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Rule"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/rule":{"post":{"tags":["Rule"],"summary":"Create rule","description":"Creates rule based on the body of the request. The body must be formatted according to the example below.","parameters":[{"schema":{"type":"integer"},"name":"version","in":"query","description":"Optional. The specific version of the business rule.","required":false},{"schema":{"type":"string"},"name":"path","in":"query","description":"Optional. The path to the business rule.","required":false},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","inputSchema","outputSchema","type","status"],"properties":{"name":{"type":"string","description":"Name of the rule"},"description":{"type":"string","description":"Description of the rule"},"inputSchema":{"type":"object","description":"Schema for input attributes","additionalProperties":{}},"outputSchema":{"type":"object","description":"Schema for output attributes","additionalProperties":{}},"decisionTable":{"type":"object","description":"Definition of the decision table","properties":{"columns":{"type":"array","items":{"type":"object","properties":{"condition":{"type":"object","properties":{"type":{"type":"string"},"inputVariable":{"type":"string"},"name":{"type":"string"}}},"columnOutput":{"type":"object","properties":{"type":{"type":"string"},"outputVariable":{"type":"string"},"name":{"type":"string"}}},"columnId":{"type":"string"},"type":{"type":"string"}}}},"rows":{"type":"array","items":{"type":"object","properties":{"cells":{"type":"array","items":{"type":"object","properties":{"column":{"type":"string"},"scalarCondition":{"type":"object","properties":{"value":{"type":"string"},"operator":{"type":"string"}}},"outputScalarValue":{"type":"object","properties":{"value":{"type":"string"}}},"type":{"type":"string"}}}}}}}}},"type":{"type":"string","enum":["decision-table","complex-rule","composition","decision-tree"],"description":"Type of rule"},"status":{"type":"string","enum":["published","pending"],"description":"Current state of the rule"},"ruleId":{"type":"string","description":"Unique identifier of the rule"},"auditLog":{"type":"object","description":"Audit log settings","properties":{"active":{"type":"boolean"},"debug":{"type":"object","properties":{"active":{"type":"boolean"}}},"ttl":{"type":"integer","description":"Time-to-live in days"}}},"version":{"type":"number","description":"Version number of the rule"},"tags":{"type":"array","items":{"type":"string"},"description":"Optional list of tags"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="info" %}
You can create the rule in a specific folder by utilizing [Folder Path](https://docs.decisionrules.io/doc/api/management-api#folder-paths).
{% endhint %}

## Update rule

> Changes the rule according to the body of the request.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Rule"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/rule/{identifier}/{version}?":{"put":{"tags":["Rule"],"summary":"Update rule","description":"Changes the rule according to the body of the request.","parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true,"description":"The ID or alias of the rule."},{"schema":{"type":"string"},"name":"version","in":"path","required":false,"description":"The version of the rule."},{"schema":{"type":"string"},"name":"path","in":"query","description":"The unique folder path leading to the rule. Use this OR the 'identifier' parameter.","required":false},{"schema":{"type":"integer"},"name":"version","in":"query","description":"Optional. The specific version of the business rule.","required":false},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name","inputSchema","outputSchema","type","status"],"properties":{"name":{"type":"string","description":"Optional name of the rule"},"id":{"type":"string","description":"Optional identifier"},"baseId":{"type":"string","description":"Optional base identifier"},"ruleAlias":{"type":"string","description":"Optional alias for the rule"},"type":{"type":"string","enum":["decision-table","complex-rule","composition","decision-tree"],"description":"Type of rule"},"tags":{"type":"array","items":{"type":"string"},"description":"Optional list of tags"},"status":{"type":"string","enum":["published","pending"],"description":"Current state of the rule"},"version":{"type":"number","description":"Version number of the rule"},"description":{"type":"string","description":"Description of the rule"},"inputSchema":{"type":"object","description":"Schema for input attributes","additionalProperties":{}},"outputSchema":{"type":"object","description":"Schema for output attributes","additionalProperties":{}},"decisionTable":{"type":"object","description":"Definition of the decision table","properties":{"columns":{"type":"array","items":{"type":"object","properties":{"condition":{"type":"object","properties":{"type":{"type":"string"},"inputVariable":{"type":"string"},"name":{"type":"string"}}},"columnOutput":{"type":"object","properties":{"type":{"type":"string"},"outputVariable":{"type":"string"},"name":{"type":"string"}}},"columnId":{"type":"string"},"type":{"type":"string"}}}},"rows":{"type":"array","items":{"type":"object","properties":{"cells":{"type":"array","items":{"type":"object","properties":{"column":{"type":"string"},"scalarCondition":{"type":"object","properties":{"value":{"type":"string"},"operator":{"type":"string"}}},"outputScalarValue":{"type":"object","properties":{"value":{"type":"string"}}},"type":{"type":"string"}}}}}}}}},"auditLog":{"type":"object","description":"Audit log settings","properties":{"active":{"type":"boolean"},"debug":{"type":"object","properties":{"active":{"type":"boolean"}}},"ttl":{"type":"integer","description":"Time-to-live in days"}}},"ruleId":{"type":"string","description":"Unique identifier of the rule"},"createdIn":{"type":"string","format":"date-time","description":"Creation timestamp"},"lastUpdate":{"type":"string","format":"date-time","description":"Last update timestamp"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="info" %}
You can target the rule using [Folder Path](https://docs.decisionrules.io/doc/api/management-api#folder-paths) instead of the :ruleId and :version parameters.
{% endhint %}

{% hint style="info" %}
Update rule might be useful when renaming a rule. First GET the rule you wish to rename, change the`name`attribute of the returned JSON object and then use PUT Update rule with the changed JSON object.
{% endhint %}

{% hint style="info" %}
Note that there are a few attributes of the rule that cannot be updated by the `PUT` endpoint. Namely, you cannot use `PUT` to change the rule ID, version and rule alias. Also, you cannot change the date of last update, since it gets updated automatically.
{% endhint %}

## Update rule status

> Changes rule status from pending to published and vice versa. If the version is not specified, the latest version will be used.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Rule"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/rule/status/{identifier}/{status}/{version}":{"put":{"tags":["Rule"],"summary":"Update rule status","description":"Changes rule status from pending to published and vice versa. If the version is not specified, the latest version will be used.","parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true,"description":"The ID or alias of the rule."},{"schema":{"type":"string"},"name":"status","in":"path","required":true,"description":"pending XOR published."},{"schema":{"type":"string"},"name":"version","in":"path","required":true,"description":"The version of the rule."},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Delete rule

> Deletes the rule.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Rule"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/rule/{identifier}/{version}?":{"delete":{"tags":["Rule"],"summary":"Delete rule","description":"Deletes the rule.","parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true,"description":"The ID or alias of the rule."},{"schema":{"type":"string"},"name":"version","in":"path","required":false,"description":"The version of the rule."},{"schema":{"type":"string"},"name":"path","in":"query","description":"The unique folder path leading to the rule. Use this OR the 'identifier' parameter.","required":false},{"schema":{"type":"integer"},"name":"version","in":"query","description":"Optional. The specific version of the business rule.","required":false},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"responses":{"200":{"description":"OK"},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="info" %}
You can target the rule using [Folder Path](https://docs.decisionrules.io/doc/api/management-api#folder-paths) instead of the :ruleId and :version parameters.
{% endhint %}

{% hint style="warning" %}
If you do not specify version of the rule to be deleted, the endpoint will delete **all versions of the rule**. Please, use it with caution! Once deleted, rules cannot be recovered.
{% endhint %}

## Create new rule version

> Creates a new version of the rule identified by :ruleId and based on the body of the request. The body must be formatted according to the example below. \
> &#x20;The new version is added to the same folder as the latest version.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Rule"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/rule/{identifier}/new-version":{"post":{"tags":["Rule"],"summary":"Create new rule version","description":"Creates a new version of the rule identified by :ruleId and based on the body of the request. The body must be formatted according to the example below. \n The new version is added to the same folder as the latest version.","parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true,"description":"Unique rule ID or alias which is common to all rule versions."},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name","inputSchema","outputSchema","type","status"],"properties":{"name":{"type":"string","description":"Name of the rule"},"description":{"type":"string","description":"Description of the rule"},"inputSchema":{"type":"object","description":"Schema for input attributes","additionalProperties":{}},"outputSchema":{"type":"object","description":"Schema for output attributes","additionalProperties":{}},"decisionTable":{"type":"object","description":"Definition of the decision table","properties":{"columns":{"type":"array","items":{"type":"object","properties":{"condition":{"type":"object","properties":{"type":{"type":"string"},"inputVariable":{"type":"string"},"name":{"type":"string"}}},"columnOutput":{"type":"object","properties":{"type":{"type":"string"},"outputVariable":{"type":"string"},"name":{"type":"string"}}},"columnId":{"type":"string"},"type":{"type":"string"}}}},"rows":{"type":"array","items":{"type":"object","properties":{"cells":{"type":"array","items":{"type":"object","properties":{"column":{"type":"string"},"scalarCondition":{"type":"object","properties":{"value":{"type":"string"},"operator":{"type":"string"}}},"outputScalarValue":{"type":"object","properties":{"value":{"type":"string"}}},"type":{"type":"string"}}}}}}}}},"type":{"type":"string","enum":["decision-table","complex-rule","composition","decision-tree"],"description":"Type of rule"},"status":{"type":"string","enum":["published","pending"],"description":"Current state of the rule"},"ruleId":{"type":"string","description":"Unique identifier of the rule"},"auditLog":{"type":"object","description":"Audit log settings","properties":{"active":{"type":"boolean"},"debug":{"type":"object","properties":{"active":{"type":"boolean"}}},"ttl":{"type":"integer","description":"Time-to-live in days"}}},"version":{"type":"number","description":"Version number of the rule"},"tags":{"type":"array","items":{"type":"string"},"description":"Optional list of tags"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="info" %}
This endpoint does not create a new rule. If no existing version of the rule is found, an error will be returned. Use the [Create rule](https://docs.decisionrules.io/doc/api/management-api#create-rule) endpoint instead.
{% endhint %}

{% hint style="info" %}
The rule’s name, alias, and ID will remain unchanged, regardless of the values provided in the request body.
{% endhint %}

## Lock / Unlock rule.

> Sets a lock on a rule version to prevent edits.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Rule"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/rule/lock/{identifier}/{version}":{"patch":{"tags":["Rule"],"summary":"Lock / Unlock rule.","description":"Sets a lock on a rule version to prevent edits.","requestBody":{"required":true,"description":"Object that defines if rule should be locked.","content":{"application/json":{"schema":{"type":"object","required":["locked"],"properties":{"locked":{"type":"boolean","description":"Indicates if the rule should be locked."}}}}}},"parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true,"description":"The ID or alias of the rule."},{"schema":{"type":"string"},"name":"version","in":"path","required":true,"description":"The version of the rule."},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"responses":{"200":{"description":"OK"},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="info" %}
You can target the rule using [Folder Path](https://docs.decisionrules.io/doc/api/management-api#folder-paths) instead of the :ruleId and :version parameters.
{% endhint %}

## Spaces

## Gets all types of rules in space

> The desired space is determined by Management API Key. This endpoint also gets set of rules used in every ruleflow.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Space"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/space/items":{"get":{"tags":["Space"],"parameters":[{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"summary":"Gets all types of rules in space","description":"The desired space is determined by Management API Key. This endpoint also gets set of rules used in every ruleflow.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Tags

## Get rules by tags

> This endpoint allows you to get all ruless with certain tags. Desired space is derived from Management API Key.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Tag"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/tags/items":{"get":{"tags":["Tag"],"summary":"Get rules by tags","description":"This endpoint allows you to get all ruless with certain tags. Desired space is derived from Management API Key.","parameters":[{"schema":{"":""},"in":"query","name":"NewParameter","description":"New parameter","required":"true"},{"schema":{"type":"string"},"name":"tags","in":"query","required":true,"description":"Comma separated list of tags. The query at the end of the url address should look like this: ?tags=tag1,tag2. Such query would select all the rules where tag array contains both tag1 and tag"},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Add tags to a specific item version

> If you specify the version, the tag/tags will be added to the specified version. If the version is not specified, the tag/tags will be added to all the versions with given ID.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Tag"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/tags/{identifier}/{version}":{"patch":{"tags":["Tag"],"summary":"Add tags to a specific item version","description":"If you specify the version, the tag/tags will be added to the specified version. If the version is not specified, the tag/tags will be added to all the versions with given ID.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"tagName":{"type":"string"},"color":{"type":"string"}},"required":["tagName","color"]}}}},"description":"Array of tags to add in JSON format"},"parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true,"description":"The ID or alias of the rule."},{"schema":{"type":"string"},"name":"version","in":"path","required":false,"description":"The version of the rule."},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Remove tags from Rule

> If you specify the version, the tag/tags will be deleted from the specified version. If the version is not specified, the tag/tags will be deleted from all the versions with given ID.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Tag"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/tags/{identifier}/{version}":{"delete":{"tags":["Tag"],"summary":"Remove tags from Rule","description":"If you specify the version, the tag/tags will be deleted from the specified version. If the version is not specified, the tag/tags will be deleted from all the versions with given ID.","parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true,"description":"The ID or alias of the rule."},{"schema":{"type":"string"},"name":"version","in":"path","required":true,"description":"The version of the rule."},{"schema":{"type":"string"},"name":"Tags","in":"query","required":true,"description":"Comma separated list of tags. The query at the end of the url address should look like this: ?tags=tag1,tag2"},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"responses":{"200":{"description":"OK"},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Folders

## Get folder structure of a node

> Retrieve folder structure either by node ID or by navigating through path. Returns a JSON with a tree like structure containing the descendant folders and rules of the target node.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Folder"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/folder/{nodeId}":{"get":{"tags":["Folder"],"summary":"Get folder structure of a node","description":"Retrieve folder structure either by node ID or by navigating through path. Returns a JSON with a tree like structure containing the descendant folders and rules of the target node.","parameters":[{"schema":{"type":"string"},"name":"nodeId","in":"path","required":true},{"schema":{"type":"string"},"name":"path","in":"query"},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Create folders

> Creates folders under a specified target, moves rules into the new structure by baseId or ruleAlias. Define which folder's structure to update by either inputting it's id as a parameter or by navigating to it using the ?path=/ query parameter. Appends the Folder Structure specified in the request body as a child of the target node.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Folder"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}},"schemas":{}},"paths":{"/folder/{nodeId}":{"post":{"tags":["Folder"],"summary":"Create folders","description":"Creates folders under a specified target, moves rules into the new structure by baseId or ruleAlias. Define which folder's structure to update by either inputting it's id as a parameter or by navigating to it using the ?path=/ query parameter. Appends the Folder Structure specified in the request body as a child of the target node.","parameters":[{"schema":{"type":"string"},"name":"nodeId","in":"path","required":true},{"schema":{"type":"string"},"name":"path","in":"query"}],"requestBody":{"description":"Example JSON body","required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["ROOTFOLDERRULE"]},"name":{"type":"string"},"id":{"type":"string"},"baseId":{"type":"string"},"version":{"type":"number"},"children":{"type":"array","items":{"$ref":"#/components/schemas/Child"}}}}}}},"responses":{"200":{"description":"OK"},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="info" %}
If the request body contains rules **(defined by baseId or ruleAlias)**, the are moved to fit with the request. In the request example below, if the space contains a rule with id "xxx-yyy-zzz", it will be moved into the newly created "Example Sub-Folder" Folder.

When moving Rules - If a version is not defined all of the rule versions will be moved.
{% endhint %}

## Create or overwrite folder structure of a node

> Define which folder's structure to overwrite by either inputting it's id as a parameter or by navigating to it using the ?path=/ query parameter. Moves rules into the new structure by baseId or ruleAlias. Overwrites the Folder Structure specified in the request body as a child of the target node.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Folder"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}},"schemas":{}},"paths":{"/folder/{nodeId}":{"put":{"tags":["Folder"],"summary":"Create or overwrite folder structure of a node","description":"Define which folder's structure to overwrite by either inputting it's id as a parameter or by navigating to it using the ?path=/ query parameter. Moves rules into the new structure by baseId or ruleAlias. Overwrites the Folder Structure specified in the request body as a child of the target node.","parameters":[{"schema":{"type":"string"},"name":"nodeId","in":"path","required":true},{"schema":{"type":"string"},"name":"path","in":"query","required":true,"description":"Path of folder names"}],"requestBody":{"description":"Example JSON body","required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["ROOTFOLDERRULE"]},"name":{"type":"string"},"id":{"type":"string"},"baseId":{"type":"string"},"version":{"type":"number"},"children":{"type":"array","items":{"$ref":"#/components/schemas/Child"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="warning" %}
Any existing Folder children of the target node will be deleted. (Rules, which aren't part of the request body will be moved to the root)
{% endhint %}

{% hint style="info" %}
If the request body contains rules **(defined by baseId or ruleAlias)**, the are moved to fit with the request. In the request example below, if the space contains a rule with id "xxx-yyy-zzz", it will be moved into the newly created "Example Sub-Folder" Folder.

When moving Rules - If a version is not defined all of the rule versions will be moved.
{% endhint %}

## Delete a folder and all of its descendants (Including it's rules!)

> Delete a folder (Including it's rules) either by node ID or by navigating through path. If you want to delete the contents of the entire space target the 'root' by Id and include the optional query parameter ?deleteAll=true

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Folder"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/folder/{nodeId}":{"delete":{"tags":["Folder"],"summary":"Delete a folder and all of its descendants (Including it's rules!)","description":"Delete a folder (Including it's rules) either by node ID or by navigating through path. If you want to delete the contents of the entire space target the 'root' by Id and include the optional query parameter ?deleteAll=true","parameters":[{"schema":{"type":"string"},"name":"nodeId","in":"path","required":true},{"schema":{"type":"string"},"name":"path","in":"query","description":"Path of folder names"},{"schema":{"type":"boolean"},"name":"deleteAll","in":"query","description":"Confirmation to delete everything in Space"}],"responses":{"200":{"description":"OK"},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="danger" %}
Data removal is permanent and cannot be undone.
{% endhint %}

## Export folder with all rules

> Export folder with all rules. If no nodeId is set, then will be exported root directory.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Folder"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/folder/export/{nodeId}":{"get":{"tags":["Folder"],"summary":"Export folder with all rules","description":"Export folder with all rules. If no nodeId is set, then will be exported root directory.","parameters":[{"schema":{"type":"string"},"name":"nodeId","in":"path","required":false,"description":"If you know your folder id, you can export it. Otherwise you export root directory"},{"schema":{"type":"string"},"name":"path","in":"query","required":false,"description":"If you know your folder id, you can export it. Otherwise you export root directory"},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Import folder and all rules

> Import folder with all rules into specific folder. If no targetNodeId is set, then will be imported into root directory.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Folder"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/folder/import/{nodeId}":{"post":{"tags":["Folder"],"summary":"Import folder and all rules","description":"Import folder with all rules into specific folder. If no targetNodeId is set, then will be imported into root directory.","parameters":[{"schema":{"type":"string"},"name":"nodeId","in":"path","required":true,"description":"If you know you targetNodeId, you can import it. Otherwise you import folder into root directory."},{"schema":{"type":"string"},"name":"path","in":"query","description":"The unique folder path leading to the rule. Use this OR the 'identifier' parameter.","required":false},{"schema":{"type":"integer"},"name":"version","in":"query","description":"Optional. The specific version of the business rule.","required":false},{"schema":{"type":"string"},"name":"Authorization","in":"header","description":"Bearer","required":true},{"schema":{"type":"string"},"name":"Content-Type","in":"header","description":"application/json","required":false}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"export":{"type":"object","properties":{"exportType":{"type":"string","enum":["FOLDER","RULE","ROOT"],"description":"Type of the export"},"version":{"type":"number","description":"Version number of the export"},"data":{"type":"object","properties":{"structure":{"type":"object","properties":{"type":{"type":"string","enum":["FOLDER","RULE","ROOT"],"description":"Type of object"},"name":{"type":"string","description":"Name of the rule or folder"},"id":{"type":"string","description":"Identifier of the rule"},"baseId":{"type":"string","description":"Base identifier"},"ruleAlias":{"type":"string","description":"Optional alias for the rule"},"version":{"type":"number","description":"Version number of the object"},"children":{"type":"array","items":{"type":"object"},"description":"Children rules or folders"}}},"rules":{"type":"array","items":{"type":"object"},"description":"List of rules"}}}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

{% hint style="info" %}
You can target the rule using [Folder Path](https://docs.decisionrules.io/doc/api/management-api#folder-paths) instead of the :ruleId and :version parameters.
{% endhint %}

## Move Folders from their current position under a new parent

> Moves folders (including descendants) and/or rules under the parent specified by targetId or targetPath attribute in the request body.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Folder"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/folder/move":{"put":{"tags":["Folder"],"summary":"Move Folders from their current position under a new parent","description":"Moves folders (including descendants) and/or rules under the parent specified by targetId or targetPath attribute in the request body.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"targetId":{"type":"string","description":"Optional target ID"},"targetPath":{"type":"string","description":"Optional target path"},"nodes":{"type":"array","description":"List of nodes","items":{"type":"object","properties":{"type":{"type":"string","enum":["FOLDER","RULE"],"description":"Type of node"},"id":{"type":"string","description":"Optional node ID"},"baseId":{"type":"string","description":"Optional base ID"},"ruleAlias":{"type":"string","description":"Optional rule alias"}},"required":["type"]}}}}}}},"responses":{"200":{"description":"OK"},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Rename a folder

> Define which folder to rename by either inputting it's id as a parameter or by navigating to it using the ?path=/ query parameter. Set a new name for a Folder in the request body with the 'name' attribute.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Folder"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/folder/rename/{nodeId}":{"patch":{"tags":["Folder"],"summary":"Rename a folder","description":"Define which folder to rename by either inputting it's id as a parameter or by navigating to it using the ?path=/ query parameter. Set a new name for a Folder in the request body with the 'name' attribute.","parameters":[{"schema":{"type":"string"},"name":"nodeId","in":"path","required":true},{"schema":{"type":"string"},"name":"path","in":"query","required":false,"description":"Path of folder names"}],"responses":{"200":{"description":"OK"},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}},"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true,"type":"string","description":"New name of folder"}}}}}
```

## Find a folder or rule by attribute

> Finds Folders and Rules which satisfy all of the criteria from the request body. Use any of the attributes listed below or their combination to find folders and rules.\
> \
> Searchable attributes:\
> \- name - Name of the Folder or Rule\
> &#x20; \* Note: this attribute searches for a RegExp match by default. If you wish to find nodes which match the input exactly, prepend the input with '^' and append with '$'. Example: '^ClientA$'\
> \- id - ID of the Folder\
> \- ruleAlias - Rule-Alias\
> &#x20; \* Note: this attribute searches for a RegExp match by default. To match exactly: '^ClientA$'\
> \- baseId - RuleId of the Rule or Rule Flow\
> &#x20; \* 'decision-table' - Decision Table\
> &#x20; \* 'decision-tree' - Decision Tree\
> &#x20; \* 'complex-rule' - Scripting Rule\
> &#x20; \* 'composition' - Rule Flow\
> \- tags - Tags on a Rule\
> \- type - Type of Node in Folder Structure\
> &#x20; \* FOLDER\
> &#x20; \* RULE\
> &#x20; \* ROOT\
> \- version - Version of the rule\
> \- ruleStatus\
> &#x20; \* published\
> &#x20; \* pending

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Folder"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/folder/find":{"post":{"tags":["Folder"],"summary":"Find a folder or rule by attribute","description":"Finds Folders and Rules which satisfy all of the criteria from the request body. Use any of the attributes listed below or their combination to find folders and rules.\n\nSearchable attributes:\n- name - Name of the Folder or Rule\n  * Note: this attribute searches for a RegExp match by default. If you wish to find nodes which match the input exactly, prepend the input with '^' and append with '$'. Example: '^ClientA$'\n- id - ID of the Folder\n- ruleAlias - Rule-Alias\n  * Note: this attribute searches for a RegExp match by default. To match exactly: '^ClientA$'\n- baseId - RuleId of the Rule or Rule Flow\n  * 'decision-table' - Decision Table\n  * 'decision-tree' - Decision Tree\n  * 'complex-rule' - Scripting Rule\n  * 'composition' - Rule Flow\n- tags - Tags on a Rule\n- type - Type of Node in Folder Structure\n  * FOLDER\n  * RULE\n  * ROOT\n- version - Version of the rule\n- ruleStatus\n  * published\n  * pending","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Optional name of the rule"},"id":{"type":"string","description":"Optional identifier"},"baseId":{"type":"string","description":"Optional base identifier"},"ruleAlias":{"type":"string","description":"Optional alias for the rule"},"type":{"type":"string","enum":["decision-table","complex-rule","composition","decision-tree"],"description":"Type of rule"},"tags":{"type":"array","items":{"type":"string"},"description":"Optional list of tags"},"status":{"type":"string","enum":["published","pending"],"description":"Current state of the rule"},"version":{"type":"number","description":"Version number of the rule"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Tools

## Find duplicates in a decision table

> Look for decision table by id and optionally version. If the decision table is found, it is returned together with an array of duplicates.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Tools"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/tools/duplicates/{identifier}/{version}?":{"get":{"tags":["Tools"],"summary":"Find duplicates in a decision table","description":"Look for decision table by id and optionally version. If the decision table is found, it is returned together with an array of duplicates.","parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true},{"schema":{"type":"string"},"name":"version","in":"path","required":false}],"responses":{"200":{"description":"OK","type":"object","content":{"application/json":{"schema":{}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Find all dependencies of a rule

> Look for dependencies by id or alias and optionally version. If the rule is found, it is returned together with an array of dependencies.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[{"name":"Tools"}],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/tools/dependencies/{identifier}/{version}?":{"get":{"tags":["Tools"],"summary":"Find all dependencies of a rule","description":"Look for dependencies by id or alias and optionally version. If the rule is found, it is returned together with an array of dependencies.","parameters":[{"schema":{"type":"string"},"name":"identifier","in":"path","required":true},{"schema":{"type":"string"},"name":"version","in":"path","required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"content":{"application/json":{"schema":{"type":"string"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## RuleFlow Export/Import

Following endpoints can be used only to export and import Rule Flows. For managing Workflows, please store your Workflows with dependent rules in folders, then use folder API endpoints.

## Export Rule Flow with all rules

> Export Rule Flow with all rules. If the version is not specified, exports the latest version.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/api/rule-flow/export/{ruleFlowId}/{version}":{"get":{"summary":"Export Rule Flow with all rules","description":"Export Rule Flow with all rules. If the version is not specified, exports the latest version.","parameters":[{"schema":{"type":"string"},"name":"ruleFlowId","in":"path","required":true,"description":"Unique rule flow ID or alias which is common to all versions."},{"schema":{"type":"number"},"name":"version","in":"path","required":false,"description":"Version of the Rule Flow."},{"schema":{"type":"string"},"name":"Authorization","in":"header","required":true,"description":"Bearer token"},{"schema":{"type":"string","enum":["application/json"]},"name":"Content-Type","in":"header","required":true,"description":"Content type"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Bad Request: Invalid API key or ruleFlowId","content":{"application/json":{}}},"426":{"description":"Upgrade Required: Operation not allowed"}}}}}}
```

## Import Rule Flow with all rules

> Importing a rule flow with rules included can overwrite previously created or imported rules having the same ruleId. If no query parameters are set, a new Rule Flow is created. If new-version and version are set, a new version of the targeted Rule Flow is created. If overwrite and version are set, a specific version of the target rule flow is overwritten.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/api/rule-flow/import":{"post":{"summary":"Import Rule Flow with all rules","description":"Importing a rule flow with rules included can overwrite previously created or imported rules having the same ruleId. If no query parameters are set, a new Rule Flow is created. If new-version and version are set, a new version of the targeted Rule Flow is created. If overwrite and version are set, a specific version of the target rule flow is overwritten.","parameters":[{"schema":{"type":"string"},"name":"new-version","in":"query","required":false,"description":"ID or alias of the target Rule Flow for creating a new version"},{"schema":{"type":"string"},"name":"overwrite","in":"query","required":false,"description":"ID or alias of the target Rule Flow for overwriting"},{"schema":{"type":"number"},"name":"version","in":"query","required":false,"description":"Version of target Rule Flow"},{"schema":{"type":"string"},"name":"Authorization","in":"header","required":true,"description":"Bearer token"},{"schema":{"type":"string","enum":["application/json"]},"name":"Content-Type","in":"header","required":true,"description":"Content type"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100,"description":"Name of the rule"},"ruleAlias":{"type":"string","maxLength":100,"description":"Optional alias"},"auditLog":{"type":"number","description":"Audit log TTL, must be positive"},"type":{"type":"string","description":"Rule type","enum":["decision-table","decision-tree","complex-rule","composition"]},"status":{"type":"string","description":"Rule state","enum":["published","pending"]},"inputSchema":{"type":"object","description":"Input schema"},"outputSchema":{"type":"object","description":"Output schema"}},"required":["name","type","status","inputSchema","outputSchema"]}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad Request: Invalid API key","content":{"application/json":{}}},"406":{"description":"Not Acceptable: Wrong Rule Flow format"},"426":{"description":"Upgrade Required: Operation not allowed"}}}}}}
```

{% hint style="danger" %}
Importing rule flow with rules included can overwrite previously created or imported rules having the same ruleId.
{% endhint %}

## Statistics

## Get space owner statistics

> Get space owner statistics.

```json
{"openapi":"3.1.1","info":{"title":"DecisionRules.io Management API","version":"1.22.0"},"tags":[],"servers":[{"url":"https://api.decisionrules.io/api"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Please insert: \"Bearer <MANAGEMENT_API_KEY>\" into Authorization header."}}},"paths":{"/statistics/owner":{"get":{"tags":["Statistics"],"summary":"Get space owner statistics","description":"Get space owner statistics.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```


# Rule Migration Strategies

In this article, we describe the recommended strategies for migrating rules between environments

{% hint style="info" %}
You may not need the rule migration strategies at all. Check out the [Automated Rule Migration](/doc/other-deployment-options/docker-and-on-premise/cd-ci-pipelines/using-migration-script-old-way) page for an off-the-shelf alternative.
{% endhint %}

As you might know, DecisionRules is using [Spaces](/doc/space/spaces) for rule and permission management. Within the cloud app, it is possible to share rules between Spaces or copy them from one Space to another. However, sometimes it is also needed to migrate one or more rules between two environments, either within the same database or between two different databases. This task can be performed with the use of our [Management API](/doc/api/management-api). We have summarized the recommended strategies for rule migration in the present article.

There are two different cases of rule migration. We either want to migrate a **standalone rule** or a **complex rule**. The former applies to Decision Tables, Decision Trees and Scripting Rules. It may also apply to Rule Flows if we only wish to migrate the model and not the individual rules used in the Rule Flow (e.g. when we know they have not changed or we want to manage them separately). The latter applies to Rule Flows for which it is possible to perform the complex migration, dealing with the Rule Flow *together with* the rules used in it. We shall treat the two migration cases separately in the two following sections.

## Migrate standalone rules

This section applies to all kinds of rules. We will only deal with the single rule model. Let us go through the individual scenarios, shortly describe the recommended procedure and provide the appropriate endpoint reference.

{% hint style="warning" %}
Note that standalone migration may break references to other rules, e.g. in the case of Rule Flows or Scripting Rules with other rules embedded in them.
{% endhint %}

### **Create a new rule**

In this scenario, we take a rule model from Environment 1, modify it as necessary and create a new rule with this model in Environment 2.

![](/files/YyyJWQW5YmRjdEWMyCjv)

#### **Get the rule model from the source environment**

You can get your current rule model by HTTP GET method with path **/api/rule/{ruleId}/{?version}** or with the **getRule** method in the SDK.

Another option is to get the rule model using a tag. The HTTP GET method **/api/tags/items** or **getRulesByTags** method in the SDK is used for this purpose.

In any case, you get the current model of the specified rule with ruleId and version as a response.

More information about the HTTP GET methods can be found at [Management API](/doc/api/management-api#get-rule). More information about the HTTP GET tag methods can be found at [Management API](/doc/api/management-api#get-rules-rule-flows-by-tags).

#### Modify the rule model

After you get the current rule model, you have to modify it before you will create a new rule on the target environment. If you want to have the rule version equal to 1, you need to change the rule version to 1 or delete the version from the model.

If the source and target environment are on *the same database*, you have to delete ruleId and baseId from the model.

If the source and the target environments are *on different databases* and you want to have the same ruleId, you do not need to make any changes. If you want to have a different ruleId than in the current environment, you have to delete the ruleId and baseId from the model.

#### **Create a new rule in the target environment**

After you modify the rule model, you can create it in the target environment by HTTP POST method with path **/api/rule** or with **createRule** method in the SDK. As a response, you get a new rule model with newly generated ruleId, baseId, and version. More information about the HTTP POST method can be found here at [Management API](/doc/api/management-api#create-rule).

### **Create a new rule version**

In this scenario, we take a rule model from Environment 1, modify it as necessary and create a new rule version with this model in Environment 2.

![](/files/bcFjkdmtmkJTr5ji1IHM)

#### Get the  rule model from the source environment

You can get your current rule model by HTTP GET method with path **/api/rule/{ruleId}/{?version}** or with the **getRule** method in the SDK.

Another option is to get the rule model using a tag. The HTTP GET method **/api/tags/items** or **getRulesByTags** method in the SDK is used for this purpose.

You get a current model of the specified rule with ruleId and version as a response. More information about the HTTP GET methods can be found here: [Management API](/doc/api/management-api#get-rule). More information about the HTTP GET tag methods can be found here: [Management API](/doc/api/management-api#get-rules-rule-flows-by-tags).

#### Modify the rule model

After you get the current rule model you have to modify it. You set the ruleId, baseId to the ruleId, baseId of the rule whose version you want to a create. Next, you have to change the version to a new version that you wish.

#### Create a new rule version for a target environment

After you modify the rule model, you can create it in the target environment by HTTP POST method with path **/api/rule** or with **createRule** method in the SDK. As a response, you get a new rule model with newly generated ruleId, baseId, and version. More information about the HTTP POST method can be found at [Management API](/doc/api/management-api#create-rule).

### **Update a rule**

In this scenario, we take a rule model from Environment 1, modify it as necessary and update an existing rule in Environment 2.

![](/files/F0CQMq7zZWhbhAm382eL)

#### Get a rule model from a source environment

You can get your current rule model by HTTP GET method with path **/api/rule/{ruleId}/{?version}** or with the **getRule** method by SDK.

Another option is to get the rule model using a tag. The HTTP GET method **/api/tags/items** or **getRulesByTags** method in the SDK is used for this purpose.

You get a current model of the specified rule with ruleId and version as a response.

More information about the HTTP GET methods can be found at [Management API](/doc/api/management-api#get-rule). More information about the HTTP GET tag methods can be found at [Management API](/doc/api/management-api#get-rules-rule-flows-by-tags).

#### Modify the rule model

After you get the current rule model you have to modify it. You have to delete baseId from the rule model.

#### Update a rule in the target environment

After you modify the rule model, you can put it in the target environment by HTTP PUT method with path **/api/rule/{ruleId}/{?version}** or with **updateRule** method in the SDK.

As a response, you get a updated rule model. More information about the HTTP PUT method can be found at [Management API](/doc/api/management-api#update-rule).

### **Create a separate Rule Flow**

In this scenario, we take a Rule Flow model from Environment 1, modify it as necessary and create a new Rule Flow with this model in Environment 2.

![](/files/UZlwrRlbZlJEmmRcKDZi)

#### Get a Rule Flow model from the source environment

You can get your current rule flow model by HTTP GET method with path **/api/rule-flow/{ruleFlowId}/{?version}** or with **getRuleFlow** method in the SDK.

Another option is to get the rule flow model using a tag. The HTTP GET method **/api/tags/items** or **getRulesByTags** method in the SDK is used for this purpose.

You get a current model of the specified rule flow with ruleFlowId and version as a response. More information about the HTTP GET method can be found at [Management API](/doc/api/management-api#get-rule-flow). More information about the HTTP GET tag methods can be found at[Management API](/doc/api/management-api#get-rules-rule-flows-by-tags).

#### **Modify the Rule Flow model**

If you want to have a rule version from 1, you have to change the rule version to 1 or delete the version from the model.

If the source and target environment are on the same database, you have to delete compositionId and baseId from the model.

If the source and target environment are on a different database and you want to have the same compositionId, you do not make any changes. If you want to have a different compositionId than in the current environment, you have to delete the compositionId and baseId from the model.

#### Create a new Rule Flow in the target environment

After you modify the rule flow model, you can create it in the target environment by HTTP POST method with path **/api/rule-flow** or with **createRuleFlow** method in the SDK.

As a response, you get a new rule flow model with newly generated compositionId, baseId, and version. More information about the HTTP POST method can be found at [Management API](/doc/api/management-api#create-rule-flow).

### **Create a new separate Rule Flow version**

In this scenario, we take a Rule Flow model from Environment 1, modify it as necessary and create a new Rule Flow version with this model in Environment 2.

![](/files/oADFLpa4AlWMtjL1woCP)

#### Get a Rule Flow model from the source environment

You can get your current rule flow model by HTTP GET method with path **/api/rule-flow/{ruleFlowId}/{?version}** or with **getRuleFlow** method by SDK.

Another option is to get the rule flow model using a tag. The HTTP GET method **/api/tags/items** or **getRulesByTags** method by SDK is used for this purpose.

You get a current model of the specified rule flow with ruleFlowId and version as a response. More information about the HTTP GET method can be found at [Management API](/doc/api/management-api#get-rule-flow). More information about the HTTP GET tag methods can be found at [Management API](/doc/api/management-api#get-rules-rule-flows-by-tags).

#### **Modify the Rule Flow model**

After you get the current rule model you have to modify it. You have to change compositionId, baseId to a compositionId which version you want to a create. Next, you have to change the version to a new version that you want.

#### Create a new Rule Flow version in the target environment

After you modify the rule flow model, you can create it in the target environment by HTTP POST method with path **/api/rule-flow** or with **createRuleFlow** method by SDK.

As a response, you get a new rule flow model with newly generated compositionId, baseId, and version. More information about the HTTP POST method can be found at [Management API](/doc/api/management-api#create-rule-flow).

### Update a separate Rule Flow

In this scenario, we take a Rule Flow model from Environment 1, modify it as necessary and update an existing Rule Flow in Environment 2.

![](/files/jSPiDnxOdEOXAVYdpL1S)

#### Get a Rule Flow model from the source environment

You can get your current rule flow model by HTTP GET method with path **/api/rule-flow/{ruleFlowId}/{?version}** or with **getRuleFlow** method by SDK.

Another option is to get the rule flow model using a tag. The HTTP GET method **/api/tags/items** or **getRulesByTags** method by SDK is used for this purpose.

You get a current model of the specified rule flow with ruleFlowId and version as a response. More information about the HTTP GET method can be found at [Management API](/doc/api/management-api#get-rule-flow). More information about the HTTP GET tag methods can be found at [Management API](/doc/api/management-api#get-rules-rule-flows-by-tags).

#### **Update a Rule Flow in the target environment**

You can create it in the target environment by HTTP PUT method with path **/api/rule-flow/{compositionId}/{?version}** or with **updateRule** method in the SDK.  As a response, you get a updated rule flow model. More information about the HTTP PUT method can be found at [Management API](/doc/api/management-api#update-rule-flow).

## Migrate complex rules

Currently, the complex rule migration is only supported for Rule Flows. Use it if you wish to migrate a Rule Flow together with all the rules that it uses. We shall go through the individual scenarios, shortly describe the recommended procedure and provide the appropriate endpoint reference.

### **Create a Rule Flow with rules**

In this scenario, we take a Rule Flow model together wit all the rules used in it from Environment 1 and create a new Rule Flow in Environment 2.

![](/files/mekkXzV6WWjQ2iaQu0hO)

#### **Get a Rule Flow model with rules from the source environment**

You can get your current rule flow model by HTTP GET method with path **/api/rule-flow/export/{ruleFlowId}/{?version}** or with **exportRuleFlow** method in the SDK.

You get a current model of the specified rule flow with all rules as a response. More information about the HTTP GET method can be found at [Management API](/doc/api/management-api#export-rule-flow-with-all-rules).

#### **Create a new Rule Flow with rules in the target environment**

You can create it in the target environment by HTTP POST method with path **/api/rule-flow/import** or with **importRuleFlow** method in the SDK.

As a response, you get a new rule flow model with all rules. More information about the HTTP POST method can be found at [Management API](/doc/api/management-api#import-rule-flow-with-all-rules).

### **Create a new Rule Flow version with rules**

In this scenario, we take a Rule Flow model together wit all the rules used in it from Environment 1 and create a new Rule Flow version in Environment 2.

![](/files/J5i68u9f8DeKxdQ2Szif)

#### Get a Rule Flow model with rules from the source environment

You can get your current rule flow model by HTTP GET method with path **/api/rule-flow/export/{ruleFlowId}/{?version}** or with **exportRuleFlow** method by SDK.

You get a current model of the specified rule flow with all rules as a response. More information about the HTTP GET method can be found at [Management API](/doc/api/management-api#export-rule-flow-with-all-rules).

#### Create a new Rule Flow version with rules for the target environment

You can create it in the target environment by HTTP POST method with path **/api/rule-flow/import** or with **importRuleFlow** method in the SDK. You have to call this method with the parameter **new-version** with a value of **compositionId** which new version you want to create.

As a response, you get a new rule flow model with all rules. More information about the HTTP POST method can be found at [Management API](/doc/api/management-api#import-rule-flow-with-all-rules).

### **Update a Rule Flow with rules**

In this scenario, we take a Rule Flow model together wit all the rules used in it from Environment 1 and update an existing Rule Flow in Environment 2.

![](/files/wipiYgg2hPjfxQV8BRHB)

#### Get a Rule Flow model with rules from the source environment

You can get your current rule flow model by HTTP GET method with path **/api/rule-flow/export/{ruleFlowId}/{?version}** or with **exportRuleFlow** method by SDK.

You get a current model of the specified rule flow with all rules as a response. More information about the HTTP GET method can be found at [Management API](/doc/api/management-api#export-rule-flow-with-all-rules).

#### Update a Rule Flow with rules in the target environment

After you modify the rule flow model, you can create it in the target environment by HTTP POST method with path **/api/rule-flow/import** or with i**mportRuleFlow** method by SDK. You have to call this method with the parameter **overwrite** with a value of **compositionId** and parameter **version** with **the value of the version** which rule flow you want to update.

As a response, you get a updated rule flow model with all rules. More information about the HTTP POST method can be found at [Management API](/doc/api/management-api#import-rule-flow-with-all-rules).


# Deprecated Endpoints

## Deprecated Endpoints

All of these endpoints will be deprecated from version 1.7.1 and newer.

### Rule

## Create rule

<mark style="color:green;">`POST`</mark> `https://api.decisionrules.io/api/rule/:spaceId`

Creates rule in space from JSON

#### Path Parameters

| Name                                      | Type   | Description |
| ----------------------------------------- | ------ | ----------- |
| spaceId<mark style="color:red;">\*</mark> | string | Id of Space |

#### Headers

| Name                                            | Type   | Description |
| ----------------------------------------------- | ------ | ----------- |
| Authorization<mark style="color:red;">\*</mark> | string | Bearer      |

{% tabs %}
{% tab title="200 Change has been made" %}

```
```

{% endtab %}

{% tab title="400 Invalid API key or ruleId" %}

```
```

{% endtab %}

{% tab title="401 " %}

```
{
    "error": {
        "message": "Authentication token missing"
    }
}
```

{% endtab %}
{% endtabs %}

## Rule Flow

## Get Rule Flow

<mark style="color:blue;">`GET`</mark> `https://api.decisionrules.io/api/rule-flow/:ruleFlowId/:version?`

If the version is not specified, get Rule Flow with the latest version.

#### Path Parameters

| Name                                         | Type   | Description                                          |
| -------------------------------------------- | ------ | ---------------------------------------------------- |
| ruleFlowId<mark style="color:red;">\*</mark> | String | Unique rule flow ID which is common to all versions. |
| version                                      | Number | Version of Rule Flow                                 |

#### Headers

| Name                                            | Type   | Description |
| ----------------------------------------------- | ------ | ----------- |
| Authorization<mark style="color:red;">\*</mark> | String | Bearer      |

{% tabs %}
{% tab title="200: OK " %}

```json
{
  "_id": "62627b2ac0fc11362331185e",
  "name": "Sample Rule Flow",
  "description": "This is sample description",
  "inputSchema": {
    "period": {},
    "productType": {},
    "promoCode": {}
  },
  "outputSchema": {
    "finalPrice": {},
    "crudePrice": {},
    "message": {}
  },
  "type": "composition",
  "status": "pending",
  "visualEditorData": {
    "drawflow": {
      "Home": {
        "data": {
          "1": {
            "id": 1,
            "data": {
              "type": "start"
            },
            "inputs": {},
            "outputs": {
              "output_1": {
                "connections": [
                  {
                    "node": "2",
                    "output": "input_1"
                  }
                ]
              }
            },
            "pos_x": 57,
            "pos_y": 218
          },
          "2": {
            "id": 2,
            "data": {
              "type": "node",
              "baseId": "f36bf7cf-bef4-1f4c-d756-c0b6f2f814ff",
              "globalVariable": "Rule_1"
            },
            "inputs": {
              "input_1": {
                "connections": [
                  {
                    "node": "1",
                    "input": "output_1"
                  }
                ]
              }
            },
            "outputs": {
              "output_1": {
                "connections": [
                  {
                    "node": "3",
                    "output": "input_1"
                  }
                ]
              }
            },
            "pos_x": 400,
            "pos_y": 150
          },
          "3": {
            "id": 3,
            "data": {
              "type": "end"
            },
            "inputs": {
              "input_1": {
                "connections": [
                  {
                    "node": "2",
                    "input": "output_1"
                  }
                ]
              }
            },
            "outputs": {},
            "pos_x": 785,
            "pos_y": 212
          }
        }
      }
    }
  },
  "dataTree": {
    "children": [
      {
        "baseId": "f36bf7cf-bef4-1f4c-d756-c0b6f2f814ff",
        "children": [
          {
            "children": [
              null
            ],
            "globalVariable": "end",
            "mapping": [
              {
                "key": "finalPrice",
                "source": "Rule_1",
                "sourceVariable": "prices.finalPrice"
              },
              {
                "key": "crudePrice",
                "source": "Rule_1",
                "sourceVariable": "prices.crudePrice"
              },
              {
                "key": "message",
                "source": "Rule_1",
                "sourceVariable": "message"
              }
            ]
          }
        ],
        "globalVariable": "Rule_1",
        "mapping": [
          {
            "key": "period",
            "source": "start",
            "sourceVariable": "period"
          },
          {
            "key": "productType",
            "source": "start",
            "sourceVariable": "productType"
          },
          {
            "key": "promoCode",
            "source": "start",
            "sourceVariable": "promoCode"
          }
        ]
      }
    ],
    "globalVariable": "start",
    "mapping": []
  },
  "compositionId": "94c5ef08-d609-ef88-066a-fbeda7d1e537",
  "version": 1,
  "createdIn": "2022-04-22T09:53:46.744Z",
  "lastUpdate": "2022-04-22T09:53:46.744Z"
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid API Key or ruleFlowId" %}

```javascript
{
  "error": {
    "message": "Invalid API key"
  }
}
```

{% endtab %}
{% endtabs %}

## Update Rule Flow Status

<mark style="color:orange;">`PUT`</mark> `https://api.decisionrules.io/api/rule-flow/status/:ruleId/:status/:version`

Changes rule status from <mark style="color:orange;">pending</mark> to <mark style="color:green;">published</mark> and vice versa. If the version is not specified, the latest version will be used.

#### Path Parameters

| Name                                      | Type   | Description                                                                                |
| ----------------------------------------- | ------ | ------------------------------------------------------------------------------------------ |
| ruleId<mark style="color:red;">\*</mark>  | String | Unique rule flow ID which is common to all versions.                                       |
| status<mark style="color:red;">\*</mark>  | String | <mark style="color:orange;">pending</mark> XOR <mark style="color:green;">published</mark> |
| version<mark style="color:red;">\*</mark> | number | rule flow version                                                                          |

{% tabs %}
{% tab title="200: OK Status has been successfully updated " %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="400: Bad Request One or more PATH parameters are invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

## Update Rule Flow

<mark style="color:orange;">`PUT`</mark> `https://api.decisionrules.io/api/rule-flow/:ruleFlowId/:version`

#### Path Parameters

| Name                                         | Type   | Description                                          |
| -------------------------------------------- | ------ | ---------------------------------------------------- |
| ruleFlowId<mark style="color:red;">\*</mark> | String | Unique rule flow ID which is common to all versions. |
| version<mark style="color:red;">\*</mark>    | Number | Version of Rule Flow                                 |

#### Headers

| Name                                            | Type   | Description |
| ----------------------------------------------- | ------ | ----------- |
| Authorization<mark style="color:red;">\*</mark> | String | Bearer      |

#### Request Body

| Name                                        | Type   | Description        |
| ------------------------------------------- | ------ | ------------------ |
| Rule Flow<mark style="color:red;">\*</mark> | Object | Model of Rule Flow |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "_id": "62627b2ac0fc11362331185e",
  "name": "Sample Rule Flow",
  "description": "This is sample description",
  "inputSchema": {
    "period": {},
    "productType": {},
    "promoCode": {}
  },
  "outputSchema": {
    "finalPrice": {},
    "crudePrice": {},
    "message": {}
  },
  "type": "composition",
  "status": "pending",
  "visualEditorData": {
    "drawflow": {
      "Home": {
        "data": {
          "1": {
            "id": 1,
            "data": {
              "type": "start"
            },
            "inputs": {},
            "outputs": {
              "output_1": {
                "connections": [
                  {
                    "node": "2",
                    "output": "input_1"
                  }
                ]
              }
            },
            "pos_x": 57,
            "pos_y": 218
          },
          "2": {
            "id": 2,
            "data": {
              "type": "node",
              "baseId": "f36bf7cf-bef4-1f4c-d756-c0b6f2f814ff",
              "globalVariable": "Rule_1"
            },
            "inputs": {
              "input_1": {
                "connections": [
                  {
                    "node": "1",
                    "input": "output_1"
                  }
                ]
              }
            },
            "outputs": {
              "output_1": {
                "connections": [
                  {
                    "node": "3",
                    "output": "input_1"
                  }
                ]
              }
            },
            "pos_x": 400,
            "pos_y": 150
          },
          "3": {
            "id": 3,
            "data": {
              "type": "end"
            },
            "inputs": {
              "input_1": {
                "connections": [
                  {
                    "node": "2",
                    "input": "output_1"
                  }
                ]
              }
            },
            "outputs": {},
            "pos_x": 785,
            "pos_y": 212
          }
        }
      }
    }
  },
  "dataTree": {
    "children": [
      {
        "baseId": "f36bf7cf-bef4-1f4c-d756-c0b6f2f814ff",
        "children": [
          {
            "children": [
              null
            ],
            "globalVariable": "end",
            "mapping": [
              {
                "key": "finalPrice",
                "source": "Rule_1",
                "sourceVariable": "prices.finalPrice"
              },
              {
                "key": "crudePrice",
                "source": "Rule_1",
                "sourceVariable": "prices.crudePrice"
              },
              {
                "key": "message",
                "source": "Rule_1",
                "sourceVariable": "message"
              }
            ]
          }
        ],
        "globalVariable": "Rule_1",
        "mapping": [
          {
            "key": "period",
            "source": "start",
            "sourceVariable": "period"
          },
          {
            "key": "productType",
            "source": "start",
            "sourceVariable": "productType"
          },
          {
            "key": "promoCode",
            "source": "start",
            "sourceVariable": "promoCode"
          }
        ]
      }
    ],
    "globalVariable": "start",
    "mapping": []
  },
  "compositionId": "94c5ef08-d609-ef88-066a-fbeda7d1e537",
  "version": 1,
  "createdIn": "2022-04-22T09:53:46.744Z",
  "lastUpdate": "2022-04-22T09:53:46.744Z"
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid API key or ruleFlowId" %}

```javascript
{
  "error": {
    "message": "Invalid API key"
  }
}
```

{% endtab %}

{% tab title="406: Not Acceptable Wrong Rule Flow format" %}

```javascript
{
    Error: Rule Flow is missing the property 'name'!
}
```

{% endtab %}

{% tab title="426: Upgrade Required Operation not allowed" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

## Create Rule Flow

<mark style="color:green;">`POST`</mark> `https://api.decisionrules.io/api/rule-flow`

#### Headers

| Name                                            | Type   | Description |
| ----------------------------------------------- | ------ | ----------- |
| Authorization<mark style="color:red;">\*</mark> | String | Bearer      |

#### Request Body

| Name                                        | Type   | Description        |
| ------------------------------------------- | ------ | ------------------ |
| Rule Flow<mark style="color:red;">\*</mark> | Object | Model of Rule Flow |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "_id": "62627b2ac0fc11362331185e",
  "name": "Sample Rule Flow",
  "description": "This is sample description",
  "inputSchema": {
    "period": {},
    "productType": {},
    "promoCode": {}
  },
  "outputSchema": {
    "finalPrice": {},
    "crudePrice": {},
    "message": {}
  },
  "type": "composition",
  "status": "pending",
  "visualEditorData": {
    "drawflow": {
      "Home": {
        "data": {
          "1": {
            "id": 1,
            "data": {
              "type": "start"
            },
            "inputs": {},
            "outputs": {
              "output_1": {
                "connections": [
                  {
                    "node": "2",
                    "output": "input_1"
                  }
                ]
              }
            },
            "pos_x": 57,
            "pos_y": 218
          },
          "2": {
            "id": 2,
            "data": {
              "type": "node",
              "baseId": "f36bf7cf-bef4-1f4c-d756-c0b6f2f814ff",
              "globalVariable": "Rule_1"
            },
            "inputs": {
              "input_1": {
                "connections": [
                  {
                    "node": "1",
                    "input": "output_1"
                  }
                ]
              }
            },
            "outputs": {
              "output_1": {
                "connections": [
                  {
                    "node": "3",
                    "output": "input_1"
                  }
                ]
              }
            },
            "pos_x": 400,
            "pos_y": 150
          },
          "3": {
            "id": 3,
            "data": {
              "type": "end"
            },
            "inputs": {
              "input_1": {
                "connections": [
                  {
                    "node": "2",
                    "input": "output_1"
                  }
                ]
              }
            },
            "outputs": {},
            "pos_x": 785,
            "pos_y": 212
          }
        }
      }
    }
  },
  "dataTree": {
    "children": [
      {
        "baseId": "f36bf7cf-bef4-1f4c-d756-c0b6f2f814ff",
        "children": [
          {
            "children": [
              null
            ],
            "globalVariable": "end",
            "mapping": [
              {
                "key": "finalPrice",
                "source": "Rule_1",
                "sourceVariable": "prices.finalPrice"
              },
              {
                "key": "crudePrice",
                "source": "Rule_1",
                "sourceVariable": "prices.crudePrice"
              },
              {
                "key": "message",
                "source": "Rule_1",
                "sourceVariable": "message"
              }
            ]
          }
        ],
        "globalVariable": "Rule_1",
        "mapping": [
          {
            "key": "period",
            "source": "start",
            "sourceVariable": "period"
          },
          {
            "key": "productType",
            "source": "start",
            "sourceVariable": "productType"
          },
          {
            "key": "promoCode",
            "source": "start",
            "sourceVariable": "promoCode"
          }
        ]
      }
    ],
    "globalVariable": "start",
    "mapping": []
  },
  "compositionId": "94c5ef08-d609-ef88-066a-fbeda7d1e537",
  "version": 1,
  "createdIn": "2022-04-22T09:53:46.744Z",
  "lastUpdate": "2022-04-22T09:53:46.744Z"
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid API key or ruleFlowId" %}

```javascript
{
  "error": {
    "message": "Invalid API key"
  }
}
```

{% endtab %}

{% tab title="406: Not Acceptable Wrong Rule Flow format" %}

```javascript
{
    Error: Rule Flow is missing the property 'name'!
}
```

{% endtab %}

{% tab title="426: Upgrade Required Operation not allowed" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

#### Ruleflow request body example

This example serves as a template for request bodies when creating rules with <mark style="color:green;">POST</mark> Create rule. \
When updating rules with <mark style="color:orange;">PUT</mark> Update rule, the body of the request must have the same format as well.&#x20;

<details>

<summary>request body example</summary>

```json
{
  "_id": "62627b2ac0fc11362331185e",
  "name": "Sample Rule Flow",
  "description": "This is sample description",
  "inputSchema": {
    "period": {},
    "productType": {},
    "promoCode": {}
  },
  "outputSchema": {
    "finalPrice": {},
    "crudePrice": {},
    "message": {}
  },
  "type": "composition",
  "status": "pending",
  "visualEditorData": {
    "drawflow": {
      "Home": {
        "data": {
          "1": {
            "id": 1,
            "data": {
              "type": "start"
            },
            "inputs": {},
            "outputs": {
              "output_1": {
                "connections": [
                  {
                    "node": "2",
                    "output": "input_1"
                  }
                ]
              }
            },
            "pos_x": 57,
            "pos_y": 218
          },
          "2": {
            "id": 2,
            "data": {
              "type": "node",
              "baseId": "f36bf7cf-bef4-1f4c-d756-c0b6f2f814ff",
              "globalVariable": "Rule_1"
            },
            "inputs": {
              "input_1": {
                "connections": [
                  {
                    "node": "1",
                    "input": "output_1"
                  }
                ]
              }
            },
            "outputs": {
              "output_1": {
                "connections": [
                  {
                    "node": "3",
                    "output": "input_1"
                  }
                ]
              }
            },
            "pos_x": 400,
            "pos_y": 150
          },
          "3": {
            "id": 3,
            "data": {
              "type": "end"
            },
            "inputs": {
              "input_1": {
                "connections": [
                  {
                    "node": "2",
                    "input": "output_1"
                  }
                ]
              }
            },
            "outputs": {},
            "pos_x": 785,
            "pos_y": 212
          }
        }
      }
    }
  },
  "dataTree": {
    "children": [
      {
        "baseId": "f36bf7cf-bef4-1f4c-d756-c0b6f2f814ff",
        "children": [
          {
            "children": [
              null
            ],
            "globalVariable": "end",
            "mapping": [
              {
                "key": "finalPrice",
                "source": "Rule_1",
                "sourceVariable": "prices.finalPrice"
              },
              {
                "key": "crudePrice",
                "source": "Rule_1",
                "sourceVariable": "prices.crudePrice"
              },
              {
                "key": "message",
                "source": "Rule_1",
                "sourceVariable": "message"
              }
            ]
          }
        ],
        "globalVariable": "Rule_1",
        "mapping": [
          {
            "key": "period",
            "source": "start",
            "sourceVariable": "period"
          },
          {
            "key": "productType",
            "source": "start",
            "sourceVariable": "productType"
          },
          {
            "key": "promoCode",
            "source": "start",
            "sourceVariable": "promoCode"
          }
        ]
      }
    ],
    "globalVariable": "start",
    "mapping": []
  },
  "compositionId": "94c5ef08-d609-ef88-066a-fbeda7d1e537",
  "version": 1,
  "createdIn": "2022-04-22T09:53:46.744Z",
  "lastUpdate": "2022-04-22T09:53:46.744Z"
}
```

</details>

## Delete Rule Flow

<mark style="color:red;">`DELETE`</mark> `https://api.decisionrules.io/api/rule-flow/:ruleFlowId/:version`

#### Path Parameters

| Name                                         | Type   | Description                                          |
| -------------------------------------------- | ------ | ---------------------------------------------------- |
| ruleFlowId<mark style="color:red;">\*</mark> | String | Unique rule flow ID which is common to all versions. |
| version<mark style="color:red;">\*</mark>    | Number | Version of Rule Flow                                 |

#### Headers

| Name                                            | Type   | Description |
| ----------------------------------------------- | ------ | ----------- |
| Authorization<mark style="color:red;">\*</mark> | String | Bearer      |

{% tabs %}
{% tab title="200: OK " %}

```javascript
```

{% endtab %}

{% tab title="400: Bad Request Invalid API key or ruleFlowId" %}

```javascript
{
  "error": {
    "message": "Invalid API key"
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
If you do not specify version of the rule to be deleted, the endpoint will delete **all versions of the rule**. Please, use it with caution! Once deleted, rules cannot be recovered.
{% endhint %}

### Spaces

## Get all rules/rule flows in space

<mark style="color:blue;">`GET`</mark> `https://api.decisionrules.io/api/space/:spaceId`

#### Path Parameters

| Name                                      | Type   | Description |
| ----------------------------------------- | ------ | ----------- |
| spaceId<mark style="color:red;">\*</mark> | string | ID of space |

#### Headers

| Name                                            | Type   | Description        |
| ----------------------------------------------- | ------ | ------------------ |
| Authorization<mark style="color:red;">\*</mark> | string | Bearer \<API\_KEY> |

{% tabs %}
{% tab title="200 " %}

```
[
  {
    "ruleId": "00bcbe6e-5274-999e-5d75-b18c4d032510",
    "name": "Client Classification",
    "state": "published",
    "version": 1,
    "last_updated": "2021-08-27T04:51:24.436Z",
    "note": "Basic client classification rule",
    "type": "Decision Table",
    "tags": ["tagName", "anotherTagName"]
  }
]
```

{% endtab %}

{% tab title="400 " %}

```
Wrong spaceId!
```

{% endtab %}

{% tab title="401 " %}

```
{
    "error": {
        "message": "Authentication token missing"
    }
}
```

{% endtab %}
{% endtabs %}

### Tags

## Get rules by tag/tags

<mark style="color:blue;">`GET`</mark> `https://api.decisionrules.io/api/tags/rules/:spaceId`

#### Path Parameters

| Name                                      | Type   | Description |
| ----------------------------------------- | ------ | ----------- |
| spaceId<mark style="color:red;">\*</mark> | string | ID of space |

#### Query Parameters

| Name                                   | Type   | Description                                                                                                                                                                                      |
| -------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| tags<mark style="color:red;">\*</mark> | string | Comma separated list of tags. The query at the end of the url address should look like this: ?tags=tag1,tag2. Such query would select all the rules where tag array contains both tag1 and tag2. |

#### Headers

| Name                                            | Type   | Description        |
| ----------------------------------------------- | ------ | ------------------ |
| Authorization<mark style="color:red;">\*</mark> | string | Bearer \<API\_KEY> |

{% tabs %}
{% tab title="200: OK Returns an array of rules." %}

```javascript
[
{
  "name": "Rule Name",
  "description": "",
  "inputSchema": {
    "Input attribute": {}
  },
  "outputSchema": {
    "Output Attribute": {}
  },
  "decisionTable": {
    "columns": [
      {
        "condition": {
          "type": "simple",
          "inputVariable": "Input attribute",
          "name": "New Condition"
        },
        "columnId": "ec57bb7c-8e90-4aee-da49-17b607a6b09a",
        "type": "input"
      },
      {
        "columnOutput": {
          "type": "simple",
          "outputVariable": "Output Attribute",
          "name": "New Result"
        },
        "columnId": "2e46eb73-de05-51bc-5913-4b261bbe2069",
        "type": "output"
      }
    ],
    "rows": [
      {
        "cells": [
          {
            "column": "ec57bb7c-8e90-4aee-da49-17b607a6b09a",
            "scalarCondition": {
              "value": "",
              "operator": "anything"
            },
            "type": "input"
          },
          {
            "column": "2e46eb73-de05-51bc-5913-4b261bbe2069",
            "outputScalarValue": {
              "value": "Hello from Solver"
            },
            "type": "output"
          }
        ]
      }
    ]
  },
  "type": "decision-table",
  "status": "published",
  "ruleId": "4ea...",
  "version": 1,
  "createdIn": "2021-09-03T06:35:42.663Z",
  "lastUpdate": "2021-09-03T06:35:42.663Z",
  "tags": ["tag1", "tag2"]
},
{
  "name": "Rule Name",
  "description": "",
  "inputSchema": {
    "Input attribute": {}
  },
  "outputSchema": {
    "Output Attribute": {}
  },
  "decisionTable": {
    "columns": [
      {
        "condition": {
          "type": "simple",
          "inputVariable": "Input attribute",
          "name": "New Condition"
        },
        "columnId": "ec57bb7c-8e90-4aee-da49-17b607a6b09a",
        "type": "input"
      },
      {
        "columnOutput": {
          "type": "simple",
          "outputVariable": "Output Attribute",
          "name": "New Result"
        },
        "columnId": "2e46eb73-de05-51bc-5913-4b261bbe2069",
        "type": "output"
      }
    ],
    "rows": [
      {
        "cells": [
          {
            "column": "ec57bb7c-8e90-4aee-da49-17b607a6b09a",
            "scalarCondition": {
              "value": "",
              "operator": "anything"
            },
            "type": "input"
          },
          {
            "column": "2e46eb73-de05-51bc-5913-4b261bbe2069",
            "outputScalarValue": {
              "value": "Hello from Solver"
            },
            "type": "output"
          }
        ]
      }
    ]
  },
  "type": "decision-table",
  "status": "published",
  "ruleId": "4ea...",
  "version": 2,
  "createdIn": "2021-09-03T06:35:42.663Z",
  "lastUpdate": "2021-09-03T06:35:42.663Z",
  "tags": ["tag1", "tag2"]
}
]
```

{% endtab %}

{% tab title="400: Bad Request Invalid API key or no query added." %}

```javascript
{
    "error": {
        "message": "Invalid API key"
    }
}
```

{% endtab %}

{% tab title="401: Unauthorized API key missing." %}

```javascript
{
    "error": {
        "message": "Authentication token missing"
    }
}
```

{% endtab %}
{% endtabs %}

## Add tags to rule

<mark style="color:purple;">`PATCH`</mark> `https://api.decisionrules.io/api/tags/rules/:spaceId/:ruleId/:version?`

If you specify the version, the tag/tags will be added to the specified version. If the version is not specified, the tag/tags will be added to all the versions with given rule ID.

#### Path Parameters

| Name                                      | Type   | Description     |
| ----------------------------------------- | ------ | --------------- |
| spaceId<mark style="color:red;">\*</mark> | string | ID of space     |
| ruleId<mark style="color:red;">\*</mark>  | string | ID of rule      |
| version                                   | string | Version of rule |

#### Headers

| Name                                            | Type   | Description        |
| ----------------------------------------------- | ------ | ------------------ |
| Authorization<mark style="color:red;">\*</mark> | string | Bearer \<API\_KEY> |

#### Request Body

| Name                                   | Type  | Description          |
| -------------------------------------- | ----- | -------------------- |
| body<mark style="color:red;">\*</mark> | array | Array of tags to add |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{message: 'ok'}
```

{% endtab %}

{% tab title="400: Bad Request Invalid API key or no tag array provided" %}

```javascript
{
    "error": {
        "message": "Invalid API key"
    }
}
```

{% endtab %}

{% tab title="401: Unauthorized API key missing." %}

```javascript
{
    "error": {
        "message": "Authentication token missing"
    }
}
```

{% endtab %}
{% endtabs %}

## Delete tags from rule

<mark style="color:red;">`DELETE`</mark> `https://api.decisionrules.io/api/tags/rules/:spaceId/:ruleId/:version?`

If you specify the version, the tag/tags will be deleted from the specified version. If the version is not specified, the tag/tags will be removed from all the versions with given rule ID.

#### Path Parameters

| Name                                      | Type   | Description     |
| ----------------------------------------- | ------ | --------------- |
| spaceId<mark style="color:red;">\*</mark> | string | ID of space     |
| ruleId<mark style="color:red;">\*</mark>  | string | ID of rule      |
| version                                   | string | Version of rule |

#### Query Parameters

| Name                                   | Type   | Description                                                                                                  |
| -------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------ |
| tags<mark style="color:red;">\*</mark> | string | Comma separated list of tags. The query at the end of the url address should look like this: ?tags=tag1,tag2 |

#### Headers

| Name                                            | Type   | Description        |
| ----------------------------------------------- | ------ | ------------------ |
| Authorization<mark style="color:red;">\*</mark> | string | Bearer \<API\_KEY> |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{message: 'ok'}
```

{% endtab %}

{% tab title="400: Bad Request Invalid API key or no query string provided" %}

```javascript
{
    "error": {
        "message": "Invalid API key"
    }
}
```

{% endtab %}

{% tab title="401: Unauthorized API key missing." %}

```javascript
{
    "error": {
        "message": "Authentication token missing"
    }
}
```

{% endtab %}
{% endtabs %}


# Business Intelligence API

The Business Intelligence API allows to get audit logs from the rule solver.

The Business Intelligence API is providing the business intelligence functionalities of DecisionRules. Most importantly, it allows to collect data from the rule solver.

## About the Business Intelligence API

The API allows you to get audits from database and delete them from the database when they are no longer needed. We describe both endpoints below.

{% hint style="info" %}
If you're using the **Regional Cloud** version of DecisionRules, read more about API calls [here](/doc/other-deployment-options/regional-cloud/region-specific-api-urls#making-api-calls-on-region-cloud-accounts).
{% endhint %}

{% hint style="danger" %}
Please note that anyone with access to a Business Intelligence API Key can also inherently access your Solver keys, as Audit Logs keep record of the Solver key used for the Solver invocation.
{% endhint %}

{% hint style="info" %}
You need to copy paste your own Business Intelligence API Key after `Bearer` . If you do not have it yet, generate your Business Intelligence API Key [in the app](https://app.decisiongrid.io/api-keys).
{% endhint %}

The Business Intelligence API Key can be also included in a query parameter instead of the header. In that case, the same request would look as follows.

{% hint style="info" %}
The rule solver does not generate audit logs by default. If you want some rule to generate audits on each solve, you have to **turn on audit logs** in its Rule Settings. More information can be found on the [Audit Logging](/doc/business-intelligence/audit-logs) Page.
{% endhint %}

## Endpoints:

{% openapi src="<https://bi.decisionrules.io/api/docs/json>" path="/audit/v2" method="get" %}
<https://bi.decisionrules.io/api/docs/json>
{% endopenapi %}

{% openapi src="<https://bi.decisionrules.io/api/docs/json>" path="/audit/v2/count" method="get" %}
<https://bi.decisionrules.io/api/docs/json>
{% endopenapi %}

{% openapi src="<https://bi.decisionrules.io/api/docs/json>" path="/audit/v2" method="delete" %}
<https://bi.decisionrules.io/api/docs/json>
{% endopenapi %}

{% hint style="warning" %}
This action results in permanent and irreversible disposal of the deleted audit logs. Please, use it carefully. More information can be found on the [Audit Logging](/doc/business-intelligence/audit-logs#deleting-audit-logs) page.
{% endhint %}

### Pagination <a href="#pagination" id="pagination"></a>

There can be a lot of audit logs in the database, of course. We therefore restrict the maximum page size, i.e., the number of audit logs that can be returned per one request, to 1.000.

To get the next page of your audit logs simply add the query parameter 'after' to your call and provide it with the cursor returned in the previous call.

**Page Size**

You can choose a custom page size smaller than 1.000 by defining the `page_size` query parameter. For example, if you set `page_size=100`, the API will always return maximum 100 audits per request, no matter how many matching audits there are in the database. If not set, the page size defaults to 1.000.

**After**

Each Audit Log has a unique identifier called "positionId." When you include the "after" query parameter in your request and set its value to a specific Audit Log's "positionId," the response will contain the set of Audit Logs that immediately follow the provided "positionId."

*Example:* If you want to retrieve the Audit Logs that come after a specific log, use its "positionId" as the value for the "after" parameter in your request.

### Filters <a href="#filters" id="filters"></a>

The rest of the query parameters work as filters that help you specify the desired audits. These filters work the same for both the Retrieve and Count audit logs endpoints.

**Correlation IDs**

`Usable in endpoints: Retrieve Audit Logs, Count Audit Logs, Delete Audit Logs`

When calling the [Rule Solver API](https://docs.decisionrules.io/doc/~/changes/VuchuDyabVa3NSXAKjpZ/api/rule-solver-api), the solver provides the audit log with the so-called correlation ID. This can happen in two distinct ways. If the request to the solver contains the **X-Correlation-Id** header, the value of this header is simply passed to the correlation ID of the audit log. If the request to the solver does not contain such header, the solver generates its own (unique) correlation ID.

Note that, in both cases, the solver returns the correlation ID in the **X-Correlation-Id** header of the response.

The correlation ID can then be used to get the desired audit log related to a particular solver request. This can be done easily by including the `correlation_ids` parameter. It takes an array of correlation IDs separated by a comma, e.g. ., `correlation_ids=af4012bd-d492-92ec-ffa4-31fd2b70b1bc,197d5d5a-f6f7-35de-1afb-dc26237ebfc9`.

**Rules**

`Usable in endpoints: Retrieve Audit Logs, Count Audit Logs, Delete Audit Logs`

If set, the `rules` parameter limits the audits to those produced by the specified rules. The individual rules are identified by ids separated by comma, i.e., `rules=af4012bd-d492-92ec-ffa4-31fd2b70b1bc,197d5d5a-f6f7-35de-1afb-dc26237ebfc9`. Moreover, one may further specify the allowed versions for each of the rules by including square brackets with the comma separated list of versions. For instance, `rules=af4012bd-d492-92ec-ffa4-31fd2b70b1bc[1,2],197d5d5a-f6f7-35de-1afb-dc26237ebfc9` will return audits for rules with id `af4012bd-d492-92ec-ffa4-31fd2b70b1bc` whose version is either 1 or 2 and audits for rules with id `197d5d5a-f6f7-35de-1afb-dc26237ebfc9` of any version.

It is also possible to filter solemnly by rule versions. To do that, use the square bracket expression without specifying rule IDs. For instance, `rules=[1,2]` will return audit logs for rules whose version is 1 or 2, no matter the rule ID.

**Solver Keys**

`Usable in endpoints: Retrieve Audit Logs, Count Audit Logs`

If set, the `solver_keys` parameter limits the audits to those produced by calling rules with the specified Solver API Key. The individual keys are separated by comma.

**Tags**

`Usable in endpoints: Retrieve Audit Logs, Count Audit Logs`

The `tags` query parameter allows you to filter the audits by tags present on the rules. For the audit to pass the filter, its rule needs to be decorated with **all the tags** specified in the query parameter. The tags are separated by comma. For example, a request with `tags=Pricing,Test` returns only audits from rules decorated by both the **Pricing** and the **Test** tag.

**Date**

`Usable in endpoints: Retrieve Audit Logs, Count Audit Logs, Delete Audit Logs`

The `date_gte` and `date_lte` parameters allow to filter audit logs by date (and time). The former serves as a lower bound on the date of the solve, the latter serves as an upper bound. In other words, audits will match this filter only if they are older than `date_gte` and younger than `date_lte`. When specifying one or both of the parameters, you can choose from a number of supported formats, including ISO 8601 and RFC 2822 Date time. For example:

```
2013-02-08
2013-02
2013-02-08 09
2013-02-08 09:30
2013-02-08 09:30:26.123
2013-02-08 09+07:00
2013-02-08 09Z
2013-02-08 09:30:26.123+07:00
...
6 Mar 17 21:22 UT
d6 Mar 2017 21:22:23 GMT
Mon, 06 Mar 2017 21:22:23 +0000
...
```

Note that special characters have to be URL encoded when passed to the query parameter. Therefore, when writing your date, please replace these characters with their respective codes. We list the most useful characters and their codes below.

```
space    %20
:        %3A
+        %2B
```

**Order**

`Usable in endpoints: Retrieve Audit Logs, Count Audit Logs`

The `order` parameter can take two values, `order=asc` or `order=desc`. It specifies the chronological order of the audits returned. For `order=asc`, the audits are sorted chronologically, starting with the oldest. For `order=desc`, they are sorted chronologically, starting with the latest. By default, the audits are returned in ascending order.

**Status Codes**

`Usable in endpoints: Retrieve Audit Logs, Count Audit Logs, Delete Audit Logs`

If set, the `status_codes` parameter limits the audit logs to those produced with the specified status code. The individual codes are separated by comma. For example, to get logs from rule solves that returned OK, use `status_codes=200`. To get audit logs from rule solves that returned some kind of rule error, use `status_codes=400, 401, 404, 406, 426`. Eventually, to get audit logs from rule solves that returned server error, use `status_codes=500`.

**Fields**

`Usable in endpoints: Retrieve Audit Logs`

If set, the `fields` parameter describes which fields of the audit logs to return. For example, if we only need the input data of each audit log we can set `fields=inputData`. Every field of audit logs can be filtered like this. If we want multiple fields to return we can separate the definitions with a comma. `fields=inputData, outputData, ruleAlias` - This example would return audit logs with only the input and output data as well as the ruleAlias.

(To specify the debugLog field, provide the "debugLogId" string)


# Deprecated Endpoints

### Get Audit Logs

This endpoint allows you to fetch audit logs from your rule solver, including metadata of the solver run as well as the input and output data.

{% hint style="info" %}
The rule solver does not generate audit logs by default. If you want some rule to generate audits on each solve, you have to **turn on audit logs** in its Rule Settings. More information can be found on the [Audit Logging](/doc/business-intelligence/audit-logs) Page.
{% endhint %}

{% openapi src="<https://bi.decisionrules.io/api/docs/json>" path="/audit" method="get" %}
<https://bi.decisionrules.io/api/docs/json>
{% endopenapi %}

{% openapi src="<https://bi.decisionrules.io/api/docs/json>" path="/audit" method="delete" %}
<https://bi.decisionrules.io/api/docs/json>
{% endopenapi %}

### Pagination v1

There can be a lot of audit logs in the database, of course. We therefore enforce a maximum page size, e.g. the number of audit logs that can be returned per one request. The maximum page size is 1.000, which means that you can never get more audits than 1.000 per one call.

#### Page Size

You can choose a custom page size smaller than 1.000 by defining the `page_size` query parameter. For example, if you set `page_size=100`, the API will always return maximum 100 audits per request, no matter how many matching audits there are in the database. If not set, the page size defaults to 1.000.

#### Page

To get more audit logs than those that can fit on one page, you can use the `page` parameter. For example, if you set `page_size=100&page=2`, you will get audits 101 - 200, while a request with `page_size=100&page=3` yields audits 201 - 300. etc. If not set, page defaults to 1 so you get the first page.

#### Limit

You can also specify the total limit on the number of audits by setting the `limit` parameter. If set, the API will never fetch any further audits than that with index equal to the limit. For example, a request with `page_size=100&page=2&limit=150` yields only the audits 101 - 150, while `page_size=100&page=3&limit=150` returns just an empty array of audits because you have exceeded your limit. There is no limit by default.

Request example

```http
URL
https://bi.decisionrules.io/audit?limit=1

Headers:
Content-Type: application/json
Authorization: Bearer DOZpz-h6xnOrKGIINlYvkd9hn41pRR3oG6cqH
```

{% hint style="info" %}
You need to copy paste your own Business Intelligence API Key after `Bearer` . If you do not have it yet, generate your Business Intelligence API Key [in the app](https://app.decisiongrid.io/api-keys).
{% endhint %}

#### BI Key

If you cannot send the Business Intelligence API Key inside the authorization header, you may use the `bi_key` query parameter; e.g. `bi_key=DOZpz-h6xnOrKGIINlYvkd9hn41pRR3oG6cqH`. In that case, the request could look as follows.

```http
URL
https://bi.decisionrules.io/audit?limit=1&bi_key=DOZpz-h6xnOrKGIINlYvkd9hn41pRR3oG6cqH

Headers:
Content-Type: application/json
```

If the `bi_key` query parameter is not set, the server will look for the authorization header as described above.

#### Response example

```javascript
{
    "audits": [
        {
            "correlationId": "7bac2e34-53c6-cbb0-d898-87f46ad50f77",
            "guid": "b88ba671-eae9-05e8-a547-f54d0cdedba7",
            "baseId": "d58e2518-57f6-a315-2458-b931b45cb543",
            "version": 1,
            "type": "decision-table",
            "status": "published",
            "outputSchema": {
                "finalPrice": {},
                "message": {}
            },
            "createdIn": "2022-06-28T13:22:11.875Z",
            "inputSchema": {
                "benefitCode": {},
                "promoCode": {},
                "price": {}
            },
            "tags": [
                "Benefit"
            ],
            "name": "Benefit Program",
            "lastUpdate": "2022-06-28T13:22:11.875Z",
            "solverKey": "QyjvIdGhdDgUP6_Lebo2DOyYaoSIA0axZlVcRrxbJzHazTOMn03GA5kiuIzgIw5z",
            "inputData": {
                "benefitCode": "SUMMER",
                "promoCode": {},
                "price": {}
            },
            "outputData": [
                {
                    "finalPrice": {},
                    "message": "discount 30%"
                },
                {
                    "finalPrice": {},
                    "message": "no discount"
                }
            ],
            "executionTime": 1,
            "statusCode": 200,
            "errorMessage": null,
            "debugData": null,
            "timestamp": "2022-06-28T13:22:28.579Z"
        }
    ]
}
```


# Datacenters & Locations

As DecisionRules is offered both in a Global Cloud and a Regional Cloud versions, this article is split to explain both

Choose your version of DecisionRules for more information:

{% content-ref url="/pages/V6PQO4Y0DERCugPz6Jfi" %}
[Global Cloud](/doc/api/geo-location/geo-location)
{% endcontent-ref %}

{% content-ref url="/pages/ihANslRqCZQMDcxxIljp" %}
[Regional Cloud](/doc/api/geo-location/regional-cloud)
{% endcontent-ref %}


# Global Cloud

DecisionRules automatically scales performance within a single location. In the unlikely event of service interruption in the whole location, our cloud immediately redirects requests to the nearest location available. This makes the service highly available and resilient.

### Can I reach certain location?

Decision Rules automatically selects a specific data center according to the client location or VPN location, when used. Therefore you do not need to call a specific location.

<table><thead><tr><th width="299.3333333333333">Datacenter</th><th>Status</th><th>Location Shorcut</th></tr></thead><tbody><tr><td><img src="/files/d9Fsu72PHcgD3y2j7d34" alt=""> Central Europe (Frankfurt)</td><td><mark style="color:green;">✓</mark> Online</td><td>eu-central-1</td></tr><tr><td><img src="/files/uGOIYyEQeshVDLT4ispH" alt=""> US East (N. Virginia)</td><td><mark style="color:green;">✓</mark> Online</td><td>us-east-1</td></tr><tr><td><img src="/files/uGOIYyEQeshVDLT4ispH" alt=""> US West (Oregon)</td><td><mark style="color:green;">✓</mark> Online</td><td>us-west-2</td></tr><tr><td><img src="/files/ekSBf0YE02orLa6nAYGe" alt=""> Brazil (São Paulo)</td><td><mark style="color:green;">✓</mark> Online</td><td>sa-east-1</td></tr><tr><td><img src="/files/8C6sKQwoCcsx624yOqqs" alt=""> Australia (Sydney)</td><td><mark style="color:green;">✓</mark> Online</td><td>ap-southeast-2</td></tr><tr><td><img src="/files/L3ZTRelfSdxWYwIrtJo7" alt=""> South Africa (Cape Town)</td><td><mark style="color:green;">✓</mark> Online</td><td>af-south-1</td></tr></tbody></table>

{% hint style="info" %}
For Rule Solver set up, check our guide [**here**](/doc/api/rule-solver-api).
{% endhint %}


# Regional Cloud

## Choice of location

Currently we offer a choice of three Region Cloud locales with each having 2 separate datacenters for ensured accessibility and security.

<table><thead><tr><th width="264">Location</th><th>Application URL</th><th data-hidden></th></tr></thead><tbody><tr><td><img src="/files/uGOIYyEQeshVDLT4ispH" alt=""> USA</td><td>us.app.decisionrules.io</td><td><mark style="color:green;">✓</mark> Online</td></tr><tr><td><img src="/files/pykvGQwOYdT3kLGUPxNK" alt="" data-size="line"> European Union</td><td>eu.app.decisionrules.io</td><td><mark style="color:green;">✓</mark> Online</td></tr><tr><td><img src="/files/8C6sKQwoCcsx624yOqqs" alt=""> Australia</td><td>au.app.decisionrules.io</td><td><mark style="color:green;">✓</mark> Online</td></tr></tbody></table>

{% hint style="info" %}
Why choose Regional Cloud? Read more [here](/doc/other-deployment-options/regional-cloud#why-decisionrules-on-a-regional-cloud).
{% endhint %}

{% hint style="warning" %}
Region-locked accounts cannot access rules of Global Cloud accounts or accounts locked to different regions.
{% endhint %}

{% hint style="warning" %}
Accessing region-locked content from outside of the region may result in request processing delays.&#x20;

E.g. attempting to use the Rule Solver API on a EU Cloud account's rule from the USA would result in longer response times. &#x20;
{% endhint %}

## Datacenters

#### USA

<table><thead><tr><th width="299.3333333333333">Datacenter</th><th>Status</th><th>Location Shorcut</th></tr></thead><tbody><tr><td><img src="/files/uGOIYyEQeshVDLT4ispH" alt=""> US East (N. Virginia)</td><td><mark style="color:green;">✓</mark> Online</td><td>us-east-1</td></tr><tr><td><img src="/files/uGOIYyEQeshVDLT4ispH" alt=""> US West (Oregon)</td><td><mark style="color:green;">✓</mark> Online</td><td>us-west-2</td></tr></tbody></table>

#### European Union

<table><thead><tr><th width="299.3333333333333">Datacenter</th><th>Status</th><th>Location Shorcut</th></tr></thead><tbody><tr><td><img src="/files/d9Fsu72PHcgD3y2j7d34" alt=""> Central Europe (Frankfurt)</td><td><mark style="color:green;">✓</mark> Online</td><td>eu-central-1</td></tr><tr><td><img src="/files/UZUIWVVbAvkC67FsaHJU" alt="" data-size="line"> Western Europe (Paris)</td><td><mark style="color:green;">✓</mark> Online</td><td>eu-west-3</td></tr></tbody></table>

#### Australia

<table><thead><tr><th width="299.3333333333333">Datacenter</th><th>Status</th><th>Location Shorcut</th></tr></thead><tbody><tr><td><img src="/files/8C6sKQwoCcsx624yOqqs" alt=""> Australia (Sydney)</td><td><mark style="color:green;">✓</mark> Online</td><td>ap-southeast-2</td></tr><tr><td><img src="/files/8C6sKQwoCcsx624yOqqs" alt=""> Australia (Sydney)</td><td><mark style="color:green;">✓</mark> Online</td><td>ap-southeast-2</td></tr></tbody></table>

\*Both datacenters for Australia are located in Sydney


# Apache Kafka Solver API

![](/files/sMiNE8SdW50GvyfbN0Fr)

DecisionRules.io supports asynchronous calls to the Rule Solver. This option should be used if your infrastructure is based on asynchronous message processing.

## Setting up Apache Kafka Solver API

{% hint style="success" %}
Kafka Solver API is now available both in the cloud and on premise.
{% endhint %}

### Before you start using the Kafka Solver API

{% hint style="info" %}
In the cloud, it is necessary to enable Kafka Solver for a specific customer manually. If you are interested, please contact us at <sales@decisionrules.io>
{% endhint %}

1. Request access rights for your client application to the DecisionRules Kafka Cluster at <sales@decisionrules.io>
2. Configure the connection of your client application to the Kafka cluster.
3. Register on the assigned Kafka topic, where you will receive the results.
4. Sending input data to the input Kafka Topic, from which DecisionRules takes it.

### Information for connecting to Kafka Cluster

| Key                | Value                                           |
| ------------------ | ----------------------------------------------- |
| **broker**         | pkc-lq8v7.eu-central-1.aws.confluent.cloud:9092 |
| **ssl**            | true                                            |
| **sasl.mechanism** | plain                                           |
| **sasl.username**  | contact us on <sales@decisionrules.io>          |
| **sasl.password**  | contact us on <sales@decisionrules.io>          |

### Example Connection Config

Java Configuration

{% code title="config.properties" %}

```properties
# Required connection configs for Kafka producer, consumer, and admin
bootstrap.servers=pkc-lq8v7.eu-central-1.aws.confluent.cloud:9092
security.protocol=SASL_SSL
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule   required username='{{ CLUSTER_API_KEY }}'   password='{{ CLUSTER_API_SECRET }}';
sasl.mechanism=PLAIN
# Required for correctness in Apache Kafka clients prior to 2.6
client.dns.lookup=use_all_dns_ips

# Best practice for Kafka producer to prevent data loss
acks=all
```

{% endcode %}

#### Python Configuration

{% code title="config.py" %}

```python
# Kafka
bootstrap.servers=pkc-lq8v7.eu-central-1.aws.confluent.cloud:9092
security.protocol=SASL_SSL
sasl.mechanisms=PLAIN
sasl.username={{ CLUSTER_API_KEY }}
sasl.password={{ CLUSTER_API_SECRET }}
```

{% endcode %}

### How to communicate from a client application using Kafka Messsages

DecisionRules.io always uses two Kafka topics to communicate with the client application.

* **Response Topic (read-only)**
  * Topic on which your client application listens
  * You will receive the evaluated data in this topic
* **Request Topic (write)**
  * Kafka Topic into which you write data for evaluating DecisionRules
  * DecisionRules is listening on this topic

| Name           | Example Topic Name                  | Permissions |
| -------------- | ----------------------------------- | ----------- |
| Request Topic  | {company}-{random\_number}-request  | WRITE       |
| Response Topic | {company}-{random\_number}-response | READ        |

### Producing data to Request Topic

#### Message Headers

| Header                 | Description                                                                                                                         |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| api-key                | <p>(mandatory)</p><p>Solver API Key. Generate your api key in the <a href="https://app.decisionrules.io/api-keys">dashboard</a></p> |
| rule-id OR ruleflow-id | <p>(mandatory)</p><p>Rule or RuleFlow ID</p>                                                                                        |
| x-correlation-id       | <p>(optional)</p><p>User-generated ID to help you correlate input and output data.</p>                                              |
| version                | <p>(optional) </p><p>Version of the rule you want to solve.</p>                                                                     |

#### Message Data

| Message Attribute | Description                                                               |
| ----------------- | ------------------------------------------------------------------------- |
| Key               | \<empty>                                                                  |
| Value             | JSON object filled according to the data model called by Rule or RuleFlow |

#### Example Request Data

{% code title="Message Value Example (JSON Object)" %}

```json
{
  "client": {
    "age": 12
  }
}
```

{% endcode %}

#### Message Data Schema

{% code title="Request Schema" %}

```json
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {},
  "required": []
}
```

{% endcode %}

### Consuming Data from Response Topic

| Attribute     | Type   | Description                                                                                                                                                                                                                                                                  |
| ------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data          | Array  | Field filled with data according to the rule evaluation. One element in the array means one result. For example, if multiple rows are matched when evaluating a decision table, they are returned as array items                                                             |
| errors        | Array  | <p>If an error occurs in the evaluation for any reason, each error is added to the error field.</p><p>If there are no errors in the evaluation, the "errors" attribute is not returned.</p><p>The contents of the "data" field will be empty when any error is returned.</p> |
| correlationId | String | <p>(optional) If the "x-correlation-id" header was filled in the input message, this value is available in the output message.</p><p>If "x-correlation-id" is not filled in the input, the attribute is not present in the output.</p>                                       |

#### Example Response Data

{% code title="Single data" %}

```json
{
  "data": [
    {
      "totalProducts": 2,
      "amountPerProduct": 500,
      "segment": "mass-market",
      "profitability": 1.2
    }
  ],
  "correlationId": "ef429e33-f2c4-41ad-b9f3-cad12ea3b95e"
}
```

{% endcode %}

{% code title="Multiple data" %}

```json
{
  "data": [
    {
      "totalProducts": 2,
      "amountPerProduct": 500,
      "segment": "mass-market",
      "profitability": 1.2
    },
    {
      "totalProducts": 1,
      "amountPerProduct": 300,
      "segment": "mass-market",
      "profitability": 1.53
    }
  ],
  "correlationId": "12429e33-f2c4-41ad-b9f3-cad12ea3b95e"
}
```

{% endcode %}

{% code title="Error response" %}

```json
{
  "errors": [
    {
      "code": 500,
      "message": "This Rule Flow belongs to another user OR Rule Flow not found"
    }
  ],
  "data": [],
  "correlationId": "ef429e33-f2c4-41ad-b9f3-cad12ea3b95e"
}
```

{% endcode %}

#### Message Data Schema

```json
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": [
        {
          "type": "object"
        }
      ]
    },
    "correlationId": {
      "type": "string"
    },
    "errors": {
      "type": "array",
      "items": [
        {
          "type": "object",
          "properties": {
            "code": {
              "type": "integer"
            },
            "message": {
              "type": "string"
            }
          },
          "required": [
            "code",
            "message"
          ]
        }
      ]
    }
  },
  "required": []
}
```


# Endpoint Settings

This guide shows you how to change your endpoints.

{% hint style="danger" %}
This section is for users who created an account before 06. April 2021
{% endhint %}

{% hint style="info" %}
The reason to change your endpoints is due to our name change to **DecisionRules.io**
{% endhint %}

{% hint style="warning" %}
Everything remains the same, just the name is different.

That means all the settings you already have are going to work, but we strongly recommend you to do the changes from below.
{% endhint %}

## Endpoints in API

The only thing you should do is to change the endpoint in your API.

The URL is in a format **<https://api.decisionrules.io/rule/solve/:ruleId/:version>** where you should replace ~~decisiondrig.io~~ with **decisionrules.io**

{% hint style="info" %}
If you're using the Regional Cloud version of DecisionRules, prepend the URL with your region shortcut.

Read more about Regional Cloud API calls [here](/doc/other-deployment-options/regional-cloud/region-specific-api-urls).
{% endhint %}

```http
URL
https://api.decisionrules.io/rule/solve/:ruleId/:version

Headers:
Content-Type: application/json
Authorization: Bearer DOZpz-h6xnOrKGIINlYvkd9hn41pRR3oG6cqH
```

## Angular library

If you are using our Angular library to connect [Decisionrules.io](https://decisionrules.io) from your web application \*\*\*\* [**npm package**](https://www.npmjs.com/package/@decisionrules/decisionrules) \*\*\*\* was changed as well.

{% hint style="danger" %}
The old[ **npm package**](https://www.npmjs.com/package/@decisionrules/decisionrules-js) \*\*\*\* will be still available, but no longer supported.

We recommend you download the new version from \*\*\*\* [**npm**](https://www.npmjs.com/package/@decisionrules/decisionrules) \*\*\*\* which will be supported.
{% endhint %}

{% hint style="info" %}
Please make sure your Angular settings are correct to have your application always up to date.
{% endhint %}


# Archive


# Rule Flow Solver API (DEPRECATED)

{% hint style="warning" %}
In version 1.16.0 and newer you can solve your ruleflow with **Rule Solver API** endpoint.

Rule flow Solver API endpoint is now deprecated.
{% endhint %}

### Solve RuleFlow

Solves desired RuleFlow stored in decisionRules.

## RuleFlow Solver

<mark style="color:green;">`POST`</mark> `https://api.decisionrules.io/composition/solve/:ruleFlowId/:version`

#### Path Parameters

| Name       | Type    | Description                                                                                                 |
| ---------- | ------- | ----------------------------------------------------------------------------------------------------------- |
| ruleFlowId | string  | Unique RuleFlow ID that is the same to all versions. You can also use the rule alias.                       |
| version    | integer | RuleFlow version. If the parameter is not filled in, the last published version will be used automatically. |

#### Headers

| Name          | Type   | Description                                                                                                                          |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| Authorization | string | Bearer                                                                                                                               |
| Content-Type  | string | application/json                                                                                                                     |
| X-Strategy    | string | STANDARD or ARRAY or FIRST\_MATCH                                                                                                    |
| X-Audit       | string | Decides whether an audit of the solve should be created and saved. In case you want the audit to be created and saved, input "true". |
| X-Audit-Ttl   | string | A number that dictates after how many days the audit will be deleted.                                                                |

#### Request Body

| Name | Type   | Description                                    |
| ---- | ------ | ---------------------------------------------- |
| data | object | JSON object that describes the input json data |

{% tabs %}
{% tab title="200 " %}

```
[
  {
    "loan": 30000,
    "tax": 1.15,
    "message": "eligible for the loan"
  }
]
```

{% endtab %}

{% tab title="400 " %}

```
{
    "error": {
        "message": "Unknown ruleFlow or version"
    }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
    "error": {
        "message": "Authentication token missing"
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
If you're using the **Regional Cloud** version of DecisionRules, read more about API calls [here](/doc/other-deployment-options/regional-cloud/region-specific-api-urls#making-api-calls-on-region-cloud-accounts).
{% endhint %}

{% hint style="info" %}
See  [**execution strategies**](/doc/rules/common-rule-features/execution-strategy) to change solver output format.
{% endhint %}

#### Request example

```http
URL
https://api.decisionrules.io/composition/solve/:ruleFlowId/:version

Headers:
Content-Type: application/json
Authorization: Bearer DOZpz-h6xnOrKGIINlYvkd9hn41pRR3oG6cqH
```

{% hint style="info" %}
Note that you can use **rule alias** instead of rule ID to identify the rule flow. In that case, make sure that the rule alias is unique within the space, otherwise the request will fail.
{% endhint %}

{% hint style="info" %}
This API Key. Generate your own [here](https://app.decisiongrid.io/api-keys)
{% endhint %}

```javascript
{
    "data": {
        // INPUT OBJECT
    }
}
```

#### Example request

```javascript
{
    "data": {
        "package": {
            "age": 30,
            "salary": 4000,
            "loanType": "household",
            "loan": 30000
        }
    }
}
```


# Console Logs API (RETIRED)

The Console Logs API is a secure REST API that provides console logs.

{% hint style="warning" %}
Console Logs API is retired from version 1.25.1. To save and fetch debug logs, please use Audit Logs with our Business Intelligence API.
{% endhint %}

## Get console logs for a specific solve.

> Retrieves console logs for a specific rule solve identified by its \`correlationId\`.\
> The \`correlationId\` can be obtained from the \`X-Correlation-Id\` response header of the Rule Solver API.\
> Logs are only generated when the solve is run in debug mode (e.g., using the \`X-Debug: true\` header).<br>

```json
{"openapi":"3.0.0","info":{"title":"Console Logs API","version":"1.0.0"},"servers":[{"url":"https://api.decisionrules.io/consoleLogs"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"ApiKey"}},"schemas":{"LogDetailResponse":{"type":"object","properties":{"_id":{"type":"string"},"apiKey":{"$ref":"#/components/schemas/ApiKey"},"id":{"type":"string"},"time":{"type":"string","format":"date-time"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/ConsoleLogEntry"}},"baseId":{"type":"string"},"input":{"$ref":"#/components/schemas/Input"},"output":{"type":"array","items":{"$ref":"#/components/schemas/OutputItem"}},"correlationId":{"type":"string","format":"uuid"}}},"ApiKey":{"type":"object","properties":{"created":{"type":"string","format":"date-time"},"type":{"type":"string"},"key":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}}},"ConsoleLogEntry":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"The timestamp of the log entry."},"level":{"type":"string","description":"The severity level of the log entry (e.g., INFO, WARN, ERROR)."},"message":{"type":"string","description":"The log message."}}},"Input":{"type":"object","additionalProperties":true},"OutputItem":{"type":"object","properties":{"prices":{"type":"object","properties":{"finalPrice":{"type":"number"},"crudePrice":{"type":"number"}}},"message":{"type":"string"}}}}},"paths":{"/{correlationId}":{"get":{"summary":"Get console logs for a specific solve.","description":"Retrieves console logs for a specific rule solve identified by its `correlationId`.\nThe `correlationId` can be obtained from the `X-Correlation-Id` response header of the Rule Solver API.\nLogs are only generated when the solve is run in debug mode (e.g., using the `X-Debug: true` header).\n","operationId":"getConsoleLogs","parameters":[{"name":"correlationId","in":"path","required":true,"description":"The unique identifier for a rule solve.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Console logs retrieved successfully.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LogDetailResponse"}}}}},"401":{"description":"Unauthorized. Invalid or missing API key."},"404":{"description":"Not Found. No logs found for the given `correlationId`, or the logs have expired."}}}}}}
```

## The ConsoleLogEntry object

```json
{"openapi":"3.0.0","info":{"title":"Console Logs API","version":"1.0.0"},"components":{"schemas":{"ConsoleLogEntry":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"The timestamp of the log entry."},"level":{"type":"string","description":"The severity level of the log entry (e.g., INFO, WARN, ERROR)."},"message":{"type":"string","description":"The log message."}}}}}}
```

## The LogsResponse object

```json
{"openapi":"3.0.0","info":{"title":"Console Logs API","version":"1.0.0"},"components":{"schemas":{"LogsResponse":{"type":"object","properties":{"correlationId":{"type":"string","format":"uuid","description":"The correlation ID for the solve."},"logs":{"type":"array","items":{"$ref":"#/components/schemas/ConsoleLogEntry"},"description":"An array of console log entries."}}},"ConsoleLogEntry":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"The timestamp of the log entry."},"level":{"type":"string","description":"The severity level of the log entry (e.g., INFO, WARN, ERROR)."},"message":{"type":"string","description":"The log message."}}}}}}
```


# About AI Assistant

The DecisionRules AI Assistant is a versatile, LLM-based tool designed to enhance the way business rules are created, tested, optimized, and understood within the DecisionRules platform. It provides contextual assistance directly in the application, combining general language model capabilities with DecisionRules-specific knowledge to support users throughout the rule lifecycle.

The AI Assistant offers a set of specialized agents. These agents answer platform- and rule-related questions, search the DecisionRules Documentation and Academy, highlight relevant UI elements, generate Decision Tables, prepare test input data, write and debug function expressions, and produce human-readable summaries of Decision Tables. Each agent is available in specific parts of the application and works with awareness of the current user context, such as the active page or selected Decision Table.

## Suggestions

Upon opening the AI Assistant panel, you will find a set of predefined **suggestions**. Selecting one of these options will automatically populate the input with an example prompt. The assistant will then generate a corresponding response. This feature provides a quick and guided way to understand the assistant’s behavior and output format.

## Agents

Apart from asking questions and getting answers, you can also use several predefined agents. Each agent is built for a specific task. You do not need to select one manually in most cases. The assistant will try to choose the right agent from context. If you have a specific task in mind, you can select the agent directly in the dropdown inside the chat input. This helps the assistant return more targeted output.

See more details about the available agents on the [AI Assistant Agents](/doc/ai-assistant/ai-assistant-features) page.

{% hint style="success" %}
Our team is continually extending and improving the AI Assistant. If you are missing a useful feature or agent, please contact our Sales team and we will be happy to discuss it.
{% endhint %}

## AI Assistant Chat History

AI Assistant now saves your conversations automatically. When you start a chat, the entire session is stored and can be accessed later. You no longer lose your progress after closing the panel.

#### Where to find it

Open the AI Assistant panel and click **History** in the header.

<figure><img src="/files/OcGnSEOdx8drijwxeb8s" alt=""><figcaption></figcaption></figure>

#### What you can do

You can:

* Open any previous session and continue the conversation.
* Search through loaded sessions by keywords from your prompts, model responses, titles, or rule names.
* Pin important sessions to keep them at the top.
* Delete sessions you no longer need.

Sessions are ordered from most recent to oldest and display a title, last message preview, and last updated time.

#### Smart navigation

When switching spaces, the history refreshes to show only relevant sessions.

### Context-Aware Assistance

The AI Assistant can work not only with the current prompt, but also with additional context provided by the user or available in the current space.

This includes:

* uploaded files attached directly in chat
* space-level knowledge and shared context related to the current working environment

These capabilities help the assistant provide more relevant, targeted, and practical answers without requiring the user to repeat all background information in every request.

## Accessing AI Assistant

The AI Assistant is currently available on **Lite Plan** or higher, and it is also included in the **Free Trial** so new users can try it out as part of our enhanced onboarding experience. It is placed in the right panel. If not already open, you can open up the assistant panel by clicking the **AI Assistant** button in the top right corner of the page.


# AI Assistant Features

This page lists the features available in the AI Assistant. Selected features are described in detail on their dedicated sub-pages.

## AI Features Overview

This section lists all features available within the AI Assistant and explains their purpose, scope, and availability inside **DecisionRules**.

#### General Assistant

**Availability:** All pages with the AI Assistant panel

The General Assistant handles general conversation and broad assistance inside the platform. It is used when the request does not clearly indicate a more specialized task.

It can help users with general product orientation, basic guidance, and simple follow-up questions. It can also direct users toward other supported AI capabilities such as rule creation, function generation, documentation search, Academy search, and UI navigation.

#### Documentation Search

**Availability:** All pages with the AI Assistant panel

Documentation Search answers questions using the DecisionRules documentation. It searches the full DecisionRules Docs and returns concise answers based only on documented content.

It is useful when users want reliable product explanations, configuration guidance, or links to the relevant documentation pages.

#### Academy Search

**Availability:** All pages with the AI Assistant panel

Academy Search helps users find relevant learning materials in DecisionRules Academy. It searches Academy courses, tutorials, and other educational content and recommends the most relevant results.

It is useful when users want to learn a feature step by step, find training materials, or discover content suited to their current level or topic.

If the request is too broad, the Assistant may ask a clarifying question to narrow the search.

#### Navigation Helper

**Availability:** All pages with the AI Assistant panel

Navigation Helper can be used to find features and controls in the DecisionRules application.

It can guide users to the next relevant page, panel, or control based on the currently visible UI. If the requested element is visible, it can highlight it directly in the interface. If the element is hidden or located on another page, it explains what to open or where to navigate first.

For some UI-related questions, it can also add short documentation-based clarification about what a feature does or how to choose between nearby options.

#### Decision Table Architect

**Availability:** Rules List

The Decision Table Architect generates a new Decision Table from natural-language instructions. It asks clarifying questions when required and then creates a structured table that matches the described logic.

The generated result is validated against the required Decision Table structure before it is offered in the UI. This helps ensure the created table is structurally correct and ready for further editing.

It is available directly on the Rules List page and supports rapid rule prototyping without manual table setup.

Read more on the dedicated [Create Decision Table](/doc/ai-assistant/ai-assistant-features/create-decision-table) page.

#### Scripting Rule Architect

**Availability:** Rules List, Scripting Rule Detail

The Scripting Rule Architect works with DecisionRules Scripting Rules.

On the Rules List page, it can generate a new scripting rule from natural-language instructions. On the Scripting Rule Detail page, it can also prepare updates to an existing scripting rule based on the user’s request.

It is useful for imperative or code-based logic that is better expressed as a scripting rule than as a Decision Table.

If the requested scripting logic depends on existing rules, the Assistant can take folder and rule structure into account before generating references.

#### Generate Functions

**Availability:** Decision Table Detail

This feature allows to generate valid function expressions for selected cells in a Decision Table. It understands the cell context, including available variables, and uses DecisionRules function definitions correctly.

In addition to generating new expressions, it can:

* Explain existing function expressions and their results
* Debug and adjust existing functions
* Combine multiple functions to achieve the desired behavior

{% hint style="info" %}
Click a cell to select it. You can see the selected cell at the bottom of the AI Assistant panel, and you can cancel the selection by clicking the cross.
{% endhint %}

This feature therefore helps users implement complex logic while maintaining correctness and readability.

#### Generate Test Data

**Availability:** Decision Table Detail, Scripting Rule Detail

This feature allows to generate input data for Decision Table evaluation. It supports both single and bulk generation and takes into account the table definition and the selected evaluation strategy.

It can generate:

* Random input data examples
* Input data satisfying specific conditions
* Input data matching selected rows of the Decision Table
* Input data resulting in specific outputs
* Input data testing edge cases, overlaps, or boundary conditions
* Input data not matching any row (uncovered cases)

It can also adjust or refine existing input data to meet specific testing requirements.

The generated inputs follow the available input schema fields so they can be used directly for testing.

#### Generate Rule Summary

**Availability:** Decision Table Detail

This feature allows to generate a human-readable summary of a Decision Table. For simple tables, the summary may describe the complete logic. For larger or more complex tables, it focuses on the main structure, conditions, and outcomes.

The summary also includes a compact overview of the rule’s input and output structure to make the rule easier to review and communicate.

This feature therefore improves understanding, reviews, and communication of decision logic without requiring readers to analyze the full table structure.

#### Templates Helper

**Availability:** Rules List

The Template Helper recommends DecisionRules templates based on the user’s described use case.

It rewrites the user’s request into a focused template-search query and returns the most relevant matching templates with short descriptions. This helps users start from an existing template instead of building a rule from scratch.

It is useful when users know the business problem they want to solve but are not sure whether a suitable template already exists.

### File Import

**Availability:** All pages with the AI Assistant panel where file attachments are supported by the selected model

File Import allows users to attach supported files directly to the AI Assistant chat. The assistant can then use both the written prompt and the uploaded content in a single request.

This is useful when users want to work with policies, specifications, spreadsheets, text documents, or structured configuration files.

Supported file types include `PDF`, `TXT`, `MD`, `CSV`, `XLSX`, `DOCX`, `XML`, and selected IBM ODM-related file formats.

Each attached file must not exceed `10 MB`. Attachment availability depends on the selected AI model.

### Space Knowledge

**Availability:** Pages where the AI Assistant can use current space context

Space Knowledge helps the AI Assistant answer with awareness of the current working space and its shared context. This allows the assistant to provide more relevant guidance without requiring the user to repeat the same background information in every prompt.

It is useful for collaborative spaces, shared rule environments, and cases where the assistant should work with persistent contextual knowledge rather than only the current chat input.


# Create Decision Table

Create Business Rules with AI

When you are on the rules list, you can access the Decision Table Architect within the AI Assistant. It lets you generate a custom Decision Table from written, human-readable instructions.

Instead of manually building a rule row by row, you can simply describe your business case, and the assistant will generate a ready-to-use decision table for you. This feature aims to simplify rule creation, especially for users who are new to the platform or working with repetitive decision logic.

<figure><img src="/files/T7c31wAAKzj0Eeb6Rtdn" alt=""><figcaption></figcaption></figure>

## How the Prompt Works

Inside the prompt window, enter your business case and provide some basic information:

* **Your case description** – be as specific and clear as possible, include all important conditions and expected outcomes
* **Input Properties** – the attributes the rule will evaluate (e.g. `age`, `amount`, `status`)
* **Output Properties** – the attributes of the output model (e.g. `approvalStatus`, `interestRate`)

Once this information is provided, the assistant begins building the rule. When the rule is ready, you will see a message confirming it is complete. Click the confirmation button to finalize the creation – then you will be redirected directly to the new rule for review or editing.

## Prompt Examples

{% hint style="info" %}
AI Assistant is limited to generating decision tables with a maximum of **10 rows**. If your described case results in more scenarios, consider simplifying the logic.
{% endhint %}

1. Simple Loan Application Evaluation:

> *I want to evaluate a loan application based on the applicant's age and credit score.*\
> \&#xNAN;*If the age is under 21, the application should be declined.*\
> \&#xNAN;*If the credit score is below 600, also decline.*\
> \&#xNAN;*Otherwise, approve.*\
> \&#xNAN;*Input model properties: `age`, `creditScore`*\
> \&#xNAN;*Output model properties: `approvalStatus`*

2. Fraud Risk Evaluation:

> *I want to assess the fraud risk of a transaction based on payment method, transaction amount, country, and customer verification status.*
>
> * *If payment is "Crypto", amount > 5000, and not verified → High risk*
> * *If payment is "Card", country is in "High-Risk List", and not verified → High risk*
> * *If payment is "BankTransfer", amount > 10000 → Medium risk*
> * *If verified and amount < 1000 → Low risk*
> * *If payment is "Card" or "BankTransfer", country is "Trusted", verified → Low risk*
> * *If payment is "Crypto" and amount < 1000 → Medium risk*
> * *If not verified and country is not known → High risk*
> * *If payment is "Card", amount > 2000, and not verified → Medium risk*
> * *Else → Low risk*
>
> *Input model properties: `paymentMethod`, `amount`, `country`, `isVerified`*\
> \&#xNAN;*Output model properties: `riskLevel`*

If the AI Assistant cannot generate the Decision Table based on your prompt, try to simplify it or re-formulate it. You may also try to change the mode (from Fast to Precise or vice versa).


# Create Scripting Rule

Create Scripting Rules with AI

When you are on the rules list, you can access the Scripting Rule Architect within the AI Assistant. It lets you generate a custom scripting rule from written, human-readable instructions.

Instead of writing the whole script manually, you can describe your business case, expected behavior, input properties, and output properties, and the assistant will prepare a ready-to-use scripting rule for you. This feature is useful when your logic is better expressed as code than as a Decision Table.

<figure><img src="/files/FTKnQC253Akh2JWGDWJ7" alt=""><figcaption></figcaption></figure>

### How the Prompt Works

Inside the prompt window, enter your business case and provide some basic information:

* **Your case description** – describe what the rule should do, including important conditions, calculations, validations, or branching logic
* **Input Properties** – the attributes the rule will receive and evaluate (e.g. `customerAge`, `amount`, `country`, `isVerified`)
* **Output Properties** – the attributes the rule should return (e.g. `approvalStatus`, `riskLevel`, `discount`, `message`)

You can also describe how the result should be computed, what should happen in edge cases, and whether the output should contain one or more calculated values.

Once this information is provided, the assistant begins building the scripting rule. When the rule is ready, you will see a message confirming it is complete. Click the confirmation button to finalize the creation and continue with review or editing.

### Prompt Examples

{% hint style="info" %}
Use this agent when your logic is procedural, calculation-heavy, or difficult to express clearly in a Decision Table.
{% endhint %}

1. Simple Shipping Price Calculation:

> *I want to calculate shipping price based on package weight and destination zone.*\
> \&#xNAN;*If weight is below 1 kg, shipping is 5.*\
> \&#xNAN;*If weight is between 1 and 5 kg, shipping is 10.*\
> \&#xNAN;*If weight is above 5 kg, shipping is 20.*\
> \&#xNAN;*If destination zone is "express", add 15.*\
> \&#xNAN;*Input model properties: `weight`, `zone`*\
> \&#xNAN;*Output model properties: `shippingPrice`*

2. Customer Discount Evaluation:

> *I want to calculate a discount for a customer based on loyalty status, total order amount, and whether a promo code is applied.*\
> \&#xNAN;*If the customer is VIP and order amount is above 500, give 20% discount.*\
> \&#xNAN;*If the customer is VIP and order amount is above 200, give 10% discount.*\
> \&#xNAN;*If a promo code is applied, increase the final discount by 5%.*\
> \&#xNAN;*The total discount must never be more than 25%.*\
> \&#xNAN;*Input model properties: `loyaltyStatus`, `orderAmount`, `hasPromoCode`*\
> \&#xNAN;*Output model properties: `discountPercent`*

3. Fraud Review Decision:

> *I want to evaluate whether a transaction should be approved, flagged for review, or rejected.*\
> \&#xNAN;*If the transaction amount is above 10000 and the customer is not verified, reject it.*\
> \&#xNAN;*If the amount is above 5000 and the country is in a risky region, flag it for manual review.*\
> \&#xNAN;*Otherwise approve it.*\
> \&#xNAN;*Input model properties: `amount`, `isVerified`, `country`*\
> \&#xNAN;*Output model properties: `decision`*

If the AI Assistant cannot generate the scripting rule based on your prompt, try to simplify it or re-formulate it.&#x20;


# Assistant Setup

This section covers how to configure and manage AI models used by the AI Assistant in DecisionRules.

DecisionRules AI Assistant supports different AI integration options depending on your deployment type.

## Cloud Version

In the **Cloud version**, AI integration is fully managed by DecisionRules.

* No additional setup is required
* The AI Assistant is available out of the box
* Configuration is maintained by our team for optimal performance and reliability

### About the Model and Limits

The assistant is powered by **Gemini for Business**. We are currently using the model `gemini-3-flash-preview`. The exact versions may change in the future.

{% hint style="success" %}
Your privacy is fully respected. **No user data is used to train any AI model**, and nothing is shared outside Decision Rules application. See more information about data governance [here](https://cloud.google.com/vertex-ai/generative-ai/docs/data-governance) and [here](https://cloud.google.com/gemini/docs/discover/data-governance).
{% endhint %}

Current usage limits for the assistant are defined by your **subscription plan**. If you are on a free trial, paid Lite or higher tier, you will have access to a limited number of AI generations each month.

## Docker (On-Premise) Version

{% hint style="info" %}
Make sure that you have set **`AI_ENGINE_URL`**  environment variable. More details: [Environment Variables](/doc/other-deployment-options/docker-and-on-premise/containers-environmental-variables#server-required)
{% endhint %}

In the **Docker version**, you can connect your own AI provider with the required credentials.

Configuration can be defined on the following levels:

* **Organization level**
* **Environment level**
* **AI Engine application level**

### Configuration Resolution

These configuration levels are evaluated in the following order:

1. **Organization level**
2. **Environment level**
3. **AI Engine application level**

This works as a fallback mechanism:

* When an **Organization-level** configuration exists, it is used
* If not, DecisionRules checks the **Environment level**
* If that is also not configured, DecisionRules uses the **AI Engine application level**

### Next Steps

For more details, see the dedicated pages for each configuration level:

* **Organization Level:** [Define AI Provider](/doc/ai-assistant/assistant-setup/define-ai-provider)
* **Environment Level:** [AI Assistant Provider](/doc/environment/ai-assistant-provider)
* **AI Engine Application Level:** [DecisionRules AI Engine](/doc/decisionrules-applications/decisionrules-ai-engine)


# Define AI Provider

## AI Provider Settings

AI Provider Settings allow you to configure which **model**, **provider**, and **credentials** the DecisionRules AI Assistant will use.

In the configuration form, the user first selects a **model**, then a compatible **provider**, and finally fills in the required provider-specific credentials such as an **API key**, **endpoint**, **credentials JSON**, or **location**.

### Supported Providers

DecisionRules currently supports these providers:

* **Google**
* **Google Vertex**
* **Anthropic**
* **OpenAI**
* **Microsoft Foundry**

### How Configuration Works

The setup always follows the same flow:

1. Select a **model**
2. Select a compatible **provider**
3. Fill in the required provider-specific credentials
4. Test the connection
5. Save the configuration

The exact fields in the form depend on the selected provider.

## Provider Setup

### Google

For the **Google** provider, the user only needs to provide:

* **API Key**

### Anthropic

For the **Anthropic** provider, the user only needs to provide:

* **API Key**

### OpenAI

For the **OpenAI** provider, the user only needs to provide:

* **API Key**

### Microsoft Foundry

For **Microsoft Foundry**, the user must provide:

* **Endpoint**
* **API Key**

#### Where to find the Endpoint

The endpoint is available in Microsoft Foundry in:

**Build → Models → Select model → Code → Endpoint**

#### Where to find the API Key

The API key is available in:

**Home → API Key**

### Google Vertex

For **Google Vertex**, the user must provide:

* **Credentials JSON**
* **Location ID**

This setup is intended for organizations that want to use Gemini through **Vertex AI** with their own Google Cloud project and service account.

How to get [Google Vertex Credentials JSON](/doc/ai-assistant/assistant-setup/google-vertex-credentials-json)


# Google Vertex Credentials JSON

Follow these steps to generate your own Google Service Account credentials needed for your Google Vertex integration.

## Google Vertex Setup Guide

### How to Generate Your Gemini Configuration

#### 1. Open Google Cloud Console

Go to **Google Cloud Console** and open **Service Accounts**.

#### 2. Select or Create a Project

Choose an existing Google Cloud project or create a new one where you want to manage AI access.

#### 3. Create a Service Account

If you do not already have one:

* Click **Create Service Account**
* Enter a name, for example `Gemini AI Access`
* Click **Create and Continue**

#### 4. Assign Roles

Grant the service account the **Vertex AI User** role, or another role with sufficient access to Vertex AI.

Then click **Done**.

#### 5. Generate a JSON Key

* Open the created service account
* Go to the **Keys** tab
* Click **Add Key** → **Create New Key**
* Select **JSON**
* Click **Create**

Download the JSON file and store it securely.

### Example Credentials JSON

When configuring **Google Vertex**, the credentials JSON should look similar to this:

```json
{
  "type": "service_account",
  "project_id": "your-gcp-project-id",
  "private_key_id": "your-private-key-id",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
  "client_email": "your-service-account@your-gcp-project-id.iam.gserviceaccount.com",
  "client_id": "123456789012345678901",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/your-service-account%40your-gcp-project-id.iam.gserviceaccount.com",
  "universe_domain": "googleapis.com"
}
```


# Rules Introduction

### What Is a Rule?

A **rule** is a basic logic statement that defines **when something should happen** and **what should be done**. It usually follows this structure:

> **If** a certain condition is true, **then** perform a specific action.

For example:

* **If** a customer is a VIP, **then** apply a 20% discount.
* **If** a loan applicant's credit score is below 600, **then** reject the application.
* **If** the delivery address is international, **then** add a shipping fee.

This kind of logic is everywhere, in forms, spreadsheets, approval workflows, pricing policies, customer segmentation, and more. Rules make that logic **explicit** and **reusable**.

<figure><img src="/files/egdhurmkRUUuxYvvyf14" alt="" width="563"><figcaption><p>What Is a Rule?</p></figcaption></figure>

***

### Why Rules Matter

Rules help automate decision-making by removing the need for someone to manually apply logic every time. Instead of writing code or doing repetitive checks, you define the rule once and the system applies it instantly, as many times as needed.

#### The benefits of using rules:

* ✅ **Faster updates**\
  Need to change a discount or threshold? Just edit the rule. No need to change or redeploy code.
* ✅ **Fewer mistakes**\
  Rules are clearly defined and consistently applied, so there's less chance of errors or forgetfulness.
* ✅ **Better clarity**\
  Everyone can see the logic. No more guessing what the system “really” does.
* ✅ **Easier testing and maintenance**\
  You can test individual rules without needing to retest an entire application.

<figure><img src="/files/7VeFo7EnBhFSlNamTuKP" alt="" width="563"><figcaption><p>Rule Automation Benefits</p></figcaption></figure>

***

### Where Rules Fit in a Rule Engine

In a rule engine like **DecisionRules**, rules are the core units of logic. You can create, manage, and run them independently or combine them into more advanced logic flows.

Here’s how different rule types work:

* **Decision Tables**\
  Great for working with structured data, like mapping ranges or looking up values in a grid.
* **Scripting Rules**\
  When you need more flexibility, like mathematical formulas or custom logic.
* **Decision Trees**\
  Visual, easy-to-follow branching logic, great for step-by-step decisions.
* **Rule Flows**\
  Link several rules together into a full decision-making process.
* **Decision Flow & Integration Flow**\
  Automate full business processes by combining rules with actions like calling APIs, transforming data, or triggering custom logic. All in a visual, step-by-step flow.
* **Lookup Table**

  Structured data repository used to store and retrieve reference data through a unique primary key.
* **AI Agent**

  Delegates decision logic to Large Language Models (LLMs) using natural language prompts instead of explicit hard-coded conditions. It is designed to handle tasks involving judgment, ambiguity, or unstructured data, returning structured JSON responses for use within your decision flows.

In the next sections, you'll find detailed descriptions of the different rule types available in DecisionRules such as Decision Tables, Trees, Scripts, and Flows. We'll also cover common rule features and settings to help you configure, test, and manage your rules effectively.


# Rule List

## Rule Panel

At the top of the main page, you'll find a compact panel designed to help you get started quickly or jump back into recent work.

This panel displays a list of your **recently updated rules**, so you can easily continue working on something without searching through the full rule list. Clicking on a rule opens it directly in the editor.

Next to your recent rules, the panel also provides quick access to **rule templates**. By selecting a template, you can instantly create a new rule based on predefined logic.

<figure><img src="/files/XDopA6pE1QLYJ8Cg0mAB" alt=""><figcaption><p>Rule Panel Overview</p></figcaption></figure>

## Templates

Templates in DecisionRules are pre-created rules with ready-to-use logic. They’re designed to help users get started quickly by providing common decision-making patterns that can be customized as needed.

These templates are built around common use cases - such as discount calculations, risk scoring, eligibility checks, and routing logic - so instead of starting from scratch, you can begin with a functional rule and simply adjust it to fit your needs.

To access templates, click the **“Templates”** from upper panel. This opens the **Templates Modal**, where you can browse a selection of predefined rules and preview their logic before creating a new instance in your workspace. It is possible to search and filter templates and also view a detail by clicking **"Explore"** button.

<figure><img src="/files/6Jfdg7E11HM4eih2Zu3j" alt=""><figcaption><p>Available Templates</p></figcaption></figure>

In template detail you can get more info like detailed description, images and statistics. Template can be shared by **"Copy Link to Share"** button.

<figure><img src="/files/51eSxjD7GqGnuSFyR7Wt" alt=""><figcaption><p>Template detail</p></figcaption></figure>

## Rule List

The **Rule List** displays all the rules that exist within the currently viewed space. This list is the main way to explore, access, and manage the rules available in your workspace.

The list supports both **rules and folders**, making it easy to organize complex logic into categories or projects. You can expand and collapse folders to keep the view tidy or focus on specific parts of your rule library.

At the top of the list, a **search bar** lets you quickly find any rule by name or keyword. The search works across the entire structure—inside and outside folders—so you can locate what you need without scrolling manually.

Each rule in the list is represented by a record that shows key information at a glance, including:

* Rule name
* Version
* Alias
* State (e.g. Published, Pending)
* And more (e.g. tags, last update date, indications)

<figure><img src="/files/U5D38qDXxpZRntpmzuhU" alt=""><figcaption><p>Rule List Overview</p></figcaption></figure>

To perform actions on a rule, a **context menu** is available. You can open it by **right-clicking** on a rule row or by clicking the **three-dot button** at the end of the row. This menu includes options like renaming, duplicating, exporting, or deleting the rule—making it easy to manage rules directly from the list without opening them.


# Rule Mode

**Rule Mode** is where you edit and configure individual rules. When you open a rule from the Rule List, it loads into Rule Mode - an interactive editor that gives you all the tools you need to build, adjust, and test your decision logic in one place.

## Main Layout

### Central Part

The central part of Rule Mode is the **Designer**. This is where the rule body lives. It's the core space where you define overall logic. The layout and available tools in the Designer vary depending on the rule type (table grid, tree structure, flow canvas, code editor..)

<figure><img src="/files/v16mYCnzZFJyuSeLkmxX" alt=""><figcaption></figcaption></figure>

Alongside the Designer, there is a **Model** tab where you define your rule's [Input and Output Model](/doc/rules/common-rule-features/input-and-output) - the data structure your rule expects to receive and produce.

<figure><img src="/files/ualkMdmmrCCXrdWf2PW5" alt=""><figcaption></figcaption></figure>

### Top Panel

At the top of the screen, you'll find a control panel with several key sections:

<figure><img src="/files/M43vjfA6D4cfnHAX8C7A" alt=""><figcaption></figcaption></figure>

#### **Integrations:**

* Access API code examples in multiple languages.
* Excel integration and Swagger documentation.

#### **Rule Actions Menu:**&#x20;

This dropdown includes additional rule-specific actions such as:

* **Clone** - Create a duplicate copy of the current rule.
* [**Share with Space**](/doc/rules/common-rule-features/cross-space-rule-sharing) - Share this rule with other spaces in your organization.
* [**Export / Import Version**](/doc/rules/common-rule-features/rule-export-and-import) - Download / Upload the rule as a file.
* [**Compare versions**](/doc/rules/common-rule-features/rule-comparison) - View differences between rule versions.
* [**Lock / Unlock**](/doc/rules/common-rule-features/rule-lock) **-** Prevent or allow editing of the rule to protect important versions.
* **Delete** - Permanently remove the rule from your space.

#### **Action Buttons:**

* **Undo / Redo** - Navigate changes while editing the rule.
* **Save** - Save your progress manually.
* [**AI Assistant**](/doc/ai-assistant/about-ai-assistant) - Access AI-powered help (Beta).

### Left Panel

On the left side, you'll find a dynamic panel with tools that support rule editing and navigation.

<figure><img src="/files/FHfwucTO75OGJv5FeiC4" alt=""><figcaption></figcaption></figure>

#### **Common Tools (Available for All Rule Types):**

* **Folders** - Quick view of the Rule List, allowing you to jump to another rule without leaving Rule Mode.
* [**Settings**](/doc/rules/common-rule-features/rule-settings) - Configure rule name, alias, status, and other rule-specific settings.
* [**History**](/doc/rules/common-rule-features/rule-history) - View all saved versions of the rule, compare changes, or revert to previous states.
* [**Dependencies**](/doc/rules/common-rule-features/rule-dependencies) - Shows on which rules this one depends, or which rules this one is using.

#### **Rule-Specific Tools:**

Depending on the rule type, additional panels may appear:

* [**Rule Variables**](/doc/rules/common-rule-features/variables/rule-variables) - Define and manage custom variables used in the rule logic: *Decision Table, Decision Tree, Scripting Rule.*
* [**Palette**](/doc/rules/flow/flow-nodes-overview) - Drag-and-drop node library for building flows: *Decision Flows, Integration Flows.*
* [**Inspect**](/doc/rules/flow/flow-designer#inspect) - View and inspect flow execution details: *Decision Flows, Integration Flows.*
* [**Jobs**](/doc/space/jobs) - Manage scheduled or long-running jobs: *Integration Flows.*

### Bottom Panel

#### **Common Tools (Available for All Rule Types):**

* [**Test Bench**](/doc/rules/common-rule-features/test-bench) - Built-in testing area for real-time rule validation.

#### **Rule-Specific Tools:**

* [**Console**](/doc/rules/decision-table/decision-table-designer#console) - View execution logs and debug information: *Decision Table, Decision Tree, Scripting Rule.*
* [**Search**](/doc/rules/decision-table/decision-table-designer#search) - Find specific values in rule or search row: *Decision Table, Flows, Lookup Table, Scripting Rule.*
* [**Go to Row**](/doc/rules/decision-table/decision-table-designer#go-to-row) - Quickly navigates to the desired row: *Decision Table, Lookup Table.*
* **+ Row** - Add new rows: *Decision Table, Lookup Table.*
* [**+ Else Row** ](/doc/rules/decision-table/decision-table-designer#else-row)- Add ELSE row for default conditions: *Decision Table.*
* [**Check duplicates**](/doc/rules/decision-table/decision-table-designer#check-table-for-duplicates) - Detect duplicate rows: *Decision Table;* built-in for primary key in *Lookup Table.*
* **Zoom controls** - Zoom in, out, or reset canvas view: *Decision Trees, Flows.*
* **Text Wrap in JSON Editor** - Enable/disable text wrapping inside JSON editor: *Decision Table, Decision Tree, Flows, Scripting Rule.*
* **Shrink cells** - Compact cell display: *Decision Tree.*
* **Format code** - Auto-format JavaScript code: *Scripting Rule.*
* **Font size** - Adjust editor font size: *Scripting Rule.*


# Common Rule Features

All rule types share a set of fundamental properties and features that define their behavior, lifecycle, and execution. Understanding these common elements helps ensure consistency when managing and configuring rules across different spaces.

Key shared properties include the **rule alias**, which provides a unique identifier for a rule, and **versioning**, allowing you to track and manage different iterations of a rule. The **test bench** enables testing rules in isolation before deployment, while the **rule status** determines whether a rule is active, inactive, or in draft mode. **Rule variables** allow dynamic data handling within rules, and the **execution strategy** defines how rules are evaluated. Additionally, the **rule comparison** feature helps analyse differences between rule versions, ensuring accuracy and efficiency. Finally, rules interact with data through the **input and output model**, defining the structure of the data processed during execution.


# Variables

Variables represent values used during rule execution. They provide a way to reference and reuse data inside rules instead of working with hardcoded values directly.

A variable can contain data provided to the rule, values created during execution, or results produced by the rule itself. Once available, the value can be reused in other conditions, calculations, expressions, or execution steps.

The available variable types and variable addressing syntax depend on the selected rule type.

***

## Variables by Rule Type

In this section you can find list of variables available for each rule type.

### Decision Tables

Decision Tables support:

* [Input Model Variables](/doc/rules/common-rule-features/input-and-output)
* [Output Model Variables](/doc/rules/common-rule-features/input-and-output)
* [Rule Variables](/doc/rules/common-rule-features/variables/rule-variables)
* Column Variables

#### Column Variables

Columns inside a Decision Table can reference values from previously evaluated columns.

This applies to:

* Condition columns
* Calculation columns
* Result columns

In each Decison Table row scenario columns are evaluated from left to right, therefore a column can only reference columns that were already evaluated earlier in the table.

*If a variable reference is used before the referenced value is created or evaluated, the variable will **not** be recognized.*

Example of variables being used correctly in Decision Table:

* Columns are referensed after their declaration/evaluation.

<figure><img src="/files/Gqpje83gGzuWZge2YgAU" alt=""><figcaption></figcaption></figure>

Incorrect use of column references in Decision Tables:

* Column is referensed before its evaluation therefore its not recognized.

<figure><img src="/files/X3KUfWTbHDwSFGlQQYkm" alt=""><figcaption></figcaption></figure>

```json
{basicPrice}  //variable from input model
{discount}    //created calculation column variable
```

***

### Decision Trees

Decision Trees support:

* [Input Model Variables](/doc/rules/common-rule-features/input-and-output)
* [Output Model Variables](/doc/rules/common-rule-features/input-and-output)
* [Rule Variables](/doc/rules/common-rule-features/variables/rule-variables)

```json
{package.weight}  //variable from input model
{rate}            //created rule variable
```

Variables are commonly used in node conditions and result branches.

<figure><img src="/files/oRDIGwkLBvmkZEoZRhPb" alt=""><figcaption></figcaption></figure>

Example how to use variables in Decision tree:

<figure><img src="/files/L7BjOQG5MNWGNzaVUyWZ" alt=""><figcaption></figcaption></figure>

***

### Scripting Rules

Scripting Rules support:

* [Input Model Variables](/doc/rules/common-rule-features/input-and-output)
* [Output Model Variables](/doc/rules/common-rule-features/input-and-output)
* [Rule variables](/doc/rules/common-rule-features/variables/rule-variables)

Variables are referenced using dot notation.

Example of variables used in Scripting Rule:

```json
input.customer.country   //variable from IO model
ruleVariables.rate       //created rule variable
output.result            //variable from IO model
```

<figure><img src="/files/S7rYga3ayNC3ZYOs2k7v" alt=""><figcaption></figcaption></figure>

***

### Decision Flows and Integration Flows

Decision Flows and Integration Flows support:

* [Input Model Variables](/doc/rules/common-rule-features/input-and-output)
* [Output Model Variables](/doc/rules/common-rule-features/input-and-output)
* Variables created in flow and during flow execution

Variables can be reused between nodes and flow steps.

Both curly bracket syntax and dot notation are supported here.

```json
{input.age}             //variable from IO model
{rule.output.pricing}   //variable referencing output of evaluated business rule
{globalVariable.rate}   //created global variable
{newVariable}           //new variable created in flow
{output.result}         //variable from IO model
```

<figure><img src="/files/uBYgiEPw61W0VlEFSoIo" alt=""><figcaption></figcaption></figure>

***

### AI Agents

AI Agents support:

* [Input Model Variables](/doc/rules/common-rule-features/input-and-output)
* [Output Model Variables](/doc/rules/common-rule-features/input-and-output)
* Attachments
* [Rule Variables](/doc/rules/common-rule-features/variables/rule-variables)

Attachments and generated values can be reused during execution.

```json
{customer.age}             //variable from input model
{attachement.policies.pdf} //variable referencing attachement added to the ai rule
```

<figure><img src="/files/f4yhROYyRQ4b25iwMUbi" alt=""><figcaption></figcaption></figure>

***

### Lookup Tables

[Lookup Tables](/doc/rules/lookup-table) **do not** support:

* Model Variables
* Rule Variables

They operate only with values defined directly inside the table.

***

## Rule Variables

Rule Variables are variables created within the context of a specific rule.

They are typically used for:

* Temporary values
* Intermediate calculations
* Shared reusable values inside the rule

Rule Variables exist only during the current rule execution.

Detailed information about Rule Variables is available on the [dedicated Rule Variables documentation page](/doc/rules/common-rule-features/variables/rule-variables).


# Rule Variables

Rule variables simplify editing when working with values that appear multiple times across your rules.

**Rule variables work identically across all rule types** - Decision Tables, Decision Trees, and Scripting Rules - though the syntax for using them [varies by rule type](/doc/rules/common-rule-features/variables).

{% hint style="info" %}
Rule variables are version-specific. Each version of a rule maintains its own set of variables.
{% endhint %}

{% hint style="info" %}
In this guideline on how to create rule variables, you need to have knowledge of [Decision Table](/doc/rules/decision-table) and [Scripting Rule](/doc/rules/scripting-rule)
{% endhint %}

## **Creating and Managing Rule Variables**

Rule Variables are managed in the **left panel** of the rule editor. Here you can add, edit, or delete variables.

<figure><img src="/files/ffLDyAQAa2ytTxF0HxUm" alt=""><figcaption></figcaption></figure>

#### **To create a new variable:**

1. Enter a **Name** (must be unique per rule).
2. Set a **Value** (number, text, or boolean).
3. Click the **Save** button or click **Enter.**

{% hint style="success" %}
Create variable names **without spaces and special symbols**, even though they are technically allowed.
{% endhint %}

#### **To edit a variable:**

1. Click the **Edit** button next to the variable.
2. Modify the value.
3. Click the **Save** button or click **Enter.**

{% hint style="warning" %}
Save your changes – otherwise, the changed value of the rule variable will not be updated.
{% endhint %}

#### **To delete a variable:**

Click the **Delete** button next to the variable.

### Supported Value Types

Rule Variables support the following data types:

#### Simple Values

<figure><img src="/files/260x9YQfSETlMFsZ8AOj" alt=""><figcaption></figcaption></figure>

```javascript
{ "output": [ 0.21, 18, 30, "EUR", "Prague", "Premium", true, false ] }
```

#### Arrays

<figure><img src="/files/HmXMuzTzSFzYwF9m1eW6" alt=""><figcaption></figcaption></figure>

```javascript
[
    { "output": [15, 30, 45, 60] },                    // priceList
    { "output": ["Junior", "Standard", "Senior"] },    // categories
    { "output": [1, 2, true, "text"] }                 // mixedArray
]
```

#### JSON Objects

<figure><img src="/files/VawMV1EaTfC0ljTpPgZt" alt=""><figcaption></figcaption></figure>

```javascript
[
  { "output": { "id": 10, "name": "Peter", "occupation": "Developer" } },
  { "output": { "tax": 0.21, "currency": "EUR", "minAmount": 50 } }
]
```

{% hint style="warning" %}
While rule variables support complex objects and arrays, we **do not recommend using overly complicated rule variables**. Keep variables simple and focused.
{% endhint %}

### What Rule Variables CANNOT Do

Rule variables have important limitations that you should understand:

#### Reference other values

Rule variables are **static values only**. You cannot reference one variable from another or perform calculations between them.

<figure><img src="/files/YPJN6IJCb0GFOSh7raFY" alt=""><figcaption></figcaption></figure>

```javascript
[
  { "output": 30},
  { "output": "{price1} * 2" } // Returns literal string, NOT 60
]
```

While you might think `{input.field}` syntax would work based on other features, **rule variables do NOT support input placeholders**. The curly braces are treated as literal text.

<figure><img src="/files/5Mvq49bGIPJyNSYDuOgu" alt=""><figcaption></figcaption></figure>

```javascript
[
    { "output": "[1, {input.value}, true, \"text\"]" },
    { "output": "{\"tax\":{income.tax},\"currency\":\"EUR\",\"minAmount\":50} }
]
```

#### Execute functions

Functions stored in rule variables are **NOT executed** - they are returned as strings.

<figure><img src="/files/3jVG2X9u3H9D08urztkn" alt=""><figcaption></figcaption></figure>

```javascript
[
  { "output": "BTW(10, {input}, 40)" },
  { "output": "GT(30, 50)" },
  { "output": "SUM(10, 20)" }
]
```

{% hint style="info" %}
If you need to use functions, write them directly in table.
{% endhint %}

## How to use Rule Variables

### **Rule Variables in Decision Tables**

There are several ways to use Rule Variables in Decision Table Designer:

#### **As the Column Condition**

In the column header, you can use the variable name directly.

<figure><img src="/files/MkUfFr8JKslIlkvFLDz9" alt=""><figcaption></figcaption></figure>

#### As the Comparison Value

In the condition cell, you will see reference with the `A` prefix

<figure><img src="/files/ZwSSLFQ3d1cW925dLF7i" alt=""><figcaption></figcaption></figure>

**Both approaches achieve the same result** - comparing input data against your rule variable. Choose the style that makes your table more readable.

{% hint style="warning" %}
The column header is always the **left side** of the comparison. When you move a variable between the column header and the condition cell, you must **reverse the operator** to maintain the same logic.
{% endhint %}

#### As Part of the Function

Rule variables can be used inside functions and mathematical expressions, just like any other value (input fields, column values, or static numbers).

<figure><img src="/files/9h5WpFsBWAHNw48UJ6fL" alt=""><figcaption></figcaption></figure>

This is useful when you want to calculate output without hardcoding them in each cell. If value change, you only update the variable once.

{% hint style="info" %}
Exactly the same use of Rule Variable applies to Decision Tree.
{% endhint %}

### **Rule Variables in Scripting Rule**

Usage of Rule Variables in Scripting Rules is super easy. All values are stored in the `ruleVariables` object that is exposed in the script. You can use these stored values everywhere in the script (as inputs for your function or as inputs for `DR.solve()` function).

You can access your Rule Variables with the dot notation same as with input and output. To get the value of a rule variable, you write `ruleVariables.<nameOfYourRuleVariable>`

```javascript
const foo = ruleVariables.foo;
const bar = ruleVariables.bar;

output.Output = `Values of Rule Variables are: ${foo} and ${bar}`;

return output;
```

{% hint style="danger" %}
You cannot set `ruleVariables` from script itself or overwrite existing Rule Variables.
{% endhint %}

### Rule Variables in AI Agent

Prompt example with used rule variables:

```json
Evaluate a loan application using customer input data, rule variables, and company policy.

Input data:
- Customer age: {age}
- Monthly income: {monthlyIncome}
- Requested loan amount: {loanAmount}

Rule variables:
- Risk score: {variables.riskScore}            //created rule variable
- Approval limit: {variables.approvalLimit}    //created rule variable

Policy document:
{attachments.policy.txt}
```


# Input & Output Model

Definition of input and output of the decision table.

There are two options on how to define the input and output of the decision table:

* [Simple Editor](/doc/rules/common-rule-features/input-and-output/simple-editor): It is understood that some of our users may not understand JSON objects' structure. Therefore, we allow non-technical users to create input and output objects using our simple tool, which creates the necessary structures.
* [JSON Editor](/doc/rules/common-rule-features/input-and-output/json-editor): This is an editor for users who have experience with JSON objects' structure.


# Simple Editor

We recognize that not all users are familiar with JSON structure, so we offer a simple tool to easily create input and output objects.

## Working with the input & output model editor

<figure><img src="/files/IiN1OUN2qOZnfzGK3WqY" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}
After making any changes to the input/output model, be sure to save them by clicking the **Save** button in the bottom-right corner. Please note that all changes apply only to the current version of the rule.
{% endhint %}

{% hint style="info" %}
There are no limitations when creating input/output models. A model can have an unlimited number of root objects and child objects.
{% endhint %}

### Adding a Root object

To create a root object, click ![](/files/-MQT2spzTHmRZpO8lZLe) button.

### Adding a Child object

To create a child object, click **+** sign on the parent object.

<figure><img src="/files/j0PTNSgqRDhFAPaOMpRF" alt="" width="261"><figcaption><p>Adding a child input object</p></figcaption></figure>

### Moving an Object (Dragging)

To move an object to another parent or make it a child, drag the object and drop it on the desired parent. To make a child object a parent, drag it and drop it at the same level as the current parent.

<figure><img src="/files/C9FnSozWi4gr9tGyIoxm" alt=""><figcaption><p>Dragging I/O objects</p></figcaption></figure>

### Showing Child Objects

To view child objects, click the arrow next to the parent object.

<figure><img src="/files/ka23CVfBQ25T6jbJpnkl" alt="" width="230"><figcaption></figcaption></figure>

### Deleting an Object

To delete an object, click the **Delete** <img src="/files/-MQT2dO6ONw50ted6hbx" alt="" data-size="line"> button on the object.

### **Viewing Object Structures**

To display the entire structure and all objects, click the ![Expand All](/files/-MQT3bAIBAWHNsHgyKw-) button. To view only parent objects, click the ![Collapse](/files/-MQT3Y4J-AIqgvpah9pQ) button.

### Renaming an Object

To rename an object, click its name. An input box will appear. After making your changes, click outside the box or press **Enter** key to close it.

{% hint style="warning" %}
Only letters, natural numbers, underscores and hyphens are allowed.
{% endhint %}


# JSON Editor

This editor is designed for experienced users familiar with the structure of JSON objects.

## Working with the JSON Editor

<figure><img src="/files/DJ7gzJewV9D00RZj7N7L" alt=""><figcaption><p>JSON Editor</p></figcaption></figure>

{% hint style="danger" %}
After making any changes to the input/output model, be sure to save them by clicking the **Save** button in the bottom-right corner. Please note that all changes apply only to the current version of the rule.
{% endhint %}

{% hint style="info" %}
There are no limitations when creating input/output models. A model can have an unlimited number of root objects and child objects.
{% endhint %}

{% hint style="warning" %}
Only letters, natural numbers, underscores and hyphens are allowed in object name.
{% endhint %}

### Creating a Model

The model follows a tree structure written in JSON format. Root objects can contain children, but only leaf objects (objects without children) can be selected as variables.

To create a leaf object, use the following format:

Object with empty `{}`:

```javascript
"objectName": {}
```

{% hint style="warning" %}
Arrays and values are not allowed.
{% endhint %}

#### Example of a Simple Model with Leaves Only:

```javascript
{
    "distance": {},
    "tariff": {},
    "weight": {},
    "longestSide": {}
}
```

#### Example of a Complex Model:

```javascript
{
  "delivery": {
    "distance": {
      "car": {},
      "ship": {},
      "plane": {}
    },
    "tariff": {}
  },
  "package": {
    "weight": {},
    "longestSide": {}
  }
}
```

### Beautify Code

To beautify the code for better readability, right-click the JSON model and choose the **Format Document** option.

<figure><img src="/files/H9DZcRkPLsohEG4TZSS5" alt=""><figcaption><p>Beautify code</p></figcaption></figure>

{% hint style="info" %}
This functionality is particularly useful when copying and pasting JSON from other sources or windows on your device.
{% endhint %}


# Rule Settings


# Rule description

The **Rule Description** provides a space where you can document the purpose and behavior of a rule. Clear descriptions help other users understand what the rule does, what inputs it expects, and how its logic should be interpreted.

<figure><img src="/files/VYc5qRZZ3zElNJ2C4TkZ" alt=""><figcaption></figcaption></figure>

#### Location

The **Description** field is located in the **right-side panel of the Rule Editor**, inside **Rule Settings → Description**.

#### Usage

You can enter explanatory text directly into the description field. The editor supports **basic rich text formatting**, which allows you to structure and highlight important information.

This makes it useful for documenting:

* the purpose of the rule
* explanations of input variables
* pricing logic or business conditions
* examples of how the rule behaves

#### Supported Formatting

The editor allows styling such as:

* **Bold text** for highlighting important values
* *Italic text* for emphasis
* Lists for structured information
* Headings for section separation
* Links to related documentation

#### Example

Below is a simple example of how a rule description can be structured:

**Ticket Price Calculation Rule**

This rule calculates the **final airline ticket price** based on several travel parameters.\
It evaluates the passenger's *origin*, *destination*, selected **travel class**, and the applied **fare tariff**.

The rule considers the following inputs:

* **Origin airport** – the departure location
* **Destination airport** – the arrival location
* **Travel class** – Economy, Business, or First Class
* **Fare tariff** – the pricing category applied to the ticket

Based on the combination of these values, the rule assigns the appropriate **ticket price** according to the configured pricing scenarios.


# Rule Alias

This page contains information about the rule alias feature.

## About the rule alias

Rule alias is a more comfortable and convenient alternative to rule ID. Unlike rule ID, the rule alias can be set by the user. Then it may be used to refer to the rule from other rules or when calling the Rule Solver API.

### Setting rule alias

Rule alias can be set via rule settings, this applies to all rule types.

{% hint style="info" %}
Rule alias can be any string containing letters, numbers and the - character.
{% endhint %}

Rules created in DecisionRules version 1.12 and smaller will have no rule alias but the user may provide one if they want. All newly created rules will have auto-generated rule aliases that can be freely edited.

<figure><img src="/files/3ck5kJrrPaxUXJv7J9Fd" alt=""><figcaption><p>setting up a custom rule alias</p></figcaption></figure>

{% hint style="warning" %}
Rule alias does not have to be strictly unique within the space. However, it is greatly recommended to keep your rule alias unique, since requests with non-unique alias will typically fail.
{% endhint %}

If you assign two identical rule aliases to several rules in a single space, the conflicting rule aliases are displayed in red color.

<figure><img src="/files/4M8rWp2huvEAFt7zw4n2" alt=""><figcaption><p>rule alias conflict</p></figcaption></figure>

### Solving rules with rule alias

Solving rules with rule alias works the same way as with rule id (rule flow id). All you need to do is to replace the rule id (rule flow id) in the request with the respective rule alias.

<figure><img src="/files/122dhsptTKpmKbvZjLpJ" alt=""><figcaption><p>call on solver endpoint made with rule alias via postman</p></figcaption></figure>

Rule aliases can be used in the `SOLVE` function in decision tables and decision trees, as well as the `DR.solve` function available in scripting rules.

<figure><img src="/files/sSO77CIYUXMTYiQBMhIQ" alt=""><figcaption><p>solving rule with calling SOLVE() function via rule alias as parameter</p></figcaption></figure>

### Using rule alias with management API

There is a possibility to use rule aliases with Management API as well. Just replace the rule ID (rule flow ID) with the respective rule alias and all the requests to the Management API should work as before.


# Rule Status

## The two rule statuses

Every Rule has two status options: `Published` and `Pending`. The status can be set on each version of the rule independently.

**Initial Status:**

* **Newly created rules:** All rules are created in `Published` status by default
* **Imported rules:** The status is determined by the value defined in the imported rule data
* **New versions:** All newly created versions start in `Pending` status

### Published status

Rule in Published status is ready for production and is available via [Solver API](/doc/api/rule-solver-api).

#### Examples:

<figure><img src="/files/cXvoPaxbshV7l0HReAcI" alt=""><figcaption><p>rules in Published status</p></figcaption></figure>

### Pending status

Some rules or versions of rules are not yet ready for production. For example, because the rule is still in development. Such a rule has a Pending status and it cannot be accessed using [Solver API](/doc/api/rule-solver-api). When trying to solve such a rule, [Solver API](/doc/api/rule-solver-api) returns the following HTTP request error:

```javascript
400 Bad Request
{
  "error": {
    "message": "Rule state is not published"
  }
}
```

{% hint style="success" %}
For the purpose of testing your rules and their versions that are not yet in production, you can execute rules in Pending status by using the **Debug** in [Test Bench](/doc/rules/common-rule-features/test-bench) feature to solve the rule directly within the platform.
{% endhint %}

#### Example:

<figure><img src="/files/1xDDtl1mEHulz9u9VZLP" alt=""><figcaption><p>rules in Pending status</p></figcaption></figure>

### How to change the rule status

The status can be changed in rule settings by clicking the **Status toggle**. The rule **must be saved** to apply the status change.

<div><figure><img src="/files/LhwAlsDLJm2fJFHC2YB9" alt="" width="303"><figcaption><p>switched to Pending</p></figcaption></figure> <figure><img src="/files/vIwxRtYzyyERuVzoSiI9" alt="" width="303"><figcaption><p>switched to Published</p></figcaption></figure></div>


# Tags

Tags provide a simple way to keep track of your rules and filter them in search results.

Every rule can be labeled by an arbitrary set of tags. These come in several colors to enable simple visual identification of distinct rules (as well as their versions). Tags contain arbitrary text of your choice. The management and usage of tags, although intuitive, is described in detail below.

## Manage & Use  Rule Tags

Tags can be managed either separately for each version of a given rule, or for all rule versions at once. Let us describe these two cases separately.

### On Rule versions

The tags belonging to a certain rule version can be managed either in the rule list or inside the rule settings of the respective version. The operations performed in these two places have the exact same effect.

<figure><img src="/files/6RC1BxFOd8w5Z8ApLVnz" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/xP4jLlBQ4onWG17QZbWX" alt=""><figcaption></figcaption></figure>

The management of tags belonging to individual rule versions involves the following operations.

#### Adding a tag

Click on the +Add tag button and start typing. You may either find an existing tag to add or create a completely new tone. Press Enter to enter the tag text. When creating a new tag, you may then select its color by clicking on one of the available tag colors. Confirm by clicking on the ![](/files/YDOQW5dIbxK8jeWOEVRD) button. Your tag should be now added to the rule version.

#### Removing a tag

Click on the tag you wish to remove next to a version and select the "Remove from this version" option. Your tag should be now removed from the rule version.

#### Changing tag color

Tag color can only be changed globally for all tags in your space that have the same text. To do that, click on the tag whose color you wish to change (anywhere in the respective space) and choose the new color under the "Change color globally" option.

{% hint style="info" %}
Note that tags exist on the level of the space, i.e., different kinds of rules may be labeled by the same tags. For example, if you create a tag for a Decision Rule, you may as well use it to label your Rule flows.
{% endhint %}

It is suggested that you choose the text of your tags carefully, as it cannot be globally changed later. If you need to change the text of a tag used to label a certain set of rules, you need to remove it from each of the rules separately and then add new tags that replace the removed one.

### On Rules themselves

Aside from the tags labeling the individual rule versions, there is also a tag list visible in every rule header within the rule list.

This overall tag list contains the set of all tags used in any of the versions of the respective rule. It allows you to perform the same tag operations like the one described above (Adding a tag, Removing a tag, Changing tag color), only with different effects of the first two:

* Adding a tag will result in adding the tag to all versions of the respective rule.
* Removing a tag will result in removing the tag from all versions of the respective rule.

The effect of changing the tag color in the rule header remains the same.

### Use tags to search

Aside from allowing for a clear visual differentiation and classification of your rules and rule versions, tags may be also used to filter search results.

<figure><img src="/files/twABjwVdWWSIBtVd3c8U" alt=""><figcaption></figcaption></figure>

When you start typing in the search bar, the existing tags are suggested to you in a dropdown menu. Upon selecting some tag from the menu, it is placed into the search bar and used to filter your search results. A rule enters the search results only if at least one of its versions contains the specified tags. The versions themselves are not filtered (you can see all of them in search results).

The functionality of searching by text is of course preserved. You may enter search text simply by typing the desired phrase and pressing Enter without selecting any tags.

{% hint style="info" %}
Note that there is a separate thin [Management API](/doc/api/management-api#tag-api) within our Management API allowing you to manage tags on your rules and reach out for rules with a specified collection of tags.
{% endhint %}


# Event Logs

Event Logs provide a detailed record of actions related to a specific rule, showing what changed, who performed the action, and when. This gives you full visibility into the rule’s history.

You can access Event Logs either from **Space → Event Logs** (to view activity across the entire space or filter by rule) or directly from an individual rule. In the **Rule Settings panel,** the *Inspect Event Logs* button takes you to the Event Logs page with that rule already preselected.&#x20;

\[[More on Event Logs →](/doc/space/event-logs-service-logs-and-notifications)]

<figure><img src="/files/mqeI3RNqT0vP8XANPsrV" alt=""><figcaption><p>Side panel with Rule Settings, section Event Logs</p></figcaption></figure>


# Rule Testing

Validate rules with saved Test cases and repeatable Test Suites.

Rule Testing lets you verify rule behavior against saved scenarios. Each scenario uses fixed input and expected output. You can rerun the same checks after any change.

This page provides a focused view of tests for an individual rule. To manage your tests from a global workspace view, navigate to the main Tests section.: [Tests](/doc/space/tests)&#x20;

### Main benefits

* Validate rule changes before release.
* Catch unwanted side effects early.
* Recheck rules after a DecisionRules update.
* Understand rule behavior faster with real examples.

#### Rule Testing vs. Test Bench

* Test Bench: Used for ad-hoc checks while actively editing a rule.
* Rule Testing: Used for saved, repeatable validation.

### Core concepts

#### Test

The smallest testing unit. It stores:

* Name
* Rule reference (Alias and Version)
* Rule strategy
* Input data
* Expected output
* Ignored output properties (Optional: Used to exclude dynamic values like current dates or generated IDs from the validation).

#### Test Suite

A Test Suite is a collection of Tests. You can think of it as a folder for related scenarios.

A Test Suite is linked to a rule by:

* Rule alias
* Rule version

This makes the Test Suite specific to one rule version.

{% hint style="info" %}
In rare cases, a Test Suite can point to a rule that no longer exists. These Tests are marked as Orphaned Tests.
{% endhint %}

#### Test Runs

After execution starts, Test Run is created with state **Waiting**. During processing, it can also be **Running**.

Finished Test Runs can end as:

* **Passed**
* **Failed**
* **Error**
* **Canceled**

### What users can do

Rule Testing covers three main areas:

1. Rule-level Test management
2. Space-level Test management
3. Test Bench integration

### Rule-level Tests tab

Rule Testing adds a **Tests** tab next to **Model** and **Designer**.

<figure><img src="/files/vCwXLbXkTkxQMPYe4Hdo" alt="Rule tabs"><figcaption><p>Rule tabs</p></figcaption></figure>

This tab is the main place to manage Tests for the opened rule. It shows all Test Suites and Tests linked to that rule.

#### Main actions

Users can:

* Create a new Test / Edit a Test
* Create a new Test Suite / Edit a Test Suite
* Filter by name
* Run all
* Run selected

If nothing is selected, the run action offers **Run all**. If the user selects one or more items, it also offers **Run selected**.

### **Test Detail Panel**

User can modify test in Test Detail window.

<figure><img src="/files/Nq5Osl6igSGGz8s1qYFu" alt="Test detail"><figcaption><p>Test detail</p></figcaption></figure>

#### Run Test

Test Run is created for selected Test.

#### Load to Test Bench

Users can copy test input directly into [Test Bench](/doc/rules/common-rule-features/test-bench). This makes failed tests easier to debug.

### Rule-level Test Runs overview

The left-side **Test Runs** panel focuses on execution results and debugging. Panel shows all Test Runs belongs to current rule. If user clicked on one Test Run, detail is shown.

<figure><img src="/files/6XeCGE9wtFAr5L7DuMyV" alt="Test Runs panel"><figcaption><p>Test Runs panel</p></figcaption></figure>

#### Test Run detail

Test Suites are collapsed by default. Users can expand a Test Suite to see its Tests.

<figure><img src="/files/Ty3afQlsYX38clHGOw24" alt="Test Run detail"><figcaption><p>Test Run detail</p></figcaption></figure>

Users can expand a test to inspect:

* Input data
* Expected output
* Received output

Differences in received output are highlighted.

<figure><img src="/files/LmMZSqBCrOzBBUMNrkui" alt="Output differencies"><figcaption><p>Output differences</p></figcaption></figure>

#### Available actions

From the left panel, users can:

* Open Test details
* Inspect Test in Test Bench

### Test Bench integration

Rule Testing integrates directly with Test Bench. Thera are few possibilities that can be shown.

<figure><img src="/files/iVWXySpwvQeV3AWZY3UM" alt="Test Bench"><figcaption><p>Test Bench</p></figcaption></figure>

#### Save as test

After running a rule in Test Bench, users can choose **Save as Test**. This opens dialog with the current input and output already available. The user then fills in:

* target Test Suite
* name

#### Existing test match

If the current Test Bench input matches an existing test, the interface shows it. It also shows whether the current output matches the expected output. If multiple tests match the same input, infoo is shown

#### Updating expected output

If the input matches a saved test but the output differs, the user can update the test.This action ask for confirmation before replacing the expected output.

### Import and export

Tests and Test Suite can be exported as JSON. This export is separate from rule export.

{% hint style="info" %}
Exporting a rule does not include tests
{% endhint %}

Tests can also be imported to space, rule or Test Suite.

### Orphaned Tests

Orphaned Tests exist when the stored alias and version do not match any existing rule. Orphaned Tests can be shown in the space-level menu. Users can then move those tests to an existing rule.

### Rule Testing vs. Test Bench

[Test Bench](/doc/rules/common-rule-features/test-bench) is best for ad-hoc checks while editing a rule. Rule Testing is best for saved and repeatable validation. Use Test Bench to explore. Use Rule Testing to verify.

### Automation

If you want to run tests programmatically, use the [Rule Testing API](/doc/api/rule-testing-api).


# Creating & Running Tests

### A. Save from Test Bench

1. Open the Test Bench tab.
2. Enter input JSON and click Run.
3. Click Save as Test.
4. In the dialog, select a target Test Suite and enter a Test Name.
5. Click Save. *Note: If the input matches an existing test, the UI displays the match. If the output differs from the saved version, you can overwrite the expected output.*

### B. Create Manually

1. Open the Tests tab.
2. Click Create New Test.
3. Select a Test Suite and enter a Name.
4. Input the Input JSON and Expected Output JSON.
5. *(Optional)* Add JSON paths to Ignored output properties.
6. Click Save.

### Executing Tests (Running Tests)

#### Manual Execution

1. Select the checkboxes next to the desired Tests or Test Suites.
2. Click Run selected.
3. *(If no checkboxes are selected, click Run all to execute all tests for the rule).*

#### API Execution

Tests can be executed programmatically for automation (e.g., CI/CD pipelines) using the Rule Testing API. [Rule Testing API](/doc/api/rule-testing-api)

### Debugging Test Runs

The left panel displays all Test Runs for the current rule.

1. Click a Test Run to view its details.
2. Expand a Test Suite to see individual Tests.
3. Expand a Test to inspect the Input, Expected Output, and Received Output.
4. Differences between expected and received outputs are highlighted automatically.

***

This page provides a focused view of tests for an individual rule. To manage your tests from a global workspace view, navigate to the main Tests section.: [Tests](/doc/space/tests)&#x20;


# Test Bench

The Test Bench is a built-in testing environment that allows you to evaluate and validate your rules before deploying them to production. By entering input data and simulating rule execution, you can verify that your rules produce the expected outputs and identify any issues early in the development process.

{% hint style="info" %}
In this guideline you need to have knowledge of [Decision Table](/doc/rules/decision-table) and [Decision Tree](/doc/rules/decision-tree).
{% endhint %}

### **Why Use Test Bench**

* **Validate logic** - Ensure rules work correctly before deployment.
* **Test edge cases** - Verify behavior with different input scenarios.
* **Debug issues** - Identify and fix problems during development with [Debug Mode](#debug-mode).
* **View detailed execution** - See exactly which rows or branches executed.
* **Iterate quickly** - Make changes and test immediately.

## Accessing Test Bench

Test Bench is available for all rule types and provides a consistent testing experience across them.

**To open Test Bench:**

1. Navigate to any rule in the designer.&#x20;
2. Click to open the **Test Bench** in the bottom bar.

<figure><img src="/files/4lnT7T4b8EVjqcbOkxsB" alt=""><figcaption></figcaption></figure>

## Test Bench Modes

Test Bench offers two interface modes to accommodate different user preferences and use cases:

### **1. Simple Bench**

A simplified interface that displays input (left side of bench) and output (right side of bench) fields as individual form fields, making it easy to test rules without JSON knowledge.

**Best for:**

* Users unfamiliar with JSON.
* Quick testing with simple inputs.
* Clear visualization of individual fields.

<figure><img src="/files/lghkAaSNZYrSLurROEb4" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Commas create arrays (e.g., `1,2,3` becomes `[1, 2, 3]`). To use a comma inside a value, wrap it in quotes: `"some,text"`.
{% endhint %}

#### Date Input **in Simple Bench**

Simple Bench provides a convenient date picker for date fields:

1. Click the **three dots** next to the field.
2. Click the **calendar icon**.

<figure><img src="/files/nwBXK4H0VOKsqdoBLUIT" alt="" width="563"><figcaption></figcaption></figure>

3. Select:
   * **Date** (day, month, year)
   * **Time** (hours, minutes)
   * **Time zone**

<figure><img src="/files/KzOMWk5UjJdjnHERaRQ0" alt="" width="375"><figcaption></figcaption></figure>

4. Click **Save**.

### 2. JSON Bench

A JSON editor interface for entering input and viewing output in standard JSON format.

**Best for:**

* Technical users comfortable with JSON.
* Complex nested data structures.
* Arrays of objects.
* Copy/paste from API responses.
* Precise control over data structure.

<figure><img src="/files/f3FdFG48lTZfKPPOfM9B" alt=""><figcaption></figcaption></figure>

### **Switching Between Modes**

**Data Persistence:**

* Input data is preserved when switching between Simple and JSON Bench.
* You won't lose your test data when changing views.

#### **Understanding Display Limitations in Simple Bench**

While Simple Bench is convenient for basic testing, it has limitations when handling complex nested structures. Here are important behaviors to be aware of:

**1. Objects Without Defined Children**

If your input model defines a parent object without specifying its children structure (as an empty object `{}`), and you provide actual nested data in JSON Bench, Simple Bench will display this as `[object Object]`.

```json
// Input Model

{
  "action": {
    "transaction": {}  // Empty object - no children defined
  }
}
```

```json
// Actual JSON Input

{
  "action": {
    "transaction": { // last children based on input model
      "transactionValue": 10000,
      "transactionCurrency": "USD",
      "transactionValueEurEquivalent": 9500
    }
  }
}

// Simple Bench Display:
action.transaction: [object Object]
```

<figure><img src="/files/iL6Rlu8y15zi4fln16J1" alt=""><figcaption></figcaption></figure>

**What this means:**

* The model doesn't define what children `transaction` should have.
* Simple Bench can't break it down into individual fields.
* Display shows `[object Object]` as a placeholder.

**It still works:**

* The rule receives and processes the complete nested data correctly.
* This is only a display limitation in Simple Bench.
* Use JSON Bench to see and edit the full structure.<br>

2. **Arrays of Objects**

Arrays of objects behave differently depending on whether they're in input or output fields.

* **Input Fields:**\
  Not Practical in Simple Bench. Arrays of objects in input fields display as `[object Object], [object Object], [object Object]...`, which doesn't allow you to see or edit the actual data.

```json
// Input Model

{
  "factorList": {} // Empty object - no children defined
}
```

```json
// Actual JSON Input
{
  "factorList": [
    { "destinationRisk": 0, "historyRisk": 0 },
    { "destinationRisk": 1000, "historyRisk": 1000 }
  ]
}

// Simple Bench Display:
factorList: [object Object], [object Object]
```

<figure><img src="/files/gESjM7sARXgV4QOLWo1S" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Use **JSON Bench** for inputs containing arrays of objects.
{% endhint %}

* **Output Fields:**\
  Arrays of objects in output fields show a **View** button that opens a detail modal.

```json
// Output Model

{
  "factorList": {} // Empty object - no children defined
}
```

```json
// Actual JSON Output
{
  "factorList": [
    { "destinationRisk": 0, "historyRisk": 0 },
    { "destinationRisk": 1000, "historyRisk": 1000 }
  ]
}

// Simple Bench Display:
factorList: View
```

<figure><img src="/files/KLB0tablP3XIJ8RiT7iA" alt=""><figcaption></figcaption></figure>

**Viewing Details:**

1. Click the **View** button
2. A **Detail View** modal opens
3. See the complete structure:
   * Each array element numbered (0, 1, 2...)
   * All properties displayed with formatting
   * Collapsible structure for navigation

<figure><img src="/files/ab6oSWkgIcyAJv9JLXlB" alt="" width="563"><figcaption></figcaption></figure>

## Execution Modes

Test Bench supports different execution modes depending on the rule type and your testing needs. For detailed information about execution strategies and modes, see [Execution Strategy](/doc/rules/common-rule-features/execution-strategy).

## Debug Mode

Debug Mode provides detailed execution information, helping you understand exactly how your rule processes data and where issues might occur.&#x20;

Debug Mode is available for **Decision Tables** and **Decision Trees** only.

### How to Enable Debug Mode

1. Open Test Bench.
2. Look for the **Debug** toggle/checkbox.
3. Enable it (toggle to ON/checked state).
4. Click **Run** to execute with debug information.

<div><figure><img src="/files/38nRrXHmssTWeMKVybNb" alt=""><figcaption></figcaption></figure> <figure><img src="/files/QpS4TWJLvUjXYNl7DcSl" alt=""><figcaption></figcaption></figure></div>

### Debug Decision Table

When Debug Mode is enabled for Decision Table, you get detailed visual feedback showing exactly how your input data matches against each condition.

#### **Visual Indicators**

**Row Highlighting:**

* The executed row(s) are visually highlighted in the table.

Shows which rows matched your input conditions.

**Cell-Level Feedback:**

* **Green cells** - Condition **passed** (evaluated to true).
* **Red cells** - Condition **failed** (evaluated to false).

This allows you to see exactly which condition caused a row to pass or fail.

**Value Display:**

* Each condition cell shows the **actual value** being compared.

You can see what the rule is evaluating against your input.

<figure><img src="/files/nxlewePUtdY8Q38nd90P" alt=""><figcaption><p>Rows 6 and 11 were executed successfully.</p></figcaption></figure>

### Debug Decision Tree

When Debug Mode is enabled for Decision Trees, you can trace the execution path through the tree structure and see exactly which conditions were evaluated and which branch was taken.

#### **Visual Indicators**

**Block Highlighting:**

* **Colored borders** show which nodes were evaluated during execution.
* **Green-highlighted blocks** indicate the path that was taken and executed.
* **Red-highlighted blocks** indicate the path that was not taken.

Shows the decision flow from top to bottom through your tree.

**Value Display:**

* Condition blocks show the actual values being compared.

<figure><img src="/files/WXBJ70PC6zyqYofWgVCx" alt=""><figcaption><p>First if-condition failed - the second if-condition applied</p></figcaption></figure>


# Versioning

Versioning allows you to manage multiple iterations of your rules, enabling safe testing and easy rollback capabilities.

## How Versioning Works

### Version Numbering

Version numbers are assigned automatically and increase sequentially (1, 2, 3, ...).\
Version numbers continue from the highest existing number, even if intermediate versions are deleted.

> Example: If you have versions 21, 22 and 24 (with 23 deleted), creating a new version from 22 will create version 25

### Version Limits

There is no limit to the number of versions you can create per rule.

## Manage rule versions

### Creating new version

You can create a new version of any rule type from folder view or inside rule.

When you have a rule open:

* Click the three-dot menu button in the top-right corner of the interface
* Select **New Version** from the dropdown menu

<figure><img src="/files/t8fhB7lv3XNLkL45a87G" alt=""><figcaption><p>creating a new version of Decision Flow while in it</p></figcaption></figure>

When browsing your rules in a folder:

* Locate the rule you want to version
* Right-click on the rule to open the context menu (or use three-dot button on the far right)
* Select **New Version**

<figure><img src="/files/KeiJxabN98E7YPLvZpWq" alt=""><figcaption><p>creating a new rule version from the folder view using the context menu</p></figcaption></figure>

A new version of the rule will create with the same **Rule Id** and **Rule alias** as the selected rule and sets the **version to 1 greater than the latest version.** The new rule has the **same structure** as the selected rule.

{% hint style="info" %}
All newly created versions start in **Pending** status. More about status options [here](https://docs.decisionrules.io/doc/rules/common-rule-features/rule-settings/rule-state)
{% endhint %}

### When to Create a New Version

Create a new version when making significant changes to your rule. New versions allow you to safely test changes while keeping the current production version intact.\
While each rule has change history, versioning provides cleaner rollback points for major updates.

### Version Comparison

You can compare different versions side-by-side to see what changed. \
See [Rule Comparison](https://docs.decisionrules.io/doc/rules/common-rule-features/rule-comparison) for details.

***

More info about using specific versions in:\
[REST API](https://docs.decisionrules.io/doc/api/api-introduction)\
[Decision Flow](https://docs.decisionrules.io/doc/rules/flow/flow-nodes-overview#business-rule)


# Rule History

{% hint style="info" %}
The **Rule History** feature is not available for **Rule Flow**. You can edit and save a Rule Flow as usual, but its previous versions are not stored or displayed in a history panel.
{% endhint %}

The **History** panel provides a complete overview of all saved versions of a rule.\
Each time you click **Save** in the editor, a new version of the rule is automatically created and recorded here. This allows you to track when and by whom each change was made, and to revisit any previous version when needed.

#### Overview

The **History** panel is located on the left side of the rule editor.\
Each entry in the list shows:

* **Timestamp** – when the rule was saved
* **User email** – who performed the save
* **Current label** – indicates the latest version

The most recent version is always marked as **Current**, while older versions have no label but remain accessible for review.

<figure><img src="/files/eTfEUZIMNWNEjXHEd63t" alt=""><figcaption></figcaption></figure>

#### Viewing previous versions

Click any item in the list to open that historical version directly in the rule Designer.\
When selected, the editor will display that version of the rule, allowing you to review its exact configuration at the time of saving.\
To return to your working copy, simply select the **Current** version again.

#### Editing and evaluation rules

Only the **Current** version of a rule is editable and can be executed (tested or run).\
Historical versions are displayed in **read-only mode** — you can view them but not modify or evaluate them.

If you want to bring a historical version back to an editable state, you have two options:

* **Restore historical version** – replaces the current version with the selected historical one. The restored version becomes the new **Current** version and can be edited and evaluated as usual. The previously current version is saved to the history list, ensuring that no data is lost.

<figure><img src="/files/xJ5eOif8u4Z7svbhqLkn" alt=""><figcaption></figcaption></figure>

* **Clone historical version** – creates a completely new rule based on the selected historical version. The new rule opens immediately in the editor and behaves like any other newly created rule.

<figure><img src="/files/cmpGUucP1G36ngtifGwZ" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Don't forget to change aliase after cloning.
{% endhint %}

#### How it relates to editing

The **History** panel records only *saved* versions of a rule.\
Actions performed using **Undo** and **Redo** affect the current unsaved state of the rule and are not stored here until you save the rule again.


# Execution Strategy

Execution strategy allows you to change the outcome produced by the rule solver. \
There are several options for the execution strategy described below.

## How to Set Execution Strategy

You can set the execution strategy in two ways:

* [**Solver API**](/doc/api/rule-solver-api) → by adding the appropriate HTTP header.
* [**Test Bench**](/doc/rules/common-rule-features/test-bench) → select the strategy from the dropdown.

<div><figure><img src="/files/uRYLcZp6MEcxKrGLhBoC" alt=""><figcaption><p>Options for Decision Table</p></figcaption></figure> <figure><img src="/files/XVAFQaCt50WQsCtnxF97" alt=""><figcaption><p>Options for Lookup Table</p></figcaption></figure></div>

## Allowed Strategies per Rule Type

| Rule Type                        | Allowed Strategies                         |
| -------------------------------- | ------------------------------------------ |
| Decision Table                   | Standard, Array, First Match, Evaluate All |
| Decision Tree                    | Standard, Array                            |
| Scripting Rule                   | Standard, Array                            |
| Rule Flow                        | Standard, Array                            |
| Decision Flow + Integration Flow | Standard                                   |
| Lookup Table                     | Lookup Exists, Lookup Value                |

## Setting Strategy via API

### Standard Rules Header

For all rule types except Lookup Tables, use the `X-Strategy` header to set the execution strategy:

| HTTP Header | Possible value |
| ----------- | -------------- |
| X-Strategy  | STANDARD       |
| X-Strategy  | ARRAY          |
| X-Strategy  | FIRST\_MATCH   |
| X-Strategy  | EVALUATE\_ALL  |

{% hint style="warning" %}
If the header is not specified or contains an invalid strategy, the system automatically uses the **STANDARD** strategy.
{% endhint %}

### Lookup Table Header

Lookup Tables use a dedicated header `X-Lookup-Method` instead of `X-Strategy` :

| HTTP Header     | Possible value |
| --------------- | -------------- |
| X-Lookup-Method | LOOKUP\_VALUE  |
| X-Lookup-Method | LOOKUP\_EXISTS |

{% hint style="warning" %}
If the header is not specified, the system automatically uses the **LOOKUP\_VALUE** strategy.
{% endhint %}

## Strategy Behavior

### Standard

Returns all matching rows in the same order as they appear in the rule.

If 2 rows are matching the input, the output will contain all matching rows:

```json
[
  {
    "client": { "segment": "affluent" },
    "profitability": 1
  },
  {
    "client": { "segment": "top affluent" },
    "profitability": 1.6
  }
]
```

#### **Useful for:**

* Getting all possible matches for a given input.
* Scenarios where multiple rules can apply simultaneously.

### First Match

Returns only the first matching row from the rule. Evaluation stops after the first match is found.

If 2 rows are matching the input, only the first match is returned:

```json
{
  "client": { "segment": "affluent" },
  "profitability": 1
}
```

#### **Useful for:**

* Priority-based rules where order matters.
* Decision scenarios where only one outcome should apply.

{% hint style="info" %}
Available for **Decision Tables only**.
{% endhint %}

### Array

Returns all matching outputs merged into a single object where each output field contains an array of all matched values.

If 2 rows are matching the input, the outputs are returned in array format:

```json
{
  "client": {
    "segment": [
      "affluent",
      "top affluent"
      ]
  },
  "profitability": [
    1,
    1.6
  ]
}
```

#### **Useful for:**

* Aggregating multiple matching results into a single response.
* Building lists of applicable values from multiple matches.

### Evaluate All

Returns a result for every row in the table regardless of whether it matched or not. Each result includes a `_match` field indicating whether that row was satisfied by the input.

```json
[
  {
    "client": {
      "segment": "affluent"
    },
    "profitability": 1,
    "_match": true
  },
  {
    "client": {
      "segment": "top affluent"
    },
    "profitability": 1.6,
    "_match": false
  }
]
```

#### **Useful for:**

* Auditing and compliance - see which rules applied and which didn't.
* Debugging complex tables with many conditions.
* Satisfiability analysis across all rows - table has N rows, the response will contain N objects.

{% hint style="info" %}
Available for **Decision Tables only**.
{% endhint %}

### **Lookup Value**

Returns the value found in the Lookup Table that match the input. This is the standard way to retrieve data from a Lookup Table.

```json
{ "output": "value 1" }

// Can return entire row if no column is specified:
{
  "output": {
    "Primary Key": "inputKey",
    "column 1": "value 1",
    "column 2": "value 2"
  }
}
```

#### **Useful for:**

* Retrieving actual data stored in the Lookup Table.
* Any scenario where you need the actual stored value.

For detailed information with examples see Lookup [Value function](/doc/rules/lookup-table/using-lookup-tables-in-rules#lookup_value).

{% hint style="info" %}
Available for **Lookup Table only**.
{% endhint %}

### **Lookup Exists**

Returns a boolean indicating whether a matching record exists in the Lookup Table, without returning the actual value.

```json
{ "output": true }
```

#### **Useful for:**

* Validating if a value is in an allowed list.
* Checking membership (e.g., is this customer in the VIP list?).
* Input validation before processing.
* Blacklist/whitelist verification.

For detailed information with examples see [Lookup Exist function](/doc/rules/lookup-table/using-lookup-tables-in-rules#lookup_exists).

{% hint style="info" %}
Available for **Lookup Table only**.
{% endhint %}


# Rule Dependencies

Discover how rules are connected

Rule dependencies show the hierarchical and interconnected relationships between rules depending on each other. Rule dependencies are crucial for understanding the logical flow of rules and ensuring that they are applied correctly.

## Dependencies tree overview

The **rule dependency view** displays a hierarchical tree structure showing how rules are linked to one another. The rule you're currently viewing is at the top of the tree, and each rule listed beneath it represents a **direct dependency**—meaning the current rule relies on the output or execution of the rule immediately below it. This relationship continues down the structure, forming a chain of dependent rules. Understanding this hierarchy helps you trace how logic flows across multiple rules and ensures that all required inputs or results are properly defined before a rule is executed.

<figure><img src="/files/jB3RUuI64y5mTwTA175n" alt=""><figcaption><p>Dependency tree in rule settings</p></figcaption></figure>

Each dependency in the structure is a clickable link to get to the rule details and solve errors.

### Possible errors

* **Rule not found -** rule with the identifier (id, alias) was not found&#x20;
* **Duplicity id / alias -** more rules with the same identifier (id, alias)&#x20;
* **Circular dependency -**  rules depend on each other in a loop
* **Rule not published -** rule is not published and cant be solved

{% hint style="warning" %}
Rule dependencies won't be found when rules point to each other dynamically (e.g., using for loop).
{% endhint %}

Overall, a rule dependency tree acts as a preventive measure by providing an organized, visual representation of rule dependencies. This aids in maintaining the integrity of the rule-based system, reduces the likelihood of errors, and supports efficient development and troubleshooting processes.


# Rule Export & Import

The rule export and import functionality allows you to transfer rules by saving them as files. This is useful for:

* Backing up rules as files.
* Editing rule tables in Excel before importing.
* Sharing rules with external parties who don't have access to your space.
* Migrating rules across different environments or instances.

#### **Supported Formats**

The available export/import formats depend on the rule type:

| Rule Type        | JSON | XLSX | CSV |
| ---------------- | ---- | ---- | --- |
| Decision Table   | ✅    | ✅    | ❌   |
| Decision Tree    | ✅    | ❌    | ❌   |
| Scripting Rule   | ✅    | ❌    | ❌   |
| Decision Flow    | ✅    | ❌    | ❌   |
| Integration Flow | ✅    | ❌    | ❌   |
| Lookup Table     | ✅    | ✅    | ✅   |
| Rule Flow        | ✅    | ❌    | ❌   |

#### **Alternative: Cross-Space Rule Sharing**

**For direct space-to-space transfers:** If you need to share a rule to another space and you are a member of both spaces, you can use the **Share with Space** button. This allows you to directly share the same rule to another space instantly, without exporting and importing files.

For more information, see [Cross-Space Rule Sharing](/doc/rules/common-rule-features/cross-space-rule-sharing)

This documentation section includes detailed guides on how to **export and import rules**, providing step-by-step instructions to help you manage rule transfers efficiently.


# Rule Export

You can export rules individually, an entire folder containing multiple rules, or export the entire space.

### **Method 1: Export from Rule List**

#### **For Individual Rules:**

1. Navigate to the **Rule List** section.
2. Right-click on the rule or click the **three dots** menu.
3. Select **Export.**
4. Choose your format: **JSON** or **XLSX** (if available for that rule type).
5. The file will be downloaded automatically.

<figure><img src="/files/smpicNfjunLfy0LjcJb4" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}
Flows can reference other rules via aliases. When exporting them individually, be aware that:

* The exported Flow will contain references to other rules by their aliases, **but not to the rules themselves**.
* If referenced rules are missing during import, the Flow may not work correctly.
  {% endhint %}

{% hint style="success" %}
Export Flow rules together with their dependencies in a folder, or export the entire space to ensure all referenced rules are included.
{% endhint %}

#### **For Entire Folders:**

1. Navigate to the **Rule List** section.
2. Right-click on the folder or click the **three dots** menu.
3. Select **Export Folder.**
4. All rules within the folder will be exported.

<figure><img src="/files/sLidHfIzqd8wrwX8cStO" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
When exporting folders, all rules are exported in the JSON format.
{% endhint %}

#### **For Entire Space:**

1. Navigate to the **Rule List** section.
2. Click the **three dots** menu next to the **Create** button in the top right corner.
3. Select **Export Space.**
4. The export includes all rules, folders, and their structure.

<figure><img src="/files/D9CyUfhdN4spQyS94uyE" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
When exporting space, all rules are exported in the JSON format.
{% endhint %}

### **Method 2: Export from the Rule Itself**

1. Open the rule you want to export.
2. Click the **three dots** in the top right corner to open **Rule Actions.**
3. Select **Export.**
4. Choose your format: **JSON** or **XLSX** (if available for that rule type).
5. The file will be downloaded automatically.

<figure><img src="/files/unXGoVtF0hOAHKXYNGCK" alt=""><figcaption></figcaption></figure>


# Rule Import

You can import rules individually, entire folders, or import the entire space. You can also update existing rules or create new versions of them.

## How to Import

### **Method 1:  Import as New Rule**

**Import from Rule List:**

1. Navigate to the **Rule Lists** section.
2. Select empty space or folder where you want to import the rule.
3. Click the **Import** button.
4. Select your file: **JSON** or **XLSX**.
5. Click the **Import** button.

<figure><img src="/files/JavIfjAgbdedhpHFj87h" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/sM21Vb9afB5EFszH3v2n" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="warning" %}
The imported rule may have the same name as an existing rule, but it cannot have the same alias. If an alias conflict is detected, you will receive a warning.
{% endhint %}

### **Method 2:  Override Current Version**

1. Open the rule you want to overwrite.
2. Click the **three dots** in the top right corner to open **Rule Actions**.
3. Select **Import Version**.
4. Choose your import **Overwrite latest version** - Replaces the current version.
5. Select your file: **JSON** or **XLSX**.
6. Click the **Import** button.

<figure><img src="/files/4fzVEPvpeRJP2YZmgkZG" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/fdWjcxUk7tbTuhonuvzc" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="info" %}
You can find all previous changes in the [history tab](/doc/rules/common-rule-features/rule-history).
{% endhint %}

### **Method 3:  Import as New Version**

1. Open the rule you want to overwrite.
2. Click the **three dots** in the top right corner to open **Rule Actions**.
3. Select **Import Version**.
4. Choose your import **Import as new version** - Creates new version of rule you are importing with name and alias of current one.
5. Select your file: **JSON** or **XLSX**.
6. Click the **Import** button.

<figure><img src="/files/4fzVEPvpeRJP2YZmgkZG" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/pvBRtvGrEFYVUW3AHwUX" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="/files/2xU6jG4fWfETZuLVxd6T" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The imported rule's status depends on the `status` field in the exported file. More details about rule statuses, see [Rule Status](/doc/rules/common-rule-features/rule-settings/rule-state).
{% endhint %}

## File Format Requirements

### JSON Format

#### Base Schema

Every rule import must include these mandatory fields:

```json
{
    "type": "rule-type",      // See rule-specific types below
    "name": "Rule Name",      // Any string
    "status": "published",    // "published" or "pending"
    "inputSchema": {},        // JSON object defining input structure
    "outputSchema": {}        // JSON object defining output structure
}
```

{% hint style="warning" %}
If no `ruleAlias` is specified in the import file, one will be generated automatically.
{% endhint %}

#### Rule Type-Specific Requirements

In addition to the base schema, each rule type requires specific additional fields:

***

**Decision Table**

```json
{
  "type": "decision-table",
  "decisionTable": {
    "columns": [],      // Array with at least one input column and one output column
    "rows": []          // Array of row data (can be empty)
  }
}
```

**Scripting Rule**

```json
{
    "type": "complex-rule",
    "script": {}         // String containing JavaScript code
}
```

**Lookup Table**

```json
{
    "type": "lookup-table",
    "primaryKeyColumn": {},   // Object defining the primary key column
    "columns": [],            // Array defining all table columns
    "data": {}                // List of objects containing table data rows (can be empty)
}
```

**Decision Flow**

```json
{
    "type": "workflow",
    "workflowData": {}    // Object containing flow structure and nodes
}
```

**Integration Flow**

```json
{
    "type": "integration-flow",
    "workflowData": {}    // Object containing integration flow structure and nodes
}
```

### **XLSX Format**

For detailed XLSX import specifications, see [Managing Decision Table in Excel/Google Sheets](/doc/rules/common-rule-features/rule-export-and-import/managing-decision-table-in-excel-google-sheets)

### CSV Format

For detailed CSV import specifications, see [Lookup Table CSV Import](/doc/rules/lookup-table/data-import-and-export)


# Managing Decision Table in Excel/Google Sheets

{% hint style="warning" %}
As of release **1.19.0**:&#x20;

The following description applies to the second version of XLSX export. Version 1, which can still be accessed via the **Deprecated → XLSX v.1** menu, is now outdated. While version 1 remains usable for imports, it lacks support for some of the newer features. **We highly recommend switching to version 2.**

For more information on deprecated formats, refer to the [dedicated section](/doc/rules/common-rule-features/rule-export-and-import/manage-tables-excel-gsheets).
{% endhint %}

## Managing Decision Tables Outside the App

You can manage decision tables outside of the DecisionRules application for easier, faster, and clearer editing. We recommend using Microsoft Excel or Google Sheets, as they support the XLSX format.

{% hint style="danger" %}
Other formats like ODT or simple XLS are not compatible.
{% endhint %}

There are two ways to create decision tables in XLSX format:

1. Create an XLSX file from scratch, following the exact format outlined here.
2. Start with a basic table in DecisionRules, export it, and then edit it.

We recommend the second option for ease of use.

## File Structure of XLSX Format

Imported and exported files require both mandatory and optional structural elements. The file contains four sheets:

## Settings

### Mandatory Elements

* **Export Version**: Always set to **2**.
* **Name**: The name of the decision table.
* **Rule Alias**: An[ alias for the rule](/doc/rules/common-rule-features/rule-settings/rule-alias); only English letters, numbers, and hyphens ("-") are allowed.
* **Version**: The [version number](/doc/rules/common-rule-features/versioning) of the rule.
* **Status**: The decision table's [status](/doc/rules/common-rule-features/rule-settings/rule-state), either **published** or **pending**.
* **Input Model:** Describes the [input variables](/doc/rules/common-rule-features/input-and-output) for the decision table, where each variable is defined as an object with attributes or substructures.
* **Output Model**: Describes the expected [output variables](/doc/rules/common-rule-features/input-and-output) for the decision table.

### Optional Elements

* **Rule ID**: The unique ID for the rule, automatically generated if not provided during import.
* **Created**: The creation date in ISO 8601 format, automatically generated if not provided.
* **Tags**: An array of [rule tags](/doc/rules/common-rule-features/rule-settings/tagging), which can be an empty array or a list of strings if provided.
* **Note**: A description of the table.

### Settings Example:

![Settings in the xlsx file](/files/DYSS4gcPZZlsnjhp2xjK)

## Rule Variables

There are no mandatory elements in this section; you can define the [rule variables ](/doc/rules/common-rule-features/variables/rule-variables)here if needed. This section includes two columns: **variable name** and **value**, just as in the application.

<figure><img src="/files/BUjW9VfBfl2r78fzpjba" alt=""><figcaption><p>Rule variables in the xlsx file</p></figcaption></figure>

<figure><img src="/files/ll5FeEMM1yOE012Eivwo" alt=""><figcaption><p>Rule variables in the app</p></figcaption></figure>

## Table

This sheet contains the decision table itself.

<figure><img src="/files/4e0YZe9pwAvbYRuBmC08" alt=""><figcaption><p>Table in the Table sheet of xlsx file</p></figcaption></figure>

<figure><img src="/files/7ne3VOkgGtwjdt21JGhe" alt=""><figcaption><p>The table in the DecisionRules app</p></figcaption></figure>

### Columns Settings

Each column requires three **mandatory** headers:

* **Column Alias**: [The unique identifier](/doc/rules/decision-table/decision-table-designer#set-column-alias) for the column, which can contain only English letters, numbers, and hyphens.
* **Column Type**: Must be set to **condition**, **calculation**, or **output**. For more information on column types and their order, refer to the [table designer](/doc/rules/decision-table/decision-table-designer#column-types-and-table-structure) section.
* **Column Title**: The name of the column.

Optional Element:&#x20;

* **Column Value**: This field, located under the column title, maps the column to a value such as input, output, or variables. While optional in the XLSX file, it is essential for table solving, and columns must be mapped once the table is imported.

<div align="center"><figure><img src="/files/8IkhMoJ6Ue5QZxGoe1RK" alt=""><figcaption><p>A column defined in xlsx</p></figcaption></figure> <figure><img src="/files/sjK8YpkQKlW2XPhMu0JK" alt=""><figcaption><p>The same column in the app </p></figcaption></figure></div>

### Rows Settings

Each row includes several options:

* **Active**: Defines whether the row is [activated or deactivated](/doc/rules/decision-table/decision-table-designer#deactivate-and-activate-row). Accepts **Yes** or **No** values; if left empty, the default is **No**.
* &#x20;**Time Validation**: Specifies the time range during which the[ row is valid](/doc/rules/decision-table/decision-table-designer#time-row-validation). This accepts an object in the format `{"from":"YYYY-MM-DD HH:MM Z", "to":"YYYY-MM-DD HH:MM Z"}`, where **Z** represents the time zone in the `±HH:MM` format.&#x20;

{% hint style="danger" %}
Time zones must be specified for both **from** and **to**, even if only one limit is needed.
{% endhint %}

<div><figure><img src="/files/Ny97RXWoW0AzIzt9Qica" alt=""><figcaption><p>Row settings xlsx</p></figcaption></figure> <figure><img src="/files/rDkSEw9VwHsCIKIhOrsD" alt=""><figcaption><p>Row settings app</p></figcaption></figure></div>

### Table Content

Each row for each column contains two parts:

* **Operator**: The table [operator](/doc/rules/data-types-and-functions/operators). Available operators can be selected from a dropdown list. Calculation columns must use the **function** operator.
* **Value**: The cell value of the table. For restrictions on cell values, refer to the [Supported Data Types](/doc/rules/data-types-and-functions/data-types) and [Operators sections](/doc/rules/data-types-and-functions/operators)

<div><figure><img src="/files/4DnTL3djeFi43ywjzaL6" alt=""><figcaption><p>Operators and values condition columns xlsx</p></figcaption></figure> <figure><img src="/files/zyZGjRnK8aQrfou0HLct" alt=""><figcaption><p>Operators and values condition columns app</p></figcaption></figure></div>

## Valid Values

This sheet defines [valid values ](/doc/rules/decision-table/decision-table-designer/table-operations/valid-values)for each column. It includes two headers:

* **Column Alias**: Maps the column to the valid value. The alias must match the alias used in the [Table sheet](#table). If the app cannot locate the column with this alias, those valid values will not be applied. This field is case-sensitive.
* **Column Name**: This optional field is for user convenience, so you don't have to memorize which alias corresponds to which column.

To add valid values for a column, enter the column alias and column name, then list the values one under the other:

<div><figure><img src="/files/HIkkEYGt3yyZNortBJJZ" alt="" width="174"><figcaption><p>Column alias in the Table sheet</p></figcaption></figure> <figure><img src="/files/jDeZMDmC2AVkJYdygLo0" alt="" width="223"><figcaption><p>Valid values for the column</p></figcaption></figure></div>

When you import the table into the app, [valid values](/doc/rules/decision-table/decision-table-designer/table-operations/valid-values) will appear in the column settings, and cells containing invalid values will be flagged:

<figure><img src="/files/llMLLuJguybZnw5gmeGf" alt="" width="200"><figcaption><p>Invalid value</p></figcaption></figure>

## Final Notes

Managing Decision Tables in Excel or Google Sheets offers a structured approach with specific settings for version control, rule variables, columns, rows, and valid values. XLSX version 2, the recommended format, supports advanced features that are not available in version 1. Adhering to the correct structure ensures smooth imports, consistent decision-making rules, and easier integration of validation for input and output variables.


# Deprecated Formats: XLSX v.1 and CSV

Decision tables management in XLSX files.

{% hint style="danger" %}
As of version 1.19.0, these export formats have been deprecated. They are still available but lack support for newer features. We recommend using the [updated XLSX format](/doc/rules/common-rule-features/rule-export-and-import/managing-decision-table-in-excel-google-sheets) for greater flexibility and better control over decision tables.
{% endhint %}

## Managing Decision Tables Outside the App

You can manage decision tables outside of the DecisionRules application for easier, faster, and clearer editing. We recommend using Microsoft Excel or Google Sheets, as they support the XLSX format.

{% hint style="danger" %}
Other formats like ODT or simple XLS are not compatible.
{% endhint %}

There are two ways to create decision tables in XLSX format:

1. Create an XLSX file from scratch, following the exact format outlined here.
2. Start with a basic table in DecisionRules, export it, and then edit it.

We recommend the second option for ease of use.

![Exported table xlsx](/files/HStZAOVpRKpqzQq1rYmZ)

This exported table includes only one row to show its structure. After export, the table consists of several key elements:

### Header

The header contains four basic elements:

![](/files/-MZlqcY0bNx0FSta2Kwk)

* **Name:** the name of the table
  * text format
  * can be changed
  * import as a new table - this name is set
  * import to existing table - name from XLSX file is not changing the name
* **Description:** text, you can write here anything that appears in the table settings
* **Type:** the only supported type is **decision-table**
* **Status:** [more information](/doc/rules/common-rule-features/rule-settings/rule-state)
  * you have to choose - pending/published

### Rule Variables

If the rows contain any rule variables, it is important to either add them to the excel or after you import the decision table into our app. If you export a decision table from our app, the rule variables will be automatically added.

* &#x20;If you choose to add them in the excel file, you have to add them to the cell D2. The rule variables are name=value pairs with equal sign in between them. The rule variables have to be separated by semicolons except for the last variable. See cell D2 to see the example.

{% hint style="warning" %}
Commas and double quote marks will most likely cause trouble, so please try to avoid it.

If you really need to use them, use these codes that will be converted in our app.

Instead of comma, write %2C

Instead of double quote mark, write %22
{% endhint %}

![](/files/LhGa3oj2o69rJMne5YL3)

### Row Activity

Row activity column is responsible for activating/deactivating row once it is imported back to our app.

* For older decision tables that don't have the 'Is Row Active?' column, it is necessary to add this exact text to the 6th row, right next to the last Result. The text inside the cell has to be exactly 'Is Row Active?'.
* Decision tables newly exported already have this column prepopulated with the values that align with the activity status in our app.&#x20;
* Only two allowed values for the activity status is either TRUE or FALSE.
* To see an example, look at the penultimate column of the decision table below.&#x20;

### Row Time Validation

Row time validation column is responsible for adding time validation to particular rows.

* For older decision tables that don't have the 'Row Time Validation' column, it is necessary to add this exact text to the 6th row, right after the row activity column. The text inside the cell has to be exactly 'Row Time Validation'.
* One of the forms the date can have looks like such:

![](/files/YJBlRF85amUOvwkmVldo)

{% hint style="warning" %}
Please note that the format can have also other forms depending on which time properties you want to validate. Best option is to add the time validation inside DecisionRules at least to one row, so that you know how it should look like.
{% endhint %}

* If the row doesn't have a time validation then simply leave the cell empty.
* To see an example, look at the last column of the decision table below.

{% hint style="warning" %}
CSV Caveat:

If you edit the decision table inside a CSV file, there are two possible scenarios...

1. Some of the rows have a date validation and others don't, in that case add the validation to the rows where it should be and to the rows that don't have date validation, simply put a comma there and leave it empty.
2. None of the rows have a date validation. If that is the case, you can simply remove the "Row Time Activity" value and not add anything to the rows.
   {% endhint %}

### Table

![](/files/dO58LxKRANXn7O5mAtt7)

The table consists of two basic parts:

* CONDITION - input (yellow)
* RESULT - output (red)

Every condition and result is a column in a table with its properties such as input/output model, column, operator and value.

### **CONDITION**

We will describe what does each line in the table means in the following example.

![](/files/-MZm2qFL7-qchCO9oCFF)

Every condition is made of 2 columns.

* **Condition -** it has to be over both columns, it indicates the input (always the same)
* **Product Count -** the name of the column in the decision table
* **productCount -** input model attribute
  * **depositSum.usd** - input model attribute with embedded attribute
* **Operator** - dropdown to choose from the operator list (the header is always the same)
* **Value** - the values by themselves (the header is always the same)

### **RESULT**

![](/files/-MZm3US0p_TtmgvrY1-H)

* **Result -** it indicates the output (always the same)
* **Client Segment -** the name of the column in the decision table
* **client.segment -** output model attribute with embedded attribute
  * **profitability** - output model attribute
* **Value** - the values by themselves (the header is always the same)

### Final notes

{% hint style="success" %}
In MS Excel or Google Sheets, you can add rows, columns, attributes, values and choose operators. The changes will be imported to Table Editor.
{% endhint %}

All the changes made in MS Excel or Google Sheets will be validated upon the import back to DecisionRules, in case of nonconformity the tool will notify the user to make sure all the details are correct and they can be imported.

{% hint style="info" %}
To add rows or columns the easiest way is to duplicate them from the table, then to change the properties.
{% endhint %}


# Cross-Space Rule Sharing

The **Share with Space** feature allows you to share rules across multiple spaces, enabling collaborative editing while maintaining a single source of truth.

**Key difference from Export/Import:**

* **Export/Import:** Creates an independent copy of the rule
* **Share with Space:** Creates a shared reference to the same rule instance

## **How Shared Rules Work**

When you share a rule with another space, the rule becomes accessible in both the original space and the shared space. However, it is still the same rule instance - not a copy.

{% hint style="warning" %}
**Share with Space** does not work with Flows because they are based on different rules in space.
{% endhint %}

### **Synchronized Changes**

Any changes made to the rule in any space where it's shared will be reflected in all other spaces.\
This includes:

* Rule logic and structure
* Input/Output models
* Rule variables
* Settings and configuration
* All version history

### Version Synchronization

When you create a new version of a shared rule in any space, that version is automatically created in **all other spaces** where the rule is shared.

**What this means:**

* Version history is identical across all shared spaces.
* New versions propagate instantly.
* Version status syncs.
* You cannot have different versions in different spaces.

{% hint style="danger" %}
**Publishing New Versions Affects All Spaces**

When someone creates a new version of a shared rule, it starts in pending status across all spaces. However, if any user with publish permissions in any shared space publishes that version, it becomes active everywhere immediately. If a Flow in your main space uses the `latest version` of that shared rule, its logic will change the moment someone publishes the new version.&#x20;

**Carefully control both version creation and publish permissions in all spaces where rules are shared.**
{% endhint %}

More about permissions you can find in section [Space Roles](/doc/organization/resources/space-roles)

## **When to Use Share with Space**

**Share with Space** is particularly useful when you want dedicated users to have permission to edit rules in their own spaces, while their changes impact a larger project they don't have direct access to.

**Example Scenario:**

* **Main Project Space:** "Production Pricing Engine" (restricted access)
* **Regional Spaces:** "EU Pricing Team", "US Pricing Team", "APAC Pricing Team".
* All spaces are within the same organization.

**How it works:**

1. Share pricing rules from Production space to regional team spaces.
2. Regional teams can edit rules within their own space.
3. Changes are automatically reflected in the Production space.
4. Regional teams never need access to the main Production space.

## How to Share a Rule

### Requirements and Prerequisites

Before you can share a rule with another space:

* You must **be a member** of both the source spaces.
* You must **have sharing permissions** in the source space.
* You must **have permission to create rules** in the target space.
* Spaces must be in the **same organization**
  * You cannot share rules between different organizations
  * You can share between your private spaces regardless of organization

### Sharing Process

#### **Method 1: From Rule List**

1. Navigate to the **Rule List** section.
2. Right-click on the rule or click the **three dots** menu.
3. Select **Share with Space.**
4. Choose the target space from the dropdown (only spaces in your organization will appear)

<figure><img src="/files/Ew7DdzN8VEYnYMzQYcsv" alt=""><figcaption></figcaption></figure>

#### **Method 2: From the Rule Itself**

1. Open the rule you want to share.
2. Click the **three dots** in the top right corner to open **Rule Actions.**
3. Select **Share with Space.**
4. Choose the target space from the dropdown.

<figure><img src="/files/apjElOCGBCSDSA5xE6tT" alt=""><figcaption></figcaption></figure>


# Rule Comparison

Some types of rules support a comparison feature, letting you easily identify differences between two separate rules or rule versions.

Read more about the comparison of the specific rule types in the articles below.

{% content-ref url="/pages/33OiWGGToI8UMFNejyuu" %}
[Decision Table Comparison](/doc/rules/common-rule-features/rule-comparison/decision-table-comparison)
{% endcontent-ref %}

{% content-ref url="/pages/UDlWNeRIOcZ2NZELHYZz" %}
[Decision Tree Comparison](/doc/rules/common-rule-features/rule-comparison/decision-tree-comparison)
{% endcontent-ref %}

{% content-ref url="/pages/z3Ul0HFfll6wwtP7eqg9" %}
[Scripting Rule Comparison](/doc/rules/common-rule-features/rule-comparison/scripting-rule-comparison)
{% endcontent-ref %}

## Accessing Comparison

{% hint style="info" %}
The rule comparison feature is available for specific subscriptions.
{% endhint %}

Only rules of the same type can be compared to each other (i.e. Tables to Tables, Scripts to Scripts).&#x20;

To enter the rule comparison view, right-click on a rule in the Folders menu and choose 'Compare'.

You can also find the same option under each rules' settings or after clicking the ![](/files/EVlKhGPKXIW94tIUU8p8)  on a rule in the 'Business Rules' menu.

<figure><img src="/files/U49wZKsVgQtqQ059zwlp" alt=""><figcaption></figcaption></figure>

You will be presented with a pop-up screen where the Original rule will have been filled in with the rule you triggered comparison on. Next you should choose which rule to compare the Original rule to (i.e. choose the Reference rule).&#x20;

<figure><img src="/files/ayRt9hiRNeG6bTrjsbQR" alt=""><figcaption></figcaption></figure>

After choosing the reference rule, click the Compare button.


# Decision Table Comparison

Table comparison view can be a bit intimidating at first. In this article, we will do our best to clearly explain how to read it and use it most effectively.

## Introduction

Imagine you have a production Decision Table and you want to make major changes to the logic behind it. Usually you would create a new version of said table and start changing it to fit your current needs. Once the table is done you test it and start using it in production.&#x20;

Now if the changes you made were really minor, you could probably remember what you changed. But for cases when you'd been working on version 2 for weeks you might forget what exactly has changed inside of each row or column. Enter Table Comparison.

{% hint style="info" %}
Decision Table Comparison is most useful when used between different versions of same rule.

When used on two completely different rules the result won't usually be very helpful.
{% endhint %}

### Common Use-Cases

* You want to review your changes before implementing a new rule version into production.
* You wish to simply and quickly [add a column](#adding-removed-cols-or-rows) from a different rule to the one in question.&#x20;
* Visualization of progress between versions of production rules.

## The Comparison view

Upon opening the comparison view, you should see a table very similar to the table you've originally opened the comparison on (i.e. the green table). The Reference table has been superimposed onto the Original table and discrepancies between the tables are shown by use of The Color System.&#x20;

{% hint style="warning" %}
Be aware that you still essentially only have the Original (Green) rule opened. Any changes you make to cells, rows or columns will affect only the Original rule.
{% endhint %}

### The Color System

In comparison view, each table is given a color. <mark style="background-color:green;">**Green**</mark> for the Original table (the currently open table) and <mark style="background-color:blue;">**Blue**</mark> for the Reference table (the table we are comparing to).&#x20;

* Rows and/or columns shown in **White** appear in both Tables.&#x20;
* If a row or column is colored in <mark style="background-color:green;">**Green**</mark> as well as displaying a circular <mark style="background-color:green;">**Green**</mark> badge, this means the row/column in question appears **ONLY** in the Green (Original) table.
* If a row or column is colored in <mark style="background-color:blue;">**Blue**</mark> as well as displaying a circular <mark style="background-color:blue;">**Blue**</mark> badge, this means the row/column in question appears **ONLY** in the Blue (Reference) table
* Changes are shown differently between rows and columns
  * If a **row** displays a circular <mark style="background-color:yellow;">**Yellow**</mark> badge at least one of it's cell will be highlighted in <mark style="background-color:yellow;">**Yellow**</mark>. This means the row appears in **BOTH** tables but the highlighted cell's value has changed.
  * If a **column** displays a circular <mark style="background-color:yellow;">**Yellow**</mark> the column appears in **BOTH** tables but some of the column's features have changed. The column might now bare a different name, might have a different Input/Output Variable and/or might have a different Valid Values selection.

<figure><img src="/files/bFfir2g8dDrsALa2FUXK" alt=""><figcaption><p>Rows 9&#x26;10 on Australian birds has been added in v2. On the other had, column labelled '<strong>Ranking</strong>' has been removed from v2 when compared to v1. The selection of birds of Asia is now missing the "Golden Pheasant" entry.  </p></figcaption></figure>

### Interactivity

Table comparison doesn't only offer great informative value, it also makes manipulation with rows and columns easier.

#### Adding removed cols or rows

Any <mark style="background-color:blue;">Blue</mark> row or column can easily be added into the Original table by clicking the <mark style="background-color:blue;">Blue</mark> circular badge next to the row's number or inside the column's header.&#x20;

#### Merging rows

By clicking the <mark style="background-color:yellow;">Yellow</mark> circular badge next to a changed rows number you can show the row's state as it appears in the Reference table. If you prefer the row's state from the Reference rule, click the arrow ![](/files/NwFl7g2jnUB4y5dETk4H) to 'Merge' these two rows - changing the row's cells to those of the Reference table

You can always revert these changes by clicking the turquoise badge and then the undo arrow ![](/files/BJlZnmdQhM4HaxP6CM66).

<figure><img src="/files/avc607MhjdrTPgx5oarH" alt=""><figcaption></figcaption></figure>

#### Real-time editing

Since the comparison view is just a different rendering of the currently open rule you can still edit the table as you would outside of the comparison view. Changing cells' values, adding and removing rows and columns etc. is still all available and the comparison should change accordingly.

{% hint style="warning" %}
This might sometimes lead to unintuitive behavior as with most changes the comparison will be re-evaluated and the result might suddenly seem different after making a seemingly insignificant change.
{% endhint %}

#### Navigation over row differences

To make navigation over compared rules easier, you can click the arrows on the comparison bar at the top to navigate to the next and previous found row differences.

### Comparison Statistics

To quickly see how and how much the compared rules differ, you can click the chart icon in the top left to display a dropdown summarizing the amount of differences between the tables, categorized over rows and columns.


# Decision Tree Comparison

In this article, we will explain the decision tree comparison.

## Introduction

Comparing rules in general can be a very useful feature. Decision trees are among the rule types that support this feature.

{% hint style="info" %}
Decision tree comparison is most useful when used between different versions of same rule. \
When used on two completely different rules, the result won't usually be very helpful.
{% endhint %}

### Common Use-Cases

* You want to review your changes before implementing a new rule version into production.
* Visualization of progress between versions of production rules.

## The Comparison View

Upon opening the comparison view, you should see a tree very similar to the tree you've originally opened the comparison on. The Reference tree will be superimposed onto the Original tree and discrepancies between the two will be shown by use of a color system, as described below.

{% hint style="info" %}
For decision trees, the comparison view does not allow any editing. To make changes in either the Original or the Reference tree, you have to quit the comparison view.
{% endhint %}

### The Color System

In comparison view, each tree is given a color. <mark style="background-color:green;">**Green**</mark> for the Original tree (the currently open one) and <mark style="background-color:blue;">**Blue**</mark> for the Reference tree (the tree we are comparing to). The color system actually identical to the color system used in decision table comparison.

* Tree nodes that are without additional coloring appear in both trees.
* If a tree node is colored in <mark style="background-color:green;">**Green**</mark>, this means that it appears **ONLY** in the Green (Original) tree
* If a tree node is colored in <mark style="background-color:blue;">**Blue**</mark>, this means that it appears **ONLY** in the Blue (Reference) tree
* Changes are displayed as two nodes, one <mark style="background-color:green;">**Green**</mark> and one <mark style="background-color:blue;">**Blue**</mark>, enclosed in a <mark style="background-color:yellow;">**Yellow**</mark> container. This means that the node was found in  **BOTH** trees, but it is not identical.

<figure><img src="/files/LKjZzBmdpWnGefE1iDFP" alt=""><figcaption></figcaption></figure>

### Comparison Statistics

To quickly see how and how much the compared rules differ, you can click the chart icon in the top left to display a dropdown summarizing the amount of differences between the trees, enumerated by counting the identical and different tree nodes.


# Scripting Rule Comparison

Comparing scripting rules together is pretty straight-forward

## Overview

Like in most modern IDEs, our Scripting Rules offer a code-comparison feature. Changed lines will be highlighted as shown in the image below.

<figure><img src="/files/gkhsSGi4ied1oQxWJyyZ" alt=""><figcaption><p>Comparison of two Scripting Rules. In rule version 1, we had a function that divides two numbers and returns the result. In rule version 2 we decided to changed this function to multiply two numbers instead.</p></figcaption></figure>


# Rule Lock

This feature further extends the control over the rules. In this article we will briefly explain how it works.

## Introduction

When you have a rule which you want to be visible to your colleagues and you also want it to be solvable, but you do not want anyone to change its logic, that’s where the Rule Lock enters the scene.

## Who can lock and unlock rules?

Considering the [3 basic roles](/doc/space/access#roles-and-permissions) in DecisionRules:

**Have** “Lock rule” permission:

* Admin
* Editor

**Do not have** “Lock rule permission”:

* Reader

You can of course create your own role and set its permissions however you want to fit your use cases. [Here](/doc/space/access#roles-and-permissions) is the part of our documentation dedicated to the topic.

<figure><img src="/files/AU5FpishrltlmZOGzME2" alt=""><figcaption></figcaption></figure>

## How to lock a rule?

You can lock a rule in three different places:

#### Folders

Just right click on the desired rule and lock / unlock the rule

<figure><img src="/files/xXXZaQzSuKMWi8jF1clW" alt=""><figcaption></figcaption></figure>

#### Rule settings

Go to the detail of the rule and lock / unlock the rule

<figure><img src="/files/pDs7RCzeoIDDl9jM31UU" alt=""><figcaption></figcaption></figure>

#### List of all rules

Go to the list of all rule and lock / unlock the rule

<figure><img src="/files/gj8iXQS8Wyf0tn2mnB4p" alt=""><figcaption></figcaption></figure>

## How to tell if the rule is locked?

You can tell the rule is locked for the first sight by the presence of the lock symbol. You can see it in three different places:

#### Folders

<figure><img src="/files/N3aluvgrFUkBYXF5OWik" alt=""><figcaption></figcaption></figure>

#### Rule detail

<figure><img src="/files/HFTYOc024C4K9Q0yhWjx" alt=""><figcaption></figcaption></figure>

#### List of all rules

<figure><img src="/files/FY5ptJU17lB4k3uZxT1S" alt=""><figcaption></figcaption></figure>

## What can not the user do with the locked rule?

When you lock the rule it basically becomes read only. That means that no one can change its logic. That includes:

* Changing Tags
* Changing Rule Variables
* Changing I/O JSON Model
* Turning on/off Audit Logs
* Adding Notes
* Publishing / Unpublishing the rule
* Changing rule-alias
* Changing name
* Doing any changes in the rule’s designer
* Changing rule’s position in folders&#x20;
* Deleting the rule
* Creating new version
* Importing a version

{% hint style="info" %}
If you are familiar with [roles](/doc/space/access#roles-and-permissions), by locking the rule you change permissions for this rule to the same permissions the Reader role does have for all rules.
{% endhint %}

## What can the user do with the locked rule?

When the rule is locked everyone can still:

* Find the rule in the space&#x20;
* Solve it
* Compare it to other rule
* Export it

{% hint style="warning" %}
You can import a new version of the rule BUT you can not overwrite the original one.
{% endhint %}

## Does locking the rule affect something else then the rule itself?

Yes it does. You can not delete a folder with at least one locked rule in it. Also, you will not be able to change the rule alias or name of a rule if there is another version of that rule which is locked (this is because the rule alias and name always have to be the same for all versions).<br>


# Teamwork Indicator

We added a teamwork indicator for rules, which tells you who is currently viewing the same rule as you

### How it works

This functionality allows you to avoid interference between individual editors, therefore it provides better user experience.

As soon as you open the rule detail you will see a badge in the navigation next to the name of the rule when someone else is viewing on the same rule.

<figure><img src="/files/HbVLJaD8vw8ns9zFnTNM" alt=""><figcaption><p>Teamwork Indicator</p></figcaption></figure>

Badge rotates periodically to show you the cumulative number of users looking at the rule (except for yourself).

When you hover over the badge, you will see email address of your colleagues currently viewing the rule.

{% hint style="warning" %}
When two or more users are logged in with the same account, they will not see each other. The teamwork indicator only indicates different accounts.
{% endhint %}


# Data Types & Functions

Rules rely on various **data types, operators, and functions** to process and evaluate information effectively. Understanding these core elements is essential for defining conditions, performing calculations, and transforming data within rules.

This section provides an overview of the **supported data types**, which include numbers, text, booleans, dates, arrays, and objects. It also introduces **operators and functions**, which are categorized into different groups such as mathematical, logical, text, date, integration, data, and array functions. These functions allow for complex rule execution, enabling dynamic decision-making and data manipulation.

Detailed pages in this section explain each **data types, operators, and function categories**, helping you apply them efficiently in your rules.


# Supported Data Types

## Data types in Decision Tables

All data in a decision table is stored as string values and is automatically cast when needed. Therefore, you don’t need to specify any data format for your[ input and output models](/doc/rules/common-rule-features/input-and-output). The automatic casting of conditions and results is described in the following sections.

### Condition Data Types

Conditions can be created using the following scalar data types:

* Number
* Boolean
* String
* Date

And collection data types:

* JSON Array

<figure><img src="/files/Z3ovaOaqYutOqMbi3xV5" alt=""><figcaption><p>examples of entry conditions</p></figcaption></figure>

{% hint style="warning" %}
The decimal separator is **always a dot**: **`5.5`**
{% endhint %}

#### Solver Request Data Example

The inputs below demonstrate the format in which you can send a request to match a particular row:

1. **Number:**

   ```json
   {
     "input": "2.31"
   }
   ```

   or

   ```json
   {
     "input": 2.31
   }
   ```
2. **Boolean (True):**

   ```json
   {
     "input": true
   }
   ```

   or

   ```json
   {
     "input": "true"
   }
   ```
3. **Boolean (False):**

   ```json
   {
     "input": false
   }
   ```

   or

   ```json
   {
     "input": "false"
   }
   ```
4. **String:**

   ```json
   {
     "input": "hello world"
   }
   ```
5. **Date and Time:**

   ```json
   {
     "input": "2024-09-23 13:27 +02:00"
   }
   ```

   or as extended ISO-8601:

   ```json
   {
     "input": "2024-09-23T13:27:00+02:00"
   }
   ```
6. **Array:**

   ```json
   {
     "input": ["first", 2, false]
   }
   ```
7. **Empty Value:**

   ```json
   {
     "input": ""
   }
   ```

{% hint style="danger" %}
The data cells now convert dates to strings. The **old object format is deprecated** but still supported. For example, the input:

<pre class="language-json"><code class="lang-json"><strong>{
</strong><strong>"input": {
</strong><strong>    "date": "2024-09-23",
</strong><strong>    "time": "13:27",
</strong><strong>    "timezone": "+02:00"
</strong><strong>    }
</strong><strong>}   
</strong></code></pre>

**will match** the new condition `2024-09-23 13:27 +02:00`.

Read more about [Date cells in the dedicated section.](/doc/rules/data-types-and-functions/operators/date-operators#date-cell-values)
{% endhint %}

#### Examples:

<table><thead><tr><th width="308.3333333333333">Condition [value in decision table]</th><th width="288">Solver Request Value [value send on API]</th><th>Result</th></tr></thead><tbody><tr><td><code>2.31</code></td><td><code>2.31</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>2.31</code></td><td><code>"2.31"</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>true</code></td><td><code>true</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>true</code></td><td><code>"true"</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>false</code></td><td><code>false</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>true</code></td><td><code>2</code></td><td><mark style="color:red;">Not Equal</mark></td></tr><tr><td><code>hello world</code></td><td><code>"hello world"</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>"2024-09-23 13:27 +02:00"</code></td><td><code>"2024-09-23 13:27 +02:00"</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>"2024-09-23 13:27 +02:00"</code></td><td><code>"2024-09-23T13:27:00+02:00"</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>"2024-09-23 13:27 +02:00"</code></td><td><p></p><pre class="language-json"><code class="lang-json">{
  "input": {
    "date": "2024-09-23",
    "time": "13:27",
    "timezone": "+02:00"
  }
}
</code></pre></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>"2021-03-17T13:17-09:00"</code></td><td><code>"2024-09-23 13:27 +02:00"</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td><code>"2021-03-17T13:17-09:00"</code></td><td><p></p><pre class="language-json"><code class="lang-json">{
  "input": {
    "date": "2024-09-23",
    "time": "13:27",
    "timezone": "+02:00"
  }
}
</code></pre></td><td><mark style="color:red;">Not Equal!</mark></td></tr><tr><td>&#x3C;empty></td><td><code>""</code></td><td><mark style="color:green;">Equal</mark></td></tr><tr><td>&#x3C;empty></td><td><em>Value not presented in input JSON</em></td><td><mark style="color:red;">Not Equal</mark></td></tr></tbody></table>

### Calculation Data Types

Calculation columns support all the data types used by result columns.

### Result Data Types

When calling the [Solver API](/doc/api/rule-solver-api), the response returns an array of results based on the decision table setup. Response values are automatically cast to the following data types:

* Boolean
* Number&#x20;
* String
* Date
* JSON Object
* JSON Array

#### Casting examples:

| Decision Table Result Value | Solver Response Value     |
| --------------------------- | ------------------------- |
| `true`                      | `true`                    |
| `false`                     | `false`                   |
| `"true"`                    | `\"true\"`                |
| `25`                        | `25`                      |
| `25.0`                      | `25`                      |
| `25.01`                     | `25.01`                   |
| `""`                        | `""`                      |
| Empty                       | `""`                      |
| `hello world`               | `"hello world"`           |
| `DATE(09.23.2024)`          | `"2024-09-22T22:00"`      |
| `{}`                        | `{}`                      |
| `{"data":123 }`             | `{"data":123 }`           |
| `{"data": "123" }`          | `{"data": "123" }`        |
| `[12,36,"542"]`             | `[12,36,"542"]`           |
| `[12,36,"542"`              | `"[12,36,\"542\""`        |
| `[12, 36, "542", [1,2] ]`   | `[12, 36, "542", [1,2] ]` |


# Operators and Functions

Description of operator types used in decision tables

## Operators in Decision Tables

Every condition cell in the decision table can have a different operator. There are three types of operators you can use: [Basic](/doc/rules/data-types-and-functions/operators/general-operators), [Dates](/doc/rules/data-types-and-functions/operators/date-operators) and [Functions](/doc/rules/data-types-and-functions/operators/functions).

### Basic Operators

Basic operators can be used for decision rules involving **Strings, Numbers**, or **Booleans**.

![Basic operators modal](/files/rz9yRHPlfdRh7nwSRt3p)

{% hint style="info" %}
List of [Basic operators](/doc/rules/data-types-and-functions/operators/general-operators).
{% endhint %}

### Date Operators

Date operators are specifically used for comparing dates.

![Dates operators modal](/files/dPyDkHUIKjWFUeld9EKD)

{% hint style="info" %}
List of [Date operators](/doc/rules/data-types-and-functions/operators/date-operators).
{% endhint %}

### Functions

Functions are specifically used to create custom function validations.

![Functions operators modal](/files/VEOqH2xwyYqF323FB2Ks)

{% hint style="info" %}
List of [Functions](/doc/rules/data-types-and-functions/operators/functions).
{% endhint %}


# Basic operators

Description of general operators used in decision tables

## List of Basic Operators

Each condition cell in the decision table allows you to select a different operator. Below is an example of some available basic operators:

![Basic operators modal](/files/rz9yRHPlfdRh7nwSRt3p)

{% hint style="danger" %}
Input values (left operands) are **auto-casted** to the necessary data type, and right-side operands are **also auto-casted**. No quotes are needed in table values.
{% endhint %}

### Anything (`ANY`)

The **Anything** operator is the simplest operator available. It always returns `true`, regardless of the input. It does not perform any comparison; it simply returns `true` for any input.

{% hint style="success" %}
The operator is useful in scenarios where you want a rule to be triggered without considering the specific content of the condition.
{% endhint %}

### Equals (`=`)

Compares scalar values like strings, numbers, and booleans and returns `true` if they are equal.

```javascript
// [request value] = [table value]

3 = 3                 // true
"3" = 3               // true
true = true           // true
"true" = true         // true
```

### Not equal (`!=`)

Compares scalar values and returns `true` if they are not equal.

```javascript
// [request value] != [table value]

3    != 3           //false
"3"  != 3           //false
3    != 4           //true
true != false       //true
```

### Is in (`IN`)

Returns `true` if the left operand is in the right operand's set, which must be an array. Members of the set can be separated by **pipe** (`|`), **comma** (`,`), **semicolon** (`;`)

```javascript
// [request value] IN [table value]

3     IN 1|2|3             // true
"a"   IN "a"|"b"|"c"       // true
"3"   IN 1|2|3             // true
"la"  IN "la-la"|"blah"    // false
```

{% hint style="warning" %}
Only exact matches.
{% endhint %}

### Not in  (`!IN`)

Returns `true` if the left operand is **not** in the right operand's set. Members of the set can be separated by **pipe** (`|`), **comma** (`,`), **semicolon** (`;`)

```javascript
// [request value] NOT IN [table value]

3   NOT IN 1|2|3              //false
4   NOT IN 1|2|3              //true
"a" NOT IN "a"|"b"|"c"        //false
"d" NOT IN "a"|"b"|"c"        //true
"3" NOT IN 1|2|3              //false
```

### Greater than or equal (`>=`)

Compares numbers or strings; returns `true` if the left operand is greater than or equal to the right operand.

* Numbers can be decimal or integer.
* String comparison is [similar to JS](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than_or_equal).

```javascript
// [request value] >= [table value]

5 >= 3              // true
3.1 >= 2.1          // true
"b" >= "a"          // true
"a" >= "a"          // true
true >= true        // true
true >= false       // true
```

### Greater than (`>`)

Returns `true` if the left operand is greater than the right operand.

* Numbers can be decimal or integer.
* String comparison is [similar to JS](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than).

```javascript
// [request value] > [table value]

5 > 3              // true
5 > 5              // false
3.1 > 2.1          // true
"b" > "a"          // true
true > true        // false
true > false       // true
```

### Less than or equal (`<=`)

Returns `true` if the left operand is less than or equal to the right operand.

* Numbers can be decimal or integer.
* String comparison is [similar to JS](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than_or_equal).

```javascript
// [request value] <= [table value]

3 <= 5              // true
3 <= 3              // true
2.1 <= 3.1          // true
"a" <= "a"          // true
"a" <= "b"          // true
true <= true        // true
false <= true       // true
```

### Less than (`<`)

Returns `true` if the left operand is less than the right operand.

* Numbers can be decimal or integer.
* String comparison is [similar to JS](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than).

```javascript
// [request value] < [table value]

3 < 5              // true
3 < 3              // false
2.1 < 3.1          // true
"a" < "b"          // true
true < true        // false
false < true       // true
```

### **Between** (`BTW`)

Returns `true` if the left operand is between the two values specified in the right operand, or is equal to one of them. The right operand must be a **range expression** defines the lower and upper boundaries for comparison.

* The operator evaluates whether the left operand falls within the inclusive range defined by the two values in the right operand array.

```javascript
// [request value] BTW [table value 1 AND table value 2]

4     BTW [3 AND 5]            // true
3     BTW [3 AND 5]            // true
4.0   BTW [3.0 AND 5.5]        // true
3.5   BTW [3.0 AND 5.5]        // true
"b"   BTW ["a" AND "c"]        // true
"a"   BTW ["a" AND "c"]        // true
true  BTW [true AND false]     // false
true  BTW [true AND true]      // true
```

{% hint style="warning" %}
The left operand can be a number, string, or boolean, and the right operand must be a range expression.
{% endhint %}

### Between left open (`BTW LO`)

Returns `true` if the left operand falls within the range defined by two values in the right operand, **excluding** the lower limit (left value) and **including** the upper limit (right value). If the left operand is equal to the lower limit, the result will be `false`.

```javascript
// [request value] BTW LO [table value 1 AND table value 2]

4     BTW LO [3 AND 5]           // true
3     BTW LO [3 AND 5]           // false
5.5   BTW LO [3.0 AND 5.5]       // true
3.0   BTW LO [3.0 AND 5.5]       // false
"b"   BTW LO ["a" AND "c"]       // true
"a"   BTW LO ["a" AND "c"]       // false
true  BTW LO [false AND true]    // true
false BTW LO [false AND true]    // false
```

{% hint style="warning" %}
The left operand can be a number, string, or boolean, and the right operand must be an array of two values.
{% endhint %}

### Between right open (`BTW RO`)

Returns `true` if the left operand falls within the range defined by two values in the right operand, **including** the lower limit (left value) and **excluding** the upper limit (right value). If the left operand is equal to the upper limit, the result will be `false`.

```javascript
// [request value] BTW RO [table value 1 AND table value 2]

4      BTW RO [3 AND 5]          // true
5      BTW RO [3 AND 5]          // false
3.0    BTW RO [3.0 AND 5.5]      // true
5.5    BTW RO [3.0 AND 5.5]      // false
"b"    BTW RO ["a" AND "c"]      // true
"c"    BTW RO ["a" AND "c"]      // false
true   BTW RO [false AND true]   // false
false  BTW RO [false AND true]   // true
```

{% hint style="warning" %}
The left operand can be a number, string, or boolean, and the right operand must be an array of two values.
{% endhint %}

### Not between (`!BTW`)

Returns `true` if the left operand does **not** fall within the range defined by two values in the right operand. This operator effectively checks if the left operand is outside the specified interval.

```javascript
// [request value] !BTW [table value 1 AND table value 2]

4     !BTW [3 AND 5]         // false
2     !BTW [3 AND 5]         // true
"b"   !BTW ["a" AND "c"]     // false
"d"   !BTW ["a" AND "c"]     // true
true  !BTW [false AND true]  // false
false !BTW [false AND true]  // false
```

{% hint style="warning" %}
The left operand can be a number, string, or boolean, while the right operand must be an array containing two values.
{% endhint %}

### Is null (`NULL`)

Returns `true` if the value being evaluated is empty. It does not accept any specific table values for comparison.

{% hint style="info" %}
The request value is checked against various types of empty values.
{% endhint %}

```javascript
// [request value] NULL [table value is empty]

null    NULL           // true
{}      NULL           // true
[]      NULL           // true
"a"     NULL           // false
3       NULL           // false
""      NULL           // false
0       NULL           // false
```

{% hint style="success" %}
This operator is useful for validating whether a value has been provided or is absent.
{% endhint %}

### Is not null (`!NULL`)

Returns `true` if the value being evaluated is not empty. It does not accept any specific table values for comparison.

{% hint style="info" %}
The request value is assessed to determine if it holds any non-empty data.
{% endhint %}

```javascript
// [request value] !NULL [table value is empty]

"a"      !NULL          //true
3        !NULL          //true
""       !NULL          //true
null     !NULL          //false
{}       !NULL          //false
[]       !NULL          //false
```

{% hint style="success" %}
This operator is useful for confirming that a value has been provided or exists in the dataset.
{% endhint %}

### Contains text (`C TXT`)

The operator checks if the left operand includes a value specified in the right operand, returning `true` if a match is found and `false` otherwise.

{% hint style="info" %}
The operator matches not only exact values but also substrings.
{% endhint %}

* Members of the set can be separated by pipe (`|`), comma (`,`), or semicolon (`;`).
* The left operand can be of type Number, String, Boolean, or an Array containing these types.

```javascript
// [request value] C TXT [table value]

[1,2,3]                             C TXT "1"             //true
[11,2,3]                            C TXT "1"             //true
[2,3,4]                             C TXT "1"             //false
"This is example 1,2,3 with true."  C TXT "1,2,3"         //true
"This is example false or true."    C TXT "true or false" //false
"This is example true with false."  C TXT true            //true
```

{% hint style="success" %}
This operator is particularly useful for scenarios where partial matches or the presence of specific elements within a collection need to be identified.
{% endhint %}

### Contains in (`C IN`)

Returns `true` if any of the values in the right operand are present in the left operand. This operator checks for both exact matches and substrings, returning `false` if no match is found.

{% hint style="info" %}
The operator matches not only exact values but also substrings.
{% endhint %}

* Members of the set in the right operand can be separated by pipe (`|`), comma (`,`), or semicolon (`;`).
* The left operand can be a Number, String, Boolean, or an Array of these types.

```javascript
// [request value] C IN [table value]

"This is example 1 with true." C IN 1|2|3          //true
"This is example 1 with true." C IN 1|true|"ok"    //true
"This is example 1 with true." C IN "is"|2|true    //true
"This is example 1 with true." C IN true|3         //true
[1,2,3]                        C IN true|3         //true
["true or falseee", "haha"]    C IN true|false     //true
"This is example 1 with true." C IN "test"|2       //false
```

{% hint style="success" %}
This operator is effective for verifying the existence of one or more elements from a list within a string or array.
{% endhint %}

### Not contains in (`!C IN`)

Returns `true` if none of the elements in the right operand are present in the left operand. This operator checks both exact values and substrings, returning `false` if any match is found.

* Members of the set in the right operand can be separated by pipe (`|`), comma (`,`), or semicolon (`;`).
* The left operand can be a Number, String, Boolean, or an Array containing these types.
* It returns `true` only when there are no matches found.

```javascript
// [request value] !C IN [table value]

"This is example 1 with true." !C IN 2|3|4          //true
"This is example 1 with true." !C IN 2|false|"ok"   //true
"This is example 1 with true." !C IN "are"|2|false  //true
"This is example 1 with true." !C IN false|3        //true
[1,2,3]                        !C IN true|3         //false
["true or falseee", "haha"]    !C IN "hello"|"bye"  //true
"This is example 1 with true." !C IN "test"|1       //false
```

{% hint style="success" %}
This operator is useful when you want to confirm that none of a given set of elements is present in a string or array.
{% endhint %}

### Equal array (`EQ ARR`)

Returns `true` if all the values in the right operand are substrings of at least one of the values in the left operand. This operator checks for matches within the elements of the left operand array, ensuring that all specified values in the right operand appear as substrings.

* The right operand set can be separated by pipe (`|`), comma (`,`), or semicolon (`;`).
* The left operand must be an array `[]`.
* It returns `true` only when all the values in the right operand match a substring in the left operand.

```javascript
// [request value] EQ ARR [table value]

[1, 2, 3]     EQ ARR  1|2|3      //true
["a", "b"]    EQ ARR  "a"|"b"    //true
[1,2,3]       EQ ARR  1|2        //true
[1111,111]    EQ ARR  1|11|111   //true
[1,2,3,4,5]   EQ ARR  1|2|3|4|6  //false
```

{% hint style="success" %}
This operator is helpful when you want to ensure that a set of substrings is found across an array of values.
{% endhint %}

### Else (`ELSE`)

The **ELSE** operator is a unique operator in decision tables, which returns `true` when no preceding row has passed the evaluation. It acts independently of the input variable in its column and only evaluates the overall flow of the table rather than specific conditions.

**Key Points**:

* The ELSE operator triggers if no other rows have passed before it.
* There can only be one row with the ELSE operator that passes.
* When evaluated, it takes into account only the conditions above it in the table.

{% hint style="success" %}
The ELSE operator is primarily used to create a default or fallback row in decision tables. This row is triggered if no other conditions match, making it ideal for handling scenarios like generating error messages or returning default responses.
{% endhint %}


# Date operators

Description of date operators used in decision tables

In each condition cell of a decision table, you have the flexibility to apply a variety of operators depending on your needs. These operators enable you to compare and manipulate date and time values effectively, ensuring that your conditions are evaluated accurately. You can choose from a range of operators, whether for simple equality checks or more complex comparisons involving date ranges. The full list of available operators can be found in the operators modal:

![Date operators modal](/files/dPyDkHUIKjWFUeld9EKD)

## Date Cell Values

When working with date operators in decision tables, using the correct format is crucial for ensuring accurate comparisons. Each condition cell can have a distinct operator for handling dates, but it’s important to understand how dates function within **DecisionRules** and how to correctly enter values into the cell.

You have two ways to input the date:

1. **Manually entering the date directly into the cell (recommended)**
2. **Using the date picker**

&#x20;Let’s explore both methods.

### Writing the Date Directly into the Cell

You can now enter the date directly into the cell (this was previously only possible using the date picker). After selecting the desired date operator, click the cell, which is now set to accept date input with enhanced functionality. When you start typing, a hint will appear displaying the recommended date format:

```json
YYYY-MM-DD HH:MM:ss Z // year-month-day hours:minutes:seconds GMT
```

{% hint style="danger" %}
We highly recommend always including the timezone (GMT) for accurate date interpretation.
{% endhint %}

<figure><img src="/files/qmjk5JoiwbrV7OdYaput" alt=""><figcaption><p>Date hint</p></figcaption></figure>

The cell will also show how your date is interpreted in real-time through a whisper. For example, if you enter **2024-09-24 09:24 +02:00**, the whisper will display the interpreted date as **"September 24, 2024, at 9:24:00 AM GMT+2."** This allows you to ensure that the date you’ve entered is correct.

<figure><img src="/files/kPiTQux94oNPRO4GIPHe" alt=""><figcaption></figcaption></figure>

#### Date Cell Validation

Date cells provide validation feedback, alerting you to any issues with date interpretation. There are two primary validation messages:

* **Invalid Date**\
  This message indicates that the input value is not recognized as a valid date. The operator will not be able to process the value, and you will need to correct it.

<figure><img src="/files/qWeIpRuq6IanWAWLBBeo" alt=""><figcaption><p>Invalid date warning</p></figcaption></figure>

* **Date Doesn't Fit Format**\
  This message means the input does not follow the recommended format (e.g., using slashes like **2024/09/24** or omitting the timezone), however, the system can still interpret the date. The whisper will show how the date is interpreted.

<figure><img src="/files/IIw1EjhuGB85TQTpa67X" alt=""><figcaption><p>Date without timezone</p></figcaption></figure>

{% hint style="warning" %}
We strongly advise sticking to the suggested format to ensure full functionality of the date operators.
{% endhint %}

### Picking the Date Using the Date Picker

If you prefer to select the date visually, the date picker functionality is still available. To use the date picker, click the calendar icon located in the edit row:

<figure><img src="/files/J9kVwUkSVVrGTDmVGqEe" alt=""><figcaption></figcaption></figure>

Clicking the icon will open a modal where you can choose the date. By default, both the date and time are set to **None**, and the timezone is pre-set to GMT. You can adjust these settings if needed. To set your desired date and time, you can either click into the respective fields and enter the values manually, or click on the date field to open a calendar dropdown and select the date visually:

<figure><img src="/files/i4T9UtShM9u4EQuDlsP0" alt=""><figcaption></figcaption></figure>

After choosing your date, time, and timezone, apply the changes by clicking the **Save** button.

<figure><img src="/files/bDAblokwYJ2DMANpU200" alt=""><figcaption></figcaption></figure>

The selected date will be set in the date cell in the recommended format, just as if you had entered it manually.

<figure><img src="/files/SY4xR0lRML0DPeKihLji" alt=""><figcaption></figcaption></figure>

#### Deleting the Date in the Date Select Modal

If you change your mind while setting the date or time in the modal, you can unselect the **Select Date** or **Select Time** option to clear the value. Alternatively, you can delete the value directly in the date cell.

### Special Case — Variables

In **DecisionRules**, you are not limited to explicitly setting a date in the date cell. Like other cells, date cells also support variables, such as:

* [Rule variables](/doc/rules/common-rule-features/variables/rule-variables)
* Input values
* Calculation column variables

{% hint style="info" %}
For more information on variables, refer to the [Table Designer](/doc/rules/decision-table/decision-table-designer#fill-cell): **Special Case — Variable Values** section
{% endhint %}

To use a variable, start typing the `"{"` symbol in the date cell, and a dropdown list of available variables will appear. When a variable is used in a date cell, the **Dynamic Date** warning will be visible in the active date cell:

<figure><img src="/files/ejQOLcy5jr9AFzOz8kA2" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}
Please note that date cells cannot validate the date passed through a variable. Ensure the date provided in the variable has the correct format.
{% endhint %}

<figure><img src="/files/7gTpwErxX8SLUuKhQyvG" alt=""><figcaption></figcaption></figure>

### Date Format

Dates are now saved as strings. To match a condition like **`2024-09-24 09:27 +02:00`**, the request must contain the same string format: **`"2024-09-24 09:27 +02:00"`**. Additionally, we support the **Extended ISO8601 Date format**, so the condition will also match the string **"`2024-09-24T09:27:00+02:00".`**

{% hint style="warning" %}
The old object format is deprecated but still supported. This means you can still pass a request using the old format, like so:

```json
"date": "2024-09-24",
"time": "09:27",
"timezone": "+02:00"
```

This will still match the **2024-09-24 09:27 +02:00** condition.
{% endhint %}

## Date Operators

### Equals  (`=` <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAABHdJREFUeF7tnc+LHEUUx79vlqwREwjTM909RsjVeBEN5IcHvQre1UME9WLO4g88iCaGJARCzgkkJwXzD+hdifgDBHOI4FEI09PTnRU0JJiZfdIH0YTs9L6qmn3dPW+v837U+36qqruqurcJ9qeqAKlmt+QwAMqdwAAYAGUFlNPbCDAAygoop7cR0HUAWV7yohrTOFLtBNrtW3rx2gXWdXDt9hkA5RFqAAyAXQPqpkmv37Xn2LrGa7fPpiCbgmwKqhulC3+flOUxnuFNJhwE4xkiRF4BG+7MjAKEm2C+iTVcHQ0GP/k02XkKYub1vCg/Y6b3APR8GtFi3zmAs8mwf4qI7rvU4Qwgm5Q/gHDYJWnnfBjfp0l0zKUuJwDjSXmKCB+7JOyqDxE+TYbRSWl9YgDT6R/Pz3lezXurOu1spfGMmA4lSf+GBIIYQJaXVwC8LUmyMraMS2kSnZDUKwcwKa+D8IIkyarYMvDNKI5ektQrB5AXfwK0R5JkVWyrW9RREg0l9ToAaPb+vqR4F9vQWxcGQEjBAAgFC21uAEIrKoxnAISChTY3AKEVFcYzAELBQpsbgNCKCuM1HoCwns6ZS59zCr4O6JyiwoIMgFCw0OYGILSiwngGQChYaHMDEFpRYTwDIBQstLkBCK2oMJ46AGkDhPWpmzd+IWYAZE/6BV+IGQADsNRpyqagpcpbH9wA1Gu0VAsDsFR564MbgHqNlmrRCQBFUey/v0mXwThSqUXg6z3a/U4c78m2o56mf+sBTKd3RrPNu78Q0YNPkDHnPdr9bB0Ebf/WA8jy8hqAVx/Z05m/SJPB8UWjoAH+Qd/83/GFWJaXGwD2bSHyrTSOnqoBoO3fcgCTIgNR8miReZzGgycXAtD2D/xWpcYI+BLAa1tMQZ+nyeCNmhGg7d/uEZDnf6WbuPczQKOHhL7Fj68/N9q7d7oIgLZ/6y/ClbhZxk8w3f4AxK+Dadbr4RrP+xfSlO5s5zZU078TALYjclNtDIAyGQNgAOwVpUV9QHogteO3ocod2Du9TUHeEvoFMAB++nl7GwBvCf0CdAKA5n5+Jb9P/tYD0N7P983fegAN2M/3PY9o92acnQc8eA3a8XVApr2f75vfzgNKOw/wWYpr7+f75m/9RdjOA5SvAX7LIH3vTowAfRndW2AA3LUL4mkAgsjoHsQAuGsXxNMABJHRPYgBcNcuiKcBCCKje5AGACjGAKXuJXTZk7M0Hjz8xN/CgsWbceO8/JqAl7sso2ttDHw1iqNXJP5iAFlenAHoI0mSFbI9ncaR6N/6iwFsbGwcuPf35m9EWF8hYWtLZea7j+3qPd3v93+vNf6fgRhA5TvOb39I4HOSRJ23JbybDqOL0jqdAFRJskn5HQhOn+2QNrLp9gx8O4qjF13a6Qyg+ojPZFqeBOh9AGsuyTvgMwf4fDKMPtnxj/j8K15Wlkcxw1ur9hkrYvzKa1x9xupHn47kPAJ8kprvfwoYAOXeYAAMgLICyultBBgAZQWU09sIMADKCiin/wfG/gCd9O/RGgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;24px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;24px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z&#x22;/></svg>" data-size="line">)

The equals (`=`) operator compares the request date and time value with the table date value, including the time zone.

```javascript
// [request value] = [table value]

"2024-09-24 09:27 +02:00" = "2024-09-24 09:27 +02:00"  // true
"2024-09-24 +02:00"       = "+02:00"                   // true

"2024-09-24 09:27 +02:00" = "2024-09-24 +02:00"        // false
"2024-09-24 09:27 +02:00" = "2024-09-24 13:27 +02:00"  // false
```

### Not equal (`!=` <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAABHdJREFUeF7tnc+LHEUUx79vlqwREwjTM909RsjVeBEN5IcHvQre1UME9WLO4g88iCaGJARCzgkkJwXzD+hdifgDBHOI4FEI09PTnRU0JJiZfdIH0YTs9L6qmn3dPW+v837U+36qqruqurcJ9qeqAKlmt+QwAMqdwAAYAGUFlNPbCDAAygoop7cR0HUAWV7yohrTOFLtBNrtW3rx2gXWdXDt9hkA5RFqAAyAXQPqpkmv37Xn2LrGa7fPpiCbgmwKqhulC3+flOUxnuFNJhwE4xkiRF4BG+7MjAKEm2C+iTVcHQ0GP/k02XkKYub1vCg/Y6b3APR8GtFi3zmAs8mwf4qI7rvU4Qwgm5Q/gHDYJWnnfBjfp0l0zKUuJwDjSXmKCB+7JOyqDxE+TYbRSWl9YgDT6R/Pz3lezXurOu1spfGMmA4lSf+GBIIYQJaXVwC8LUmyMraMS2kSnZDUKwcwKa+D8IIkyarYMvDNKI5ektQrB5AXfwK0R5JkVWyrW9RREg0l9ToAaPb+vqR4F9vQWxcGQEjBAAgFC21uAEIrKoxnAISChTY3AKEVFcYzAELBQpsbgNCKCuM1HoCwns6ZS59zCr4O6JyiwoIMgFCw0OYGILSiwngGQChYaHMDEFpRYTwDIBQstLkBCK2oMJ46AGkDhPWpmzd+IWYAZE/6BV+IGQADsNRpyqagpcpbH9wA1Gu0VAsDsFR564MbgHqNlmrRCQBFUey/v0mXwThSqUXg6z3a/U4c78m2o56mf+sBTKd3RrPNu78Q0YNPkDHnPdr9bB0Ebf/WA8jy8hqAVx/Z05m/SJPB8UWjoAH+Qd/83/GFWJaXGwD2bSHyrTSOnqoBoO3fcgCTIgNR8miReZzGgycXAtD2D/xWpcYI+BLAa1tMQZ+nyeCNmhGg7d/uEZDnf6WbuPczQKOHhL7Fj68/N9q7d7oIgLZ/6y/ClbhZxk8w3f4AxK+Dadbr4RrP+xfSlO5s5zZU078TALYjclNtDIAyGQNgAOwVpUV9QHogteO3ocod2Du9TUHeEvoFMAB++nl7GwBvCf0CdAKA5n5+Jb9P/tYD0N7P983fegAN2M/3PY9o92acnQc8eA3a8XVApr2f75vfzgNKOw/wWYpr7+f75m/9RdjOA5SvAX7LIH3vTowAfRndW2AA3LUL4mkAgsjoHsQAuGsXxNMABJHRPYgBcNcuiKcBCCKje5AGACjGAKXuJXTZk7M0Hjz8xN/CgsWbceO8/JqAl7sso2ttDHw1iqNXJP5iAFlenAHoI0mSFbI9ncaR6N/6iwFsbGwcuPf35m9EWF8hYWtLZea7j+3qPd3v93+vNf6fgRhA5TvOb39I4HOSRJ23JbybDqOL0jqdAFRJskn5HQhOn+2QNrLp9gx8O4qjF13a6Qyg+ojPZFqeBOh9AGsuyTvgMwf4fDKMPtnxj/j8K15Wlkcxw1ur9hkrYvzKa1x9xupHn47kPAJ8kprvfwoYAOXeYAAMgLICyultBBgAZQWU09sIMADKCiin/wfG/gCd9O/RGgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;24px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;24px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z&#x22;/></svg>" data-size="line">)

The not equal (`!=`) operator returns `true` if the request date string and the table date string differ in any way.

```javascript
// [request value] != [table value]

"2024-09-24 09:27 +02:00" != "2024-09-24 +02:00"         // true 
"2024-09-24 09:27 +02:00" != "09:27 +02:00"              // true
"2024-09-24 09:27 +02:00" != "+02:00"                    // true

"2024-09-24 09:27 +02:00" != "2024-09-24 09:27 +02:00"   // false
"2024-09-24 +02:00"       != "+02:00"                    // false
```

### Greater than (`>` <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAABHdJREFUeF7tnc+LHEUUx79vlqwREwjTM909RsjVeBEN5IcHvQre1UME9WLO4g88iCaGJARCzgkkJwXzD+hdifgDBHOI4FEI09PTnRU0JJiZfdIH0YTs9L6qmn3dPW+v837U+36qqruqurcJ9qeqAKlmt+QwAMqdwAAYAGUFlNPbCDAAygoop7cR0HUAWV7yohrTOFLtBNrtW3rx2gXWdXDt9hkA5RFqAAyAXQPqpkmv37Xn2LrGa7fPpiCbgmwKqhulC3+flOUxnuFNJhwE4xkiRF4BG+7MjAKEm2C+iTVcHQ0GP/k02XkKYub1vCg/Y6b3APR8GtFi3zmAs8mwf4qI7rvU4Qwgm5Q/gHDYJWnnfBjfp0l0zKUuJwDjSXmKCB+7JOyqDxE+TYbRSWl9YgDT6R/Pz3lezXurOu1spfGMmA4lSf+GBIIYQJaXVwC8LUmyMraMS2kSnZDUKwcwKa+D8IIkyarYMvDNKI5ektQrB5AXfwK0R5JkVWyrW9RREg0l9ToAaPb+vqR4F9vQWxcGQEjBAAgFC21uAEIrKoxnAISChTY3AKEVFcYzAELBQpsbgNCKCuM1HoCwns6ZS59zCr4O6JyiwoIMgFCw0OYGILSiwngGQChYaHMDEFpRYTwDIBQstLkBCK2oMJ46AGkDhPWpmzd+IWYAZE/6BV+IGQADsNRpyqagpcpbH9wA1Gu0VAsDsFR564MbgHqNlmrRCQBFUey/v0mXwThSqUXg6z3a/U4c78m2o56mf+sBTKd3RrPNu78Q0YNPkDHnPdr9bB0Ebf/WA8jy8hqAVx/Z05m/SJPB8UWjoAH+Qd/83/GFWJaXGwD2bSHyrTSOnqoBoO3fcgCTIgNR8miReZzGgycXAtD2D/xWpcYI+BLAa1tMQZ+nyeCNmhGg7d/uEZDnf6WbuPczQKOHhL7Fj68/N9q7d7oIgLZ/6y/ClbhZxk8w3f4AxK+Dadbr4RrP+xfSlO5s5zZU078TALYjclNtDIAyGQNgAOwVpUV9QHogteO3ocod2Du9TUHeEvoFMAB++nl7GwBvCf0CdAKA5n5+Jb9P/tYD0N7P983fegAN2M/3PY9o92acnQc8eA3a8XVApr2f75vfzgNKOw/wWYpr7+f75m/9RdjOA5SvAX7LIH3vTowAfRndW2AA3LUL4mkAgsjoHsQAuGsXxNMABJHRPYgBcNcuiKcBCCKje5AGACjGAKXuJXTZk7M0Hjz8xN/CgsWbceO8/JqAl7sso2ttDHw1iqNXJP5iAFlenAHoI0mSFbI9ncaR6N/6iwFsbGwcuPf35m9EWF8hYWtLZea7j+3qPd3v93+vNf6fgRhA5TvOb39I4HOSRJ23JbybDqOL0jqdAFRJskn5HQhOn+2QNrLp9gx8O4qjF13a6Qyg+ojPZFqeBOh9AGsuyTvgMwf4fDKMPtnxj/j8K15Wlkcxw1ur9hkrYvzKa1x9xupHn47kPAJ8kprvfwoYAOXeYAAMgLICyultBBgAZQWU09sIMADKCiin/wfG/gCd9O/RGgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;24px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;24px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z&#x22;/></svg>" data-size="line">)

The greater than (`>`) operator checks if the request date string is later than the table date string.

```javascript
// [request value] > [table value]

"2024-09-24 09:27 +02:00" > "2024-09-23 09:27 +02:00"  // true
"2024-09-24 09:27 +02:00" > "2024-09-24 +02:00"        // true

// assuming "2024-09-24" is in the future:
"2024-09-24 09:27 +02:00" > "09:27 +02:00"             // true
"2024-09-24 09:27 +02:00" > "+02:00"                   // true

// assuming "2024-09-24" is in the past:
"2024-09-24 09:27 +02:00" > "09:27 +02:00"             // false
"2024-09-24 09:27 +02:00" > "+02:00"                   // false

"2024-09-24 09:27 +02:00" > "2024-09-24 09:27 +02:00"  // false
"2024-09-24 09:27 +02:00" > "2024-09-25 09:27 +02:00"  // false
```

### Less than (`<` <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAABHdJREFUeF7tnc+LHEUUx79vlqwREwjTM909RsjVeBEN5IcHvQre1UME9WLO4g88iCaGJARCzgkkJwXzD+hdifgDBHOI4FEI09PTnRU0JJiZfdIH0YTs9L6qmn3dPW+v837U+36qqruqurcJ9qeqAKlmt+QwAMqdwAAYAGUFlNPbCDAAygoop7cR0HUAWV7yohrTOFLtBNrtW3rx2gXWdXDt9hkA5RFqAAyAXQPqpkmv37Xn2LrGa7fPpiCbgmwKqhulC3+flOUxnuFNJhwE4xkiRF4BG+7MjAKEm2C+iTVcHQ0GP/k02XkKYub1vCg/Y6b3APR8GtFi3zmAs8mwf4qI7rvU4Qwgm5Q/gHDYJWnnfBjfp0l0zKUuJwDjSXmKCB+7JOyqDxE+TYbRSWl9YgDT6R/Pz3lezXurOu1spfGMmA4lSf+GBIIYQJaXVwC8LUmyMraMS2kSnZDUKwcwKa+D8IIkyarYMvDNKI5ektQrB5AXfwK0R5JkVWyrW9RREg0l9ToAaPb+vqR4F9vQWxcGQEjBAAgFC21uAEIrKoxnAISChTY3AKEVFcYzAELBQpsbgNCKCuM1HoCwns6ZS59zCr4O6JyiwoIMgFCw0OYGILSiwngGQChYaHMDEFpRYTwDIBQstLkBCK2oMJ46AGkDhPWpmzd+IWYAZE/6BV+IGQADsNRpyqagpcpbH9wA1Gu0VAsDsFR564MbgHqNlmrRCQBFUey/v0mXwThSqUXg6z3a/U4c78m2o56mf+sBTKd3RrPNu78Q0YNPkDHnPdr9bB0Ebf/WA8jy8hqAVx/Z05m/SJPB8UWjoAH+Qd/83/GFWJaXGwD2bSHyrTSOnqoBoO3fcgCTIgNR8miReZzGgycXAtD2D/xWpcYI+BLAa1tMQZ+nyeCNmhGg7d/uEZDnf6WbuPczQKOHhL7Fj68/N9q7d7oIgLZ/6y/ClbhZxk8w3f4AxK+Dadbr4RrP+xfSlO5s5zZU078TALYjclNtDIAyGQNgAOwVpUV9QHogteO3ocod2Du9TUHeEvoFMAB++nl7GwBvCf0CdAKA5n5+Jb9P/tYD0N7P983fegAN2M/3PY9o92acnQc8eA3a8XVApr2f75vfzgNKOw/wWYpr7+f75m/9RdjOA5SvAX7LIH3vTowAfRndW2AA3LUL4mkAgsjoHsQAuGsXxNMABJHRPYgBcNcuiKcBCCKje5AGACjGAKXuJXTZk7M0Hjz8xN/CgsWbceO8/JqAl7sso2ttDHw1iqNXJP5iAFlenAHoI0mSFbI9ncaR6N/6iwFsbGwcuPf35m9EWF8hYWtLZea7j+3qPd3v93+vNf6fgRhA5TvOb39I4HOSRJ23JbybDqOL0jqdAFRJskn5HQhOn+2QNrLp9gx8O4qjF13a6Qyg+ojPZFqeBOh9AGsuyTvgMwf4fDKMPtnxj/j8K15Wlkcxw1ur9hkrYvzKa1x9xupHn47kPAJ8kprvfwoYAOXeYAAMgLICyultBBgAZQWU09sIMADKCiin/wfG/gCd9O/RGgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;24px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;24px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z&#x22;/></svg>" data-size="line">)

The less than (`<`) operator returns `true` if the request date string is earlier than the table date string.

```javascript
// [request value] < [table value]

"2024-09-24 09:27 +02:00" < "2024-09-25 09:27 +02:00"  // true
"2024-09-24 09:27 +02:00" < "2024-09-25 +02:00"        // true

// assuming "2024-09-24" is in the past:
"2024-09-24 09:27 +02:00" < "09:27 +02:00"             // true
"2024-09-24 09:27 +02:00" < "+02:00"                   // true

// assuming "2024-09-24" is in the future or today:
"2024-09-24 09:27 +02:00" < "09:27 +02:00"             // false
"2024-09-24 09:27 +02:00" < "+02:00"                   // false

"2024-09-24 09:27 +02:00" < "2024-09-24 09:27 +02:00"  // false
"2024-09-24 09:27 +02:00" < "2024-09-23 09:27 +02:00"  // false
```

### Greater than or equal (`>=` <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAABHdJREFUeF7tnc+LHEUUx79vlqwREwjTM909RsjVeBEN5IcHvQre1UME9WLO4g88iCaGJARCzgkkJwXzD+hdifgDBHOI4FEI09PTnRU0JJiZfdIH0YTs9L6qmn3dPW+v837U+36qqruqurcJ9qeqAKlmt+QwAMqdwAAYAGUFlNPbCDAAygoop7cR0HUAWV7yohrTOFLtBNrtW3rx2gXWdXDt9hkA5RFqAAyAXQPqpkmv37Xn2LrGa7fPpiCbgmwKqhulC3+flOUxnuFNJhwE4xkiRF4BG+7MjAKEm2C+iTVcHQ0GP/k02XkKYub1vCg/Y6b3APR8GtFi3zmAs8mwf4qI7rvU4Qwgm5Q/gHDYJWnnfBjfp0l0zKUuJwDjSXmKCB+7JOyqDxE+TYbRSWl9YgDT6R/Pz3lezXurOu1spfGMmA4lSf+GBIIYQJaXVwC8LUmyMraMS2kSnZDUKwcwKa+D8IIkyarYMvDNKI5ektQrB5AXfwK0R5JkVWyrW9RREg0l9ToAaPb+vqR4F9vQWxcGQEjBAAgFC21uAEIrKoxnAISChTY3AKEVFcYzAELBQpsbgNCKCuM1HoCwns6ZS59zCr4O6JyiwoIMgFCw0OYGILSiwngGQChYaHMDEFpRYTwDIBQstLkBCK2oMJ46AGkDhPWpmzd+IWYAZE/6BV+IGQADsNRpyqagpcpbH9wA1Gu0VAsDsFR564MbgHqNlmrRCQBFUey/v0mXwThSqUXg6z3a/U4c78m2o56mf+sBTKd3RrPNu78Q0YNPkDHnPdr9bB0Ebf/WA8jy8hqAVx/Z05m/SJPB8UWjoAH+Qd/83/GFWJaXGwD2bSHyrTSOnqoBoO3fcgCTIgNR8miReZzGgycXAtD2D/xWpcYI+BLAa1tMQZ+nyeCNmhGg7d/uEZDnf6WbuPczQKOHhL7Fj68/N9q7d7oIgLZ/6y/ClbhZxk8w3f4AxK+Dadbr4RrP+xfSlO5s5zZU078TALYjclNtDIAyGQNgAOwVpUV9QHogteO3ocod2Du9TUHeEvoFMAB++nl7GwBvCf0CdAKA5n5+Jb9P/tYD0N7P983fegAN2M/3PY9o92acnQc8eA3a8XVApr2f75vfzgNKOw/wWYpr7+f75m/9RdjOA5SvAX7LIH3vTowAfRndW2AA3LUL4mkAgsjoHsQAuGsXxNMABJHRPYgBcNcuiKcBCCKje5AGACjGAKXuJXTZk7M0Hjz8xN/CgsWbceO8/JqAl7sso2ttDHw1iqNXJP5iAFlenAHoI0mSFbI9ncaR6N/6iwFsbGwcuPf35m9EWF8hYWtLZea7j+3qPd3v93+vNf6fgRhA5TvOb39I4HOSRJ23JbybDqOL0jqdAFRJskn5HQhOn+2QNrLp9gx8O4qjF13a6Qyg+ojPZFqeBOh9AGsuyTvgMwf4fDKMPtnxj/j8K15Wlkcxw1ur9hkrYvzKa1x9xupHn47kPAJ8kprvfwoYAOXeYAAMgLICyultBBgAZQWU09sIMADKCiin/wfG/gCd9O/RGgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;24px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;24px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z&#x22;/></svg>" data-size="line">)

The greater than or equal (`>=`) operator checks if the request date string is either later than or exactly the same as the table date string.

```javascript
// [request value] >= [table value]

"2024-09-24 09:27 +02:00" >= "2024-09-24 09:27 +02:00"  // true
"2024-09-24 09:27 +02:00" >= "2024-09-23 09:27 +02:00"  // true
"2024-09-24 09:27 +02:00" >= "2024-09-24 +02:00"        // true

// assuming "2024-09-24" is in the future or today:
"2024-09-24 09:27 +02:00" >= "09:27 +02:00"             // true
"2024-09-24 09:27 +02:00" >= "+02:00"                   // true

// assuming "2024-09-24" is in the past:
"2024-09-24 09:27 +02:00" >= "09:27 +02:00"             // false
"2024-09-24 09:27 +02:00" >= "+02:00"                   // false

"2024-09-24 09:27 +02:00" >= "2024-09-25 09:27 +02:00"  // false
```

### Less than or equal (`<=` <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAABHdJREFUeF7tnc+LHEUUx79vlqwREwjTM909RsjVeBEN5IcHvQre1UME9WLO4g88iCaGJARCzgkkJwXzD+hdifgDBHOI4FEI09PTnRU0JJiZfdIH0YTs9L6qmn3dPW+v837U+36qqruqurcJ9qeqAKlmt+QwAMqdwAAYAGUFlNPbCDAAygoop7cR0HUAWV7yohrTOFLtBNrtW3rx2gXWdXDt9hkA5RFqAAyAXQPqpkmv37Xn2LrGa7fPpiCbgmwKqhulC3+flOUxnuFNJhwE4xkiRF4BG+7MjAKEm2C+iTVcHQ0GP/k02XkKYub1vCg/Y6b3APR8GtFi3zmAs8mwf4qI7rvU4Qwgm5Q/gHDYJWnnfBjfp0l0zKUuJwDjSXmKCB+7JOyqDxE+TYbRSWl9YgDT6R/Pz3lezXurOu1spfGMmA4lSf+GBIIYQJaXVwC8LUmyMraMS2kSnZDUKwcwKa+D8IIkyarYMvDNKI5ektQrB5AXfwK0R5JkVWyrW9RREg0l9ToAaPb+vqR4F9vQWxcGQEjBAAgFC21uAEIrKoxnAISChTY3AKEVFcYzAELBQpsbgNCKCuM1HoCwns6ZS59zCr4O6JyiwoIMgFCw0OYGILSiwngGQChYaHMDEFpRYTwDIBQstLkBCK2oMJ46AGkDhPWpmzd+IWYAZE/6BV+IGQADsNRpyqagpcpbH9wA1Gu0VAsDsFR564MbgHqNlmrRCQBFUey/v0mXwThSqUXg6z3a/U4c78m2o56mf+sBTKd3RrPNu78Q0YNPkDHnPdr9bB0Ebf/WA8jy8hqAVx/Z05m/SJPB8UWjoAH+Qd/83/GFWJaXGwD2bSHyrTSOnqoBoO3fcgCTIgNR8miReZzGgycXAtD2D/xWpcYI+BLAa1tMQZ+nyeCNmhGg7d/uEZDnf6WbuPczQKOHhL7Fj68/N9q7d7oIgLZ/6y/ClbhZxk8w3f4AxK+Dadbr4RrP+xfSlO5s5zZU078TALYjclNtDIAyGQNgAOwVpUV9QHogteO3ocod2Du9TUHeEvoFMAB++nl7GwBvCf0CdAKA5n5+Jb9P/tYD0N7P983fegAN2M/3PY9o92acnQc8eA3a8XVApr2f75vfzgNKOw/wWYpr7+f75m/9RdjOA5SvAX7LIH3vTowAfRndW2AA3LUL4mkAgsjoHsQAuGsXxNMABJHRPYgBcNcuiKcBCCKje5AGACjGAKXuJXTZk7M0Hjz8xN/CgsWbceO8/JqAl7sso2ttDHw1iqNXJP5iAFlenAHoI0mSFbI9ncaR6N/6iwFsbGwcuPf35m9EWF8hYWtLZea7j+3qPd3v93+vNf6fgRhA5TvOb39I4HOSRJ23JbybDqOL0jqdAFRJskn5HQhOn+2QNrLp9gx8O4qjF13a6Qyg+ojPZFqeBOh9AGsuyTvgMwf4fDKMPtnxj/j8K15Wlkcxw1ur9hkrYvzKa1x9xupHn47kPAJ8kprvfwoYAOXeYAAMgLICyultBBgAZQWU09sIMADKCiin/wfG/gCd9O/RGgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;24px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;24px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z&#x22;/></svg>" data-size="line">)

The less than or equal (`<=`) operator returns `true` if the request date string is earlier than or exactly the same as the table date string.

```javascript
// [request value] <= [table value]

"2024-09-24 09:27 +02:00" <= "2024-09-24 09:27 +02:00"  // true
"2024-09-24 09:27 +02:00" <= "2024-09-25 09:27 +02:00"  // true
"2024-09-24 09:27 +02:00" <= "2024-09-25 +02:00"        // true

// assuming "2024-09-24" is in the past:
"2024-09-24 09:27 +02:00" <= "09:27 +02:00"             // true
"2024-09-24 09:27 +02:00" <= "+02:00"                   // true

// assuming "2024-09-24" is in the future:
"2024-09-24 09:27 +02:00" <= "09:27 +02:00"             // false
"2024-09-24 09:27 +02:00" <= "+02:00"                   // false

"2024-09-24 09:27 +02:00" <= "2024-09-23 09:27 +02:00"  // false
```

### **Between** (`BTW` <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAABHdJREFUeF7tnc+LHEUUx79vlqwREwjTM909RsjVeBEN5IcHvQre1UME9WLO4g88iCaGJARCzgkkJwXzD+hdifgDBHOI4FEI09PTnRU0JJiZfdIH0YTs9L6qmn3dPW+v837U+36qqruqurcJ9qeqAKlmt+QwAMqdwAAYAGUFlNPbCDAAygoop7cR0HUAWV7yohrTOFLtBNrtW3rx2gXWdXDt9hkA5RFqAAyAXQPqpkmv37Xn2LrGa7fPpiCbgmwKqhulC3+flOUxnuFNJhwE4xkiRF4BG+7MjAKEm2C+iTVcHQ0GP/k02XkKYub1vCg/Y6b3APR8GtFi3zmAs8mwf4qI7rvU4Qwgm5Q/gHDYJWnnfBjfp0l0zKUuJwDjSXmKCB+7JOyqDxE+TYbRSWl9YgDT6R/Pz3lezXurOu1spfGMmA4lSf+GBIIYQJaXVwC8LUmyMraMS2kSnZDUKwcwKa+D8IIkyarYMvDNKI5ektQrB5AXfwK0R5JkVWyrW9RREg0l9ToAaPb+vqR4F9vQWxcGQEjBAAgFC21uAEIrKoxnAISChTY3AKEVFcYzAELBQpsbgNCKCuM1HoCwns6ZS59zCr4O6JyiwoIMgFCw0OYGILSiwngGQChYaHMDEFpRYTwDIBQstLkBCK2oMJ46AGkDhPWpmzd+IWYAZE/6BV+IGQADsNRpyqagpcpbH9wA1Gu0VAsDsFR564MbgHqNlmrRCQBFUey/v0mXwThSqUXg6z3a/U4c78m2o56mf+sBTKd3RrPNu78Q0YNPkDHnPdr9bB0Ebf/WA8jy8hqAVx/Z05m/SJPB8UWjoAH+Qd/83/GFWJaXGwD2bSHyrTSOnqoBoO3fcgCTIgNR8miReZzGgycXAtD2D/xWpcYI+BLAa1tMQZ+nyeCNmhGg7d/uEZDnf6WbuPczQKOHhL7Fj68/N9q7d7oIgLZ/6y/ClbhZxk8w3f4AxK+Dadbr4RrP+xfSlO5s5zZU078TALYjclNtDIAyGQNgAOwVpUV9QHogteO3ocod2Du9TUHeEvoFMAB++nl7GwBvCf0CdAKA5n5+Jb9P/tYD0N7P983fegAN2M/3PY9o92acnQc8eA3a8XVApr2f75vfzgNKOw/wWYpr7+f75m/9RdjOA5SvAX7LIH3vTowAfRndW2AA3LUL4mkAgsjoHsQAuGsXxNMABJHRPYgBcNcuiKcBCCKje5AGACjGAKXuJXTZk7M0Hjz8xN/CgsWbceO8/JqAl7sso2ttDHw1iqNXJP5iAFlenAHoI0mSFbI9ncaR6N/6iwFsbGwcuPf35m9EWF8hYWtLZea7j+3qPd3v93+vNf6fgRhA5TvOb39I4HOSRJ23JbybDqOL0jqdAFRJskn5HQhOn+2QNrLp9gx8O4qjF13a6Qyg+ojPZFqeBOh9AGsuyTvgMwf4fDKMPtnxj/j8K15Wlkcxw1ur9hkrYvzKa1x9xupHn47kPAJ8kprvfwoYAOXeYAAMgLICyultBBgAZQWU09sIMADKCiin/wfG/gCd9O/RGgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;24px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;24px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z&#x22;/></svg>" data-size="line">)

The between (`BTW`) operator checks if the request date string falls within the range of two table date strings, inclusive of both the start and the end values.

{% code fullWidth="false" %}

```javascript
// [request value] BTW [table value 1 AND table value 2]

"2024-09-24 09:27 +02:00" BTW "2024-09-24 09:27 +02:00" AND "2024-09-25 09:27 +02:00"  // true
"2024-09-24 09:27 +02:00" BTW "2024-09-23 09:27 +02:00" AND "2024-09-24 09:27 +02:00"  // true
"2024-09-24 09:27 +02:00" BTW "2024-09-24 +02:00"       AND "2024-09-27 +02:00"        // true
"2024-09-24 09:27 +02:00" BTW "2024-09-23 +02:00"       AND "2024-09-24 09:27 +02:00"  // true
"2024-09-24 +02:00"       BTW "2024-09-23 09:27 +02:00" AND "2024-09-25 09:27 +02:00"  // true

"2024-09-24 09:27 +02:00" BTW "2024-09-28 09:27 +02:00" AND "2024-09-29 09:27 +02:00"  // false
"2024-09-24 +02:00"       BTW "2024-09-24 09:27 +02:00" AND "2024-09-25 09:27 +02:00"  // false

// assuming "2024-09-24" is in the future:
"2024-09-24 09:27 +02:00" BTW "2024-09-23 09:27 +02:00" AND "10:27 +02:00"             // false

// assuming "2024-09-24" is today or in the past:
"2024-09-24 09:27 +02:00" BTW "2024-09-23 09:27 +02:00" AND "10:27 +02:00"             // true
```

{% endcode %}

### Not between (`!BTW` <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAABHdJREFUeF7tnc+LHEUUx79vlqwREwjTM909RsjVeBEN5IcHvQre1UME9WLO4g88iCaGJARCzgkkJwXzD+hdifgDBHOI4FEI09PTnRU0JJiZfdIH0YTs9L6qmn3dPW+v837U+36qqruqurcJ9qeqAKlmt+QwAMqdwAAYAGUFlNPbCDAAygoop7cR0HUAWV7yohrTOFLtBNrtW3rx2gXWdXDt9hkA5RFqAAyAXQPqpkmv37Xn2LrGa7fPpiCbgmwKqhulC3+flOUxnuFNJhwE4xkiRF4BG+7MjAKEm2C+iTVcHQ0GP/k02XkKYub1vCg/Y6b3APR8GtFi3zmAs8mwf4qI7rvU4Qwgm5Q/gHDYJWnnfBjfp0l0zKUuJwDjSXmKCB+7JOyqDxE+TYbRSWl9YgDT6R/Pz3lezXurOu1spfGMmA4lSf+GBIIYQJaXVwC8LUmyMraMS2kSnZDUKwcwKa+D8IIkyarYMvDNKI5ektQrB5AXfwK0R5JkVWyrW9RREg0l9ToAaPb+vqR4F9vQWxcGQEjBAAgFC21uAEIrKoxnAISChTY3AKEVFcYzAELBQpsbgNCKCuM1HoCwns6ZS59zCr4O6JyiwoIMgFCw0OYGILSiwngGQChYaHMDEFpRYTwDIBQstLkBCK2oMJ46AGkDhPWpmzd+IWYAZE/6BV+IGQADsNRpyqagpcpbH9wA1Gu0VAsDsFR564MbgHqNlmrRCQBFUey/v0mXwThSqUXg6z3a/U4c78m2o56mf+sBTKd3RrPNu78Q0YNPkDHnPdr9bB0Ebf/WA8jy8hqAVx/Z05m/SJPB8UWjoAH+Qd/83/GFWJaXGwD2bSHyrTSOnqoBoO3fcgCTIgNR8miReZzGgycXAtD2D/xWpcYI+BLAa1tMQZ+nyeCNmhGg7d/uEZDnf6WbuPczQKOHhL7Fj68/N9q7d7oIgLZ/6y/ClbhZxk8w3f4AxK+Dadbr4RrP+xfSlO5s5zZU078TALYjclNtDIAyGQNgAOwVpUV9QHogteO3ocod2Du9TUHeEvoFMAB++nl7GwBvCf0CdAKA5n5+Jb9P/tYD0N7P983fegAN2M/3PY9o92acnQc8eA3a8XVApr2f75vfzgNKOw/wWYpr7+f75m/9RdjOA5SvAX7LIH3vTowAfRndW2AA3LUL4mkAgsjoHsQAuGsXxNMABJHRPYgBcNcuiKcBCCKje5AGACjGAKXuJXTZk7M0Hjz8xN/CgsWbceO8/JqAl7sso2ttDHw1iqNXJP5iAFlenAHoI0mSFbI9ncaR6N/6iwFsbGwcuPf35m9EWF8hYWtLZea7j+3qPd3v93+vNf6fgRhA5TvOb39I4HOSRJ23JbybDqOL0jqdAFRJskn5HQhOn+2QNrLp9gx8O4qjF13a6Qyg+ojPZFqeBOh9AGsuyTvgMwf4fDKMPtnxj/j8K15Wlkcxw1ur9hkrYvzKa1x9xupHn47kPAJ8kprvfwoYAOXeYAAMgLICyultBBgAZQWU09sIMADKCiin/wfG/gCd9O/RGgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;24px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;24px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z&#x22;/></svg>" data-size="line">)

The not between (`!BTW`) operator checks if the request date string falls outside the range of two table date strings, returning `true` if the value is not within the range.

```javascript
// [request value] !BTW [table value 1 AND table value 2]

"2024-09-24 09:27 +02:00" !BTW "2024-09-28 09:27 +02:00" AND "2024-09-29 09:27 +02:00"  // true
"2024-09-24 +02:00"       !BTW "2024-09-24 09:27 +02:00" AND "2024-09-25 09:27 +02:00"  // true

"2024-09-24 09:27 +02:00" !BTW "2024-09-24 09:27 +02:00" AND "2024-09-25 09:27 +02:00"  // false
"2024-09-24 09:27 +02:00" !BTW "2024-09-23 09:27 +02:00" AND "2024-09-25 09:27 +02:00"  // false
"2024-09-24 09:27 +02:00" !BTW "2024-09-24 +02:00"       AND "2024-09-27 +02:00"        // false
"2024-09-24 09:27 +02:00" !BTW "2024-09-23 +02:00"       AND "2024-09-24 09:27 +02:00"  // false
"2024-09-24 +02:00"       !BTW "2024-09-23 09:27 +02:00" AND "2024-09-25 09:27 +02:00"  // false

// assuming "2024-09-24" is in the future:
"2024-09-24 09:27 +02:00" !BTW "2024-09-23 09:27 +02:00" AND "10:27 +02:00"             // true

// assuming "2024-09-24" is in the past or today:
"2024-09-24 09:27 +02:00" !BTW "2024-09-23 09:27 +02:00" AND "10:27 +02:00"             // false
```


# Functions

On this page, you'll get an introduction to the key principles of writing functions in DecisionRules. A detailed guide to all available functions is found in the following sections.

DecisionRules functions are essential for building decision processes of any complexity. These functions can be applied in different rule types, such as [Decision Table](/doc/rules/decision-table), [Decision Tree](/doc/rules/decision-tree) and [Flow](/doc/rules/flow), allowing users to write mathematical and logical expressions in both conditions and results.

<figure><img src="/files/LsqLfJLkUD03w1ZZO5xJ" alt=""><figcaption><p>how functions can be used in a Decision Table</p></figcaption></figure>

## Categories of Functions

Functions are divided into several categories based on their area of application:

* **Math functions**
* **Logical functions**
* **Date and time functions**
* **Text functions**
* **Data functions**
* **Array functions**
* **Integration functions**

## General Usage and Principles

Though the functions have broad applications and behaviours, they share several core principles. These apply universally across all functions. Below is a quick overview, supported by basic examples.

### Syntax

The syntax for DecisionRules functions is simple. Functions are written using their names (always uppercase, occasionally containing underscores) followed by parentheses that enclose the function arguments, separated by commas.

```javascript
SUM(1,4,5)  --> 10
```

Each function accepts a variable number of arguments, some optional, while others do not need any arguments at all.

Example of no-argument function:

```javascript
NOW()   --> returns the current date and time
```

{% hint style="warning" %}
In Decision Tables, functions can be used in condition, result, and calculation columns.

* **Condition columns**: You can choose the function from the operators modal, which opens when you click the operator badge. Functions in these columns must evaluate to boolean values (true or false).
* **Calculation and result columns**: These do not have the operators modal. Simply start typing the function name, and a dropdown whisper will appear, showing all matching functions.
  {% endhint %}

### Values

DecisionRules supports several data types:

* **Primitive types**: number, string, boolean, null.
* **Complex types**: arrays, objects.
* **Additional types for functions**: date, regular expressions.

{% hint style="info" %}
Read more in the [Supported Data Types](/doc/rules/data-types-and-functions/data-types) section.
{% endhint %}

Basic syntax examples:

```json
12.1          --> number
"abc"         --> string
true          --> boolean
false         --> boolean
null          --> null
```

{% hint style="info" %}
As shown above, strings are typically enclosed in double quotes. For simple string expressions that do not contain special characters \[\*/+-(),%{}], the quotes can be omitted. However, we recommend keeping them for clarity and consistency.
{% endhint %}

Special characters within strings can be handled with either single quotes or escape sequences:

```json
"abcd"        --> abcd
'ab"cd'       --> ab"cd
"ab\"cd"      --> ab"cd
"ab\'cd"      --> ab'cd
"ab'cd"       --> ab'cd
"ab\\cd"      --> ab\cd
```

#### Type Conversion

Functions in DecisionRules often handle type casting automatically. If possible, they will convert values to the required type.

```json
SUM(1,4,"5")    --> 10
```

However, type casting does not always work. If values cannot be converted, the function will either fail validation or return an error at runtime.

```json
SUM(1,4,"abc")    --> invalid
```

#### Arrays and Objects

Some functions accept arrays or objects as arguments. DecisionRules uses JSON-like syntax for arrays and objects.

```json
SUM([1,4,5])    --> 10
```

```json
[1,4,5]                     --> array of numbers
[{"id":"A5B52","price":45}] --> array of objects
{"id":"A5B52","price":45}   --> object with key-value pairs
```

#### Nesting Functions

Functions can be nested inside each other. For instance, one function's result can be passed as an argument to another function.

```json
SUM(MAX(1,2),1)    --> 3
```

Here, `MAX(1,2)` evaluates to `2`, which is then used in the `SUM` function.

#### Variables

There are five types of variables that can be used in functions:

* **Input variables**: represent the rule's input data.
* **Output variables**: represent the rule's output data.
* **Rule variables**: user-defined variables with rule-level scope.
* **Calculation column variables**: variables declared in calculation columns in Decision Tables.
* **Abstract function variables**: special variables used in certain functions.

Variables are referenced using curly brackets (`{}`).

```javascript
// number = 3

SUM({number},6)   --> 9
```

In cases where the value from the variable cannot be used, the evaluation will fail and return an empty value:

<pre class="language-javascript"><code class="lang-javascript"><strong>// number = "a"
</strong>
SUM({number},6)   --> null
</code></pre>

#### Functions in Decision Tables

In Decision Tables, functions can be used in condition, result, and calculation columns.

* **Condition columns** must evaluate to boolean values (true or false).
* **Calculation columns** allow users to define variables or intermediary values that can be used in other columns for more complex calculations.
* **Result columns** can contain any type of function.

<figure><img src="/files/71eQf172veQsn1n07qCI" alt=""><figcaption><p>Example of functions in the condition and calculation columns</p></figcaption></figure>

When using functions in a decision table, you can turn on the Debug Mode and open the Console to see the detail of how they evaluated.


# Logical Functions

## List of logical functions

* [EQ](#equal-eq)
* [NE](#not-equal-ne)
* [GT](#greater-than-gt)
* [GTE](#greater-than-or-equal-gte)
* [LT](#less-than-lt)
* [LTE](#less-than-or-equal-lte)
* [BTW](#between-btw)
* [NOT\_BTW](#not-between-not_btw)
* [BTW\_LEF&#x54;*\_*&#x4F;PEN](#between-left-open-btw_left_open)
* [BTW\_RIGH&#x54;*\_*&#x4F;PEN](#between-right-open-btw_right_open)
* [AND](#and-and)
* [OR](#or-or)
* [IS\_NULL](#is-null-is_null)
* [IS\_NOT\_NULL](#is-not-null-is_not_null)
* [NVL](#null-value-logic-nvl)
* [IF](#condition-if)
* [NOT](#negation-not)

{% hint style="info" %}
The return value of logical functions is always boolean, i.e., true or false, with the exception of IF.
{% endhint %}

#### Deprecated functions

* [REGEXP](#regular-expression-regexp-deprecated)

### Equal (EQ)

Returns `true` if two values are equal to each other, or `false` otherwise.

* Takes 2 arguments.

```javascript
input1 = 3
input2 = [1,3]

[function] --> [output]

EQ(10,10)                     --> true
EQ(10,15)                     --> false
EQ(10,"10")                   --> true
EQ(10,"aa")                   --> false
EQ({input1},3)                --> true
EQ("a","a")                   --> true
EQ([1,3],{input2})            --> true
EQ({"price":10},{"price":11}) --> false

EQ(10)                        --> invalid

```

### Not equal (NE)

Returns `true` if the first value is not equal to the second value.

* Takes 2 arguments.

```javascript
input = 2

[function] --> [output]

NE(10,20)         --> true
NE({input},3)     --> true
NE(20,10)         --> true
NE("a","b")       --> true
NE(20,20)         --> false

NE("a")           --> invalid
```

### Greater than (GT)

Returns `true` if the first value is greater than the second value, or `false` otherwise.

* Takes 2 arguments.
* Both arguments have to be numbers, variables or strings.
* When used with strings, it returns `true` or `false` based on their alphabetical order.

```javascript
input = 4

[function] --> [output]

GT(20,10)         --> true
GT(20,20)         --> false
GT({input},3)     --> true
GT("a","a")       --> false
GT("b","a")       --> true

GT(15)            --> invalid
```

### Greater than or equal (GTE)

Returns `true` if the first value is greater than or equal to the second value, or `false` otherwise.

* Takes 2 arguments.
* Both arguments have to be numbers, variables or strings.
* When used with strings, it returns `true` or `false` based on their alphabetical order.

```javascript
input = 4

[function] --> [output]

GTE(20,10)         --> true
GTE(20,20)         --> true
GTE({input},3)     --> true
GTE("a","a")       --> true
GTE("b","a")       --> true

GTE(15)            --> invalid
```

### Less than (LT)

Returns `true` if the first value is lower than the second value.

* Takes 2 arguments.
* Both arguments have to be numbers, variables or strings.
* When used with strings, it returns `true` or `false` based on their alphabetical order.

```javascript
input = 4

[function] --> [output]

LT(10,20)         --> true
LT(10,10)         --> false
LT(3,{input})     --> true
LT("a","a")       --> false
LT("a","b")       --> true

LT(15)            --> invalid
```

### Less than or equal (LTE)

Returns `true` if the first value is less than or equal to the second value.

* Takes 2 arguments.
* Both arguments have to be numbers, variables or strings.
* When used with strings, it returns `true` or `false` based on their alphabetical order.

```javascript
input = 4

[function] --> [output]

LTE(10,20)         --> true
LTE(20,20)         --> true
LTE(3,{input})     --> true
LTE("a","a")       --> true
LTE("a","b")       --> true

LTE(15)            --> invalid
```

### Between (BTW)

Returns `true` if the second value is between the first and the third value, meaning in particular that first argument ≤ second argument ≤ third argument.

* Takes 3 arguments.

```javascript
input = 12

[function] --> [output]

BTW(10,15,20)         --> true
BTW(10,10,20)         --> true
BTW(10,{input},20)    --> true
BTW("a","f","z")      --> true
BTW(10,8,20)          --> false
BTW(20,10,15)         --> false

BTW(20,10)            --> invalid
```

### Not between (NOT\_BTW)

Returns `true` if the second value is between the first and the third value, meaning in particular that first argument < second argument or second argument > third argument.

* Takes 3 arguments.

### Between left open (BTW\_LEFT\_OPEN)

Returns `true` if the second value is between the first (excluding) and the third (including) value, meaning in particular that first argument < second argument ≤ third argument.

* Takes 3 arguments.

### Between right open (BTW\_RIGHT\_OPEN)

Returns `true` if the second value is between the first (including) and the third (excluding) value, meaning in particular that first argument ≤ second argument < third argument.

* Takes 3 arguments.

### And (AND)

Returns `true` if all of its arguments evaluate to `true`.

* Must have at least 1 argument.
* Arguments have to be booleans, numbers or variables.
* If the argument is a number, 0 is evaluated as `false` and anything else as `true`.
* Alternatively, OR can take an array of values in any argument.

```javascript
input = true

[function] --> [output]

AND(true,EQ(10,10))         --> true
AND(LT(10,10),GTE(10,10))   --> false
AND(true,EQ(10,20))         --> false
AND(true, {input}, false)   --> false
AND([true,true,true])       --> true
AND(1,true)                 --> true

AND("a","b")                --> invalid
```

### Or (OR)

Returns `true` if at least one of its arguments evaluates to `true`.

* Must have at least 1 argument.
* Arguments have to be booleans, numbers or variables.
* If the argument is a number, 0 is evaluated as `false` and anything else as `true`.
* Alternatively, OR can take an array of values in any argument.

```javascript
input = true

[function] --> [output]

OR(false,EQ(10,10))        --> true
OR(LT(10,10),GTE(10,10))   --> true
OR(false,EQ(10,20))        --> false
OR(false, false, {input})  --> true
OR([true,false,false])     --> true
OR(1,true)                 --> true

OR("a","b")                --> invalid
```

### Is null (IS\_NULL)

Returns `true` if the value is null (empty).

* Must have 1 argument.

```javascript
input1 = {}
input2 = null
input3 = "null"
input4 = "abc"
input5 = 3

[function] --> [output]

IS_NULL(input1)   --> true
IS_NULL(input2)   --> true
IS_NULL(input3)   --> true
IS_NULL(input4)   --> false
IS_NULL(input5)   --> false

IS_NULL("abc")    --> false
IS_NULL(3)        --> false
```

### Is not null (IS\_NOT\_NULL)

Returns `true` if the value is not null (empty).

* Must have 1 argument.

```javascript
input1 = {}
input2 = null
input3 = "null"
input4 = "abc"
input5 = 3

[function] --> [output]

IS_NOT_NULL(input1)   --> false
IS_NOT_NULL(input2)   --> false
IS_NOT_NULL(input3)   --> false
IS_NOT_NULL(input4)   --> true
IS_NOT_NULL(input5)   --> true

IS_NOT_NULL("abc")    --> true
IS_NOT_NULL(3)        --> true
```

### Null value logic (NVL)

Returns a specified default value when the input value is null according to [IS\_NULL](#is-null-is_null) logic.

* Must have 2 arguments.

```javascript
input = false

[function] --> [output]

NVL(null, "default value")                                  --> "default value"
NVL("null", "default value")                                --> "default value"
NVL({}, "default value")                                    --> "default value"
NVL([], "default value")                                    --> "default value"
NVL("not null", "default value")                            --> "not null"
NVL("not null", "default value" ,"not null default value")  --> "not null default value"

// other usage
{"animal":NVL(null, "default value"),"legs":4} --> {"animal":"default value","legs":4} 

```

### Negation (NOT)

Returns the opposite of a boolean value.

* Must have 1 argument.

```javascript
input = false

[function] --> [output]

NOT(true)          --> false
NOT({input})       --> true
NOT(LT(1,4))       --> false
NOT(EQ(256,256))   --> false
```

### Condition (IF)

Returns the second argument if the first argument is `true`, otherwise returns the third argument.

* Must have 3 arguments.
* The first argument is a condition. The condition must be of the boolean type (`true`/`false`).
* The second argument is an arbitrary value.&#x20;
* The third argument is an arbitrary value.

```javascript
input = false
number = 8

[function] --> [output]

IF(true,"Input truthy","Input falsy")       --> "Input truthy"
IF({input},"Input truthy","Input falsy")    --> "Input falsy"
IF(LT(0,{number}),"Positive","Negative")    --> "Positive"
```

### Regular expression (REGEXP) (deprecated)

{% hint style="warning" %}
This function is deprecated. Use TEST instead (see [Text Functions](/doc/rules/data-types-and-functions/operators/functions/text)).
{% endhint %}

Returns `true` if the first argument matches against a regular expression in the second argument.

* Must have 2 arguments.
* Arguments have to be numbers, strings or variables.

```javascript
input = hello

[function] --> [output]

REGEXP("abc","bc")       --> true
REGEXP(12233,23)         --> true
REGEXP({input},"lo")     --> true
REGEXP("xxx","yy")       --> false
REGEXP("hello","ho")     --> false

REGEXP("bye")            --> invalid
```


# Math Functions

## List of math functions

* [ABS](#absolute-value-abs)
* [AVG](#average-avg)
* [CEILING](#ceiling-ceiling)
* [COUNT](#count-count)
* [EXP](#exponential-exp)
* [FLOOR](#floor-floor)
* [MAX](#maximum-max)
* [MEDIAN](#median-median)
* [MIN](#minimum-min)
* [MODULO](#modulo-modulo)
* [POW](#power-pow)
* [RANDOM](#random-random)
* [ROUND](#round-round)
* [ROUNDE](#round-to-even-rounde)
* [SUM](#summation-sum)
* [NUMHASH](#numerical-hash-numhash)
* [+ (Plus)](#plus)
* [- (Minus)](#minus)
* [**\***  (Times)](#times)
* [/  (Division)](#division)

### Absolute Value (`ABS`)

Returns the absolute value of a number.

* Takes 1 argument.
* The argument has to be a number or a variable.

```javascript
input = 3

[function] --> [output]

ABS(6)            --> 6
ABS(0)            --> 0
ABS(-2.5)         --> 2.5
ABS({input})      --> 3

ABS("a")          --> invalid
```

### Average (`AVG`)

Returns the average (arithmetic mean) of the arguments.

* Takes any number of arguments greater than 0.
* Each argument must be a number or a variable.
* Alternatively, AVG can take an array of numbers in any argument.

```javascript
input1 = 3
input2 = [1,2,3]

[function] --> [output]

AVG(6,8)           --> 7
AVG(1,2,3)         --> 2
AVG({input1},7)    --> 5
AVG({input2})      --> 2
AVG("1",3)         --> 2

AVG("a","b")       --> invalid
```

### Ceiling (`CEILING`)

Returns a number rounded up to the nearest whole number.

* Takes 1 argument.
* The argument must be a number or a variable.

```javascript
input = 3.28

[function] --> [output]

CEILING(1.34)          --> 2
CEILING({input})       --> 4
CEILING("1.15")        --> 2

CEILING(6,8)           --> invalid
CEILING("a","b")       --> invalid
```

### Count (`COUNT`)

Counts the number of its arguments or elements of provided arrays.

* Takes any number of arguments greater than 0.
* When given an array, it looks inside the array and counts in its elements.

```javascript
input = 3

[function] --> [output]

COUNT(6,8)           --> 2
COUNT(1,2,3)         --> 3
COUNT({input},7)     --> 2
COUNT([1,2,3])       --> 3
COUNT([1,2,3],4)     --> 4
COUNT(1)             --> 1
COUNT("a","b")       --> 2

COUNT()              --> invalid
```

### **Exponential (`EXP`)**

Returns the value of exponential function of the given numerical argument.

* Takes 1 argument.
* The argument must be a number or a variable.

```javascript
input = 2.5

[function] --> [output]

EXP(0)              --> 1
EXP(1)              --> 2.718281828459045
EXP(2.5)            --> 12.182493960703473
EXP({input})        --> 12.182493960703473
EXP(-2.5)           --> 0.0820849986238988
EXP("2.5")          --> 12.182493960703473

EXP("x")            --> invalid
```

### Floor (`FLOOR`)

Returns a number rounded down to the nearest whole number.

* Takes 1 argument.
* The argument must be a number or a variable.

```javascript
input = 3.28

[function] --> [output]

FLOOR(1.34)          --> 1
FLOOR({input})       --> 3
FLOOR("1.15")        --> 1

FLOOR(6,8)           --> invalid
FLOOR("a","b")       --> invalid
```

### Maximum (`MAX`)

Returns the largest number from those provided.

* Takes any number of arguments greater than 0.
* Each argument must be a number or a variable.
* Alternatively, MAX can take an array of numbers in any argument.

```javascript
input1 = 3    
input2 = [1,2,3]

[function] --> [output]

MAX(5,8)           --> 8
MAX(1,2,3)         --> 3
MAX({input2},6)    --> 6
MAX({input2})      --> 3
MAX({input2},10)   --> 10
MAX(1)             --> 1
MAX("1")           --> 1

MAX("a","b")       --> invalid
```

### Median (`MEDIAN`)

Returns the median of the given numbers. The median is the number in the middle of a set of numbers.

* Takes any number of arguments greater than 0.
* Each argument must be a number or a variable.
* Alternatively, MEDIAN can take an array of numbers in any argument.

```javascript
input = 3

[function] --> [output]

MEDIAN(6,8)           --> 7
MEDIAN(1,2,2,3)       --> 2
MEDIAN({input},7)     --> 5
MEDIAN(0,[2,5])       --> 2
MEDIAN(1)             --> 1
MEDIAN("1","3")       --> 2

MEDIAN("a","b")       --> invalid
```

### **Minimum (`MIN`)**

Returns the smallest number from those provided.

* Takes any number of arguments greater than 0.
* Each argument must be a number or a variable.
* Alternatively, MIN can take an array of numbers as an argument.

```javascript
input1 = 3  
input2 = [1,2,3]

[function] --> [output]

MIN(5,8)           --> 5  
MIN(1,2,3)         --> 1  
MIN({input1},6)    --> 3  
MIN({input2})      --> 1  
MIN({input2},10)   --> 1  
MIN(1)             --> 1  
MIN("1")           --> 1  

MIN("a","b")       --> invalid  
```

### Modulo (`MODULO`)

Returns the remainder of the division of two numbers. This function captures the remainder when the first argument is divided by the second, which can be useful in scenarios requiring evaluations based on divisibility or cyclic behavior.

* Takes 2 arguments.
* Both arguments must be numbers or variables.

```javascript
input1 = 5
input2 = 3

[function] --> [output]

MODULO(10, 3)              --> 1
MODULO(10, 5)              --> 0
MODULO(15, {input2})       --> 0
MODULO({input1}, {input2}) --> 2
MODULO(9, 4)               --> 1

MODULO(10)                 --> invalid
MODULO("a", 2)             --> invalid
```

### **Power (`POW`)**

Returns an arbitrary power of an arbitrary number.

* Takes 2 arguments.
* Both arguments have to be numbers or a variables.
* The first argument is the base, the second argument is the exponent.

```javascript
input = 3

[function] --> [output]

POW(2,6)            --> 64
POW(0,6)            --> 0
POW(10,0)           --> 1
POW(10,-2.5)        --> 0.00316227766
POW(2,{input})      --> 8

POW(-4,0.5)         --> invalid
POW("a",2)          --> invalid
```

### Random (`RANDOM`)

Returns a pseudo-random number within a defined interval.

* Takes 0, 1, or 2 arguments.
* When called with no arguments, returns a random number in the interval \[0, 1).
* When called with 1 argument (max), returns a random number in the interval \[0, max).
* When called with 2 arguments (min, max), returns a random number in the interval \[min, max).
* The decimal part has no fixed length (typically 15-18 decimal places).

```javascript
min = 2
max = 5

[function] --> [output]

RANDOM()             --> 0.47823211671827814
RANDOM()             --> 0.115179000076884
RANDOM(3)            --> 2.47422361052683
RANDOM(3)            --> 0.349574130802466
RANDOM(5, 10)        --> 8.718
RANDOM({min}, {max}) --> 2.145
RANDOM(10)           --> 7.167259743003298

RANDOM("a")          --> invalid
RANDOM(1, "b")       --> invalid
```

### Round (`ROUND`)

Rounds a number to the closest number of the specified decimal place.

* Takes 1 or 2 arguments.
* The first argument is the number to be rounded.
* The second (optional) specifies the number of decimal places (defaults to 0 if omitted and can be negative).

<pre class="language-javascript"><code class="lang-javascript">input = 8.358

[function] --> [output]

ROUND(24.89)         --> 25
ROUND(24.89, 2)      --> 24.89
ROUND(24.89, -1)     --> 20
<strong>ROUND({input})       --> 8
</strong>ROUND({input},1)     --> 8.4
ROUND("24.89")       --> 25

ROUND("a",2)         --> invalid
</code></pre>

### Round **to Even** (`ROUNDE`)

The round-to-even method is used in engineering, finance, and computer science to reduce bias when you use rounded numbers to estimate sums and averages. The round-to-even method works like this:

* If the difference between the number and the nearest integer is less than 0.5, round to the nearest integer. This familiar rule is used by many rounding methods.
* If the difference between the number and the nearest integer is exactly 0.5, look at the integer part of the number. If the integer part is EVEN, round towards zero. If the integer part of the number is ODD, round away from zero. In either case, the rounded number is an even integer.

```javascript
[function] --> [output]

ROUNDE(1.465,2)      --> 1.46
ROUNDE(1.5)          --> 2
ROUNDE(2.5)          --> 2
ROUNDE("a",2)        --> invalid
```

### Summation (`SUM`)

Sums up numerical values.

* Takes any number of arguments greater than 0.
* Each argument must be a number or a variable.
* Alternatively, SUM can take an array of numbers in any argument.

```javascript
input1 = 3
input2 = [1,2,3]

[function] --> [output]

SUM(1,2)           --> 3
SUM(1,2,3)         --> 6
SUM({input1},6)    --> 9
SUM({input2})      --> 6
SUM({input2},4)    --> 10
SUM("1")           --> 1
SUM(1)             --> 1

SUM("a","b")       --> invalid
```

### **Numerical Hash (NUMHASH)**

Converts the input into a number. Uses a variant of the djb2 hash function.

* Takes any amount arguments.
* Arguments can be of any type.
* Is idempotent
* Uniqueness is not guaranteed

```javascript
[function]   -->     [output]

'hello'         -->     261238937
{"test": 123}   -->     1271012719
5*(-2)          -->     68779267
```

### Plus (`+`)

* Takes 2 arguments.
* Both arguments have to be numbers or a variables.

```javascript
input = 6

[function] --> [output]

4+2             --> 6
{input}+2       --> 8
3+{input}       --> 9

x+x             --> invalid
```

### Minus (`-`)

* Takes 1 or 2 arguments, yet the second argument always has to be there.
* Both arguments have to be numbers or a variables.

```javascript
input = 6  

[function] --> [output]

4-2             --> 2
{input}-1       --> 5
9-{input1}      --> 3
-1              --> -1

3-              --> invalid
x-x             --> invalid
```

{% hint style="danger" %}
For the minus operation to work correctly, it is necessary to use brackets to specify the desired order of the operations, e.g. write `(1-1)-1` or `(-3)*5` instead of merely `1 - 1 - 1` or `-3*5`, respectively.
{% endhint %}

### **Times (\*)**

Performs multiplication between two numbers.

* Takes 2 arguments.
* Both arguments have to be numbers or a variables.

```javascript
input = 6

[function] --> [output]

4*2             --> 8
{input}*2       --> 12
5*(-2)          --> -10

x*x             --> invalid
```

### Division (`/`)

Takes 2 arguments. Both arguments must be numbers or variables.

```javascript
input = 6

[function] --> [output]

4/2             --> 2
18/{input}      --> 3
30/(-6)         --> -5

x/x             --> invalid
```

## Combining Function Operators

You can combine basic operations to create more complex expressions using parentheses `()`. \
For example:

```javascript
input = 6

[function] --> [output]

1+2+(-3)                            --> 0
1-(4+5+2*{input})/3                 --> -4
(4+9)*(4+9) - (4*4 + 2*4*9 + 9*9)   --> 0
```

You can also use arithmetic operations in conjunction with other functions:

```javascript
input = 9

[function] --> [output]

SUM(1,2,-3)                                 --> 0
1-AVG(4,5,2*{input})                        --> -8
POW(4+9,2) - (POW(4,2) + 2*4*9 + POW(9,2))  --> 0
```


# Date and Time Functions

## List of date and time functions

* [NOW](#now-now)
* [CURDATE](#current-date-curdate)
* [CURTIME](#current-time-curtime)
* [DATE](#date-date)
* [DATE\_MAX](#date-max-date_max)
* [DATE\_MIN](#date-min-date_min)
* [DATEDIFF](#date-difference-datediff)
* [DATE\_COMPUTE](#date-compute-date_compute)
* [DATETIME\_COMPUTE](#date-time-compute-datetime_compute)
* [DATE\_FORMAT](#date-format-date_format)
* [DAY](#day-day)
* [MONTH](#month-month)
* [YEAR](#year-year)
* [WEEKDAY](#weekday-weekday)

{% hint style="info" %}
Within DecisionRules functions, date and time are represented by a date/time ISO string. Functions generating date like NOW or DATE therefore return string which can be then picked up by other date functions. On the other hand, most of the other date functions return numbers, like DATEDIFF, DAY, MONTH or YEAR.
{% endhint %}

{% hint style="warning" %}
Note that DATE function converts dates to Coordinated Universal Time (UTC) based on specified time zone and Daylight Saving Time (DST) settings. If no time zone is specified, CET (Central European Time) is used by default.\
\
For example, when entering a date like "04.16.2024", it adjusts to "2024-04-15T22:00" (using GMT+2 by default) to align with UTC. If another function uses DATE as a parameter, this adjusted date ("04.15.2024") is then utilized as required.\
\
**Tip!** \
You can append the letter "Z" to the end of the date provided within the DATE function. This indicates that the date should be treated as UTC and will not be converted to UTC.\
\
\&#xNAN;*Examples:*&#x20;

```json
DATE("04.16.2024Z") ---> "2024-04-16T00:00"
DATE("04.16.2024 15:30 Z") ---> "2024-04-16T15:30"
```

{% endhint %}

### Now (NOW)

Returns the current date and time.

* Takes 1 optional argument.
* When present, the optional argument specifies time zone.

```javascript
input = "+02:00"

[function] ---> [output]

NOW()              ---> "2021-06-01T11:01"
NOW("+08:00")      ---> "2021-06-01T19:01"
NOW("-08:00")      ---> "2021-06-01T03:01"
NOW({input})       ---> "2021-06-01T13:01"

NOW(1)             ---> invalid
NOW("abc")         ---> invalid
```

### Current date (CURDATE)

Returns the current date.

* Takes 1 optional argument.
* When present, the optional argument specifies time zone.

```javascript
input = "+02:00"

[function] ---> [output]

CURDATE()              ---> "2021-06-01"
CURDATE("+08:00")      ---> "2021-06-01"
CURDATE("-02:00")      ---> "2021-06-01"
CURDATE({input})       ---> "2021-06-01"
CURDATE("+10:00")      ---> "2021-07-01"

CURDATE(1)             ---> invalid
CURDATE("xx")          ---> invalid
```

### Current time (CURTIME)

Returns the current time.

* Takes 1 optional argument.
* When present, the optional argument specifies time zone.

```javascript
input = "+02:00"

[function] ---> [output]

CURTIME()              ---> "11:16"
CURTIME("-02:00")      ---> "09:16"
CURTIME("+08:00")      ---> "19:16"
CURTIME({input})       ---> "13:16"

CURTIME(1)             ---> invalid
CURTIME("xx")          ---> invalid
```

### Date (DATE)

Takes a string and returns a date (a date ISO string that can be picked up by other functions). The returned date and time are localized to UTC.

* Takes 1 to 3 arguments.
* The first argument is a string representing a date.
* The second optional argument specifies custom format of the given date.
* Third argument determinate what units are used for flooring. Possible values are: s= seconds,  m= minutes and h= hours.

{% hint style="info" %}
For details on how to write the second parameter specifying the date format, please see the [Day.js Documentation](https://day.js.org/docs/en/parse/string-format).
{% endhint %}

```javascript
input = "12/25/2021"

[function] ---> [output]

DATE("2021-12-25T23:00")       ---> "2021-12-25T22:00"
DATE("12/25/2021")             ---> "2021-12-24T23:00"
DATE({input})                  ---> "2021-12-24T23:00"
// Append "Z" at the end if you want the date to be treated as UTC
DATE("12/25/2021 Z")           ---> "2021-12-25T00:00"
DATE("12.25.2021 Z")           ---> "2021-12-25T00:00"
DATE({input}Z)                 ---> "2021-12-25T00:00"

DATE("2.20.2022 GMT+3")        ---> "2022-02-19T21:00"
DATE("2.20.2022 15:00 GMT+3")  ---> "2022-02-20T12:00"

DATE("18/06/2022T08:15","DD/MM/YYYYTHH:mm")  ---> 2022-06-18T06:15
DATE("18.06.2022 08:15 +03:00","DD.MM.YYYY HH:mm Z")  ---> 2022-06-18T05:15

DATE("18/06/2022T08:15:44","DD/MM/YYYYTHH:mm:ss", "s")  ---> 2022-06-18T06:15:44
DATE("18/06/2022T08:15:44","DD/MM/YYYYTHH:mm:ss", "m")  ---> 2022-06-18T06:15
DATE("18/06/2022T08:15:44","DD/MM/YYYYTHH:mm:ss", "h")  ---> 2022-06-18T06:00

DATE("1710510160000", "x") --> "2024-03-15T13:42"

DATE()                         ---> invalid
DATE(12/25/2021)               ---> invalid
```

{% hint style="warning" %}
Note that the function returns the result even for an invalid date as follows:

* The values for the day can take 1-31 (depending on the month). If the range is exceeded, it will bubble up to the next month.
* The values for the month can take 0-11 (Months are zero indexed, so January is month 0). If the range is exceeded, it will bubble up to the next year.
  {% endhint %}

<pre class="language-javascript"><code class="lang-javascript">[function] ---> [output]

//Invalid day
DATE("2021-12-<a data-footnote-ref href="#user-content-fn-1">33</a>T22:00")       ---> "2022-01-02T21:00"
DATE("02/30/2022")             ---> "2022-03-01T23:00"

//Invalid month
DATE("2023-13-30T22:00")       ---> "2024-01-30T21:00"
DATE("2022-18-04T12:00")       ---> "2023-06-04T10:00"
</code></pre>

### Date Max (DATE\_MAX)

Gets the maximum of inputted dates.

* Takes 1 argument.
* The argument is an array (or spread) date (obtained from DATE or NOW).

```javascript
[function] ---> [output]

DATE_MAX(
    DATE("2002-11-25T12:45:30", "YYYY-MM-DDTHH:mm:ss", "s"), 
    DATE("2002-11-29T12:45:30", "YYYY-MM-DDTHH:mm:ss", "s")
) --> "2002-11-29T11:45:30"

DATE_MAX([
    DATE("2002-11-25T12:45:30", "YYYY-MM-DDTHH:mm:ss", "s"), 
    DATE("2002-11-29T12:45:30", "YYYY-MM-DDTHH:mm:ss", "s")
]) --> "2002-11-29T11:45:30"

// Different date format example
DATE_MAX(
    DATE("2002/11/25 12:45:30", "YYYY/MM/DD HH:mm:ss", "s"), 
    DATE("2002/11/29 12:45:30", "YYYY/MM/DD HH:mm:ss", "s")
) --> "2002-11-29T11:45:30"
```

### Date Min (DATE\_MIN)

Gets the minimum of inputted dates.

* Takes 1 argument.
* The argument is an array (or spread) date (obtained from DATE or NOW).

```javascript
[function] ---> [output]

DATE_MIN(
    DATE("2002-11-25T12:45:30", "YYYY-MM-DDTHH:mm:ss", "s"), 
    DATE("2002-11-29T12:45:30", "YYYY-MM-DDTHH:mm:ss", "s")
) --> "2002-11-29T11:45:30"

DATE_MIN([
    DATE("2002-11-25T12:45:30", "YYYY-MM-DDTHH:mm:ss", "s"), 
    DATE("2002-11-29T12:45:30", "YYYY-MM-DDTHH:mm:ss", "s")
]) --> "2002-11-29T11:45:30"

// Different date format example
DATE_MIN(
    DATE("2002/11/25 12:45:30", "YYYY/MM/DD HH:mm:ss", "s"), 
    DATE("2002/11/29 12:45:30", "YYYY/MM/DD HH:mm:ss", "s")
) --> "2002-11-29T11:45:30"
```

### Date difference (DATEDIFF)

Returns the number of specified time units between two dates. It may return negative or positive numbers, based on the order of the dates.

* Takes 3 arguments.
* The first and second argument is a date.
* The third argument specifies the time unit, as listed below.

```javascript
"s" -- seconds
"m" -- minutes
"H" -- hours
"D" -- days
"W" -- weeks
"M" -- months
"Y" -- years
```

```javascript
input = "01/02/2016"

[function] ---> [output]

DATEDIFF(DATE("01/31/2020"), DATE("01/31/2021"), "D")  ---> -366
DATEDIFF(DATE("01/31/2021"), DATE("01/31/2020"), "D")  ---> 366
DATEDIFF(DATE("01/31/2021"), DATE("01/31/2020"), "M")  ---> 12
DATEDIFF(DATE("01/31/2021"), DATE("01/31/2020"), "Y")  ---> 1
DATEDIFF(DATE({input}), DATE("12/30/2015"), "D")       ---> 3
```

### Date compute (DATE\_COMPUTE)

Takes a date and adds or subtracts a specified time.

* Takes 2 arguments.
* The first argument is a date (obtained from DATE or NOW).
* The second argument is the number of days to add.

```javascript
input = "12/01/2021"
[function] ---> [output]

DATE_COMPUTE(DATE("12/01/2021"), "+20") ---> "2021-12-21"
DATE_COMPUTE(DATE({input}), +20)        ---> "2021-12-21"
DATE_COMPUTE(DATE("12/30/2021"), "-20") ---> "2021-12-10"

DATE_COMPUTE(DATE("12/01/2021"))        ---> invalid
DATE_COMPUTE()                          ---> invalid
```

### Date Time compute (DATETIME\_COMPUTE)

Takes a date and adds or subtracts a specified time unit.

* Takes 3 arguments.
* The first argument is a date (obtained from DATE or NOW).
* The second argument is the number of units to add.
* Third argument specifies units (s= seconds, h= hours, M= month, m= minutes, y= years)

Output date format is: `YYYY-MM-DDTHH:mm:ss`

```javascript
input = "12/01/2021"
[function] ---> [output]

DATETIME_COMPUTE(DATE("12/01/2021 14:44 GMT+02:00", "DD/MM/YYYY HH:mm Z"), "+24", "h") ---> "2021-01-13T12:44:00"
DATETIME_COMPUTE(DATE({input}, "DD/MM/YYYY"), "+24", "m") ---> "2021-01-11T23:24:00"
DATETIME_COMPUTE(DATE("12/30/2021", "MM/DD/YYYY"), "-24", "h") ---> "2021-12-28T23:00:00"
DATETIME_COMPUTE(DATE("2002-11-25T12:45:30", "YYYY-MM-DDTHH:mm:ss", "s"),"2","s") --> "2002-11-25T11:45:32"

//Example with timestamp
DATETIME_COMPUTE(DATE("1710510160000", "x"), "6", "h")

DATETIME_COMPUTE(DATE("12/01/2021", "DD/MM/YYYY"))  ---> invalid
DATETIME_COMPUTE()                          ---> invalid
```

{% hint style="info" %}
Notice that all return values are in UTC format. For the precise calculation specify date format in DATE function.
{% endhint %}

### Date format (DATE\_FORMAT)

Takes a date and converts it to required format.

* Takes 2 arguments.
* The first argument is the date to be converted (obtained from DATE, NOW or CURDATE).
* The second argument is the required date format.

{% hint style="warning" %}
**Note:**\
This function depends on the output of the DATE function. For further details, refer to the info block at the [beginning of this page](#list-of-date-and-time-functions)
{% endhint %}

```javascript
input = "04/16/2024"
[function] ---> [output]

// If no letter 'Z' is appeneded then the date is converted to UTC first
DATE_FORMAT(DATE("04/16/2024"), "DD.MM.YYYY")       ---> "15.04.2024"
// Add 'Z' at the end of the date if you do not want it to be converted
DATE_FORMAT(DATE("04/16/2024Z"), "DD.MM.YYYY")      ---> "16.04.2024"

DATE_FORMAT(DATE({input}Z), "DD-MM-YYYY")           ---> "16-04-2024"
DATE_FORMAT(DATE("04/16/2024 Z"), "DD MMMM YY")     ---> "16 April 24"
DATE_FORMAT(DATE("04/16/2024 Z"), "dddd MMM YY")    ---> "Tuesday Apr 24"
DATE_FORMAT(DATE("04/16/2024 Z"), "ddd")            ---> "Tue"

DATE_FORMAT(DATE("04/16/2024 15:00 Z"), "dddd DD MMMM hh a") 
    ---> "Tuesday 16 April 03 pm"
DATE_FORMAT(DATE("04/16/2024 15:30 GMT+5"), "dddd, MMMM D, YYYY h:mm A") 
    ---> "Tuesday, April 16, 2024 10:30 AM"
DATE_FORMAT(DATE("04/16/2024T15:30:44","MM/DD/YYYYTHH:mm:ss", "s"), "DD.MM.YYYY HH:mm:ss") 
    ---> "16.04.2024 13:30:44"

// First parametr must be a DATE, NOW or CURDATE function
DATE_FORMAT("04/16/2024", "DD.MM.YYYY")         ---> invalid
```

{% hint style="info" %}
For a list of all possible date format values, please refer to the [Day.js documentation](https://day.js.org/docs/en/display/format) under "List of available formats" (excluding Advanced and Localized format tokens)
{% endhint %}

### Day (DAY)

Returns day from date

Takes 1 argument

The arguments must be a DATE object. Use the DATE function.

```javascript
[function] ---> [output]

DAY(DATE("12-31-2025 GMT")) => 31
```

### Month (MONTH)

Gets the month of the year for a given date.

* Takes 1 argument.
* The argument is a date (obtained from DATE or NOW).

```javascript
input = "12/01/2021"
[function] ---> [output]

MONTH(DATE("12/01/2021"))            --> 12
MONTH(DATE({input}))                 --> 12

MONTH()                              --> invalid
```

### Year (YEAR)

Gets the year of a given date.

* Takes 1 argument.
* The argument is a date (obtained from DATE or NOW).

```javascript
input = "12/01/2021"

[function] ---> [output]

YEAR(DATE("12/31/2015"))            --> 2015
YEAR(DATE({input}))                 --> 2021

YEAR()                              --> invalid
```

### Weekday (WEEKDAY)

Finds the day of the week of the given date.

* Takes 1 argument.
* The argument is a date (obtained from DATE or NOW).

The WEEKDAY function returns a number from 0 (meaning Sunday) to 6 (meaning Saturday).

```javascript
input = "12/01/2021"

[function] ---> [output]

WEEKDAY(DATE("09/05/2022"))        --> 1 (Monday)
WEEKDAY(DATE({input}))             --> 3 (Wednesday)

WEEKDAY()                          --> invalid
```

[^1]:


# Text Functions

## List of text functions

* [CONCAT](#concatenation-concat)
* [CONCAT\_WS](#concatenation-with-a-separator-concat_ws)
* [LEN](#length-len)
* [UPPER\_CASE](#upper-case-upper_case)
* [LOWER\_CASE](#lower-case-lower_case)
* [LEFT](#left-left)
* [RIGHT](#right-right)
* [TRIM](#trim-trim)
* [TRIM\_LEFT](#trim-left-trim_left)
* [TRIM\_RIGHT](#trim-right-trim_right)
* [SUBSTR](#substring-substr)
* [RE](#replace-replace)
* [TEST](#test-test)
* [TEXT](#text-text)
* [MATCH](#match-match)
* [REPLACE](#replace-replace)
* [SPLIT](#split-split)

#### Deprecated functions

* [STRINGFORMAT](#string-format-stringformat-deprecated)

### Concatenation (CONCAT)

Adds two or more strings together.

* Takes at least 1 argument.
* All arguments must be strings, numbers, variables or alternatively arrays.

```javascript
input = "week"

[function] --> [output]

CONCAT("pine","apple")      --> "pineapple"
CONCAT("he","ll","o")       --> "hello"
CONCAT(1,2)                 --> 12
CONCAT({input},"end")       --> "weekend"
CONCAT(1+1,"nd")            --> "2nd"
CONCAT(["a","b","c"])       --> "abc"

CONCAT()                    --> invalid
```

{% hint style="warning" %}
CONCAT trims leading and trailing spaces from each argument before joining.\
If you need separator between concatenated values - use CONCAT\_WS function.
{% endhint %}

```javascript
value = 10

[function] --> [output]

CONCAT("The value is: ", {value})  -->  "The value is:10" 
CONCAT({value}, " is the value")   -->  "10is the value" 
```

### Concatenation with a separator (CONCAT\_WS)

Adds two or more strings together with a separator.

* Takes at least 2 arguments.
* The first argument specifies the separator.
* The other arguments are the values to be concatenated.
* The arguments have to be strings, numbers or variables.
* All arguments except the first one can also take arrays.

```javascript
input = "week"

[function] --> [output]

CONCAT("-","pine","apple")      --> "pine-apple"
CONCAT_WS("+","he","ll","o")    --> "he+ll+o"
CONCAT_WS("_"1,2)               --> 1_2
CONCAT_WS(" ",{input},"end")    --> "week end"
CONCAT_WS("^",1+1,"nd")         --> "2^nd"
CONCAT_WS("separator","word")   --> "word"
CONCAT_WS("!",["a","b","c"])    --> "a!b!c"

CONCAT_WS()                     --> invalid
```

### Length (LEN)

Returns the length of a string.

* Takes 1 argument.
* The argument has to be a string, number, or a variable.

```javascript
[function] --> [output]

LEN("Hello")       --> 5
LEN("555")         --> 3
LEN(555)           --> 3

LEN("Hello", "bye")    --> invalid
```

### Upper case (UPPER\_CASE)

Converts a string to the upper case.

* Takes 1 argument.
* The argument has to be a string or a variable.

```javascript
[function] --> [output]

UPPER_CASE("Hello World")       --> "HELLO WORLD"
UPPER_CASE("I AM NEW HERE")     --> "I AM NEW HERE"
UPPER_CASE("2ae3")              --> "2AE3"

UPPER_CASE("Hello", "World")       --> invalid
```

### Lower case (LOWER\_CASE)

Converts a string to the lower case.

* Takes 1 argument.
* The argument has to be a string or a variable.

```javascript
[function] --> [output]

LOWER_CASE("Hello World")       --> "hello world"
LOWER_CASE("I AM NEW HERE")     --> "i am here"
LOWER_CASE("2AE3")              --> "2ae3"

UPPER_CASE("Hello", "World")       --> invalid
```

### Left (LEFT)

Returns the first character of a string or the specified number of characters from the beginning.

* Takes 1 or 2 arguments.
* The first argument has to be a string, number or a variable.
* The second optional argument specifies the number of characters to be taken from the left side. If not specified, it defaults to 1.

```javascript
input = "123"

[function] --> [output]

LEFT("abcd")           --> "a"
LEFT("")               --> ""
LEFT("abcd",2)         --> "ab"
LEFT({input},2)        --> "12"
```

### Right (RIGHT)

Returns the last character of a string or the specified number of characters from the end.

* Takes 1 or 2 arguments.
* The first argument has to be a string, number or a variable.
* The second optional argument specifies the number of characters to be taken from the right side. If not specified, it defaults to 1.

```javascript
input = "123"

[function] --> [output]

RIGHT("abcd")           --> "d"
RIGHT("")               --> ""
RIGHT("abcd",2)         --> "cd"
RIGHT({input},2)        --> "23"
```

### Trim (TRIM)

Trims leading and trailing spaces in a string.

* Takes 1 argument.
* The argument has to be a string, number or a variable.

```javascript
input = "  123  "

[function] --> [output]

TRIM("   abcd   ")       --> "abcd"
TRIM("")                 --> ""
TRIM("abcd")             --> "abcd"
TRIM({input})            --> "123"
```

### Trim left (TRIM\_LEFT)

Trims leading spaces in a string.

* Takes 1 argument.
* The argument has to be a string, number or a variable.

```javascript
input = "  123"
[function] --> [output]

TRIM_LEFT("   abcd")          --> "abcd"
TRIM_LEFT("   abcd   ")       --> "abcd   "
TRIM_LEFT("")                 --> ""
TRIM_LEFT({input})            --> "123"
```

### Trim right (TRIM\_RIGHT)

Trims trailing spaces in a string.

* Takes 1 argument.
* The argument has to be a string, number or a variable.

```javascript
VARIABLE = "123  "
[function] --> [output]

TRIM_RIGHT("abcd   ")              --> "abcd"
TRIM_RIGHT("abcd")                 --> "abcd"
TRIM_RIGHT("")                     --> ""
TRIM_RIGHT({VARIABLE})             --> "123"
```

### Substring (SUBSTR)

Returns a substring from a specified position of a string.

* Takes 2 or 3 arguments.
* The first argument has to be a string or a variable.
* The second argument is the index of the first character to appear in the substring
* The third, optional argument is the index of the last character to appear in the substring
* The second and third argument has to be a number or a variable.
* If the third argument is not provided, the substring spans till the end of the original string.

```javascript
[function] --> [output]

SUBSTR("ab123ABCD",3,5)          --> 123
SUBSTR("ab123ABCD",6,6)          --> "A"
SUBSTR("ab123ABCD",0,5)          --> "ab123"
SUBSTR("ab123ABCD",3)            --> "123ABCD"

SUBSTR("ab123ABCD")              --> invalid
```

### Regular expression (RE)

Builds a regular expression for use in other text functions (TEST, MATCH, REPLACE, SPLIT).

* Takes 1 or 2 arguments.
* The first argument is a string representation of the regular expression.
* The second optional argument is a string representation of custom flags.

```javascript
[function] --> [output]

RE("[A-Z]")        --> /[A-Z]/
RE("[A-Z]","g")    --> /[A-Z]/g
```

### Test (TEST)

Tests a string for a match against a regular expression and returns true or false.

* Takes 2 arguments.
* The first argument specifies to string to be tested.
* The first argument has to be a string, number or a variable.
* The second argument specifies the substring whose presence is to be tested.
* The second argument can take a string or the RE function.

```javascript
[function] --> [output]

TEST("Hello, World!","ll")             --> true
TEST("Hello, World!","[A-Z]")          --> true
TEST("Hello, World!",RE("l{2}"))       --> true
TEST("Hello, World!",RE("l{3}"))       --> false
TEST("Hello, World!",RE("H[ae]llo"))   --> true
TEST("Hello, World!",RE("h[ae]llo"))   --> false
```

### Text (TEXT)

Returns the input exactly as it is, without evaluating variables or executing functions.

* It outputs the raw form of whatever you pass in.
* Takes 1 argument.
* The argument can be string, number, date, array, object.

```javascript
[function] --> [output]

TEXT("Hello, World!")                   --> "Hello, World!"
TEXT('Hello, World!')                   --> "Hello, World!"
TEXT(Hello, World!)                     --> "Hello, World!"
TEXT("Let's go!")                       --> "Let's go!"
TEXT({"key":"Hello", "value":"World!"}) --> "{\"key\":\"Hello\", \"value\":\"World!\"}"
TEXT("^\d{5}$")                         --> "^\d{5}$"
TEXT(TEXT())                            --> "TEXT()"
```

### Match (MATCH)

Tests a string for a match against a regular expression and returns an array of matches (or null for no matches).

* Takes 2 arguments.
* The first argument specifies to string to be tested for matches.
* The first argument has to be a string, number or a variable.
* The second argument specifies the regular expression to be used for the matching.
* The second argument can take a string or the RE function.
* When the second argument is given as a plain string, the match is performed with the g (global) flag.

```javascript
[function] --> [output]

MATCH("Hello, World!","ll")             --> ["ll"]
MATCH("Hello, World!","[A-Z]")          --> ["H","W"]
MATCH("Hello, World!",RE("[A-Z]"))      --> ["H"]
MATCH("Hello, World!",RE("[A-Z]","g"))  --> ["H","W"]
MATCH("Hello, World!",RE("l{3}"))       --> null
MATCH("Hello, World!",RE("h[ae]llo"))   --> null
```

### Replace (REPLACE)

Takes a string, matches it against a regular expression and replaces the matches with a given replacement string.

* Takes 3 arguments.
* The first argument specifies to string to be tested for matches.
* The first argument has to be a string, number or a variable.
* The second argument specifies the regular expression to be used for the matching.
* The second argument can take a string or the RE function.
* When the second argument is given as a plain string, the match is performed with the g (global) flag.
* The third argument specifies the replacement string.

{% hint style="info" %}
Argument 1 --> **where** to replace

Argument 2 --> **what** to replace

Argument 3 --> **for what** to replace
{% endhint %}

```javascript
[function] --> [output]

REPLACE("Hello World", "o", "a")                    --> "Hella warld"
REPLACE("Hello, World!", "ll", "zz")                --> "Hezzo, World!"
REPLACE("Hello, World!", RE("[A-Z]","g"), "X")      --> "Xello, Xorld!"
REPLACE("John Smith", RE("(\w+)\s(\w+)"), "$2, $1") --> "Smith, John"
```

### Split (SPLIT)

Takes a string, matches it against a regular expression and splits it into an array of strings.

* Takes 2 arguments.
* The first argument specifies to string to be tested for matches.
* The first argument has to be a string, number or a variable.
* The second argument specifies the regular expression to be used for the matching.
* The second argument can take a string or the RE function.
* When the second argument is given as a plain string, the match is performed with the g (global) flag.

```javascript
[function] --> [output]

SPLIT("Hello, World!", "ll")                --> ["He","o, World!"]
SPLIT("Hello, World!", "l{2}")              --> ["He","o, World!"]
SPLIT("Hello, World!", RE("[A-Z]","g"))     --> ["","ello, ","orld!"]
```

### String format (STRINGFORMAT) (deprecated)

{% hint style="warning" %}
This function is deprecated. Use plain text with variables instead.
{% endhint %}

Includes variables into a string.

* Must have 1 argument, the string with variables to include.

```javascript
input = "hi"

[function] --> [output]

STRINGFORMAT("Hello,World")             --> "Hello,World"
STRINGFORMAT("1, 2")                    --> 1 2
STRINGFORMAT("{INPUT}bye")              --> "hiby"
STRINGFORMAT("Hello")                   --> "Hello"
STRINGFORMAT("ha he")                   --> "ha he"
```


# Data Functions

## List of data functions

* PICK
* RAW\_VALUE

### Pick a value from an array or object (PICK)

Given an array or object and a JSON path to certain value inside it, the PICK function picks this value and returns it.

* Takes 2 arguments, the array / object and the path.
* The first argument must be a variable or another function returning the object or array.
* The second argument must be a string specifying JSON path to the desired string values.

{% hint style="info" %}
The json path is simply the sequence of keys separated by dots. You can access elements in an array by writing the index of the element in square brackets behind the key pointing to that array. Note that elements in an array are indexed from 0! For example, animals\[0] points to the first element of the animals array.
{% endhint %}

#### PICK function examples:

```javascript
input1 = {"order":{"code":"A"}}

input2 = ["A", "B", "C"]

input3 = { "order": [ {"code":"A2", "price":22}, {"code":"B3", "price":11} ] }
 
[function] --> [output]

PICK({input1}, "order.code")        --> "A"
PICK({input2}, "[2]")               --> "C"
PICK({input3}, "order[0].code")     --> "A2"
PICK({input3}, "order[1].price")    --> 11
```

### Keep the same type without auto-casting (RAW\_VALUE)

For the given argument, it ignores auto-casting and the return value of the same type. In most cases, we want to call this function first, because the output of the function cell is automatically auto-casted, and this function prevents this behaviour.

* Take 1 argument of any type

#### RAW\_VALUE function examples:

```javascript
[function] --> [output]

RAW_VALUE(true)                  -->    true
RAW_VALUE(false)                 -->    false
RAW_VALUE("0001")                -->    "0001"
RAW_VALUE(11)                    -->    11
RAW_VALUE(null)                  -->    null
RAW_VALUE(TEXT(true))            -->    "true"
RAW_VALUE({"a": 10, "b": 20})    -->    {"a": 10, "b": 20}
RAW_VALUE(["a", "b", 1, 2])      -->    ["a", "b", 1, 2]
```


# Array Functions

## List of array functions

* [ARRAY\_PICK](#pick-values-from-and-array-of-nested-objects-array_pick)
* [ARRAY\_MAP](#map-array-to-another-array-array_map)
* [ARRAY\_REDUCE](#reduce-array-with-custom-function-array_reduce)
* [ARRAY\_FILTER](#filter-array-with-custom-function-array_filter)
* [ARRAY\_INCLUDES](#check-if-array-includes-an-element-array_includes)
* [ARRAY\_FLATTEN](#flatten-an-array-array_flatten)

#### Deprecated functions

* [ARRAY\_AND](#logical-conjunction-over-an-array-array_and-deprecated)
* [ARRAY\_OR](#logical-disjunction-over-an-array-array_or-deprecated)
* [ARRAY\_SUM](#summation-over-an-array-array_sum-deprecated)
* [ARRAY\_CONCAT](#concatenation-over-an-array-array_concat-deprecated)
* [ARRAY\_CONCAT\_WS](#concatenation-over-an-array-with-a-separator-array_concat_ws-deprecated)

## Examples

The below provided decision table contains examples of all the supported array functions (excluding the deprecated ones). Import the decision table to your space to see them working.

{% file src="/files/NsyBJGCW8DqIdoOa2cBL" %}

## Specifications

Below you will find the specifications of all the array functions.

### Pick values from and array of nested objects (ARRAY\_PICK)

Given an array of objects and a JSON path to certain (string) values nested inside these objects, the ARRAY\_PICK function picks these values and returns them in an array.

* Requires 2 arguments: the array and the path.
* The first argument must be a variable or another function returning an array.
* The second argument must be a string specifying JSON path to the desired string values.

{% hint style="info" %}
The JSON path is simply the sequence of keys separated by dots. You can access elements in an array by writing the index of the element in square brackets behind the key pointing to that array. Note that elements in an array are indexed from 0! For example, animals\[0] points to the first element of the animals array.
{% endhint %}

```javascript
INPUT1 = [
    {"order":{"code":"A"}},
    {"order":{"code":"B"}},
    {"order":{"code":"C"}}
  ]
 
INPUT2 = [
    {"order": [
        {"code":"A2", "price":22},
        {"code":"B3", "price":11}
               ]
    },
    {"order": [
        {"code":"A5", "price":55},
        {"code":"B8", "price":88}
        ]
    }
  ]
 
[function] --> [output]

ARRAY_PICK({INPUT1}, "order.code")        --> ["A", "B", "C"]
ARRAY_PICK({INPUT2}, "order[0].code")     --> ["A2", "A5"]
ARRAY_PICK({INPUT2}, "order[1].price")    --> [11, 88]
```

### Map array to another array (ARRAY\_MAP)

Thanks to ARRAY\_MAP, you can transform an array of values or objects to another array. Given an array and a representation of a custom function of a single argument, the ARRAY\_MAP function applies the custom function to every element of the given array and returns the resulting array.

* Requires 3 arguments: the array, name of a custom argument and a custom function.
* The first argument must be a variable or another function returning an array.
* The second argument must be a string specifying the name of a custom argument.
* The third argument must be a function of the custom argument.

```javascript
INPUT = [1,2,3]
 
[function] --> [output]

ARRAY_MAP({INPUT}, "x", SUM({x},1))   --> [2,3,4]
ARRAY_MAP({INPUT}, "z", TIMES(3,{z})) --> [3,6,9]
ARRAY_MAP({INPUT}, "element", CONCAT_WS(" ", "number", {element}))
                                      --> ["number 1","number 2","number 3"]
```

### Reduce array with custom function (ARRAY\_REDUCE)

Thanks to ARRAY\_REDUCE, you can reduce an array of values to a single value. Given an array and a representation of a custom function of 2 arguments, the ARRAY\_REDUCE function applies the custom function successively (to the first couple of elements, to the result and the third element, to the result and the fourth element, etc.) and returns the resulting value.

* Requires 4 arguments: the array, 2 names of custom arguments and a custom function.
* The first argument must be a variable or another function returning an array.
* The second argument must be a string specifying the name of the first custom argument.
* The third argument must be a string specifying the name of the second custom argument.
* The last, fourth argument must be a function of the 2 custom arguments.

```javascript
INPUT1 = [1,2,3,4]
INPUT2 = [true,true,false]
 
[function] --> [output]

ARRAY_REDUCE({INPUT1}, "x", "y", SUM({x},{y}))     --> 10
ARRAY_REDUCE({INPUT1}, "a", "b", TIMES({a},{b}))   --> 24
ARRAY_REDUCE({INPUT1}, "word1", "word2", CONCAT_WS("_",{word1},{word2}))
                                                   --> "1_2_3_4"
ARRAY_REDUCE({INPUT2}, "a", "b", AND({a},{b}))     --> false
ARRAY_REDUCE({INPUT2}, "a", "b", OR({a},{b}))      --> true
```

### Filter array with custom function (ARRAY\_FILTER)

The ARRAY\_FILTER function filters an array based on a custom function and returns another array with a subset of the elements of the original array.

* Requires 3 arguments: the array, a name of a custom argument and a custom function.
* The first argument must be a variable or another function returning an array.
* The second argument must be a string specifying the name of the custom argument.
* The third argument must be a function of the custom argument returning a boolean value.

```javascript
INPUT1 = [1,8,12,4]

INPUT2 = [
    {"code":"A","quantity":"1"}
    {"code":"B","quantity":"4"}
    {"code":"A","quantity":"3"}
    {"code":"B","quantity":"5"}
  ]
 
[function] --> [output]

ARRAY_FILTER({INPUT1}, "x", LT({x},5))    --> [1,4]
ARRAY_FILTER({INPUT2}, "a", EQ(PICK({a},"code"),"B"))
--> [
      {"code":"B","quantity":"4"}
      {"code":"B","quantity":"5"}
    ]
```

### Check if array includes an element (ARRAY\_INCLUDES)

Checks whether an array includes a given element.

* Requires 2 arguments: the array and the element to search for.
* The first argument must be a variable or another function returning an array.
* The second argument can have any value.

```javascript
INPUT = [
    {"code":"A","quantity":"1"}
    {"code":"B","quantity":"4"}
    {"code":"A","quantity":"3"}
    {"code":"B","quantity":"5"}
  ]
 
[function] --> [output]

ARRAY_INCLUDES([1,5,10],6)                              --> false
ARRAY_INCLUDES([1,5,10],5)                              --> true
ARRAY_INCLUDES({INPUT},{"code":"A","quantity":"3"})     --> true
```

### Flatten an array (ARRAY\_FLATTEN)

Flatten an array of arrays up to the specified depth.

* Takes 1 or 2 arguments
* The first argument is a string to flatten.
* The second optional argument specifies the depth to which to flatten the array (by default the argument is flattened into one dimension).
* If the first provided argument isn't an array the function returns `null`
* The second optional argument has to be a positive Integer, else the function returns `null`

```javascript
INPUT = [1, 2, [3,4], [[5]]]

[function] --> [output]

ARRAY_FLATTEN({INPUT})   --> [1,2,3,4,5]
ARRAY_FLATTEN({INPUT}, 1) --> [1,2,3,4,[5]]
ARRAY_FLATTEN({INPUT}, "string") --> null
ARRAY_FLATTEN({INPUT}, -1) --> null
```

### Summation over an array (ARRAY\_SUM) (deprecated)

{% hint style="warning" %}
This function is deprecated. Use SUM instead (if you need to get nested values, you can use SUM in combination with ARRAY\_PICK).
{% endhint %}

Given an array of numeric values (or alternatively objects), ARRAY\_SUM returns their sum.

* Requires 1 argument, the array.
* The argument must be a variable or another function returning an array.
* There can be a second optional argument of type string specifying JSON path to numeric values nested within the elements of the array (in case they are objects).
* Can be a part of an embedded function.

{% hint style="info" %}
The json path is simply the sequence of keys separated by dots. You can access elements in an array by writing the index of the element in square brackets behind the key pointing to that array. Note that elements in an array are indexed from 0! For example, animals\[0] points to the first element of the animals array.
{% endhint %}

```javascript
INPUT1 = [1,2,3]

INPUT2 = [
    {"order":{"price":20}},
    {"order":{"price":30}},
    {"order":{"price":40}}
  ]
 
INPUT3 = [
    {"order": [
        {"code":"A2", "price":22},
        {"code":"B3", "price":11}
               ]
    },
    {"order": [
        {"code":"A5", "price":55},
        {"code":"B8", "price":88}
        ]
    }
  ]
 
[function] --> [output]

ARRAY_SUM({INPUT1})                       --> 6
ARRAY_SUM({INPUT2}, "order.price")        --> 90
ARRAY_SUM({INPUT3}, "order[0].price")     --> 77
ARRAY_SUM({INPUT3}, "order[1].price")     --> 99
```

### Concatenation over an array (ARRAY\_CONCAT) (deprecated)

{% hint style="warning" %}
This function is deprecated. Use CONCAT instead (if you need to get nested values, you can use CONCAT in combination with ARRAY\_PICK).
{% endhint %}

Given an array of string values (or alternatively objects), the ARRAY\_CONCAT function concatenates these values and returns the concatenated string.

* Requires 1 argument, the array.
* The argument must be a variable or another function returning an array.
* There can be a second optional argument of type string specifying JSON path to numeric values nested within the elements of the array (in case they are objects).
* Can be a part of an embedded function.

{% hint style="info" %}
The json path is simply the sequence of keys separated by dots. You can access elements in an array by writing the index of the element in square brackets behind the key pointing to that array. Note that elements in an array are indexed from 0! For example, animals\[0] points to the first element of the animals array.
{% endhint %}

```javascript
INPUT1 = ["a","b","c"]

INPUT2 = [
    {"order":{"code":"A"}},
    {"order":{"code":"B"}},
    {"order":{"code":"C"}}
  ]
 
INPUT3 = [
    {"order": [
        {"code":"A2", "price":22},
        {"code":"B3", "price":11}
               ]
    },
    {"order": [
        {"code":"A5", "price":55},
        {"code":"B8", "price":88}
        ]
    }
  ]
 
[function] --> [output]

ARRAY_CONCAT({INPUT1})                      --> "abc"
ARRAY_CONCAT({INPUT3}, "order[0].code")     --> "A2A5"
ARRAY_CONCAT({INPUT3}, "order[1].code")     --> "B3B8"
```

### Concatenation over an array with a separator (ARRAY\_CONCAT\_WS) (deprecated)

{% hint style="warning" %}
This function is deprecated. Use CONCAT\_WS instead (if you need to get nested values, you can use CONCAT\_WS in combination with ARRAY\_PICK).
{% endhint %}

Given a separator and an array of string values (or alternatively objects), the ARRAY\_CONCAT\_WS function concatenates these values with the given separator and returns the concatenated string.

* Requires 2 arguments: the separator and the array.
* The first argument must be a string separator.
* The second argument must be a variable or another function returning an array.
* There can be a third optional argument of type string specifying JSON path to numeric values nested within the elements of the array (in case they are objects).
* String arguments should be enclosed in **""**.

{% hint style="info" %}
The json path is simply the sequence of keys separated by dots. You can access elements in an array by writing the index of the element in square brackets behind the key pointing to that array. Note that elements in an array are indexed from 0! For example, animals\[0] points to the first element of the animals array.
{% endhint %}

```javascript
INPUT1 = ["a","b","c"]

INPUT2 = [
    {"order":{"code":"A"}},
    {"order":{"code":"B"}},
    {"order":{"code":"C"}}
  ]
 
INPUT3 = [
    {"order": [
        {"code":"A2", "price":22},
        {"code":"B3", "price":11}
               ]
    },
    {"order": [
        {"code":"A5", "price":55},
        {"code":"B8", "price":88}
        ]
    }
  ]
 
[function] --> [output]

ARRAY_CONCAT_WS("_", {INPUT1})                      --> "a_b_c"
ARRAY_CONCAT_WS("_", {INPUT2}, "order.code")        --> "A_B_C"
ARRAY_CONCAT_WS("_", {INPUT3}, "order[0].code")     --> "A2_A5"
ARRAY_CONCAT_WS(" ", {INPUT3}, "order[1].code")     --> "B3 B8"
```

### Logical conjunction over an array (ARRAY\_AND) (deprecated)

{% hint style="warning" %}
This function is deprecated. Use AND instead (if you need to get nested values, you can use AND in combination with ARRAY\_PICK).
{% endhint %}

Given an array of boolean values (or alternatively objects), ARRAY\_AND returns their logical conjunction.

* Requires 1 argument, the array.
* The argument must be a variable or another function returning an array.
* There can be a second optional argument of type string specifying JSON path to numeric values nested within the elements of the array (in case they are objects).
* Can be a part of an embedded function.

{% hint style="info" %}
The json path is simply the sequence of keys separated by dots. You can access elements in an array by writing the index of the element in square brackets behind the key pointing to that array. Note that elements in an array are indexed from 0! For example, animals\[0] points to the first element of the animals array.
{% endhint %}

```javascript
INPUT1 = [true,true,false]

INPUT2 = [
    {"order":{"sent":true}},
    {"order":{"sent":true}},
    {"order":{"sent":true}}
  ]
 
[function] --> [output]

ARRAY_AND({INPUT1})                   --> false
ARRAY_AND({INPUT2}, "order.sent")     --> true
```

### Logical disjunction over an array (ARRAY\_OR) (deprecated)

{% hint style="warning" %}
This function is deprecated. Use OR instead (if you need to get nested values, you can use OR in combination with ARRAY\_PICK).
{% endhint %}

Given an array of boolean values (or alternatively objects), ARRAY\_OR returns their logical disjunction.

* Requires 1 argument, the array.
* The argument must be a variable or another function returning an array.
* There can be a second optional argument of type string specifying JSON path to numeric values nested within the elements of the array (in case they are objects).
* Can be a part of an embedded function.

{% hint style="info" %}
The json path is simply the sequence of keys separated by dots. You can access elements in an array by writing the index of the element in square brackets behind the key pointing to that array. Note that elements in an array are indexed from 0! For example, animals\[0] points to the first element of the animals array.
{% endhint %}

```javascript
INPUT1 = [true,false,false]

INPUT2 = [
    {"order":{"sent":false}},
    {"order":{"sent":false}},
    {"order":{"sent":false}}
  ]
 
[function] --> [output]

ARRAY_OR({INPUT1})                   --> true
ARRAY_OR({INPUT2}, "order.sent")     --> false
```


# Integration functions

## List of Integration functions

* [SOLVE](#solve-function-solve)
* [HTTP\_GET](#http_get)
* [HTTP\_POST](#http_post)
* [HTTP\_PUT](#http_put)
* [HTTP\_PATCH](#http_patch)
* [HTTP\_DELETE](#http_delete)
* LOOKUP\_VALUE
* LOOKUP\_EXISTS

## Solve function (SOLVE)

The SOLVE function has the ability to call any other rule within your space and retrieve the output of the rule depending on the provided input data.

* Takes 2 or 3 arguments.
* The first argument is the rule ID or alias of the rule you would like to call.
* The second argument is the object containing input data for the rule you are trying to solve.
* The third optional argument is an object specifying further options like execution strategy, version of the rule or JSON path to the value you want to return.

{% hint style="info" %}
If you are using alias, make sure it is unique in your space, otherwise the solve will fail.
{% endhint %}

{% hint style="info" %}
Note that when specifying the input data object, you can take advantage of our [Functions in JSON](/doc/rules/data-types-and-functions/operators/functions/functions-and-json) notation to specify dynamical values in your data.
{% endhint %}

```
SOLVE("rule-id", {"foo":"bar"})

SOLVE("rule-alias", {"foo":"bar"})

SOLVE("rule-id",
    {"foo":"bar"}, 
    {"version": "1","strategy":"FIRST_MATCH","path":"person.name"}
)
```

### Solve function result caching

To optimize the performance of your business logic, it is important to understand how DecisionRules handles external requests and the implications for orchestration.

#### Request Caching Mechanism

DecisionRules implements a built-in caching layer for external calls. When a request is made, the system caches the response and automatically reuses it across all cells that share identical:

* URL
* Parameters (Query strings)
* Request Body

This deduplication significantly reduces latency and ensures the final decision is executed with maximum efficiency.

#### Orchestration Constraints

Because of this caching behavior, the Solve function is not intended to be used for complex orchestration or workflows where multiple calls to the same endpoint are expected to yield different results within a single execution context.

> Note: If your logic requires fetching "fresh" data from the same URL multiple times (e.g., polling a status or triggering sequential state changes), the Solve function may return a cached result instead of hitting the external server again.

### Examples

The below provided decision table contains examples for the SOLVE function. Import the decision table to your space to review them. For the examples to actually work, you will also need to import another decision table which will be called via the SOLVE function. This dependent table is also provided below.

{% file src="/files/CINt90zvB48M19DOef2t" %}

Take care to import the following dependent table only **once**, otherwise the provided examples will not work. For the SOLVE function to work, it must be given rule ID or a unique alias.

{% file src="/files/fqXKy1qfTCCuucNmV5Sh" %}

### Version

Defines the version of the rule you want to call. If not specified, the SOLVE function calls the latest published version.

### Strategy

If you are solving a decision table, you can use the `strategy` option to specify one of the existing execution strategies. The allowed values are as follows.

```
STANDARD
ARRAY
FIRST_MATCH
EVALUATE_ALL
```

Their effect is described at the [Execution Strategy](/doc/rules/common-rule-features/execution-strategy) page.

### Path

The `path` option allows you to reach for a value inside the output data returned when the desired rule is solved. It takes a string specifying the JSON path to the value you want to retrieve. For example, suppose that the output of the rule is the following.

```
[
    {
        person: {
            name: "Joe" 
        }
    }
]
```

Then you can use `"path":"person.name"`. As a result, your solve function will only return

```
"Joe"
```

and not the whole object above. Therefore, the `path` option is handy when you want to get just a small portion of the output.

If you are calling a decision table, note that the `path` option will have different effect for different [execution strategies](/doc/rules/common-rule-features/execution-strategy). Below, we will describe the behavior for each of them in detail.

#### First Match

The the `path` option behaves as expected with the First Match strategy. It reaches inside the returned output object, as shown in the example above.

#### Standard and Evaluate All

For these strategies, the output is an array that may contain more than one element with output data, depending on how many (passing) rows you have in your decision table.

The path will always look into **the first element** of the array. For example, if the whole output of the called table is

```
[
    {
        person: {
            name: "Joe" 
        }
    },
    {
        person: {
            name: "Jane" 
        }
    }
]
```

and we use `"path":"person.name"`, the solve function will simply return

```
"Joe"
```

and it will ignore the other matched rows.

#### Array

In case of the Array Strategy, the output data take another form. They may look for example as follows.

```
[
    {
        person: {
            name: ["Joe","Jane"] 
        }
    }
]
```

By using `"path":"person.name"`, we tell the SOLVE function to unpack the name attribute for us, and it will return

```
["Joe","Jane"]
```

Therefore, if you are interested in an array of values where each value comes from one of the outputted rows of the solved decision table, you may use the SOLVE function with the Array Strategy and the `path` option.

{% hint style="info" %}
If you need some more complex transformation of the output data, you may be able to perform it with the help of [Data Functions](/doc/rules/data-types-and-functions/operators/functions/data) or [Array Functions](/doc/rules/data-types-and-functions/operators/functions/array).
{% endhint %}

### Excluded and included condition columns

When you are calling a decision table with the SOLVE function, you can specify the excluded and included condition columns within the options object. These work the same way as in the [Solver API](/doc/api/rule-solver-api) options.

```
SOLVE("plant-items",{data},
{"strategy":"ARRAY","path":"name","excludedConditionCols":["group"]}
)
```

## HTTP functions

These functions allow you to send an HTTP request to an external API, with using any of the HTTP methods. Before we describe the individual functions and their syntax, we provide some general information on how the functions work.

### Caching

Calling an external API always takes some time. To minimize the effect on the overall execution time of the rule, the rule solver automatically caches the responses. If you use an HTTP function exactly once in your rule, caching does not do anything. However, if you use the same HTTP function with the same arguments on multiple places in your rule, the request is sent upon evaluation of the first occurrence of the HTTP function, and the response is cached. Then, when another occurrence of the same function with the same arguments is encountered, the HTTP request is not sent again, but rather instantly read from the cache.

For example, imagine that you use the function

```
HTTP_GET("my.api.com")
```

in every cell within one row of your decision table. If you have 10 rows, there will be overall 10 identical functional expressions including this expression. When the decision table is solved, the solver first encounters this function on row 1 and sends the GET request. It waits for the response, and when it arrives, it continues the evaluation. Each time it encounters the same function again (on row 2, 3, 4, ...), it uses the data from the first call. Therefore, the actual HTTP call only happens once.

Now imagine you add a new column with another HTTP function in every cell of that column, e.g.

```
HTTP_GET("another.api.com")
```

The solver will now also have to evaluate many HTTP functions, but now there are two kinds of them, one using `my.api.com`, another using `another.api.com`. When solving the given decision table, the solver will send a request to the external API upon the first occurrence of each of the two different HTTP functions, therefore waiting only for 2 requests. All other results of the HTTP functions will be drawn from the cache.

### Limits

Note that there may be a limit on the allowed number of HTTP functions in a rule. In general, the limit depends on your plan.

{% hint style="info" %}
Within On-premise / Docker, the default limit is 100 HTTP functions per rule. Nevertheless, it can be set arbitrarily by the [DT\_HTTP\_CALL\_LIMIT](https://docs.decisionrules.io/doc/on-premise-docker/containers-environmental-variables#optional-server-environment-variables) environment variable.
{% endhint %}

### HTTP\_GET

HTTP\_GET *function can perform classic GET request with given URL.* HTTP\_GET returns JSON object of called API.

#### Syntax

The HTTP\_GET function syntax has the following arguments:

* **URL** - Required. Target url.
* **OPTIONS** - Optional. Object of optional arguments that can enhance HTTP request. Only available options at this moment is `headers` object that can contain custom request headers that are appended to request before sending.

#### Examples

**1) HTTP\_GET&#x20;**<mark style="color:orange;">**without**</mark>**&#x20;options**

```
HTTP_GET("my.api.com")
```

**2) HTTP\_GET&#x20;**<mark style="color:blue;">**with**</mark>**&#x20;options**

```
HTTP_GET("my.api.com", {"headers": {"X-DEMO": "1"}})
```

### HTTP\_POST

HTTP\_POST *function can perform classic POST request with given URL and request DATA.* HTTP\_POST returns JSON object of called API.

#### Syntax

The HTTP\_POST function syntax has the following arguments:

* **URL** - Required. Target url.
* **DATA** - Required. Request body as valid JSON object.
* **OPTIONS** - Optional. Object of optional arguments that can enhance HTTP request. Only available options at this moment is `headers` object that can contain custom request headers that are appended to request before sending.

#### Examples

**1) HTTP\_POST&#x20;**<mark style="color:orange;">**without**</mark>**&#x20;options**

```
HTTP_POST("my.api.com", {"foo":"bar"})
```

**2) HTTP\_POST&#x20;**<mark style="color:blue;">**with**</mark>**&#x20;options**

```
HTTP_POST("my.api.com", {"foo":"bar"}, {"headers": {"X-DEMO": "1"}})
```

### HTTP\_PATCH

HTTP\_PATCH *function can perform classic* PATCH *request with given URL and request DATA.* HTTP\_PATCH returns JSON object of called API.

#### Syntax

The HTTP\_PATCH function syntax has the following arguments:

* **URL** - Required. Target url.
* **DATA** - Required. Request body as valid JSON object.
* **OPTIONS** - Optional. Object of optional arguments that can enhance HTTP request. Only available options at this moment is `headers` object that can contain custom request headers that are appended to request before sending.

#### Examples

**1) HTTP\_PATCH&#x20;**<mark style="color:orange;">**without**</mark>**&#x20;options**

```
HTTP_PATCH("my.api.com", {"foo":"bar"})
```

**2) HTTP\_PATCH&#x20;**<mark style="color:blue;">**with**</mark>**&#x20;options**

```
HTTP_PATCH("my.api.com", {"foo":"bar"}, {"headers": {"X-DEMO": "1"}})
```

### HTTP\_PUT

HTTP\_PUT *function can perform classic* PUT *request with given URL and request DATA.* HTTP\_PUT returns JSON object of called API.

#### Syntax

The HTTP\_PUT function syntax has the following arguments:

* **URL** - Required. Target url.
* **DATA** - Required. Request body as valid JSON object.
* **OPTIONS** - Optional. Object of optional arguments that can enhance HTTP request. Only available options at this moment is `headers` object that can contain custom request headers that are appended to request before sending.

#### Examples

**1) HTTP\_PUT&#x20;**<mark style="color:orange;">**without**</mark>**&#x20;options**

```
HTTP_PUT("my.api.com", {"foo":"bar"})
```

**2) HTTP\_PUT&#x20;**<mark style="color:blue;">**with**</mark>**&#x20;options**

```
HTTP_PUTH("my.api.com", {"foo":"bar"}, {"headers": {"X-DEMO": "1"}})
```

### HTTP\_DELETE

HTTP\_DELETE *function can perform classic GET request with given URL.* HTTP\_DELETE returns JSON object of called API.

#### Syntax

The HTTP\_DELETE function syntax has the following arguments:

* **URL** - Required. Target url.
* **OPTIONS** - Optional. Object of optional arguments that can enhance HTTP request. Only available options at this moment is `headers` object that can contain custom request headers that are appended to request before sending.

#### Examples

**1) HTTP\_DELETE&#x20;**<mark style="color:orange;">**without**</mark>**&#x20;options**

```
HTTP_DELETE("my.api.com")
```

**2) HTTP\_DELETE&#x20;**<mark style="color:blue;">**with**</mark>**&#x20;options**

```
HTTP_DELETE("my.api.com", {"headers": {"X-DEMO": "1"}})
```

### Lookup Table functions

These functions let you query any Lookup Table within your space directly from your rules — retrieve reference data with LOOKUP\_VALUE, or check whether a key exists with LOOKUP\_EXISTS. They are available in Decision Tables, Decision Trees and assorted Flow nodes (e.g. Assign, Global Variable, etc...).

{% hint style="info" %}
If you are using alias, make sure it is unique in your space, otherwise the lookup will fail.
{% endhint %}

{% hint style="info" %}
For a detailed guide on Lookup Tables, including further examples, see Using Lookup Tables in Rules.
{% endhint %}

#### LOOKUP\_VALUE

LOOKUP\_VALUE *function queries a Lookup Table and retrieves data from the row matching the given primary key.* LOOKUP\_VALUE returns the value of the specified column, or the entire row as an object when no column is specified. If no matching row (or no such column) is found, it returns `null`.

**Syntax**

The LOOKUP\_VALUE function syntax has the following arguments:

* **TABLE** - Required. The alias or ID of the Lookup Table to query.
* **KEY** - Required. The value to search for in the primary key column.
* **VERSION** - Optional. The version of the Lookup Table to query. The latest published version is used when omitted or `null`.
* **COLUMN** - Optional. The name of the column to return. The entire row is returned as an object when omitted.

**Examples**

Given a Lookup Table with alias `product-catalog`:

| product\_code (PK) | product\_name | price | category    |
| ------------------ | ------------- | ----- | ----------- |
| SKU-001            | Widget Pro    | 29.99 | Electronics |
| SKU-002            | Gadget Plus   | 49.99 | Electronics |

**1) LOOKUP\_VALUE** <mark style="color:orange;">**without**</mark> **optional arguments**

```
LOOKUP_VALUE("product-catalog", "SKU-001")
```

Returns the entire row from the latest published version: `{"product_name": "Widget Pro", "price": 29.99, "category": "Electronics"}`

**2) LOOKUP\_VALUE** <mark style="color:blue;">**with**</mark> **version and column**

```
LOOKUP_VALUE("product-catalog", {input.productCode}, 1, "price")
```

With input `{productCode: "SKU-001"}`, returns `29.99`. With a key that has no matching row, returns `null`.

{% hint style="info" %}
To specify the COLUMN argument while still using the latest published version, pass `null` (or `"latest"`) as the VERSION argument: `LOOKUP_VALUE("product-catalog", "SKU-001", null, "price")`
{% endhint %}

{% hint style="warning" %}
Any non-numerical value in the version arguments results in the function invoking the latest published version of the Lookup Table
{% endhint %}

#### LOOKUP\_EXISTS

LOOKUP\_EXISTS *function checks whether a row with the given primary key exists in a Lookup Table.* LOOKUP\_EXISTS returns `true` if a matching row is found, and `false` otherwise.

**Syntax**

The LOOKUP\_EXISTS function syntax has the following arguments:

* **TABLE** - Required. The alias or ID of the Lookup Table to query.
* **KEY** - Required. The value to search for in the primary key column.
* **VERSION** - Optional. The version of the Lookup Table to query. The latest published version is used when omitted.

**Examples**

**1) LOOKUP\_EXISTS** <mark style="color:orange;">**without**</mark> **version**

```
LOOKUP_EXISTS("product-catalog", {input.productCode})
```

With input `{productCode: "SKU-001"}`, returns `true`; with `{productCode: "SKU-055"}`, returns `false`.

**2) LOOKUP\_EXISTS** <mark style="color:blue;">**with**</mark> **version**

```
LOOKUP_EXISTS("product-catalog", "SKU-002", 1)
```


# Functions and JSON

DecisionRules supports mixing native functional expressions with JSON. On this page, we will shortly explain how to write these mixed functional/JSON expressions and provide one realistic example of their usage.

## Overview

In this section we give a brief overview of all the supported types of mixed functional/JSON expressions together with examples and recommendations for their use.

### Placement as key and value

Functional expressions can be passed as a value into an object.

```
{"animal":{data}}
```

They can also define the key.

```
{{data}:["dog","cat","bird"]}
```

{% hint style="info" %}
Since JSON only allows strings as keys, make sure that the dynamically generated key evaluates to a string. If not, it will be automatically casted to string, which might not make good sense. Also note that the key must be unique within the object.
{% endhint %}

### Placement inside an array

Functional expressions can also represent an element of an array.

```
["dog",{data},"bird"]
```

### Variables

In the above examples, we have passed a variable `data` inside the JSON. This can be any kind of [variable](/doc/rules/data-types-and-functions/operators/functions#variables) supported within functions. Mixed expressions even work with abstract function variables:

```
ARRAY_MAP({data}, "letter", {"letter": {letter}})
```

### Functions

We can of course use functions.

```
{"average": AVG(10,30)}
```

```
{1+2:"three"}
```

### Combinations

The above listed types of expressions can be arbitrarily combined.

```
{"animals": {data}, "number": COUNT({data})}
```

## Example

Suppose you have a rule **Delivery Price** with alias `delivery-price` which gives you the price of delivery based on package weight. Its input model is

```json
{
  "package": {
    "weight": {}
  }
}
```

and the output model is

```json
{
  "price": {},
  "currency": {},
  "deliveryInHours": {}
}
```

Now, imagine we wish to call this rule from a decision table. We can easily do that with the [**SOLVE**](/doc/rules/data-types-and-functions/operators/functions/integration-functions#solve-function) function. In the respective output cell where we want to get the result, we can write something like

```
SOLVE("delivery-price", {"package": {"weight": 12}})
```

Note that the object in the second argument of the SOLVE function corresponds to the input model of our **Delivery Price** rule. This is because it supplies the input data for it. The SOLVE function evaluates the rule and returns the output, which may look like this:

```json
[
  {
    "price": 28,
    "currency": "USD",
    "deliveryInHours": "24 Hours"
  }
]
```

Of course, the exact form and data returned depends on the **Delivery Price** rule itself. We could now take this output, process it with the help of [Data Functions](/doc/rules/data-types-and-functions/operators/functions/data) or [Array Functions](/doc/rules/data-types-and-functions/operators/functions/array) and return it in the outputs or use it in our next steps.

The interesting part comes when we want to pass some dynamic data to our **Delivery Price** rule. For example, imagine we have an input variable `packageWeight` and want to solve **Delivery Price** with the value from this variable. We can do that by simply writing the variable inside to the object:

```
SOLVE("delivery-price", {"package": {"weight": {packageWeight}}})
```

The variable `packageWeight` will be automatically interpreted and passed to the object, which will be then picked up by the SOLVE function and used as input for the **Delivery Price** rule.

But we can do much more than this. The JSON can be also mixed with arbitrary functions. For example, imagine we want to limit the `packageWeight` to be always greater than 10 before passing it to the SOLVE function. No problem, just write the appropriate function expression:

```
SOLVE("delivery-price", {"package": {"weight": MIN(10,{packageWeight})}})
```

Following this logic, it is possible to mix arbitrary functional expressions and JSON to get the desired behavior.

## More examples

The below provided decision table contains examples of functions with JSON. Import the decision table to your space to see them working.

{% file src="/files/N6qhnE7dKOm4RBLdQ71B" %}


# Decision Table

Welcome to the Decision Tables section, the most popular tool within [DecisionRules](https://decisionrules.io/). This section provides comprehensive guidance on how to effectively utilize this powerful feature for creating business tables.

### What Is a Decision Table?

A **decision table** is a structured way to represent business logic using conditions and corresponding outcomes. Each row in the table represents a **scenario** — a specific combination of input values that leads to a defined output.

### What will you find in the section?

Here, you'll find detailed instructions on using the table designer, which is the dedicated area for designing tables. Additionally, this section covers the import and export options for rules, as well as how to manage this data seamlessly.

Furthermore, you’ll discover advanced functionalities, including the various functions available for evaluating cells within tables.

## What You Can Find in This Space

{% content-ref url="/pages/-MQSmvHqH7oi-nO76NVu" %}
[Table Designer](/doc/rules/decision-table/decision-table-designer)
{% endcontent-ref %}

{% content-ref url="/pages/-MN5T-WToSwRae5FlXRD" %}
[Input & Output Model](/doc/rules/common-rule-features/input-and-output)
{% endcontent-ref %}

{% content-ref url="/pages/-MOcGP\_57jY2RLntj9cS" %}
[Supported Data Types](/doc/rules/data-types-and-functions/data-types)
{% endcontent-ref %}

{% content-ref url="/pages/-MOcE5p68rUxyxrhg6iu" %}
[Operators and Functions](/doc/rules/data-types-and-functions/operators)
{% endcontent-ref %}

{% content-ref url="/pages/-ManB6dQvaV-fFix9Ks\_" %}
[Functions](/doc/rules/data-types-and-functions/operators/functions)
{% endcontent-ref %}

{% content-ref url="/pages/S3pSlOKPkdJlBeYuL5ak" %}
[Rule Export & Import](/doc/rules/common-rule-features/rule-export-and-import)
{% endcontent-ref %}

{% content-ref url="/pages/-MhTHc7S0EYMgMyfPnUL" %}
[Table Operations](/doc/rules/decision-table/decision-table-designer/table-operations)
{% endcontent-ref %}


# Table Designer

The heart of the Decision Table

In this section, you can easily create your decision tables, then link them to input and output data. Business rules are created to easily design or change the rules and deploy them quickly.

<figure><img src="/files/noOSNKjgT81JkKAQmVIL" alt=""><figcaption></figcaption></figure>

## **Editing and Saving Changes**

When editing a rule, you can make changes directly in the rule editor.\
Use the control buttons in the top-right corner of the editor to manage your edits:

* **Undo** ⟲ – reverts your last action
* **Redo** ⟳ – restores the reverted change
* **Save** 💾 – saves the current version of the rule

<figure><img src="/files/OqXWryn0e27a0btq8RVh" alt=""><figcaption></figcaption></figure>

These actions help you safely adjust the rule before saving it.\
Each time you save, a new version of the rule is created and recorded in the **History** panel, where you can review or restore past versions. You will find more information about Rule History here on [dedicated page](/doc/rules/common-rule-features/rule-history).

## Column Types and Table Structure

A Decision Table consists of three types of columns:

* **Condition**: Defines input values. As the name suggests, these are the conditions that determine whether a table row matches the input data.
* **Calculation**: Used to perform various calculations. These calculations are not initially bound to an input or output model, but they can be mapped to an input or output value if needed.
* **Result**: Specifies the output values.

Every Decision Table requires **at least two columns:** a condition or calculation column and a result column. Condition columns must be placed on the left side of the table, while result columns are on the right. Calculation columns can be positioned anywhere within the table.

## Column Operations and Settings

### Add Column

To add a new column, hover over an existing column header and click the plus symbol that appears on either side of the column.

<figure><img src="/files/ihNLQVGGHYDzM4i7sXZ8" alt=""><figcaption></figcaption></figure>

Next, select the column type (e.g., "Add Calculation").&#x20;

As noted in the previous section, there are specific restrictions on where certain types of columns can be placed:

* A condition column can be added between existing condition columns or at the start of the table as the first column.
* A result column can be added between existing result columns or as the last column, after any result or calculation columns.
* Any type of column can be added between condition and result columns.
* Calculation columns can be placed anywhere in the table.

### Rename Column

New columns are initially named according to their type. You can rename a column for better clarity and organization within the table. To do this, click on the existing name (e.g., "Condition") and type the new name. Then, click anywhere outside the field or press the Enter key to confirm.

### Select Column Value

Next, select a value for the column. To do this, click the input field under the column name. This will expand a list of all possible values, allowing you to choose one.

<div align="center"><figure><img src="/files/TyUeXPVIaoAYWWyAEEP4" alt=""><figcaption></figcaption></figure></div>

#### There are different types of values that you can map a column to, depending on the column type:

* **Condition Columns**: Can be mapped to an input value from the I/O Model, rule variables, or a calculation column variable (only in columns that are to the right of the specified calculation column).
* **Calculation Columns**: Are not mapped to an existing value. Instead, a new calculation variable is created. See the detailed explanation below.
* **Result Columns**: Can only be mapped to output values from the I/O Model.

{% hint style="info" %}
More information is in the [Binding To Model](/doc/rules/decision-table/binding-to-model).
{% endhint %}

#### Special Case: Calculation Column

Calculation columns are not bound to any existing value. When creating a calculation column, the result is assigned to a variable, which is defined in the calculation column header.

By default, the column is assigned a variable name like `varX` (where X is a natural number). You can change this name by clicking on it. To confirm the new name, click anywhere outside the field or press the Enter key.

<div align="center"><figure><img src="/files/Q2JTlPSFfTj5IQN6HjEp" alt=""><figcaption></figcaption></figure></div>

Once defined, these variables can be used elsewhere in the table in the same way as rule variables or input and output values.

<figure><img src="/files/FFyspR64gcwq0aDHiA9z" alt=""><figcaption><p>Calculation variables</p></figcaption></figure>

### Set Column Alias

Each column has a column alias, a unique identifier within the scope of the table. You can use the alias to reference the column when using the [included/excluded condition column](/doc/api/rule-solver-api#included-condition-cols) feature or when binding column [valid values](/doc/rules/decision-table/decision-table-designer/table-operations/valid-values) in an [XLSX file](/doc/rules/common-rule-features/rule-export-and-import/managing-decision-table-in-excel-google-sheets#valid-values).

Aliases are automatically generated for each column, but you can set your own, more descriptive alias. To set a column alias, click the arrow icon in the column header and select the "Set Column Alias" option. The new alias must be unique within the table and can only contain English letters, numbers, and dashes, with a maximum length of 30 characters. To confirm the new alias, click anywhere outside the field or press the Enter key.

<figure><img src="/files/NG1rtaR3LSV37RRiqJp4" alt=""><figcaption><p>Column alias</p></figcaption></figure>

### Delete Column

To delete a column from the Designer, click an arrow icon near the column name in the header of the condition, then click the remove button in the dropdown menu.

<figure><img src="/files/3zGcdcZE2GkTNeZSmVVN" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
For more information about other column dropdown options, refer to the [Table Operations](/doc/rules/decision-table/decision-table-designer/table-operations) section.
{% endhint %}

## Row

A row represents one rule for specified data. If it's called, the [Rule Solver](/doc/api/rule-solver-api) or the [Test Bench](/doc/rules/common-rule-features/test-bench) with Input Data corresponding to **conditions** in a row, the[ Rule Solver](/doc/api/rule-solver-api) or the [Test Bench](/doc/rules/common-rule-features/test-bench) response will have the same data specified in **results** in the corresponding row.

### Add Row

To add a new row, click the  <img src="/files/3C58CYzVNrSwzTXq458H" alt="" data-size="line"> button in the bottom panel. This will create a new row at the end of the table with `ANY` condition operators.

### Fill Cell

The basic structure for every cell is **operator + value**.

#### Operators

{% hint style="info" %}
Possible operators are specified in [Operators](/doc/rules/data-types-and-functions/operators) section
{% endhint %}

To change the operator in a **Condition** column, click the operator label, and an operator selection modal will open. Select the desired operator to apply it to the cell.

{% hint style="warning" %}
**Note:** For function operators, selecting a new function operator will not overwrite the existing one in the cell, as function operators can be nested. This ensures that your existing functions are preserved.
{% endhint %}

For **Calculation** columns, the operator is predefined as a function; therefore, the operator label is not visible in the cell.

For **Result** columns, there are two types of operators:

* **Simple Value** (`Equal`): Used for strings and simple math operations like addition (`+`), subtraction (`-`), multiplication (`*`), etc.
* **Function**: Used for advanced operations, including logical functions (e.g., AND, OR), mathematical functions (e.g., `ABS`, `MAX`) and others, see the whole list in [Functions section](/doc/rules/data-types-and-functions/operators/functions). The function operator can handle everything the Simple Value operator can, but also allows the use of more complex functions.&#x20;

To switch between Simple Value and Function operators, click the operator badge and choose from the dropdown:

<figure><img src="/files/IGv0xeishVInSL4zHhgt" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}

#### **Warning: Operator Precedence and Brackets**

When using function operators in **Result** and **Calculation** columns, be mindful of operator precedence. In some cases, the solver evaluates subtraction and other operations from **right to left**. For example, if you write an expression like `10 - 5 - 2`, the solver will first calculate `5 - 2`, resulting in `3`, and then subtract that from `10`, returning `7` instead of the expected `3`.

To avoid unexpected results, always use brackets to clarify the order of operations. For example, to get the correct result of `3`, you should write the expression as `(10 - 5) - 2`.

This behavior applies to both **Result** and **Calculation** columns when using function operators.<br>

Read more in [Math function](/doc/rules/data-types-and-functions/operators/functions/math#minus) section.
{% endhint %}

#### Values

{% hint style="info" %}
Possible values for data types are specified in [Data Types](/doc/rules/data-types-and-functions/data-types) section.
{% endhint %}

To change the cell value, click on the cell and start typing. To confirm the value, click elsewhere or press the **Esc** key. You can also enter multiline values by pressing **Enter**. When the cell is closed, only the first line is visible.

<figure><img src="/files/G4eroOe2370G4RskfPMZ" alt=""><figcaption></figcaption></figure>

For longer values, you can use the maximize mode. To do this, hover over the cell and click  <img src="/files/9mUaZIs9DU7cZjrLNJAW" alt="maximize" data-size="line"> icon. This will open the maximized mode:

<figure><img src="/files/DYCSV4BicTrDX3IzioTY" alt=""><figcaption></figcaption></figure>

To confirm the new value and exit maximized mode, click the cross icon in the top-right corner, press **Esc**, or click elsewhere.

#### Special Case — Variable Values

In addition to classic values, you can also use variables such as input & output values, rule variables, and calculation column variables. To do this, start typing `{` in the cell, and a dropdown with all available variables will appear.

<figure><img src="/files/WuslOsrn3NszP9py2rWZ" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}

* **Output values** are available only in result columns.&#x20;
* **Calculation variables** are available only after they are declared — i.e., in columns to its right.
  {% endhint %}

Once added, each variable is displayed with its own badge based on its type for better orientation within the table:

* Input variable ![](/files/CobudRXZouQDTk03PkpJ)
* Output variable ![](/files/dEkaPwaAajm73Y4EcBuu)
* Rule variable ![](/files/Tx9jM2TmxiUuRhPvQlZg)
* Calculation variable ![](/files/114AgxopiFXRIeLviKvx)

If a variable is deleted, it will appear with a red badge in the cells, indicating that the reference is now broken.

### Copy Row

To copy a row, click the ![](/files/TiWC2VLbefWfsSGCVRax) button at the beginning of the row. Then, select the "**Copy**" option. The row will be duplicated with the same set of rules as the original.

{% hint style="info" %}
To copy multiple rows at once, hold the **Ctrl** key and click on the rows you want to copy. Then, right-click anywhere in the rows settings area. When the context menu opens, select the "**Copy to**" option and choose where you want the rows to be copied: either the start or end of the table.
{% endhint %}

### Clear Row

To clear all sets of conditions and result values, click the ![](/files/TiWC2VLbefWfsSGCVRax) button at the beginning of the row. Then, select the "**Clear row**" option. This will remove all values from the row.

{% hint style="info" %}
To clear multiple rows at once, hold the **Ctrl** key and click on the rows you want to delete. Then, right-click anywhere in the rows settings area. When the context menu opens, select the "**Clear rows**" option.
{% endhint %}

### Deactivate and Activate Row

To Inactive the row, toggle the ![](/files/QbG18UuGkykYpq1O9ya4) switch at the beginning of the row.&#x20;

By default, all rows in the table are **ACTIVE**. You can use this functionality when you don’t want to use a specific row in the rule for validation, but might need it in the future.

If a row is set to **INACTIVE**, it behaves as if it does not exist.

{% hint style="info" %}
To activate or deactivate multiple rows at once, hold the **Ctrl** key and click on the rows you want to delete. Then, right-click anywhere in the rows settings area. When the context menu opens, select the "**Activate rows**" or "**Deactivate rows**" option.
{% endhint %}

### Delete Row

To delete a row, click the ![](/files/2vEqcf66HTu4lHPqRxWw) icon at the beginning of the row and select the "**Delete Row**" option.

{% hint style="info" %}
To delete multiple rows at once, hold the **Ctrl** key and click on the rows you want to delete. Then, right-click anywhere in the rows settings area. When the context menu opens, select the "**Delete Rows**" option.
{% endhint %}

### Use Row in Test Bench

To use a row in the **Test Bench c**lick the ![](/files/SmVgByXdT39iQjsVorQv) button. Then, the row's condition columns values are copied to the Test Bench input at the bottom of the page, and the solution is evaluated as if you had clicked the **Run** button.

### Change the Order of Rows

To change the position of the row, click the ![](/files/2vEqcf66HTu4lHPqRxWw) button. Then, select **Move** optio&#x6E;**.** This will open a modal, where you can specify the new position of selected row.

![](/files/kZvTvZ3zHQqayZD8MBv9)

{% hint style="info" %}
To move multiple rows at once, hold the **Ctrl** key and click on the rows you want to delete. Then, right-click anywhere in the rows settings area. When the context menu opens, select the **Move** option.
{% endhint %}

### Time Row Validation

You can specify in which time period the row will be active. To set the time validation, click the <img src="/files/2vEqcf66HTu4lHPqRxWw" alt="" data-size="original"> icon and then choose the **Time validation** option. A modal will appear, allowing you to select a **From** and **To** time range.

![Row validation from 29 April 2022 00:00:00 GMT+2 to 30 April 2022 23:59:59 GMT+2](/files/3mDW3jx39x9hLbkZTOK5)

{% hint style="warning" %}
The **Date** and **GMT** must be set; **Time** is optional. You do not need to set both limits — you can specify only the end date until which the row will be valid or only the start date from which it will be valid.
{% endhint %}

By default, all rows are not time-limited and will always be evaluated. If time validation is set, the row will only be evaluated within the specified period.

{% hint style="info" %}
Once time validation is set for one row, the icon <img src="/files/uytK1knBbKHXdqgX2FYm" alt="" data-size="line"> will appear next to the other rows. You can then click this icon to set time validation for another row directly, without needing to go through the context menu.
{% endhint %}

## Debug

Debug Mode provides detailed execution information, helping you understand exactly how your rule processes data and where issues might occur.&#x20;

For detailed information about how Debug Mode works see [Debug Decision Table](/doc/rules/common-rule-features/test-bench#debug-decision-table).

## Console

The Console panel displays execution logs generated when Debug Mode is enabled. When you run a rule with Debug Mode turned on, the Console automatically captures and shows a detailed breakdown of how your rule was evaluated.

{% hint style="info" %}
Console logs in the UI are temporary and only visible during your current session. To preserve logs, use the Console Logs API (see below).
{% endhint %}

### **What Console Shows:**

* **Timestamp** - When the execution occurred.
* **Row-by-row evaluation** - How rows were processed.
* **Condition columns** - Input field name, actual value, condition, and result `true` / `false`.
* **Result columns** - Output field name and the value produced.

```json
[20/02/2026, 12:15:13]
[
  [
    "ROW 1 COL 1 (headlightStatus, Off, = Off) => true",
    "ROW 1 COL 2 (nightTime, Yes, anything ) => true",
    ...
    "ROW 1 COL 5 (action, common Turn headlights ON) => Turn headlights ON"
  ],
  [
    "ROW 2 COL 1 (headlightStatus, Off, = Off) => true",
    "ROW 2 COL 2 (nightTime, Yes, = Yes) => true",
    ...
    "ROW 2 COL 5 (action, common Turn headlights ON) => Turn headlights ON"
  ],
  ...
]
```

### **Retrieving Console Logs via API**

For production environments or persistent logging, you can retrieve console logs programmatically using the Console Logs API. This allows you to:

* Access historical logs after leaving the rule.
* Integrate logging into your monitoring systems.
* Analyze execution patterns over time.

For detailed API documentation, see [Console Logs API](/doc/api/archive/console-logs-api-retired).

## Additional Options

### Else Row

This option adds a default row with `ELSE` conditions at the end of the table. This row is evaluated if no other rows match the input.

<figure><img src="/files/CVYuYtWUuL0QSLKIoYQq" alt=""><figcaption></figcaption></figure>

### Check Table for Duplicates

To check the table for duplicate rows, click the Check Duplicate button in the bottom panel. This action compares the **input** values in the table. If any duplicate rows are found, they will be highlighted.

![Duplicate rows](/files/UAfTTTbS09WhZBnnS8J0)

{% hint style="warning" %}
This feature only works on the **input** values, as the output values can be identical.
{% endhint %}

### Search

The **Search** option in the Settings menu allows you to search through the entire table and highlights the cells that match your input. To use this feature, select the **Search** option, and a search bar will appear:

<figure><img src="/files/RnL77gJyohpy9kweGBYj" alt=""><figcaption></figcaption></figure>

Start typing the value you want to find. The cells that match will be highlighted in green. The search bar will display the number of **rows** that contain matches (not the number of matched **cells**). You can navigate between the matched rows using the arrow buttons.

<figure><img src="/files/ls3Lt7R2lGaaZgwcQ1WL" alt=""><figcaption></figcaption></figure>

### Go to Row

In large tables, scrolling to a specific row can be challenging. The **Go to Row** option helps you quickly navigate to the desired row. Click this option, and a bar will appear where you can type the number of the row you want to go to, then press Enter. The table will scroll to that row, and the row settings area will be highlighted in green.

<figure><img src="/files/BnRcUohjUcbuc25jqoPr" alt=""><figcaption></figcaption></figure>

## Highlight Active Columns and Rows

If you find it difficult to navigate between columns and rows, you can use the option to highlight active rows and columns. This function is available under the Settings button in the navigation toolbar at the bottom of the Decision Tables page.

Choose whether you want to highlight rows, columns, or both, and activate the option. The selected row or column will be highlighted in light green, as demonstrated in the picture below.

<figure><img src="/files/w7XRXpnkXfObqvjYcHjc" alt=""><figcaption></figcaption></figure>


# Table Operations

## Kinds of Table Operations

Managing decision tables that contain thousands of rows and hundreds of columns can be challenging, especially when you need to locate and edit specific values. To enhance usability and streamline your workflow, we've implemented several powerful features designed to simplify navigation and editing. These operations, including filtering, sorting, and defining valid values, allow you to quickly focus on relevant data, ensuring a more efficient and organized approach to managing your decision tables. With these tools at your disposal, you can easily manipulate and refine your data, making the overall experience more intuitive and productive.

You can access these options by clicking the arrow icon in a column header:

<img src="/files/5BAkLuwXEk85Y72yJoOF" alt="" width="290">

{% content-ref url="/pages/-MhTHiYCUJpynxUyT8tT" %}
[Filter Values](/doc/rules/decision-table/decision-table-designer/table-operations/filter)
{% endcontent-ref %}

{% content-ref url="/pages/-MhTIQF8iixh9LuYXdvM" %}
[Valid Values](/doc/rules/decision-table/decision-table-designer/table-operations/valid-values)
{% endcontent-ref %}

{% content-ref url="/pages/-MhTI4Sk-JF\_1dUfsyWU" %}
[Sorting](/doc/rules/decision-table/decision-table-designer/table-operations/sort)
{% endcontent-ref %}

{% hint style="success" %}
For more information on additional context menu options and table manipulations, please refer to the [Table Designer](/doc/rules/decision-table/decision-table-designer#column-operations-and-settings) section.
{% endhint %}


# Filter Values

Finds the value in the columns

## Filter Values in Decision Table

Filtering values in a decision table allows you to narrow down rows based on the values in a particular column. This is especially useful when working with large datasets.

{% hint style="success" %}
Filtering is **case-insensitive** and supports **partial matches**. For example, if you filter by "2", it will match values like "120", "240", and "2+4".
{% endhint %}

## How to Apply Filters

<figure><img src="/files/c653r1DTlOZrgO9VgGyH" alt="" width="328"><figcaption></figcaption></figure>

1. **Access Filters**: Click the arrow icon in the header of the column you want to filter, then select **Filter Values**.
2. **Set Filter Expressions**:\
   A filter input field will appear where you can add one or more filter expressions. Simply type your expression and press **Enter** to apply it.
   * To remove a filter, click the cross icon next to the expression.
3. **Confirm Filters**:\
   Once your filters are set, confirm them by either clicking outside the filter modal or pressing the **Esc** key.

<figure><img src="/files/ZH1gLcsTd9J7vCGXDWyd" alt=""><figcaption></figcaption></figure>

## Managing Filters

* You can apply filters to multiple columns simultaneously.
* When a column has an active filter, a filter icon will appear in the column header. Clicking this icon will reopen the filter input.
* To clear all filters, click the cross icon at the end of the filter input field.

<figure><img src="/files/zuNAuSOt1NZ8bBin0T5H" alt=""><figcaption></figcaption></figure>


# Valid Values

The Valid Values feature in Decision Tables plays a crucial role in maintaining the integrity and accuracy of your data. By restricting cell entries to a predefined set of valid options, you can prevent errors and ensure consistency across your decision-making processes.

Valid values can be defined in three ways:

1. **Value** - A predefined list of allowed values in specific column.
2. **Regex** - Pattern-based validation using regular expressions.
3. **Lookup Table Reference** - Values from another Lookup Table.

This functionality enhances the reliability of your tables, streamlines data entry, and establishes clear guidelines for data input, fostering a more dynamic and responsive decision-making environment.

## How to Apply Valid Values

1. Click the **arrow icon** in the header of the column.
2. Select **Valid Values**.

<figure><img src="/files/YsGaq8GZF0PAFnECUtkP" alt="" width="555"><figcaption></figcaption></figure>

3. A modal will open with three validation type tabs: **Value**, **Regex**, and **Lookup Table Reference**.

<figure><img src="/files/zvth1suwSfeLYb6pEFr9" alt="" width="563"><figcaption></figcaption></figure>

4. Choose your validation type and configure it (see sections below).
5. Click **Save values** to apply.

{% hint style="warning" %}
Valid Values **apply to simple cells only**.

Valid values **do NOT apply** when a cell is set to **function mode**.

Valid values **cannot be set** for **calculated columns** (calc columns are always in function mode).
{% endhint %}

### **Validation Type 1: Value (Predefined List)**

Define a specific list of allowed values for the column.

**How to set up:**

1. Open the Valid Values modal.
2. Select the **Value** tab.
3. Type valid value and **press Enter to confirm**.
4. Repeat for all allowed values.
5. Click **Save values**.

<figure><img src="/files/WWYR87Mj2eyYXsD2wN7x" alt="" width="563"><figcaption></figcaption></figure>

Once valid values are applied, every cell (except for functions) in the column is checked against the predefined list. If a cell contains an invalid value, it will be flagged.

<figure><img src="/files/0G8P3UJLEComiVNNUkt6" alt="" width="554"><figcaption></figcaption></figure>

Additionally, when valid values are set, you cannot directly type into the cells in that column. Instead, a dropdown with the list of valid values will appear when you click on a cell, allowing you to select the appropriate value.

<figure><img src="/files/qPN7J2bY8f4QHWF6kYPR" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="success" %}
You can use not just simple values, but also variables, dates, or even full expressions as valid values. Spaces and operators are also allowed within a valid value.
{% endhint %}

<figure><img src="/files/s36L2SfVdiCZAm5j9im4" alt="" width="563"><figcaption></figcaption></figure>

### **Validation Type 2: Regex (Pattern Matching)**

Use regular expressions to validate cell values against a pattern.

**How to set up:**

1. Open the Valid Values modal.
2. Select the **Regex** tab.
3. Enter your regular expression in the **Expression** field. Examples:
   1. Email validation `^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$`
   2. Phone (US) `^\d{3}-\d{3}-\d{4}$`
   3. Postal Code `^\d{5}(-\d{4})?$`
   4. Alphanumeric `^[A-Za-z0-9]+$`
4. Test your regex:

* Enter a test string in the **Test String** field.
* Click **Test Regex** to verify if the pattern matches.

5. Click **Save values**.

<figure><img src="/files/dl42xM40rqqsNwLFqJ1D" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="/files/ER2aa1kne2XWZG269gy0" alt="" width="563"><figcaption></figcaption></figure>

For more information about regular expressions and pattern syntax, see:

* [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions)
* [Regex101](https://regex101.com/)

### **Validation Type 3: Lookup Table Reference**

Validate values against data from a Lookup Table in your space.

**For detailed information** about Lookup Table References and how they work, see [Lookup Table Reference](/doc/rules/lookup-table/using-lookup-tables-in-rules)


# Sorting

Sorts the values in the column in ascending/descending order

## Sort Values in Decision Tables

The sorting feature helps you rearrange the rows of your table in either ascending or descending order based on the values in a specific column.

## How to Apply Sorting

<figure><img src="/files/k4r6HkkuJYhlv3OSl2mR" alt="" width="557"><figcaption></figcaption></figure>

1. **Access Sorting**: Click the arrow icon in the header of the column you want to sort, then select **Sorting**.
2. **Choose Sort Order**:
   * **Sort by A-Z** (ascending)
   * **Sort by Z-A** (descending)

## Managing Sorting

* Only one column can be sorted at a time. Applying sorting to another column will reset the sorting of the previous one.
* When a column is actively sorted, a sorting icon will appear in the column header.
* To change the sorting direction, click the arrow icon in the column header, select **Sorting**, and choose the desired order.
* To remove sorting, click the arrow icon in the header, select **Sorting**, and choose **Reset sorting**.

<figure><img src="/files/jMo0FlFVyPcW1iEam21g" alt=""><figcaption></figcaption></figure>

## Sorting Rules

When a column contains multiple data types, sorting follows specific rules. Here’s how DecisionRules handles sorting:

### Descending Order

1. **Text**: Zz-Aa
2. **Numbers**: 9-0
3. **Operator**: `ELSE`
4. **Number fields**: (e.g., `BTW`)
5. **Dates**
6. **Date fields**: (e.g., `BTW`)
7. **Functions**
8. **Operator**: `ANY`

### Ascending Order

1. **Operator**: `ELSE`
2. **Numbers**: 0-9
3. **Text**: aA-zZ
4. **Number fields**: (e.g., `BTW`)
5. **Dates**
6. **Date fields**: (e.g., `BTW`)
7. **Functions**
8. **Operator**: `ANY`

<div><figure><img src="/files/qlB7pckI69UM648WdeCb" alt="" width="337"><figcaption><p>Example of Sort by A-Z option</p></figcaption></figure> <figure><img src="/files/SH647YDmfFBV1u45rPcq" alt="" width="339"><figcaption><p>Example of Sort by Z-A option</p></figcaption></figure></div>


# Binding to Model

Binding Input and Output model to Decision Table in decision table designer.

After creating the [input and output models](/doc/rules/common-rule-features/input-and-output), you need to bind these models to your Decision Table. The binding determines which data fields are used in your rule logic.

**Basic Binding:**

* **Input Model** → Bound to **condition columns**.
* **Output Model** → Bound to **result columns**.

## **Understanding Model Binding**

### **What Can Be Bound**

You can select any **leaf field** from the input/output model as a condition or result variable.

{% hint style="warning" %}
You cannot select a parent/root field that contains children as a condition/result variable. Only leaf fields (fields with no children) can be bound.
{% endhint %}

### **Use Case Example**

Consider the following model structure:

<figure><img src="/files/f7LnPmn1TaLgQWAHYACl" alt="" width="563"><figcaption></figcaption></figure>

From this model structure, here's what can and cannot be bound to columns:

#### **Can be bound:**

**Input:**

* `delivery.distance.car`
* `delivery.distance.ship`
* `delivery.distance.plane`
* `delivery.tariff`
* `package.weight`
* `package.longestSide`

**Output:**

* `shippingCost`
* `deliveryMethod`
* `status`

#### **Cannot be bound:**

* `delivery` (has children: `distance`, `tariff`)
* `delivery.distance` (has children: `car`, `ship`, `plane`)
* `package` (has children: `weight`, `longestSide`)

### **Flexible Usage**

**You don't need to use every field as a column.** Model fields can be used in different ways:

* As column bindings (condition or result columns).
* In calculations and expressions without being bound to a column.
* Referenced multiple times in different columns or cells.

This flexibility applies to both input and output models.

## **How to Bind Models**

### **Binding Input Model to Condition Columns**

1. Navigate to the **Decision Table Model**.
2. Create new input field.
3. Navigate to the **Decision Table Designer**.
4. Create a new **condition column**.
5. In the column header dropdown, select the input field you want to bind.

<figure><img src="/files/KHq7TZzVbO4O7NFvtPJj" alt=""><figcaption></figcaption></figure>

### **Binding Calculation field to Condition Columns**

1. Navigate to the **Decision Table Designer**.
2. Create new **calculation column** (rename it for better readability)
3. Create a new **condition column**.
4. In the column header dropdown, select the calculation field you want to bind.

<figure><img src="/files/akhPd5psgVo7fEPi6ww4" alt=""><figcaption></figcaption></figure>

### **Binding Output Model to Condition Columns**

1. Navigate to the **Decision Table Model**.
2. Create new output field.
3. Navigate to the **Decision Table Designer**.
4. Create a new **result column**.
5. In the column header dropdown, select the output field you want to bind.

<figure><img src="/files/uwvR44q2n6VPEcW6gzaq" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Condition columns can also be bound to [Rule variables](/doc/rules/common-rule-features/variables/rule-variables)
{% endhint %}


# Decision Tree

Decision Trees allow you to build your decision making logic in a simple tree structure. That means, given input data, you can make and branch out conditions that gradually lead towards the desired output.

It is a visual representation of business rules that uses **IF-THEN-ELSE** logic to map out decision-making processes. It allows users to define conditions and actions step-by-step, making it easy to create both simple and complex decision structures. The design process is made simple thanks to our clear graphical representation.

### What can you find in this section?

{% content-ref url="/pages/0FJNbnywUKBX0CWk84zc" %}
[Tree Designer](/doc/rules/decision-tree/tree-designer)
{% endcontent-ref %}


# Tree Designer

Decision Tree Designer is the interface for building Decision Trees. In this section, we describe how you can easily create your Decision Tree, link it to the input and output data and deploy it.

<figure><img src="/files/ndOmZIo7L9qpbbXSI5Cl" alt=""><figcaption><p>Decision Tree Designer</p></figcaption></figure>

## About the Decision Tree Designer

When you open the Decision Tree Designer with an empty tree (by creating a new Decision Tree in the Decision Trees section and choosing Blank Decision Tree), you will see the initial empty screen. Create first condition by clicking the respective button. A new **IF block** will be added.

<figure><img src="/files/bQIAkSO7oUcvXKgkq8Zr" alt=""><figcaption><p>Create first Tree condition</p></figcaption></figure>

### The IF Block

Every IF block consists of 2 parts. The left-hand part holds the conditions that have to be met in order for the right-hand part to take action.

<img src="/files/8Nm3yJ4mQJBbiLb1jx3J" alt="IF block" width="261">

You can add conditions by clicking the Add button in the left-hand part of the block. By default, all conditions have logical **AND** between them. That is, if you add two conditions, the right-hand part of the IF block will activate if and only if both of them are satisfied. However, you can add the OR block. The OR block contains so-called OR groups which have logical **OR** between them. They are visually separated by a line with the word 'or' in the middle (see below). The OR block is evaluated as true whenever at least one of its OR groups is evaluated as true.

#### Example

To understand the above concept faster, see the following example. We provide our IF block with several conditions. Let us explore the conditions upon which the right-hand part of the block (empty for now) will take action.

Suppose that we require <mark style="color:purple;background-color:purple;">**permission**</mark> to equal true AND one (or both) of the following conditions to be satisfied: (a) <mark style="color:purple;background-color:purple;">**credit**</mark> is greater than 10 OR (b) <mark style="color:purple;background-color:purple;">**subscription**</mark> has value A1 AND <mark style="color:purple;background-color:purple;">**subscription\_active**</mark> is true.

For those who prefer logical pseudo-language: `permission = true AND (credit >= 10 OR (subscription = A1 AND subscription_active = true))`

This collection of conditions can be represented in our IF Block simply as follows.

{% hint style="info" %}
Note that, in order to be able to work with input properties like <mark style="color:purple;background-color:purple;">**permission**</mark> or  <mark style="color:purple;background-color:purple;">**credit**</mark>, these have to be set up in the [Input/Output Model](/doc/rules/common-rule-features/input-and-output) in Rule Settings.
{% endhint %}

![AND & OR Tree conditions](/files/t08ZJfeyf9wAaSpbITWb)

#### Manage OR groups

The OR groups can be easily managed. One can add OR groups by clicking the settings icon of the OR block and selecting Add OR group. On the other hand, OR groups can be removed by clicking the trash can icon at the bottom left corner of the OR group that you want to remove.

{% hint style="info" %}
Note that the conditions inside an OR group implicitly have logical AND between them
{% endhint %}

#### The right-hand side of the IF block

The right-hand side of the if block is triggered whenever the condition in the left-hand side is satisfied. It can hold two kinds of blocks: another IF blocks or THEN blocks. The IF blocks simply further branch out your Decision Tree. More interesting are the THEN blocks, which will be activated every time the conditions of their parent IF block are satisfied.

### The THEN Block

The THEN block represents our results. When all the conditions leading to some THEN block are satisfied, the THEN block is triggered. The rule then returns the results specified within this THEN block.

#### Back to our example

Let us provide our simple example with some result. We click the Add button in the right-hand part of our IF block and select Then. This will add a THEN block. Inside we will set up the results that we want to output whenever the provided conditions are satisfied. In our case, we want to simply take a property called <mark style="color:green;background-color:green;">**order\_accepted**</mark> and set it to true.

{% hint style="info" %}
Again, to add the <mark style="color:green;background-color:green;">**order\_accepted**</mark> as a result, we have to set up this property in the [Input/Output Model](/doc/rules/common-rule-features/input-and-output) in Rule Settings. Our final Input/Output model is depicted below.
{% endhint %}

![Decision Tree Input & Output model](/files/hXzCqTswRNS7VDDiLc72)

![Adding new result into the Tree](/files/rBaA8adMYppNBgtA3Tb8)

&#x20;Congratulations, your first Decision Tree (well, decision trunk) is complete!

### The ELSE Block

If you click the Add button in the right-hand part of any IF block or in the root (the one not contained in any block), you may select to add an ELSE block. This block will be triggered whenever none of the conditions of its preceding IF blocks is satisfied.

#### Back to our example

We can use the ELSE block in our example from above. In fact, it is very handy. By adding the ELSE block after our IF block, we can treat the case that the condition of the IF is not met. Here, we just add a THEN block where we set the <mark style="color:green;background-color:green;">**order\_accepted**</mark> property to false, because the order should not be accepted in this case.

<figure><img src="/files/eslnZK5bRev2Do19gQBP" alt="" width="364"><figcaption><p>Adding ELSE block</p></figcaption></figure>

![Simple Tree with all types of blocks](/files/pzAVYDvlncYg8iQznm7J)

#### The ELSE Block Behavior

As we said before, the ELSE block will be only triggered when no conditions in its preceding IF blocks are satisfied. In other words, the ELSE block will look for all IF blocks directly above it and check if at least one of them was triggered. If it was, the ELSE block is automatically skipped. If not, the logical structure inside the ELSE block will take action.

{% hint style="info" %}
Currently, it is allowed to place the ELSE block anywhere, even if there are no IF blocks above them. When placed in this way, the ELSE block will be always triggered. However, such placement makes little to no sense, and is therefore not recommended.
{% endhint %}

### Branching

You can branch your Decision Tree to arbitrary extent. Branching is done by nesting IF blocks in the right-hand part of other IF or ELSE blocks. This creates the familiar tree structure. Moreover, blocks can be also placed next to each other.

#### Multiple blocks

When multiple IF, THEN or ELSE blocks are placed below each other, they are evaluated successively from top to bottom. Therefore, if we have several THEN blocks in the Decision Tree setting the same property, and all of them happen to take effect, the respective property is eventually overwritten by the THEN block which is placed at the **lowest** position in the Decision Tree.

### Setting conditions and results

The basic structure for every condition is **operator + value**.

#### Operators and functions

For condition IF and OR blocks both operators and function can be used to build the condition, in THEN  block function or simple value (=) are used.

{% hint style="info" %}
Possible operators are specified in [Operators](/doc/rules/data-types-and-functions/operators) section
{% endhint %}

To change the operator in IF block, click the operator/function label, and a selection modal will open. Select the desired operator or function to apply it to the cell.

<figure><img src="/files/MDtPONc2dVSVzsmql6Qp" alt="" width="487"><figcaption><p>Change condition operator</p></figcaption></figure>

To change the operator in the THEN block, click the function/simple value label and small dropdown will show up. Select preferred option.

<figure><img src="/files/FUFwAJFEFOXY6jGETWAR" alt="" width="501"><figcaption><p>Change result operator</p></figcaption></figure>

{% hint style="warning" %}
**Note:** For function operators, selecting a new function operator will not overwrite the existing one in the cell, as function operators can be nested. This ensures that your existing functions are preserved.
{% endhint %}

## Designer bottom bar

### Test Bench

Test Bench allows you to test your Decision Tree to ensure that the rule is evaluating correctly. More about using Test Bench you can find in [dedicated documentation section](/doc/rules/common-rule-features/test-bench).

## **Editing and Saving Changes**

When editing a rule, you can make changes directly in the rule editor.\
Use the control buttons in the top-right corner of the editor to manage your edits:

* **Undo** ⟲ – reverts your last action
* **Redo** ⟳ – restores the reverted change
* **Save** 💾 – saves the current version of the rule

<figure><img src="/files/22ANglfprT9Nnlr2ps7F" alt=""><figcaption></figcaption></figure>

These actions help you safely adjust the rule before saving it.\
Each time you save, a new version of the rule is created and recorded in the **History** panel, where you can review or restore past versions. You will find more information about Rule History here on [dedicated page](/doc/rules/common-rule-features/rule-history).


# Flow

In DecisionRules, **Flows** are a rule type used to connect multiple decision-making steps into a single process.\
They let you visually orchestrate rules, transform data, branch logic, and integrate with external systems, all in one execution path.

#### Flow rules exist to:

* Combine multiple rules (Decision Tables, Decision Trees, Scripting Rules, etc.).
* Control execution order and branching.
* Prepare and pass data between steps.
* Integrate with APIs, databases, or external services.

#### **Types of Flows**

* **Decision Flow** – More versatile nodes (scripts, conditions, API calls, DB connectors) for complex orchestration and branching. Future-ready for more integrations.
* **Integration Flow** – Runs as a background job with extended time limits. Ideal for large datasets, heavy API calls, and long-running logic.

#### **When to Use**

Use a Flow when:

* You need to combine multiple rules into one workflow.
* The logic spans several steps or depends on external data.
* You want to keep decision-making modular and reusable.
* You require both quick responses and heavy batch processing.

The following sections explain each Flow type in more detail, including their features, differences, and typical use cases:

{% content-ref url="/pages/N1T44fnYEnB4qHkigk3S" %}
[Flow Designer](/doc/rules/flow/flow-designer)
{% endcontent-ref %}

{% content-ref url="/pages/mvBCC1t8IwGUAx55MqFy" %}
[Flow Nodes Overview](/doc/rules/flow/flow-nodes-overview)
{% endcontent-ref %}

{% content-ref url="/pages/RH9BnKC6uKNpkFo0xLeT" %}
[Flow Limits](/doc/rules/flow/flow-limits)
{% endcontent-ref %}


# Decision Flow vs. Integration Flow

### **Introduction**

In DecisionRules, there are two main ways to execute a flow of rules: **Decision Flow** and **Integration Flow**.\
Both are used to link and evaluate multiple rules together, but they differ in execution, time limits, and how results are returned.

The **Decision Flow** is intended for quick, real-time decisions, while the **Integration Flow** was created for cases where the evaluation might take longer than the standard execution time limit.\
This article provides a comparison of the two, explains why Integration Flow was introduced, and shows when to use each.

### **Why Integration Flow Was Created**

The Decision Flow can handle most use cases where decisions need to be made quickly, within the allowed execution time (typically 1–8 seconds depending on your plan or environment settings for on-premise).\
However, for example **long-running processes retrieving a large number of database rows**, or **very large bulk input processing** can exceed this limit and cause timeouts.

Integration Flow was created to solve this problem. It uses a background job infrastructure that has **24 hours for process**, allowing the evaluation to run until completion or until it is cancelled.

### **Key Differences**

<table data-full-width="false"><thead><tr><th width="118"></th><th>Decision Flow</th><th>Integration Flow</th></tr></thead><tbody><tr><td><strong>Evaluation</strong></td><td>Uses <code>api.decisionrules.io/rule/solve/</code> endpoint and any Decision Table, Decision Tree, or Scripting rule.</td><td>Uses <code>api.decisionrules.io/job/start/</code> endpoint to trigger a background job.</td></tr><tr><td><strong>Execution</strong></td><td>Synchronous — you wait for the evaluation to finish and receive output in the same API response.</td><td>Asynchronous — starts a job, returns a <code>jobId</code>, and the results are retrieved later.</td></tr><tr><td><strong>Time Limit</strong></td><td>1–8 seconds for Decision Flow execution, API calls, and rule solve limit.</td><td>Job execution limit of 24 hours, 1–8 seconds API call and rule solve limit, and 5 minutes inactivity limit for database node queries.</td></tr><tr><td><strong>Output Data</strong></td><td>Returned directly in the same API response; the connection must remain open until it finishes.</td><td>Returned after job completion — either automatically via <a href="/pages/xZLTvRNLx01cOICkdZME">Webhook</a> or by checking the job status using <a href="/pages/20voSVZXEFBa3K5HbcMe">API</a> with the <code>jobId</code>.</td></tr><tr><td><strong>Best for</strong></td><td>Quick decisions, small to medium complexity, smaller datasets.</td><td>Long-running processes, large datasets, complex decisions.</td></tr></tbody></table>

### **Use Cases**

#### **Decision Flow**

* **Typical decision-making with one input set** – most cases where only one set of input data is evaluated.
* **Linking results of multiple partial rules** such as Decision Tables and Decision Trees.
* **Multiple inputs of medium complexity** – can use the Bulk input approach unless the time limit is exceeded.
* **External REST API calls** – possible, but must be tested to ensure they won’t cause timeouts.
* **Databases** – suitable for smaller queries or single row lookups; larger queries may exceed time limits.

#### **Integration Flow**

* **Long-running REST API calls** – avoids timeouts from slow responses.
* **Database queries returning large numbers of rows** – can process each row without time limits.
* **Large bulk inputs / highly complex flows** – handles large datasets and complex logic where Decision Flow might time out.

### **Switching Between the Two**

If you design a Decision Flow and find it cannot complete within the allotted time, you can **switch it to an Integration Flow** without losing your work.\
This allows you to start simple and then adapt to more demanding workloads when necessary.

<figure><img src="/files/w3F5FcccbB0cGXSKrhJq" alt=""><figcaption><p>Change Flow type</p></figcaption></figure>

### **Combining Decision Flow and Integration Flow**

Sometimes, you need **both immediate decisions and large-scale processing**. For example:

* **Immediate**: A frontend application needs to validate one record instantly.
* **Batch**: A backend process needs to evaluate an entire database table.

**Recommended approach:**

1. **Create a Decision Flow** for real-time evaluations of single inputs.
2. **Create an Integration Flow** that:
   * Retrieves bulk data from the database.
   * Sends each record to the Decision Flow for evaluation.
   * Stores the results back in the database.

This way, you maintain **one central logic** in the Decision Flow, while also supporting both **fast** and **long-running** execution with Integration Flow.


# Decision Flow

{% hint style="info" %}
Decision Flow was formerly called Workflow. If you are looking for Workflow, you are probably looking for this page. Our team decided to rename this rule type to be more aligned with its actual functionality.
{% endhint %}

This section introduces the DecisionRules Decision Flow feature and gives a high-level overview of its possible applications.

Decision Flow is a feature brought in version 1.19.0 of DecisionRules. It allows to design complex decisioning processes. It can be used to orchestrate other rules, make data transforms and calculations, run inline scripts, perform conditional branching, call external API, DB connectors, and more. The list is not final. Decision Flow will be given even more capabilities in the future, like integrations to 3rd party tools, etc.

## Decision Flow Features

Looking at its versatility and potential, Decision Flow can be considered a whole new feature category within the DecisionRules universe. After all, with Decision Flow in its repertoire, DecisionRules are gaining some of the major capabilities of a Decision Flow engine. On the other hand, from the user's perspective, Decision Flow fits perfectly into the same picture as other rules. It is listed as an item in the folder structure, it has the same settings, and it has a designer tab for editing the Decision Flow.

Like its predecessor, the [Rule Flow](/doc/rules/rule-flow), Decision Flow is built by placing boxes on canvas and connecting them with lines. The boxes are called nodes (as in a graph), and the lines are called connections. Unlike in Rule Flow, there are numerous types of nodes, and the connections also have slightly different meaning, which will be explained on following pages of this doc section.


# Integration Flow

Integration Flow uses mostly the same designer options as the Decision Flow (formerly Workflow), the main difference is that it is intended to be used for long running execution mainly for example while evaluating larger batches of data from databases.

### Creating an Integration Flow

The Integration Flow can be created anywhere where other rules are created, so using the Create button, both while right clicking in the Rules view (or right clicking on a folder) and using the create button on top of the folder structure.

<figure><img src="/files/oGQiIbOrmmvDR42I8kqI" alt=""><figcaption></figcaption></figure>

Additionally you can freely change any Decision Flow into an Integration Flow and vice versa using the Integration/Decision Flow switch in the top right of the designer. This will allow you to not lose any work if you start creating a Decision Flow, that runs too long and the switch to Integration Flow has to be made.

{% hint style="danger" %}
Please note that both rule types use different API endpoints and therefore the call to trigger them will be different.
{% endhint %}

<figure><img src="/files/Xf2YsDzkYSNB4utWJrLl" alt=""><figcaption></figcaption></figure>

### Using test bench

The test bench for Integration Flow has slight differences to the normal Test Bench you might be used to. The Input data panel works exactly the same as it does normally, but the Run button is replaced by Start a new Job button which will create a new background job that you will see in the job menus, after triggering the job you will also see additional information about the state (waiting, running, completed etc.) in the middle panel. After the job is completed, you will see the output data in the right panel as in the case of regular test bench.

During execution in the middle panel you will have information about how long is the job executing for, and after the completion you will be shown exact execution time.

<figure><img src="/files/uBX370whcNFoxty389C4" alt=""><figcaption></figcaption></figure>

You can select any job in the Jobs panel and you will see this information for the chosen job, **you don't need to keep the page open to not lose the information.**

<figure><img src="/files/x0G6jKIr3BunQJLMXB6A" alt=""><figcaption></figcaption></figure>

#### Executing an Integration Flow

Please note that the Integration Flow and the subsequent job, can only be triggered via the specific endpoint by REST API, it cannot be triggered using the SOLVE function of via a regular Decision Flow.


# Flow Designer

{% hint style="info" %}
See our Decision Flow tutorial available in [DecisionRules Academy](https://academy.decisionrules.io/rule-types/decision-flow/create-a-decision-flow).
{% endhint %}

### Accessing Decision Flow

Let us create the first Decision Flow. Click the Create button in the Rule list. Here you can choose to create a blank Decision Flow (if you do not seem to have access to it, please see the [Flow Limits](/doc/rules/flow/flow-limits) page).

Upon creating a blank Decision Flow, you will be taken to the rule detail. Note the Settings and the Designer tab. You can review the Settings, which should not surprise any DecisionRules user. As mentioned above, the settings are (almost) the same as for regular business rules. In particular, pay attention to the input/output models. As usual, these models define the format of the input and output data of the Decision Flow at question. We can leave all the defaults here and turn our attention to the Designer tab.

The blank designer features the canvas with a single node: the Start. The designer window features the usual bottom bar, where we can open the test bench. Next, on the right hand side, there are several additional tabs. For now, we will focus to the most important one: the Palette.

{% hint style="info" %}
You can try one of our Decision Flow examples. Simply click on the Examples card on the Rule list. Exmaple window will show up. Select Rule examples section, then choose one of the examples with Decision Flow tag.
{% endhint %}

<figure><img src="/files/1n80PhOww9NSuGACRmiZ" alt=""><figcaption><p>The Decision Flow designer</p></figcaption></figure>

## Flow Designer

### Canvas

You can think of the Flow canvas as a real canvas where you can place nodes, connect them to create from simple to complex processes. On the canvas there is a enough space for all your nodes and  branches.

#### Navigation

Navigation through the canvas is intuitive - move around by dragging your mouse, zoom in and out scrolling the mouse wheel.

#### **Editing and Saving Changes**

When editing a rule, you can make changes directly in the rule editor.\
Use the control buttons in the top-right corner of the editor to manage your edits:

* **Undo** ⟲ – reverts your last action
* **Redo** ⟳ – restores the reverted change
* **Save** 💾 – saves the current version of the rule

<figure><img src="/files/SHGFbpqvUrDb0KdhWnTr" alt=""><figcaption></figcaption></figure>

These actions help you safely adjust the rule before saving it.\
Each time you save, a new version of the rule is created and recorded in the **History** panel, where you can review or restore past versions. You will find more information about Rule History here on [dedicated page](/doc/rules/common-rule-features/rule-history).

### Sidebar

#### Palette

The palette has a simple purpose. It lists all the available node types with brief description. If you want to use any of the nodes in your Flow, just drag it from the palette and drop it on the canvas.

{% hint style="info" %}
The maximum number of nodes you can add to a Flow is determined by your plan, ensuring optimal performance tailored to your subscription level. To discover how Decison Flow limits works, please refer to [page](/doc/rules/flow/flow-limits#nodes-limit) dedicated to it.

In the Palette you can see how many nodes are in the Decision or Integration Flow.&#x20;
{% endhint %}

By clicking on the node in the list node description opened. You can find the functionality of such node there, along with common use cases.

<figure><img src="/files/aRVupKFPFDTtqE6vliqI" alt=""><figcaption><p>Node description in the Palette</p></figcaption></figure>

#### Inspect

On the Inspect tab you will find details of node evaluation once you run the Decision Flow in the Test Bench.

{% hint style="info" %}
See more information about Decision Flow Evaluation in the [section](#decision-flow-evaluation) below.
{% endhint %}

<figure><img src="/files/JpUvoxwr3Sh1NmACSYgY" alt=""><figcaption><p>Inspect tab detail</p></figcaption></figure>

### Nodes

Nodes in the Decision Flow act as containers for specific actions or steps. Each node represents a task, such as declaring and assigning values, processing data, evaluate other business rules or run custom code. These nodes help structure and visualize the Decision Flow.

Once present on the canvas, the node can be clicked in order to open its detail. Each node type has different configuration options, depending on its functionality. If you want to read more about individual node types and their configuration options, check out the [Flow Nodes Overview](/doc/rules/flow/flow-nodes-overview).

#### Node modal

As mentioned node represents a task. Such task can be set in the modal opened by clicking on the node on canvas. Depending on the node type in the modal, you can define new data sources and targets, along with their corresponding values, or utilize the existing ones.

In every open node modal you can find *Data Dictionary*, a collapsible section holding Decision Flow variables already declared. Their values can be used by simple dragging to desired field.

{% hint style="warning" %}
*Please note that by design some types of declared* Decision Flow *variables cannot be used as a target to be overwritten.*
{% endhint %}

You can also find a description of each node by clicking the ![](https://docs.decisionrules.io/~gitbook/image?url=https%3A%2F%2F437457296-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MN4F4-qybg8XDATvios%252Fuploads%252FKYk6GEhI2GvXJ61JIkDj%252Fhint.png%3Falt%3Dmedia%26token%3Df0428c14-2dcb-452b-a5db-4f998c0299ce\&width=300\&dpr=4\&quality=100\&sign=626a0892\&sv=1) (How-To) icon in the node modal.

{% hint style="info" %}
Multiple node modals can be opened at the same time.
{% endhint %}

{% hint style="info" %}
Once the Decision Flow node is set in the modal, node on canvas shows details about the content and setting.

<img src="/files/XlBZVEyTy1D4E4AeHZ9t" alt="workflow node on canvas showing details" data-size="original">
{% endhint %}

#### Node Interaction

Nodes can be moved around the canvas dragging them by their headers.&#x20;

Hovering or right-clicking on node shows context menu containing three options: Inpect, Clone and Delete.

* Inspect: Opens Inspect tab of selected node on the right side of the Designer.
* Clone: Creates a clone of selected node. Creating a clone will duplicate the content within the modal.
* Delete: Selected node is removed from the Decision Flow. Can be undone using Undo/Redo buttons.

#### Naming Nodes

To better fit you process, you can name your nodes on canvas. Node name have to be unique in your Decision Flow and only English letters, numbers and underscores are allowed to use.

### Connections

In your Decision Flow, connecting nodes together is essential for creating a logical flow of operations. By linking nodes, you enable the transfer of data and outcomes from one step to the next, allowing the Decision Flow to process complex conditions and make decisions based on prior results.

#### Connecting Nodes

To connect nodes in the Decision Flow, simply click and drag a connection from the right connector of one node to the left connector of another. This establishes a link between the two nodes, allowing them to interact and pass data.

<figure><img src="/files/q00nOPPKOsR3HrWWpNAo" alt=""><figcaption><p>Creating node connections</p></figcaption></figure>

### Rule Bottom Bar

Located at the bottom of the rule designer, you'll find a set of additional tools:

* Test Bench: Here you can test your Decision Flow. Simply enter input data and click **Run**. More about Test Bench can be found [here](/doc/rules/common-rule-features/test-bench).
* Console: Here you can find all Decision Flow process data.
* Center: Allows you to quickly return to the starting point of the Decision Flow, making it easy to navigate back to the beginning
* Zoom: Use zoom buttons the adjust the view of your Decision Flow.

## Simple Decision Flow Example

Let us consider a simple example. Among other things, Decision Flows can do everything that rule flows can do, that is, call other rules. We can thus build a simple Decision Flow which calls a decision table and sends its results to the output. This should be easy enough.

First we need a decision rule to start with. Create a blank new table, call it Segment and go to its settings. We shall adjust the input/output models. Let us assume that this decision table will get client segment on the input and will return the segment name. The input model will thus have a single `segmentCode` attribute, while the output will have the `segmentName`.

{% file src="/files/elH0XucWy3yNQn19ihCk" %}
Segment decision table
{% endfile %}

<figure><img src="/files/F1vIDqPhbMwoGBDG9GT9" alt=""><figcaption><p>The Segment decision table I/O model</p></figcaption></figure>

As for the table itself, let us keep things simple and just add a couple of rows. Based on the matched segment code, we will return the corresponding segment name. The table can look e.g. as follows.

<figure><img src="/files/Vnc6fVCmSbla9jW09KFm" alt=""><figcaption><p>The Segment decision table</p></figcaption></figure>

Try to solve the table from the Test Bench to be sure it works as expected.&#x20;

We can now return to our Decision Flow. Assuming that we just want to call the Segment decision table and return its results, the input/output model of the Decision Flow can be exactly the same as that of the table. Open the Decision Flow Settings tab and edit the models to have `segmentCode` in the input and `segmentName` in the output.

We are ready to return to the Decision Flow designer. Upon opening the Designer tab of our blank Decision Flow, we see just empty canvas with the Start node. Open the palette on the right hand side menu, find the Business Rule node and drag it to the canvas.

<figure><img src="/files/ZmXb7zuZIK61hgQuq0HE" alt=""><figcaption><p>Decision Flow designer with the Business Rule node</p></figcaption></figure>

The purpose of Business Rule is, well, to call a business rule. To make sure this actually happens, we have to connect the Start with the Business Rule. Notice the small circles on the side of the nodes: these are connectors. Dragging a line from one connector to another, create a so-called connection. Next thing, notice the little `rule` label at the bottom left corner of the Business Rule. This is the *node alias*. It is a unique name used for referencing this node elsewhere in the Decision Flow. To satisfy the best practices, edit the node alias to be more descriptive, rewriting it e.g. to `segments`. We will later use this keyword to map results of the table to output.

We have created the Business Rule node, now we have some configurations to do. Click the inside of the Business Rule box, opening its detail window.

<figure><img src="/files/CwLv18Pwms0szmrt0ms5" alt=""><figcaption></figcaption></figure>

The detail of Business Rule has two main parts. In the first part one chooses the business rule to call. Open the dropdown and find the Segment decision table prepared beforehand. We can leave the default Standard strategy and skip to the second part. Here we have to define the rule input mapping, telling which data will be sent to the input of the decision table.

At this point, it is suitable to pay some attention to the Data Dictionary section on the left hand side of the window. Upon expanding the items, we shall see the predefined input and output attributes. Since we want to send the inputted `segmentCode` to the input of the decision table, we just drag and drop the `input.segmentCode` from the Data Dictionary next to the `segmentCode` item in the rule input mapping. Click the Save button and we are done! We have just configured our first Business Rule node.

Our Decision Flow will now be able to call the Segments table and get its results. However, we have not yet specified what to do with them. To actually get something useful in the Decision Flow output, we have to assign the result of the Business Rule node to the output of the Decision Flow. For this we can use the Assign node. Drag it to the canvas from the palette and connect it after the Business Rule. Then click in the middle of the node in order to review its configuration.

<figure><img src="/files/pohjCB4kZfieeHjjI5XQ" alt=""><figcaption><p>The desired Assign configuration</p></figcaption></figure>

The node detail window is already familiar to us. We just need to add a single assignment. See that the Assign configuration contains target and source. Under target, we will put `output.segment`, and in source we enter the result from our Business Rule. It can be found in the Data Dictionary by its node alias segments, and we are interested in its output, therefore using `segments.output`. Both these variables can be simply dragged and dropped from the Data Dictionary. Our Assign is complete.

Finally let us test the resulting Decision Flow. Open Test Bench, enter a `segmentCode` matching some segment code from the Segments decision table and click Run. If the configuration was done correctly, you should get the corresponding segmentName on the output.

<figure><img src="/files/2ZkFml4JMkVClLDPYsKS" alt=""><figcaption><p>Testing our Decision Flow</p></figcaption></figure>

Note that the `segment` attribute on the output actually contains an array `[]` with a single object `{}`, which in turn contains the `segmentName`. This rather complex data structure follows from how we set up our Assign. Under `segment`, we have mapped the whole output of the Segment table. Later we will see how the result can be simplified or transformed to any form you like.

This is it, you have your own first functioning Decision Flow! Of course, there is much more to Decision Flow: the inspect, the variables, the distinct nodes, loops, etc. Nevertheless, this example brought to light the most important principles, and showed the usual ways of work. You can use following Decision Flow as a reference.

{% file src="/files/CsdNxpGsLNyTgKmTEshd" %}

In the next section, we shall dive more deeply in how Decision Flow is evaluated.

## Decision Flow Evaluation

Although Decision Flow looks similarly to rule flow, it is fundamentally different. Decision Flow has the ability of running only some of its branches (sets of connected nodes) while leaving other branches to sleep. We call this ability *branching*. But before we show branching in action, we need to take a deeper dive into how Decision Flow is evaluated.

It is clear that each node has some specific functionality. One can imagine it as a black box that consumes some data, performs calculations, and returns some other data data on the output. It can also have side effects (like setting variables elsewhere in the Decision Flow), but about this later. Naturally, each node takes some time to evaluate. But what determines which nodes will run and when? Of course, it is the connections.

As we mentioned earlier, the connections in Decision Flow have a slightly different meaning than those in rule flow. A priori, they do not say much about how data are flowing through the graph. Instead, the connections in Decision Flow determine chronology. When node A is connected to node B (in that very order), it means that node B is supposed to run as soon as node A is finished. Moreover, when we add node A' and also connect it to B, then B will wait for signals from both nodes A and A', and will run as soon when both A and A' are finished.

There are four states in which node can be during the evaluation (solve) of a Decision Flow:

* Ready = waiting for signal(s) to run
* Done = finished successfully and sent a run signal to its successors
* Error = finished with an error and sent a cancel signal to its successors
* Canceled = got a cancel signal and resent it to its successors without running

Once you run the solve of the Decision Flow, the Start node sends a signal to run, and the Decision Flow evaluates along the connections of the graph according to this principle. Some branches might run successfully, some may get canceled (due to an error or intentionally). When all branches reach their last node, the Decision Flow evaluation ends and rule returns its outputs.

{% hint style="info" %}
The End node can be used at the end of a branch for clarity. However, it has no effect on the evaluation. The branch finishes with or without it.
{% endhint %}

When running a Decision Flow solve from the Test Bench, it is automatically evaluated in the so-called debug mode. Thanks to that, the application gets detailed data about the run and shows the final node states (as described above) in the top right corner of each node box on the canvas. To review details about the node evaluation, you can use the Inspect tool (click the icon of magnifying glass emerging above the top right corner of the node box). It shows relevant data from the node evaluation. The Decision Flow must be solved successfully at least once in order to use the Inspect.

We have described how the Decision Flow is evaluated and what can happen along the way. Of course, there are several special cases which make things more complicated, but the reader now has a good overall idea about the process.


# Flow Nodes Overview

This page lists all the node types currently available in the Flow, along with a brief description of their functionality.

For better navigation, the nodes are divided into logical sections and listed in the same order as they appear in the Flow palette. You can also find a description of each node by clicking on the node in the palette or by clicking the ![How-To ](/files/Ow3D7fZeuRLWIZBcZKUj) (How-To) icon in the node modal.

## Node versions

Nodes can exist in multiple versions.

* The **palette always displays the latest version** of each node.
* **Older versions** can be recognized by a badge with the format **(e.g.,**  <img src="/files/ZMHRcekx2VtxldIJQB1N" alt="" data-size="line">**)**.
* Some older versions can be **automatically converted** to the latest version, but this does not apply to all.

In the following documentation for each node:

* The **current version** of the node is always indicated. If no version is shown, the node is in **version 1**.
* For each **feature** of a node, if it is only supported from a certain version onward, a **version badge (e.g.,**  <img src="/files/ZMHRcekx2VtxldIJQB1N" alt="" data-size="line">**)** is displayed.
* If no version badge is shown, the feature is supported starting from **version 1**.

## Basic

### &#x20;<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAdtJREFUeF7tmU1OwzAQhccN7BEhVXoBOAAVa9YIjtF2xY5jsGJF4RhwC8QFuEADTquKJWpqxC4RoZ5mkibYr8tmPPZ8fm+cH0We/5Tn9RMAQAGeE4AFPBcAmiAsAAt4TgAW8FwAOAVgAVjAcwKwgOcC4J0CiV5cGrO++U+wlOrdxtHhs23NLAu868XEGHNvS9ap64omcRQ+2NYEADZCP9ehAFigpAcwPcZRmDQm+UividRdIQ9zfdV7AHMCaXGc8Y0DSPR8TIamVQhzCpDGzNL0jDJ1kc+z1wueoujg1ZbbCQXYitx0HQA49EqPwQ71AE4Nf8VAARx6iZ6PyFDxtlLROI7CR874pmPKnlWafxbokAUkFnXCAgBQdqvOVCgUwGlQEolx8ktjJOuDAjj0JYQ5+aUxkvVBARz6u3wjFPfDwqZovRxmJnvhrHPbmEAFw+oK2HY2ZjwAQAEdtMAuP4wM+kfnebdo/XmyMl/Ft1G/7TRQpI7zfxsyb0Q02+S8gPZHrB7AtG9rYY0fg61VxpwYAJp+GGJuRGthUAAUUP3LFU6B1oxb48Te9wCtl6erdXaVZ1rrp7EaN6tzqZzoARKqACCh58JYKMCFXZTUAAVI6LkwFgpwYRclNXwDDUKOHrqLH2MAAAAASUVORK5CYII=" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M540-288H144v-384h672v108h-72.33v-36H216v240h324v72Zm-324-72v-240 240Zm528 204v-132H612v-72h132v-132h72v132h132v72H816v132h-72Z&#x22;/></svg>" data-size="line">  Assign&#x20;

The **Assign** node is essential in Flow for managing data transformations and storage. It allows users to assign fixed values or the results of expressions to outputs or variables, streamlining data flow and facilitating dynamic decision-making within Flows.

#### Key Features

* **Assign Fixed Values:** Directly set specific values to variables or output fields.
* **Map Data Between Variables:** Transfer or transform data from one variable to another using simple assignments or complex mappings.
* **Expression Evaluation:** Evaluate expressions and assign the result to variables, enabling dynamic and conditional data handling.

#### Use Cases

* **Data Initialization:** Initialize variables with specific values at the start of a Flow to ensure they are ready for use.
* **Dynamic Calculations:** Use expressions to perform calculations and assign the result to a variable for later use in the Flow.
* **Data Synchronization:** Map data from inputs to internal Flow variables to maintain consistency and integrity across different Flow stages.

### <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAA15JREFUeF7tmE1PE1EUhs+ZKS0KraXtTAsudGGCCdEFZaEJSpCEuOI3uFBw7crf4MK1ZeXauHKhSzUaJIEq0Rg1YYELpWU6tpSvUqdzzBBqSjv9mHboR+bMdu49c85z3/fcewfB4Q86vH5gAKwAhxNgCzhcANwE2QJsAYcTYAtYFYCiKF4NXFGr84rjXYA7kuSPm81XlExUA/I2G1sk/6os466V+ZYVoCiZiQIVVqx8pHQsAcWH5dCE2fzNrVQcAcebjS2iOFENbrWYDMAqbVYAW6B+D0CApzrBTzN1oQC/I1Jw0exdQlHnSYcRs3cCwgUCuFNLsSKKUUnyf7Si6tPpAQQbLpEmQ6HQLyvJVBubSqXOawV8DwgX6wDooiZoE4RkcjdMcLhcr3gDTPftAi1CyGazof1c/gMAXmpESe0CEC1QYbUsoWdAMAYIYxWJEmwI6Lkuy4OJRooojjGK38vl3yHgZZOYXxFhpbwntKsHVAIgiHncwsPDvG74tBIC0DpS/2Q4PJhsBEImkxk6yGtLpsUDrHn6hOnDvP4IEO6VxuucAghikXDwfjqd9rcKwSg+d1h4CwhXTGCtiajflCRpJ5FUFzsFoPIoTLAYCQcXjIRbgaCqqu+vBoaKKoonoBUX0oxRvPGdbgNwpIDiim1vbwcOctob80LgG5xxTw17vUr5Cm9tqbd1gFcmnl8WBX22WPwxgBggzJeOFUAYl+WhT43YrDjGnnNAiQKKgWspgYC+D/S7b/h8vlR5sgklPQekPweAvqN3BEtAgdlIBPdKx3abAv5boDTJpiGkMreooL1EwHhYDswgYq4CVOd6QHZUo3zshPQQX4Sl4GMz6R3b4TUgXDXbzuise9rMDglVvaYHAp9HEPfN4iYV9YFONHdiF4C+u7J8bv1ULWAleCN2AIIv/R5xyu/3p5uJ3eocyz2g2Q/W3B06CKFtAOpukQgL1W6JzUJvZF5bAdSE4BQABoSk8meBiJ6cWCEG4BALsALYAtwDuAnyLsDbIJ8D+CDEJ0E+CvNdgC9DfBssJcDXYb4OO+OXmKF6Rdkb1iA/WuoAF7h/SNLAZiP/8ewc0/Z/gnYmb0csBmAHxV6OwQro5dWzI3dWgB0UezkGK6CXV8+O3FkBdlDs5RiOV8A//TVUX64702sAAAAASUVORK5CYII=" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M444-192v-273.24L264-645v117h-72v-240h240v72H315l201 201v303h-72Zm138-339-51-51 114-114H528v-72h240v240h-72v-117L582-531Z&#x22;/></svg>" data-size="line">  Switch

The **Switch** node is designed to direct the Flow based on conditional logic, allowing for branching based on case evaluations. This node evaluates a series of cases, each defined by a specific set of conditions, and branches the Flow accordingly.

#### Functionality

* **Case Evaluation:** Each case within the node has a set of conditions. The Flow branches off when these conditions are met.
* **Default Case:** If no conditions are met for any case, the Flow defaults to a predefined path, ensuring that the Flow  continues smoothly.
* **Visibility of Case Fulfillment:** It is possible to track whether each case's conditions have been met, providing clarity and transparency in Flow execution.

#### Evaluation Strategies

* **All Winning Cases:** This strategy evaluates all cases that meet their conditions. If no cases are deemed profitable, the default case is executed.
* **First Winning Case:** This strategy identifies and executes the first case that meets its conditions. If no cases qualify, the default case is executed.

#### Use Cases

* **Complex Decision Making:** Ideal for scenarios requiring multiple conditions to determine the Flow path.
* **Error Handling:** Can be used to manage different error conditions and direct to appropriate recovery paths.
* **User Input Handling:** Direct Flow based on various user inputs or actions within a system.

This node is crucial for implementing complex decision-making capabilities within Flows, allowing for dynamic and condition-based Flow branching.

### <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAuBJREFUeF7tWz+L1FAQn8kqeNi4m79rITZWgnDHYnHgNxAEO7GxUE/80yj4JQQbFdyzshFs9QuchVgcpxY2goWNZJNNgtUhSnYkyElYsrs3b/P2ZdlJl7zfezPze/NmJi8vCCt+4YrbD0KAeMCKMyBLYBEOEEXJ5RHguTplIdJvQOv7ERy9cxznh+rY2j0gGmZbRPRcVcFZ/YhoHxAedj3n2SxsVbtWAgbD9DoQvFBRjN0HrUuB237D7aeNgDDKbiOS0qxwjfiHp2+B55zh9tVCwEJnvmTxyO0cP4m4zyGhdgLCOLmLgE+qlCCge4CtLxwFJ2GR8gcAeLHcboG17nntz5zxayVgyswTAFwJPPs1R7lp2EGUbgPCjTKmha2e657Y48iojYAwTu4g4NMK4bUbX8hoFAGLNr5RBJgwvjEEmDK+EQSYNN44AaaNN0pAmKZnMYfqXI54NXA7r8qZIIyTnfI9En4NfHvr4Jlq+yBK+4Bwc6wO2PC89ietaXA4/NnLKd8dEzIx1Q3itGj7fxHQXtdzegcPVNuNpcEqAgjgZdezr1Uxr2rgLIKa5QEE22W3LhOhkQAzlWDlEhACxANkCUgMKOX2VQyC/cC3b1WlQdVCZ1ahtDRpkFOVcbCNKoRgShrkGMXBCgGmtsS4hRBnVjlY8QDxAEO7wrIEqvYDJAtMfhniBDYOVoKgBEEJgsuxI8RZ1xysxACJARIDJAYYOSAhpbCUwhXfBuVdQN4FJn4Y4RQ3HKwUQgYLoY2c8rGzePSWsPWYM4PzYo0dlCSitWiYsY6jzmvsYfv7bmcNEX8dFl/glA5KhnHyEQHXOYJ0Ywlot+s557lylAiIonSTEN5zhenEYws2fdv+wJWhREAhpDgUDQSPEPEYV2id+OKHCcuy7vtup68yrjIBhbAsy079yeEC0eg0ER5VUUC1z9L8MqNq4KL6zeUBi1JSpxwhQCe7yzC2eMAyzJJOHf8CLgpXbktKuBAAAAAASUVORK5CYII=" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M360-528h72v-144h-72v144Zm120 0h72v-144h-72v144Zm120 0h72v-144h-72v144ZM263.72-96Q234-96 213-117.15T192-168v-504l192-192h312q29.7 0 50.85 21.15Q768-821.7 768-792v624q0 29.7-21.16 50.85Q725.68-96 695.96-96H263.72Zm.28-72h432v-624H414L264-642v474Zm0 0h432-432Z&#x22;/></svg>" data-size="line">  Declare

The **Declare** node plays a critical role in managing data within Flows. It allows for the creation of runtime variables that can be modified during the execution of a Flow. All variables established by this node are accessible in the data dictionary, providing a centralized view of Flow data.

#### Key Features

* **Runtime Variable Creation:** Enables the dynamic creation of variables that can be adjusted as the Flow progresses.
* **Data Dictionary Integration:** All variables are listed in a data dictionary, making them easily accessible and manageable throughout the Flow.
* **Encapsulation:** Variables are grouped under the name of the node, which helps in organizing and isolating data within complex Flows.
* **Flexible Variable Definition:** Supports defining both entities (complex data structures) and inline variables (simple data types), providing versatility in data handling.

#### Use Cases

* **Data Handling:** Ideal for scenarios where data needs to be initialized and potentially modified based on Flow conditions or user inputs.
* **State Management:** Useful in long-running Flows where state needs to be tracked and manipulated across different stages of the Flow.

This node is essential for Flows that require a high degree of data flexibility and accessibility, ensuring efficient management and manipulation of variables during runtime.

### ![](/files/FI0x5W9aXAMew6unNiWE)  Global Variables

The **Global Variables** node is essential for establishing a set of global variables accessible throughout the entire Flow. This node is typically configured at the start of the Flow to ensure that all variables are defined and available for use from the beginning.

#### Key Features

* **Global Scope:** Variables defined in this node are available throughout the entire duration of the Flow, across all nodes.
* **Initial Configuration:** Placed right at the start of the Flow, this node sets up essential variables that are critical for the entire process.
* **Easy Access:** All global variables are readily accessible and modifiable by any part of the Flow, enhancing data sharing and manipulation.

#### Benefits

* **Consistency:** Ensures that all parts of the Flow have consistent access to the same set of variables.
* **Simplicity:** Simplifies the management of data that needs to be shared across multiple parts of the Flow.
* **Efficiency:** Reduces the need to repeatedly define the same variables in different nodes, thus optimizing Flow performance.

#### Use Cases

* **Configuration Data:** Ideal for storing configuration settings that need to be accessed by multiple nodes throughout the Flow.
* **Shared Resources:** Useful for scenarios where data needs to be shared or visible across various stages of the Flow, such as user permissions, environmental settings, or operational parameters.

This node provides foundational support for Flows that require global data accessibility, ensuring that critical information is uniformly available across all stages of the process.

### ![](/files/Cij1NHSXjjPYzAE8sMI2)  Foreach

The **Foreach** node is used for iterating over arrays within a Flow, making it essential for processing collections of data. This node utilizes a "Loop Connector" to iterate through each item in the input array, providing powerful functionality for data manipulation and analysis.

#### Key Features

* **Loop Connector** iterates over every item in the specified input array, ensuring that each element is processed sequentially.
* Access to **Current Item**: during each iteration, the current item is accessible via the `[foreach node name].currentItem` attribute, allowing for direct manipulation of each array element as an object.

Iteration Context provides additional iteration parameters such as:

* `index`: Indicates the number of the current iteration.
* `length`: Indicates the total length of the input array.

#### Advanced Usage

Nested Loops

* For nested arrays, multiple Foreach nodes can be nested within each other. This allows for the handling of complex data structures and multi-dimensional arrays with ease.

Parallel Loops

* When **Parallel Loop** is enabled on a node, the output data from that node is automatically segmented into smaller portions. Each of these segments is then evaluated in **parallel** rather than sequentially. This is especially useful when working with arrays or batch data, allowing for faster execution by running multiple evaluations simultaneously. When the toggle is off, the entire output is processed as a single unit in a sequential manner.

#### Use Cases

* **Data Processing**: Ideal for scenarios requiring detailed processing or transformation of each item within an array.
* **Batch Operations**: Efficient for performing operations on batches of data, such as calculations, filtering, or aggregation.
* **Complex Data Structures**: Useful in Flow that need to navigate and manipulate nested or hierarchical data structures.

This node is crucial for Flow that involve array processing, providing robust tools for iterating over data and applying specific operations to each element effectively.

### <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAw5JREFUeF7tmjuLE1EUx/9nzHa7ojuZyUPEUmzNggoWYiEoC4K1xeKS3Q/gl3F9sAi2NiI2lsIWSiorO0EwmVcICBaavUciCEkMmTNzZzLJ5Ka9557H7/7vvWcmQ1jzH615/TAAjALWnIDZAmsuAHMImi2QdAuEYXjlt6LrFuGiUrCSzs/D3rKgFONbhTZOHOfslyQxEinAC/sPWfExgEqSIIuyZcYv6wzt16rbr6QxxQA8L3zARK+ljgu1I+t+3Tn/RpKDCIDv86ZC1AVoU+J0CWwGytm+0CT6GZeLEED/pgJ/iHO2TONs8bVGtfoxLicRgJ4fPQLwYtIZv2WmTlyARYwTcQug3fFYFnjPdasv4+KLAHhB/5CZn0w4IxzWHftpXIBFjOvkZwBIVkiHsMS/ro1OfkYBEvo6hCX+dW108jMKkNDXISzxr2ujk59IAb0gOgDjKO4aHNmxQlO3oHnzycL36etXmt8svyIAUsJdP+wQ6GqeABjcabjVnfEY0vwMgBkEjAIkcpVKrLRboBdEbTAm+37CQd2xn40DDIJBawjekkBNa1MB/XCccxMPYdL8cj8D0halO0+qUAMg70NQdyXTzjcK0HhfUfg1WHdtUQ7z1LE0CkhzDRoARgErsAWkjUbPi46Y+HKS07zhVm9NNlPB1hCVVhIfUGqXCI+nnlb/a9RWog8IgsHOKZ9+SgRgdmWit9aiE1jneTtpIVkBIMadWs1+HxdfBEDnmolLYHo8AwDMwH7DtUd/4sb+ygYgUfEjOmUCkLj4MgFIVXxZAKQuvgwAtIpfdQDaxa8ygEyKX1UAmRW/igAyLV4MoOuHewSa6qzy+USGgCYI7Zkt3Iw30bGtXoyBqBHKoD3VzTPzlf+XkAjAyLjrRV+JcEm3klTzCe26Yz9PNTcLBYx8+H7/rgK/yyOJOT5zW/nECvirAr9/j1gdg8hdAIjcixcfgtPF9sLBbajhDWbayAuEBXyu1ezcP80VnwF5FVq0XwOg6BUoOr5RQNErUHR8o4CiV6Do+EYBRa9A0fH/AFUN2V/N3TTYAAAAAElFTkSuQmCC" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M216-216h336v-192h192v-336H216v528Zm0 72q-29.7 0-50.85-21.15Q144-186.3 144-216v-528q0-29.7 21.15-50.85Q186.3-816 216-816h528q29.7 0 50.85 21.15Q816-773.7 816-744v360L576-144H216Zm72-264v-72h192v72H288Zm0-144v-72h384v72H288Zm-72 336v-528 528Z&#x22;/></svg>" data-size="line">  Sticky Note

The **Sticky Note** node is used to create notes within the Flow. This node serves as a simple yet effective way to add annotations, comments, or reminders directly in the Flow, enhancing clarity and communication among team members.&#x20;

#### Key Features

* **Annotation**: Add textual notes to any part of the Flow to explain the purpose of nodes, document decisions, or provide additional information.
* **Visibility**: Notes are visible within the Flow interface, making it easy for anyone reviewing the Flow to understand the context and reasoning behind specific nodes.
* **Non-Functional**: This node does not affect the Flow's execution; it is purely for documentation and informational purposes.

#### Use Cases

* **Documentation**: Use Sticky Notes to document the logic and reasoning behind complex Flow sections.
* **Collaboration**: Facilitate better communication among team members by adding notes that explain specific parts of the Flow.
* **Reminders**: Add reminders for future modifications or considerations that need to be addressed.

This node is essential for maintaining clear and comprehensive documentation within your Flow, ensuring that all stakeholders understand the Flow's structure and intent.

### <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAA3tJREFUeF7tmktrE1EUgM+5mdSFpTZNZpoo4sKFuLWCFrWiO0UR3IggUrQP3OgfcOd/EJ+UgogbN+JjqSB0oYgrhYqo4GLeIRtd9DFHRkxJbJN7JjOdzHRmtvc8v3PuucmdQcj4gxnPH3IAeQdknEC+BTLeAPkQzLdA0C3gOM7+ZQ8PC4TdngciqP5myAsBnkfwU8HigqoOLQbxEagDTKd+iTyaAwAliJO4ZIlgSRTw6mhl5BHXJxuAaTrnCfEp13Bf5VCcq6qlZ5wYWAAsiwY9cHUAHOQYTYBMw1NHdu1E/C2LhQmgftQDeiszlqR1EnSoVqm8k8XEAmBY7hUAeNhujJ4T4QeZgzjWEWkMAM+0+hJAk5pWmZf5ZwEw7fosEd1pM4YwW1XL92QO4lgPE18OgFOhMIQ59sPKhIkv7wAOfcN2p4Ggfb8jzFTV8n2OfpQyhuXeKGDxlaoOfWnate1ftRVY2tfqR4GBRVXdrst8p6oDDMu9BQA3gciEbcp4dXj4uyxB2XpqAOi2cxsJr60lFBEEFgDDdmeA4G6/jkHDrl8EosfrqklkFcTARNA/QK12WADCTFlZC3LXdcuZR8DLG0Aw/0FYmwlcm75cagD4wXaCQASOIopHWgcjF0KqAGwGhNQBiBpCKgFECSG1AKKCwAIQ9hi07cbYird6ljuYAsghIlwHgOH/dYjABQUmauXy5272WADCHoMb6gfIsldRzumwpQH44GQQMgEAFDjeaStsaQCy6rN/CaZ4CPqV/9T3IdjrEJPpRfHTOJYtIEukl/UokmdvgbDHYC8JdtOJKvlUAogy+dQB2Iw7gdTMgG7Jh7kfZAEIewyGnQGG5V4AgCcdrsSO9XIR0rTFApCEIdjXS9EkAPAr1rdrccN2p4Cg/SUIwnRVLT8I295B9f0XIwKUF5q242tTNzMvRjrBCtOhqZkB3TolBxDi+4W8AzhDSLecSQT0P49reTL0iYxtNw6u0up7DqykyAgQBzSt9FEWD2sL+EZ00/2BCHtkBhOxTvCtOlrey4mFDcCy6qc8oJcco/2WIRQnamrpDScONoC/XWDVTyN5c4CocYzHL0M6gZiqaSPsQgUC0EzIcBonwVsZJ8Ji/Emu94hIy4SFhZpaeh00np4ABHWSZPkcQJKrE0dseQfEQTnJPvIOSHJ14ogt74A4KCfZxx+xCaZfDkdZcgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M216-144q-29.7 0-50.85-21.15Q144-186.3 144-216v-528q0-29.7 21.15-50.85Q186.3-816 216-816h528q29.7 0 50.85 21.15Q816-773.7 816-744v72h-72v-72H216v528h528v-72h72v72.21Q816-186 794.85-165T744-144H216Zm456-144-51-51 105-105H384v-72h342L621-621l51-51 192 192-192 192Z&#x22;/></svg>" data-size="line">  End

The **End** node serves as a visual indicator for the termination of a Flow branch and provides insight into the final data state of that branch. While not mandatory, as output mapping can be achieved with the [Assign ](#assign)node, the End Node adds value by enhancing Flow clarity and inspection.

#### Key Features

* **Flow** **Inspection:** Displays the data associated with the relevant Flow path in the inspector, offering a clear view of the output data and making it easier to debug and verify the Flow's final state.
* **Optional Use:** The End node is optional and is primarily used to provide a clear endpoint for Flow branches. This helps in enhancing organization and readability but does not replace nodes like the [Assign ](#assign)node for output mapping.

The End node is beneficial for Flows that require distinct termination points and a way to easily inspect final data states, ensuring both ease of use and enhanced Flow clarity.

## DecisionRules

### <img src="/files/GLSwkk6x4eJc4DV6s7lY" alt="" data-size="line">  Business Rule <img src="/files/ZMHRcekx2VtxldIJQB1N" alt="" data-size="line">

The **Business Rule** node allows you to connect and execute different types of business rules within your Flow.

With this node, you **statically select** a specific business rule and a particular version of that rule - either a specific version or the latest published version. This node is intended for scenarios where the rule and version are pre-defined and do not change dynamically at runtime.

{% hint style="danger" %}
**Integration Flow cannot be called from a Business Rule node.**

Integration Flows are designed for longer-running asynchronous processes, making them incompatible with the synchronous execution of the Business Rule node, see more [here](/doc/rules/flow/decision-flow-vs.-integration-flow).
{% endhint %}

#### Execution Strategy

The strategy defines how the rule is evaluated and how results are returned. Available strategies depend on the selected rule type. For detailed information see [Execution Strategy](/doc/rules/common-rule-features/execution-strategy).

#### Use Cases

* **Decision Automation:** Ideal for scenarios where complex business logic needs to be automated through Decision Tables or Trees.
* **Batch Processing:** Employ the Standard or Evaluates All strategies to handle multiple results from business rules, enabling batch processing and comprehensive evaluations.

This node is pivotal for integrating complex business logic into your Flows, ensuring that decisions are made based on the latest rules and data.

#### Versions

* <img src="/files/PJNxQQiwRn46E6YljjO2" alt="" data-size="line"> -> <img src="/files/ZMHRcekx2VtxldIJQB1N" alt="" data-size="line">
  * When converting version 1 of Business Rule node that calls a Scripting Rule, it is necessary to update mapping whenever any other node uses outputs from this node, based on how it was referenced:
    1. node.currentItem → change to node.output
    2. node.currentItem.attribute → change to node.output.attribute
    3. node.output - mapping can be kept, however it will no longer contain an array but an object, so its usage has to be adjusted

### <img src="/files/GLSwkk6x4eJc4DV6s7lY" alt="" data-size="line">  Dynamic Business Rule <img src="/files/ZMHRcekx2VtxldIJQB1N" alt="" data-size="line">

The **Dynamic Business Rule** node allows you to **dynamically connect and execute** different types of business rules within your Flow.

Unlike the Business Rule node, both the **rule** and its **version** are selected **at runtime** based on Flow variables, enabling flexible rule execution that adapts to the current context:

* If no version is specified, the **latest published version** of the rule is executed by default.

{% hint style="danger" %}
**Integration Flow cannot be called from a Dynamic** **Business Rule node.**

Integration Flows are designed for longer-running asynchronous processes, making them incompatible with the synchronous execution of the Dynamic Business Rule node, see more [here](/doc/rules/flow/decision-flow-vs.-integration-flow).
{% endhint %}

#### Solving Strategies

The strategy defines how the rule is evaluated and how results are returned. Available strategies depend on the selected rule type. For detailed information see [Execution Strategy](/doc/rules/common-rule-features/execution-strategy).

#### Use Cases

* Dynamically choosing the rule to be executed via the input.
* Triggering a rule for all of the rule aliases retrieved from a Table. This allows you to filter the list of rules based on any conditions you might want to set up without having to use switches in the Flow itself.

This node is pivotal for integrating complex business logic into your Flows, ensuring that decisions are made based on the latest rules and data.

#### Versions

* <img src="/files/PJNxQQiwRn46E6YljjO2" alt="" data-size="line"> -> <img src="/files/ZMHRcekx2VtxldIJQB1N" alt="" data-size="line">
  * When converting version 1 of a Dynamic Business Rule node that does not use latest version of executed rule but the version specified by a mapped attribute, please make sure that such an attribute contains number (in version 1, if the version attribute does not contain a number, latest version is used automatically, while in higher versions such situation causes an error)

### ![](/files/Uu1l0UQMEZZMv7xMLM1l) AI Agent

The **AI Agent** node executes an [AI Agent](/doc/rules/ai-agent) directly within a Flow. It passes input data to a configured AI model and returns structured results that downstream nodes can use.

Unlike the Business Rule node, the AI Agent node has **two output connectors**:

* **Success connector**: follows the path when the model returns a response
* **Error connector**: follows the path when inference fails or the response cannot be parsed

{% hint style="info" %}
It is recommended to handle the error path — for example, use an Assign node to set a fallback value and continue the Flow gracefully.
{% endhint %}

#### **Key Features**

* **Two output connectors**: separate paths for success and failure, giving you full control over how the Flow behaves when the model does not return a valid response
* **Caching**: when enabled in the AI Agent, identical inputs return the cached result without calling the model, reducing latency and cost. See [Caching](/doc/rules/ai-agent/caching)
* **Explainable AI**: when enabled in the AI Agent, each result includes a structured `explanation` object with confidence score, reasoning, source fragments, and warnings. See [Explainable AI](/doc/rules/ai-agent/explainable-ai)

#### **Use Cases**

* **Decision making in a Flow**: pass scored or evaluated output from an AI Agent into a Switch node or Decision Table to drive downstream routing based on the model's recommendation
* **Deep analysis as a pre-processing step**: extract structured fields from documents or records upstream, so the rest of the Flow works with clean, typed data instead of raw text
* **Report generation mid-Flow**: generate a plain-language summary at a specific point in the Flow and pass it to a downstream node for storage, notification, or further processing
* **Policy validation before rule execution**: normalize and validate incoming data with an AI Agent before it reaches a Business Rule node, reducing the chance of mismatches or missing values

## Array Functions

### <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAzJJREFUeF7tmr9rFEEUx79v7/xZxIt3u3ebUkEELYSkUxPRVkEU/4AImkbMf2AaCwsLLQQVFGsRRLSy8Sd2AQstxCI2ye3turmACCK5fXJFIBfumLd5bm4vN9fOm+985/PezNzuDmHIfzTk84cFYCtgyAnYJTDkBWA3QbsE0i6BKFqZaKF1jICxJIGTtn8W8Y6DhBmLBSp8dt3SfJoxUlVAI4rnmDEH5HbpMMA3al7lphSCGEAQ/rwO0F2pcD/jGHzN9yr3JB5EAJrNZunP31adiHZLRPsew/y74LDvuu4vkxcRgHrUPEWcvDGJ5amdGMer1fInkycRgCCMLwN41CnGr5gp1YZjMrPZdiIeB+js+v4Mnva9yhOTpghAI1qeYeb7HWKEmZpbfmgaYCvaNf4sAEmGNIQl+toYjT9bARL6GsISfW2Mxp+tAAl9DWGJvjZG489WgIS+hrBEXxuj8SergEZ8kQnPtEa3sj8xX6hWK89NY4oA1OP4CLXwxSSWp/YC7TjsuiPfTJ5EANoi9TB+R8CkSTAP7Qx89L3ySYkXMYAgWDkAZ/U1QAclwn2LYSzwTue0Pzr6Q+JBDKAtxsx7GlFzFpwcBWGMkY9XYgQkYCyCnK81b/8tycTXYlIBSCM8KLEWwKBkKiuftgKyIjsourYC0mRqqI/BQfojhF2FM7VSaUGSXPESqIfxBwJOSET7HcPAe98rT0l8iAAM4sOQg+Ihz9v33QRBBiCMLxHw1CSWq3bHOV+rjL4weRIB0LxwMBnod7sFIMmArYCcfxuUJLFXjF0CEnpBFF8F40FHbI6+DkfRyvhq0jq33l/RKbyU3BfaFhWg2aMsAMkS0BCW6GtjNP5EFVAP42kCHnca3ZorMuRgaeNNlI1rvtsVGaDTX689QQQgippTLU7eajO1mf4Mnve9ysT6vl0zbhLvsWmLAPTzmlw3AF1PpSwBtLWDMJ4FcMc0zv9uz0UFrE0qiOIrYNwGMPK/J9pLL1cA2iaXmPcWo+XJBDzBTMWsQeRiE8x6klr9zI9BrcGs+1sAiqdV0TGYdQa1+pk/DGkN5rn/tqgADWALQENvO/Qd+gr4B/PgGF/vcb+fAAAAAElFTkSuQmCC" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M216-216v-144 16-4 132Zm-.3 72q-32.7 0-52.2-19.5T144-216v-144q0-33 19.5-52.5T216-432h528q33 0 52.5 19.5T816-360H216v144h396v72H215.7Zm.3-384q-33 0-52.5-19.5T144-600v-144q0-33 19.5-52.5T216-816h528q33 0 52.5 19.5T816-744v144q0 33-19.5 52.5T744-528H216Zm0-72h528v-144H216v144Zm0 0v-144 144ZM744-84v-60h-60v-72h60v-60h72v60h60v72h-60v60h-72Z&#x22;/></svg>" data-size="line">  Append

Array append involves adding elements to an existing array. Unlike merging, where elements are combined from two different arrays, appending adds new elements to the end of an array.

Let's say you have an existing JSON array:

```javascript
// Original Array:

[
    { "id": 1, "name": "John" },
    { "id": 2, "name": "Alice" }
]
```

Now, you want to append a new element to this array:

```javascript
// Element to Append:

{ "id": 3, "name": "Bob" }
```

After appending, the resulting array would be:

```javascript
// Appended Array:

[
    { "id": 1, "name": "John" },
    { "id": 2, "name": "Alice" },
    { "id": 3, "name": "Bob" }
]
```

**In this appended array:**

* The original elements remain unchanged.
* The new element `{ "id": 3, "name": "Bob" }` is added to the end of the array.

### <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAA7hJREFUeF7tWt1OE0EUPme7qMSYwna3bN9Ai/FCTLzTICZGUtREH0HgQh9HE0WfwSigxERDjBdGo5j401dgYbYrjZGfsN1jFoS0dH9mO1sEdno75/eb75ydOR2EjP8w4/mDBEAyIOMIyBLIOAFkE5QlwFMCjK0MuV5jjEc2SAYV/Gwa2mwSfYs5Y+TRUBKdZllVyc0YRt+XOH0uBiwxZ5KIHsUZC10nmDIHCpNJ9K2l2hQgjCfRaZFFmDSNwlScvgQgDiF/XTIg6yVgsdoEEDxuZQvNEmFsk/F1ut0EEf1miZX97QGcTYanxERlAkuUM77OmyCnA9HkePQlAEE9inODJAO6TTEe+6IysgRkCQQc1dPsAYHngD0OLItOklobLOn6J1FKR+lbtn0R3MIP08Q/O3I88YXZTKUJMsZOuYTzQFBWVBwZKBQ+dAMExn5ddr3GHCBUVaRhwzB+hx7V02RAVJOp1+va2ro7Dwjn/GCIaE1VctcNo/9dmiD8S/41Ih7fskvw7VgPXtI0rd71Jhg0D/Dv27qe/2mx2lcEPL03WULlSsnon08DBMu2R8DDN20+CKqlgcJgWHypzQOiklhctu8h4IP24GhDVXLXRJlg2fZVasDs7s43OSKg+6Wi/lAEZK4eEOcgCgTMQcXU9bbdi7Ppr/vJg4evAKCnTR5h3DQKT3nsRMmkAsBWsKx2FwieBDjbBIVGk4IQkTwBwkQayfuxhgJgMadCHl1IgjAC3AGEwSAdBXC0WNTmeOz580Agmg6UJfhOAM947OzIRF3HwwEQncm1R7hJgLdKRc2ndOhvcdkZRaAXAKAmSTJSNmImuZ8A+DG6BHgzDISuJL/9yQwdykoAwqgjPJYWK4HngZ2/05roiAEd/DGBALcB4WxQnIRYKRnaS54c/AYMRDP/tQnyBNosc+Q+g0kAyPRBKBNHYcZWzrte40YzK1QlN63r+arFnAUEONO8RkSroOQqaV6GqAEziNjb6geqZlEbsu16OSg+w+hbiGMy11E47jq8uu6+R4Ty1ieXaK0bM4Gg63DvCXU4n887Xb8OxzlwHCe/4Xpvj+xAxGK1cf801UKn7QvJ7uXHnwo1EMumrn+Mo53IeshILDa+MJ/CJSCSTFq6cQyN8iMB4NkFEYR57IvKiMQnGcCDvgjCPPZFZUTikwzgQV8EYR77ojIi8XExQD6RyfojKflMTjIg409lM/9YWvQzdZD1uT6DBzkB0dgkAKIIHnZ9yYDDvoOi8UsGiCJ42PUzz4C/aG1XbkizXH8AAAAASUVORK5CYII=" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M144-144v-240h72v168h168v72H144Zm432 0v-72h168v-168h72v240H576ZM288-336l-51-51 57-57H96v-72h198l-57-57 51-51 144 144-144 144Zm384 0L528-480l144-144 51 51-57 57h198v72H666l57 57-51 51ZM144-576v-240h240v72H216v168h-72Zm600 0v-168H576v-72h240v240h-72Z&#x22;/></svg>" data-size="line">  Join

Joining two JSON arrays by a key involves combining the arrays based on a common identifier or key within the JSON objects.

Let's say you have two JSON arrays:

```javascript
// Array 1:

[
    {"id": 1, "name": "John"},
    {"id": 2,"name": "Alice"}
]

// Array 2:

[
    {"id": 1, "age": 30},
    {"id": 3, "age": 25}
]
```

You want to join these arrays based on the "id" key. After merging, the resulting array should contain all unique elements from both arrays, with matching elements combined based on the "id" key. If an element exists in one array but not the other, it should still be included in the merged array.

```javascript
// Merged Array:

[
    {"id": 1, "name": "John", "age": 30},
    {"id": 2, "name": "Alice"},
    {"id": 3, "age": 25}
]
```

**In this join array:**

* The object with `id` equal to 1 exists in both arrays, so their properties are joined into one object.
* The object with `id` equal to 2 only exists in the first array, so it's included as is.
* The object with `id` equal to 3 only exists in the second array, so it's included as is.&#x20;

### <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAABOdJREFUeF7tWt9rHFUU/s5kkwq2qTs/dmej9UWrCD4IDZgHteJDRExo0FeRqk3ig6Ci4H8gCloFEU2siNhHBdFSFF/USiDaPulLfatKd3Z+bNMoPjS798iIm+5uJp0zO7PbxJ15veee893vfPfcX0MY8o+GfPzICcgVMOQM5FNgyAWQF8F8CiSdAr7v37WhaEojHFAKWtL+/bDXNCjF+L1AoyuWNX4+SYxECqj59SdY8UcACkmCDMqWGVe0EXqmbOonpTHFBNRq/mNM9JnU8XW1I+2IbRW/kGAQEeC6vFchqAK0V+J0B9isKUu/eYLo7zgsQgLq9ynwmThnO6mdNb63Ypo/xmESEeC4wdMAPux0xqeY6VxcgEG0E/EhgGbaY2ngo6WS+XFcfBEBNa++yMzvdzgjLNqWsRwXYBDtafDlBEgylIZhif+0Nmnw5QqQsO94wTwYnfOdsGBbxgfd/atu8BQxz4GwapfMV7vbPW/9zgZfWZLEjbIhpvN22Vhsb0uCr9unSAHSAI4XvADGW60gzPxJpWw+2R7U89Ymm9z8qVcCGHyuUjInB03AAhidWYtYBaqu/y2BDl8Fx3/aJXN8AASI8EUqSpIJxwtEARy3/g7Az20qAPxdpWQ++H8gQFQDPM/b11T0HohmGVjZU6BFXdd/GwABInw9KyDNMiNRWFqbNPhERTBNgLSDk/RPgy8noN8MS/yntckVkOKwJpoC0o1QmEnXvXy7osYsiFds01zduhP0JhpKW+g166ThYvcpNAm+vu4Ea7Vgmglft4IQ4aWyZRwfmmWw6gZfEfDw5oCZXbtslvtNwI6pAY4bhNmfbiOgZpdNe9cTIJ1jrlt/RIFPbw6Y8KJtGW/3mwApvp53gkkCuO7lg4oaM0z8Q8U0t5z6PG93FsFjYHSe/QnztmWc6LWaZ9kvCIJbNpp4HMyTAN0Dwt0Q4pMug6LTYJaDSuMrCIIDG0T7bV3/Jc6PiIA0VTYOwPVuzwmQZGDoFSBdBcI3xCaCdwk0B8bqnjFtvlgsXpAugwxcogIdtnX9Z0lisrARTQH5lVgQrvnPt4AxcKZSMh6QEkCM6XLZ+CZuYJ63dqihmrPtdgVt5EvLuinxU52UANGVU9UNvifg/qvA+C+7ZO4TEnDCLhnzcYMP26WKlPiSEiBaBh3Xfw2gV9oUcLpSMh6NI4AZ9RvGtNuKxeKaBLRUkRJfUgJECvgvO8egeJZJW6mU9Ne7QUQ9jBDRySSbqoErYKetAlniESkgy4ASWcbZZIknJyCO7ayrriReaON563c00JyItFdqJrxtam9jxpvQtFNR9gWMXLSs8V+j2kQKqLr+UQKFv8e1fdn8IjNWwHHDMNa7wTm1YDk80UkJu6YdY8kuG8/2TEC48Why82wmYLqcjI5g/zYELIHQ8+VpZ65SEhA6q9aCC0S4NWsSlKXfGPU7m1MLdhYBjn/pCJT6PGsCRkdwwDCMP/o8BZa7f6poxRPVgJZxzffnVBPLRGRlRoTGU1HvB45Xn2EV3vBs/aJ+iwO2r0mk0Vnb0iMLZCICWlAcf+0hqMYUM42lJYJG6VPJzU17nIFvhdMOMuv+A98IZT2AtP5yAlI8hnaT31MNSJvBtP1zBQy7Av5dIlm93K4kIu2N7Za6ayluV06BtFOog7gsne1GX0OvgH8Ax2OcbvWqL2cAAAAASUVORK5CYII=" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M684-48v-108H576v-72h108v-108h72v108h108v72H756v108h-72ZM216-216v-528 528Zm.37 72Q186-144 165-165.15 144-186.3 144-216v-528q0-29.7 21.15-50.85Q186.3-816 216-816h528q29.7 0 50.85 21.15Q816-773.7 816-744v333q-17-8-35-12.5t-37-6.5v-314H216v528h266q-2 18-1 36t5 36H216.37Zm107.42-144q15.21 0 25.71-10.29t10.5-25.5q0-15.21-10.29-25.71t-25.5-10.5q-15.21 0-25.71 10.29t-10.5 25.5q0 15.21 10.29 25.71t25.5 10.5Zm0-156q15.21 0 25.71-10.29t10.5-25.5q0-15.21-10.29-25.71t-25.5-10.5q-15.21 0-25.71 10.29t-10.5 25.5q0 15.21 10.29 25.71t25.5 10.5Zm0-156q15.21 0 25.71-10.29t10.5-25.5q0-15.21-10.29-25.71t-25.5-10.5q-15.21 0-25.71 10.29t-10.5 25.5q0 15.21 10.29 25.71t25.5 10.5ZM432-444h240v-72H432v72Zm0-156h240v-72H432v72Zm0 312h68q9-20 21.5-38t27.5-34H432v72Z&#x22;/></svg>" data-size="line">  Collect

The **Collect** node is used to create an object by collecting multiple values and nodes into a single object. This node aggregates data inputs and adds them to a specified target, making it a valuable tool for data consolidation within Flows. **This node is designed to be used at the of the loop only.** &#x20;

#### Key Features

* **Creating Objects:** Allows the inclusion of multiple values from different nodes or direct inputs into a single object.
* **Target Addition:** Adds the collected data to a specified target object, providing an organized way to manage aggregated data.

#### Use Cases

* **Post-Loop Data Consolidation:** Useful for scenarios where data from multiple sources or nodes needs to be combined into one object for further processing.
* **Final Structured Outputs:** Ideal for Flows that require the aggregation of data points into a structured object before applying further operations or transformations.
* **Organizing Final Data:** Helps in organizing and simplifying outputs by combining related data into a single object structure.

This node is essential for Flows that involve combining and organizing data from various sources into a single object, facilitating efficient data handling and processing.

#### Example

If you have several nodes generating different pieces of data, you can use the Collect Outputs node to gather all these pieces into one object `newTarget`

**Input Nodes:**

* **Node A:** Generates value `1` with key `a`
* **Node B:** Generates value `2` with key `b`
* **Node C:** Generates value `3` with key `c`

**Configuration**

* **Select or Create Target:** Choose or create the target object where the collected data will be added.
* **Object Mapping:** Map the attributes from each input node to the corresponding keys in the target object.

**Output**

* `newTarget` will contain `{a: 1, b: 2, c: 3}`. This reflects the newly created or updated object with the collected data in the specified target.

## Data & Integrations

### <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAoVJREFUeF7tV0ty00AQfS2xoIpNsKwfBwj7OAfgAj5GPpUtB4BbBPkcLOAEsEhgDQdAVoRSLLIENyXZEorxjKZcU4QptVayPN3z5vV73RJh5BeN/PwQAkQBI2dALDByAUgTFAuIBUbOgFhg5AKQKSAWEAuMnAGxwMgFIFNALCAWGDkDYoGRC8BsCpTlj9nP1a95TRZ5+JaEwaIlLi+q1+39I+9xFoZP8vr3sryd84pnQwSncdDFL8vqlFd4povR7b8rzid8jKLgnSqnkQVqYGBkdRIGX6fR9LhNuLypuL33yZ+F4cGnhoCiWoBwMkRAEgUdhvzm+xWBtKTp9lcekug8DicN/u3LlIATMJqq6wB48I6i6OnnDQEZCKf/AwFMfJmG04t/SkBRVi9XzI1tAKQEOlzf8h0D1y2YNJq+6NRUVBkTP2+sBhwClG5icga+Ns+ZviRxcLZLgXVxANz9Fc/Ikjg435uAorw9Y+Y3QwrwyT8Ow4PucO2GuniVQu5ZiLHoH7ofs2XBbn/TeFMLdD0A4JyZuiZIhFe7esA9kJoeYkiAsoJ9AmqbMtA0YRDPCXS0Fp1FBeg8/dAKUGLTKGgPBagp6E+BB1GAAhoxXcTx5HLvHrAsq24K6CzQnwJbBCiniMYCf6aIRsJKC2wSe8CHOA7eq/YxUoCLTVBn1f5/QoAJU6IAB98DTAq7eWEaXrrPx1A/qy5e2QR7H1Pk0VUSTt7uWqv6GBs+1XqFUQ8wTebiOiHAxarZxCwKsMmmi7lEAS5WzSZmUYBNNl3MJQpwsWo2MYsCbLLpYi5RgItVs4lZFGCTTRdziQJcrJpNzKIAm2y6mEsU4GLVbGIWBdhk08VcvwGC1eRQFRnijgAAAABJRU5ErkJggg==" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M144-384v-192h48v72h48v-72h48v192h-48v-72h-48v72h-48Zm240 0v-144h-48v-48h144v48h-48v144h-48Zm192 0v-144h-48v-48h144v48h-48v144h-48Zm144 0v-192h120q9.6 0 16.8 7.2 7.2 7.2 7.2 16.8v72q0 9.6-7.2 16.8-7.2 7.2-16.8 7.2h-72v72h-48Zm48-120h48v-24h-48v24Z&#x22;/></svg>" data-size="line">  REST API Client

The **REST API Client** node is used to request data from an external API. This node facilitates communication with external services, making it a valuable tool for integrating third-party data into your Flows.

#### Key Features

* **Request Type:** Supports various HTTP request types such as GET, POST, PUT, DELETE, etc.
* **Enter URL:** Allows the user to specify the URL of the external API endpoint.
* **Connector:** Select an existing connector or create a new one. (Optional)
* **Headers:** Enables the inclusion of custom headers for authentication and other purposes. Headers defined in the Headers section take priority over headers defined via the connector.
* **Body:** Allows the user to define the body of the request.

#### Use Cases

* **Data Retrieval:** Useful for scenarios where data needs to be fetched from external APIs for processing within the Flow.
* **Data Submission:** Ideal for Flows that require sending data to external services.
* **Integration:** Helps in integrating third-party services by facilitating API communication.

This node is essential for Flows that involve requesting data from or sending data to external APIs, facilitating seamless integration with third-party services.

#### Example

If you need to request data from an external API, you can use the REST API Client node to set up and send the request:

**Configuration**

* **Request Type:** Select the type of HTTP request (e.g., GET, POST).
* **Enter URL:** Specify the URL of the API endpoint (e.g., `https://api.example.com/data`).
* **Connector:** Choose a connector to safely provide Authorization headers (optional).
* **Headers:** Add any necessary headers (e.g., `Content-Type: application/json`).
* **Body:** Define the body of the request if needed, with the option to use formats like JSON, plain text, or HTML (e.g., `{ "key1": "value1", "key2": "value2" }` for a JSON POST request).

**Output**

The response from the API will be accessible via the following properties:

* `[node name].data`**:** The main data returned from the API.
* `[node name].status`**:** The HTTP status code of the response.
* `[node name].responseOk`**:** A boolean indicating whether the request was successful (status in the 200-299 range).
* `[node name].responseHeaders`**:** The headers returned by the API response.
* `[node name].state`**:** The state of the request, which can be used for handling different stages of the API call.

### **Relational Database Query Nodes**

The list of supported databases you can find [here](/doc/space/connectors#supported-connectors).

The Relational Database Query nodes allow you to connect to and query SQL databases. They provide functionality to:

* Create or select an existing database connector
* Write SQL queries with dynamic variable support
* Test queries with sample values before execution

**Key Properties**

* **Connector** – Select an existing connector or create a new one to your database.
* **Query** – Input the SQL query to be executed during runtime.
* **Test Query** – Use a sandbox to test your query with sample variable values.
* **Loop Connector** – Iterates over every item returned by the query. The current row is accessible via `[databaseNode].currentRow` during each iteration, allowing direct manipulation of returned data.

**Examples**\
\&#xNAN;*Example 1 – Basic SQL Query*

```sql
SELECT * FROM customers LIMIT 10
```

Retrieves the first 10 records from the `customers` table.

*Example 2 – Query with Variables*

```sql
SELECT * FROM orders 
WHERE customer_id = {input.customerId} 
AND order_date > TO_DATE({input.startDate})
```

Variables in curly braces (`{input.variableName}`) are replaced with actual values at runtime. You can test your query by entering sample values in the **Variables** tab and clicking **Test**.

### **Relational Database Single Row Nodes**

The list of supported databases you can find [here](/doc/space/connectors#supported-connectors).

Single Row database nodes work the same way as their standard counterparts, with one important difference: **only the first row returned by the query is passed forward** in the workflow.

These nodes are useful when you expect a single result (for example, fetching one specific record by ID). Unlike multi-row nodes, they do not loop through multiple results — the returned row is available directly via `{nodeName.row}`.

The rest of the functionality — connectors, queries, variables, and testing — remains identical to the standard Relational Database Query nodes.

## Advanced

### ![](/files/NvPny54EgSN5XfjvYmt6) Debug

The Debug node is used for inspecting data at specific points in a Flow. It allows users to view the output of preceding nodes, helping with troubleshooting and validation during development.

#### Features

* **Data Inspection**: Displays the data from preceding nodes in the inspector, making it easier to debug and understand the flow of information.
* **Development Use Only**: The Debug node is useful for testing and validation but is not recommended for production Flows, as it may slow down solve time.
* **Non-Disruptive**: It does not alter the Flow execution but simply provides visibility into the data being processed.

The Debug node is an essential tool for Flow development, aiding in diagnosing issues and refining logic before deployment. However, for optimal performance, it should be removed or disabled in production environments.

### <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAl9JREFUeF7tl81u00AURr87rikSmyQTuzULxIp9k/Kz4wnCA8CW0gUSKx6AF2DBCgrsEIglbwECAqyRkJBAxPXYoSBUqUB8UVIc3NC4SIwiwtxZWRrbmnv8nbljguODHK8fAkAS4DgBUcDxAMgmKAqIAo4TEAUcD4B0AVFAFHCcgCjgeACkC4gCooDjBEQBxwMwmy5gzFb7ez7oDGGTwoflQN+eBJ8kH1eY8nN5/vuaiHjH9+ie1vq97Q82EwVik10CY2O4eAZ3o7C5Wi4kzrIzGOBxVXHMvL3oq6ONRuOTTQizArAGxuir7wvAZOP5quIU1EoY1l/95wD4CwPdokgCnS2uFVQrDOsv5xFAtQIVivQ2s2tFwQvq8EYQHOnNHYBN019n5lvTFDho3mbBk+/6R/aA/nkw399d3F4FRp0DtEOKby41m49sw7AKoJekzwnUHi2SsLYc6LvDy9hkF8G4My0BzLyYpP3LzNzh4ZOlUd4DfA/HtNbvbEKwDaBLoNZPAOtFv/+biMdJxkXBHnmrQVAbb5A2QNgGUE7AGMBB54Cqg9IEgHYQ1F7YKPxXl7H4trICDH4NoNixIwKd+LNzwBy3wV6SPiXQycoTHfhZFDZPle8p7xFzfRCKk+wGgCuVABjXoyV9dQ+AND2NnJ5UP8fbhxYo0lp/thhauz9DzOzHJrsApuP7LVJBvQnD2kMi+jY5b8xWK8egM+Vn6Cv73oOoXn9rs/jdZuX4EACOB0AUEAVEAccJiAKOB0C6gCggCjhOQBRwPADSBUQBUcBxAqKA4wGQLiAKiAKOE/gBoigTUFwSrkwAAAAASUVORK5CYII=" alt="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; height=&#x22;20px&#x22; viewBox=&#x22;0 -960 960 960&#x22; width=&#x22;20px&#x22; fill=&#x22;#e8eaed&#x22;><path d=&#x22;M312-384q-10 0-17-7t-7-17v-72h48v48h48v-144h48v168q0 10-7 17t-17 7h-96Zm216 0q-10.2 0-17.1-6.9-6.9-6.9-6.9-17.1v-36h48v12h48v-36h-72q-10.2 0-17.1-6.9-6.9-6.9-6.9-17.1v-60q0-10.2 6.9-17.1 6.9-6.9 17.1-6.9h96q10.2 0 17.1 6.9 6.9 6.9 6.9 17.1v36h-48v-12h-48v36h72q10.2 0 17.1 6.9 6.9 6.9 6.9 17.1v60q0 10.2-6.9 17.1-6.9 6.9-17.1 6.9h-96Z&#x22;/></svg>" data-size="line">  Custom Code

The **Custom Code** node is used to execute custom JavaScript code within your Flow. This node provides a flexible way to perform operations or transformations that are not covered by standard nodes.

#### Key Features

* **JavaScript Execution:** Allows you to write and execute custom JavaScript code.
* **Custom Logic:** Enables the implementation of bespoke logic and algorithms tailored to your specific needs.
* **Input Access:** Provides access to inputs from other nodes, allowing for dynamic and context-aware code execution.
* **Output:** Returns the result of the JavaScript code execution, which can be used for further processing in the Flow.

#### Use Cases

* **Custom Transformations:** Ideal for scenarios where standard nodes do not meet your requirements, and custom logic is needed.
* **Data Processing:** Useful for performing complex data manipulations or calculations.
* **Integration:** Helps in integrating with other systems or APIs that require specific JavaScript code execution.

#### Example

If you need to perform a custom calculation or data transformation, you can use the Custom Code node to run JavaScript code:

**Configuration**

* **JavaScript Code:** Write the JavaScript code to be executed. For example, you can perform a calculation or transform input data:

```javascript
// Example JavaScript code

let inputData = items[0].json; // Access input data
let result = inputData.value * 2; // Perform a calculation
return { result: result }; // Return the result
```

## Conclusion

With the new Flow feature, you have access to a variety of nodes that allow you to create powerful, automated processes without needing extensive coding knowledge. Each node type serves a specific purpose, and by combining them, you can easily build Flows tailored to your needs.

Our intuitive interface is designed to make it easy to get started: experiment with different nodes, explore their functionalities, and see how they can simplify your tasks and processes.&#x20;


# Flow Limits

Here we briefly describe the limits connected to Decision Flow and how you can manage them.

On our public cloud, Decision Flow is subjected to a couple of plan-related limits. These limits are described below. In particular, you will learn how to enable Decision Flow for your account and how the number of Decision Flow nodes will be limited.

{% hint style="info" %}
This page applies primarily to public cloud. To find out about Decision Flow limits in on-premise deployments, please contact our Sales team.
{% endhint %}

## Decision Flow Enabler

The most important limit related to Decision Flow is the so-called Decision Flow enabler. This limit determines whether you can use Decision Flow at all. The easiest way to find out abut this is to go to Plans (clicking the account icon in the top right corner and choosing Current plan) -> Account Limits and find the Decision Flow item at the bottom of the table.

<figure><img src="/files/9ROCICgy2356tnRWRjhA" alt=""><figcaption><p>This is how it looks when Decision Flow is enabled</p></figcaption></figure>

Decision Flow is enabled in one of two ways. First, it is enabled in the free trial period. Therefore, if you have registered recently, you will have Decision Flow enabled out of the box. Second, Decision Flow is included by default in some of the plans. In particular, if you have Business plan or higher, you will have Decision Flow enabled free of any additional charge.

## Nodes Limit

The number of Decision Flow nodes is limited in 2 ways.

First, there is a limit on the number of nodes in a single Decision Flow. It is currently set to 150 nodes. This is a merely technical limit, ensuring that the Decision Flow does not exceed the size supported by the platform.

The second way is putting an upper bound on Decision Flow nodes as well. Notably, it works a little differently for new plans and old plans. For the new plans, the number of Decision Flow nodes is limited by the shared Rule/Node limit. This limit can be found in Plans -> Account Limits. It works as follows. Consider all rules (including rule flows) and all Decision Flows in all spaces owned by the account (including organization spaces). For each of the Decision Flows, count all nodes except Business Rules, Start, End and Note. Then add up all the rules (including rule flows) and found Decision Flow nodes. Compare this number to the Rule/Node limit. If the number is smaller then the limit, then you can create more nodes (otherwise not).

For older plans, the mechanism is similar but the role of the Rule/Node limit is here taken by the Rules and Rule Flows limits, in particular their sum. Also, the counting of rules, rule flows and Decision Flow nodes is not done over the whole account, bot over individual spaces.

{% hint style="info" %}
If you need more information on the particular Decision Flow node limit on your account, feel free to contact us through our [support portal](https://support.decisionrules.io/).
{% endhint %}


# AI Agent

## What Is an AI Agent?

An **AI Agent** is a rule type that delegates decision logic to a large language model (LLM). Instead of defining explicit conditions and outcomes — as you would in a Decision Table or Decision Tree — you describe what you want the model to do via a natural language prompt and a structured output schema. The model then reasons over the input and returns a typed, structured JSON response every time the rule is called.

What makes AI Agents different from other rule types is their ability to handle **judgment, language, and ambiguity**. They can read a contract and extract its key terms, evaluate a supplier narrative and produce a risk score, validate a dataset against a policy, or write a plain-language summary of a complex decision, all without a single hard-coded condition.

Each AI Agent is best built around a single, clearly defined task. In practice, the most common patterns are:

* **Decision making:** evaluating input and producing a decision, score, or routing outcome
* **Deep analysis:** reading documents, records, and signals to extract structured intelligence
* **Report writing:** condensing complex input into a concise, decision-ready narrative
* **Policy validation:** checking data against rules and standards; fixing and normalizing non-conforming records

If your use case doesn't fit any of these patterns, you can define the role and task freely from scratch in the prompt.

{% hint style="info" %}
**When not to use an AI Agent:** \
If your logic can be fully expressed as explicit conditions and outcomes, a Decision Table or Decision Tree will be faster, more predictable, and easier to audit. Use an AI Agent when the complexity or ambiguity of the input makes explicit rules impractical.
{% endhint %}

## AI Agent vs. Other Rule Types

<table><thead><tr><th width="147.12890625">Parameters</th><th width="193.74609375">Decision Table</th><th width="192.421875">Decision Tree</th><th>AI Agent</th></tr></thead><tbody><tr><td><strong>Input type</strong></td><td>Structured values</td><td>Structured values</td><td>Structured or unstructured</td></tr><tr><td><strong>Logic definition</strong></td><td>Condition/result rows</td><td>Branching conditions</td><td>Natural language prompt</td></tr><tr><td><strong>Output</strong></td><td>Fixed result values</td><td>Fixed result values</td><td>Typed JSON generated by LLM</td></tr><tr><td><strong>Determinism</strong></td><td>Fully deterministic</td><td>Fully deterministic</td><td>Probabilistic (caching available)</td></tr><tr><td><strong>Auditability</strong></td><td>Full row-level trace</td><td>Full branch trace</td><td>Explainable AI output (optional)</td></tr><tr><td><strong>Best for</strong></td><td>Tabular business rules</td><td>Hierarchical decisions</td><td>Reasoning, scoring, extraction</td></tr></tbody></table>

## What You Will Find in This Section

{% content-ref url="/pages/MlilQLNhoNUiqGjvHFC1" %}
[AI Agent Designer](/doc/rules/ai-agent/ai-agent-designer)
{% endcontent-ref %}

{% content-ref url="/pages/yieN93bDrmLHN3QsTChc" %}
[Caching](/doc/rules/ai-agent/caching)
{% endcontent-ref %}

{% content-ref url="/pages/FWAHDlfDzQkobvtjOZtg" %}
[Explainable AI](/doc/rules/ai-agent/explainable-ai)
{% endcontent-ref %}




---

[Next Page](/doc/llms-full.txt/1)

