# Forms configuration

## Form model

#### Form DTO fields:

* `id` - \[string] uuid of form
* `orgId` - \[string] uuid of organization
* `locale` - \[string] locale which the form was created for
* `availableForAgents` - \[boolean] determines whether agents can access and send the form
* `name` - \[string] name of the form
* `config` - \[object] configuration of the form's inputs (see input types below)
* `expireInterval` - (optional)\[number] - milliseconds after which the form can no longer be submitted
* `sendInterval` - (optional)\[number] - milliseconds after which the form can be sent again
* `blockIfPreviousUnsubmitted` - \[boolean] - determines whether the form can be sent if previous has not been submitted yet
* `routeOnSubmit` - \[boolean] - determines whether submitting the form should result in opening and assignment of the conversation
* `tagGroupIds` - list\[string] - list of tag group's uuids. Form will be available only in rooms with one of the given `tagGroupIds`. Form with empty `tagGroupIds` is available in any room

## Inputs form

{% hint style="info" %}
Use this form to collect information
{% endhint %}

#### Config (inputs) fields:

* `radioButtonsInputs` - array of objects representing radio buttons input
* `multipleButtonsInputs` - array of objects representing multiple buttons input
* `radioListInputs` - array of objects representing radio list input
* `checkboxListInputs` - array of objects representing checkbox list input
* `textInputs` - array of objects representing text input

### **Buttons (multiple choice)**

`multipleButtonsInputs`

![Mulitple buttons input](/files/lHZEfIyRTCUt98nbVDgh)

<details>

<summary>Click here to see the code</summary>

The input above is represented by the following object:

```json
{
    "index": 0,
    "name": "conversation_expectation",
    "displayName": "I expect the conversation to be:",
    "buttons": [
        {
            "value": "quick",
            "displayName": "Quick"
        },
        {
            "value": "nice",
            "displayName": "Nice & kind"
        },
        {
            "value": "helpful",
            "displayName": "Helpful"
        }
    ]
}
```

</details>

### Buttons (single choice)

`radioButtonsInputs`

![Radio buttons input](/files/kysNpRI7YUWtydJEjUA1)

<details>

<summary>Click here to see the code</summary>

The input above is represented by the following object:

```
{
    "index": 1,
    "name": "device_type",
    "displayName": "I have a problem with my:",
    "buttons": [
        {
            "value": "phone",
            "displayName": "Phone"
        },
        {
            "value": "laptop",
            "displayName": "Laptop"
        },
        {
            "value": "elbow",
            "displayName": "Elbow"
        }
    ]
}
```

</details>

### Radio input with list of options (single choice)

`radioListInputs`

![Radio list input](/files/nUXjNEl6fxr50veLvxSO)

<details>

<summary>Click here to see the code</summary>

The input above is represented by the following object:

```
{
    "index": 2,
    "name": "timeline",
    "displayName": "I have been a customer for:",
    "options": [
        {
            "value": "under_six_months",
            "displayName": "<= 6 months"
        },
        {
            "value": "six_months_to_two_years",
            "displayName": "<= 2 years"
        },
        {
            "value": "longer",
            "displayName": "> 2 years"
        }
    ]
}
```

</details>

### Input with list of options (multiple choice)

`checkboxListInputs`

![Checkbox list input](/files/gUicNn7Ghj9cDYwT1duK)

<details>

<summary>Click here to see the code</summary>

The input above is represented by the following object:

```
{
    "index": 3,
    "name": "favorite_colors",
    "displayName": "Colors I like:",
    "options": [
        {
            "value": "white",
            "displayName": "White"
        },
        {
            "value": "black",
            "displayName": "Black"
        },
        {
            "value": "yellow",
            "displayName": "Yellow"
        }
    ]
}
```

</details>

### Text input

`textInputs`

![Text input](/files/HmaEPEoAW2qDekQucBmj)

<details>

<summary>Click here to see the code</summary>

The input above is represented by the following object:

```
{
    "index": 4,
    "name": "language_name",
    "displayName": "The best programming language is:",
    "placeholder": "Type language name here..."
}
```

</details>

### Full example

Inputs order in the form is determined by \`index\` property of representing object

<details>

<summary>Click here to see form with inputs represented above</summary>

```
{
    "id": "0b05797b-a15b-42a5-96ec-XXXXXXXXXXXX",
    "orgId": "95a25389-5b2f-4b43-a311-XXXXXXXXXXXX",
    "locale": "en",
    "config": {
        "radioButtonsInputs": [
            {
                "index": 1,
                "name": "device_type",
                "displayName": "I have a problem with my:",
                "buttons": [
                    {
                        "value": "phone",
                        "displayName": "Phone"
                    },
                    {
                        "value": "laptop",
                        "displayName": "Laptop"
                    },
                    {
                        "value": "elbow",
                        "displayName": "Elbow"
                    }
                ]
            }
        ],
        "multipleButtonsInputs": [
            {
                "index": 0,
                "name": "conversation_expectation",
                "displayName": "I expect the conversation to be:",
                "buttons": [
                    {
                        "value": "quick",
                        "displayName": "Quick"
                    },
                    {
                        "value": "nice",
                        "displayName": "Nice & kind"
                    },
                    {
                        "value": "helpful",
                        "displayName": "Helpful"
                    }
                ]
            }
        ],
        "radioListInputs": [
            {
                "index": 2,
                "name": "timeline",
                "displayName": "I have been a customer for:",
                "options": [
                    {
                        "value": "under_six_months",
                        "displayName": "<= 6 months"
                    },
                    {
                        "value": "six_months_to_two_years",
                        "displayName": "<= 2 years"
                    },
                    {
                        "value": "longer",
                        "displayName": "> 2 years"
                    }
                ]
            }
        ],
        "checkboxListInputs": [
            {
                "index": 3,
                "name": "favorite_colors",
                "displayName": "Colors I like:",
                "options": [
                    {
                        "value": "white",
                        "displayName": "White"
                    },
                    {
                        "value": "black",
                        "displayName": "Black"
                    },
                    {
                        "value": "yellow",
                        "displayName": "Yellow"
                    }
                ]
            }
        ],
        "textInputs": [
            {
                "index": 4,
                "name": "name",
                "displayName": "The best programming language is:",
                "placeholder": "Type language name here..."
            }
        ]
    },
    "availableForAgents": true,
    "name": "Problem questionaire",
    "expireInterval": 60000,
    "sendInterval": 10000,
    "blockIfPreviousUnsubmitted": true,
    "routeOnSubmit": false
}
```

</details>

## Auto assign form

{% hint style="info" %}
Use this form to route clients' conversations based on their choice
{% endhint %}

![Auto assign form](/files/HlNXC6231txECLJXFfQu)

<details>

<summary>Click here to see form configuration</summary>

The form above is represented by the following object:

```
{
    "id": "2909d885-d34c-49b9-8e8e-XXXXXXXXXXXX",
    "orgId": "d90482fe-17bf-48d5-aa75-XXXXXXXXXXXX",
    "locale": "en",
    "config": {
        "type": "auto_assign_form",
        "tagGroups": [
            {
                "tagGroupId": "23b133fa-f2d1-4140-bddc-XXXXXXXXXXXX",
                "displayName": "First tag group"
            },
            {
                "tagGroupId": "c0f47b47-8269-4002-9734-XXXXXXXXXXXX",
                "displayName": "Second tag group"
            },
            {
                "tagGroupId": "c972191f-ddea-40df-bbbe-XXXXXXXXXXXX",
                "displayName": "Third tag group"
            }
        ]
    },
    "availableForAgents": true,
    "name": "assignment_form",
}
```

</details>

## &#x20;Predefined message form

Predefined message is a  form to send simple text without any inputs as a adviser message. Form configuration accepts the only property `` message` ``. Such form could be used to send links and messages with additional conversation data:

* {{roomId}} - conversation room id

![Predefined meesage](/files/uUDdp40NNwPg41cE9255)

<details>

<summary>Click here to see form configuration</summary>

The form above is represented by the following object:

```
{
    "id": "b5cb64ec-9d85-4fe1-8df7-c8a4b8131b2d",
    "orgId": "95a25389-5b2f-4b43-a311-7625f73da813",
    "locale": "pl",
    "config": {
        "type": "predefined_message_form",
        "message": "Simple predefined message with in room id = {{roomId}}"
    },
    "availableForAgents": true,
    "name": "Simple message",
    "routeOnSubmit": false
}
```

</details>

## API

#### Create

**`POST - /api/message-widgets`**

* Creates new form
* Requires apiKey header of an adviser with `settings_action_forms` permission
* Requires body with following fields:
  * required: `locale`, `name`, `availableForAgents`, `config` (described above), `blockIfPreviousUnsubmitted`, `routeOnSubmit`
  * optional: `expireInterval`, `sendInterval`

<details>

<summary>Click here to see an example</summary>

```
Example
curl --location --request POST 'https://spinner.closer.app/api/message-widgets' \
--header 'x-api-key: your-api-key-here' \
--header 'Content-Type: application/json' \
--data-raw '{
    "locale": "en",
    "name": "a_problem_questionaire",
    "availableForAgents": true,
    "config": {
        "textInputs": [
            {
                "index": 0,
                "name": "best_language",
                "displayName": "The best programming language is:",
                "placeholder": "Type language name here..."
            }
        ]
    },
    "blockIfPreviousUnsubmitted": true,
    "routeOnSubmit": true
}'
```

</details>

#### Update

**`PUT - /api/message-widgets/{messageWidgetId}`**

* Updates existing form
* Requires apiKey header of an adviser with `settings_action_forms` permission
* Requires body with the same schema as POST request, but without `locale`

<details>

<summary>Click here to see an example</summary>

```
Example
curl --location --request PUT 'https://spinner.closer.app/api/message-widgets/d7f68940-e47f-4cd3-bc99-79e112749559' \
--header 'x-api-key: your-api-key-here' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "a_problem_questionaire",
    "availableForAgents": false,
    "config": {
        "textInputs": [
            {
                "index": 0,
                "name": "best_language",
                "displayName": "The best programming language is:",
                "placeholder": "Type language name here..."
            }
        ]
    },
    "blockIfPreviousUnsubmitted": true,
    "routeOnSubmit": true
}'
```

</details>

#### Read

**`GET - /api/message-widgets?locale={locale}`**

* Gets all created forms' DTOs
* Requires apiKey of organization's adviser

<details>

<summary>Click here to see an example</summary>

```
Example
curl --location --request GET 'https://spinner.stage.closer.app/api/message-widgets?locale=en' \
--header 'x-api-key: your-api-key-here'
```

</details>

**`GET - /api/message-widgets/{messageWidgetId}?orgId={orgId}`**

* Gets single form DTO
* Does not require authentication

<details>

<summary>Click here to see an example</summary>

```
Example
curl --location --request GET 'https://spinner.closer.app/api/message-widgets/0b05797b-a15b-42a5-96ec-fd821456c69e?orgId=95a25389-5b2f-4b43-a311-7625f73da813
```

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://support.closer.app/guide/getting-deeper/forms-configuration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
