# XML Descriptions for Integration Template

When you build a custom CRM or Helpdesk integration for Cloud Voice, you describe it in an XML template. The template declares the connection details the phone system needs, API endpoints, data fields, authentication, and the functional scenarios that drive each integration feature. This page documents every element, attribute, and variable you can use in that template.

## Template conventions

Templates conform to the **XML 1.1** specification. The sections below explain the variable, function, and element syntax you will work with throughout a template.

### Variables

A template can reference variables so that data is resolved dynamically. Each variable is replaced with its actual value when Cloud Voice runs the template.

Variable values come from three places:

- Predefined variables supplied by Cloud Voice.
- Parameter values a user enters while configuring the integration.
- Values extracted from an API response. You pull a value out of the response body with a JSON path, for example:

  ```xml
  <Output Name="UserUniqueId" Path="data.#.id"></Output>
  ```

  To pull the first value that meets a condition:

  ```xml
  <Output Name="BusinessNumber2" Path="identities.#(type==&quot;phone_number&quot;)#|1.value"></Output>
  ```

:::tip
The path expression follows GJSON syntax. See the [GJSON path syntax reference](https://github.com/tidwall/gjson/blob/master/README.md#path-syntax) for the full grammar.
:::

Variables are referenced using Go's [`text/template`](https://pkg.go.dev/text/template) syntax:

| Form | Example |
| --- | --- |
| Standard variable | `{{.varname}}` |
| Conditional variable | `{{ if .varname }} Welcome, member! {{ else }} Please sign up. {{ end }}` |
| Function call on a variable | `{{ Capitalize .varname }}` |

### Functions

Functions transform or format a variable's value inline. The following functions are available.

| Function | Purpose and example |
| --- | --- |
| `TimeFormat` | Formats a timestamp.<br />**Format:** `{{ TimeFormat Timestamp_variable "format_string" "convert_to_UTC" }}`<br />**Example:** `{{ TimeFormat .StartTimeUnix "yyyy-MM-ddTHH:mm:ss.000Zz" "1" }}`. If `.StartTimeUnix` is `1672531199`, the result is `2023-01-01T00:59:59.000Z`. |
| `ToMillis` | Converts a seconds timestamp to milliseconds.<br />**Format:** `{{ ToMillis Timestamp_variable }}`<br />**Example:** `{{ ToMillis .StartTimeUnix }}`. If `.StartTimeUnix` is `1672531199`, the result is `1672531199000`. |
| `Capitalize` | Capitalizes the first letter of a string.<br />**Format:** `{{ Capitalize variable_string }}`<br />**Example:** if the value is `hello world`, the result is `Hello world`. |
| `UrlEncode` | URL-encodes a string (replaces spaces and other reserved characters with percent-escapes so the value is safe inside a URL).<br />**Format:** `{{ UrlEncode .variable }}`<br />**Example:** if the value is `hello world!`, the result is `hello%20world%21`. |
| `ToMinutes` | Converts an `hh:mm:ss` duration to a total number of minutes.<br />**Format:** `{{ ToMinutes duration_variable }}`<br />**Example:** `{{ ToMinutes .ChatDuration }}` (used in the [Chat journal scenario](#chat-journal-scenario)). |
| `TsSecToMilliSec` | Converts a seconds timestamp to a milliseconds timestamp (same result as `ToMillis`).<br />**Format:** `{{ TsSecToMilliSec Timestamp_variable }}`<br />**Example:** `{{ TsSecToMilliSec .EndTimeUnix }}` (used in the [Chat journal scenario](#chat-journal-scenario)). |

### Elements

These are the main building blocks of a template. Together they define how Cloud Voice connects to the third-party system and processes the data each feature needs.

The overall structure looks like this:

```xml
<Information>
  <Scenarios>
    <Scenario Id="1" Type="REST">
      <Parameters>
        <Parameter Name="example" Value="example"></Parameter>
        ...
      </Parameters>
      <Requests>
        <Request Name="ExampleRequest" Method="GET" URL="https://api.example.com/getuser">
          <Outputs>
            <Output Name="ContactId" Path="data.#.id" Type="string"></Output>
            ...
          </Outputs>
        </Request>
      </Requests>
    </Scenario>
  </Scenarios>
</Information>
```

| Element | Description |
| --- | --- |
| `<Information>` | The root element. Its attributes carry the template's basic information and configuration overview (see [Template property](#template-property)), and it holds the `<Scenarios>` child that defines each integration capability. |
| `<Scenarios>` | A collection of `<Scenario>` elements. Each scenario holds children such as `<Parameters>`, `<Requests>`, and `<Outputs>` that describe one functional capability. Cloud Voice loads the configured scenarios and runs the HTTP requests or operations they define. Supported scenarios: [Authentication](#authentication-scenario), [User association](#user-association-scenario), [Automatic contact synchronization](#automatic-contact-synchronization-scenario), [Automatic contact creation](#automatic-contact-creation-scenario), [Automatic ticket creation](#automatic-ticket-creation-scenario-helpdesk-only) (Helpdesk only), [Call journal](#call-journal-scenario), and [Chat journal](#chat-journal-scenario). |
| `<Parameters>` | A collection of parameters tied to a scenario or request, dynamic values or configuration settings needed to run it. Depending on the case, they are passed in the request URL, body, or headers. |
| `<Requests>` | A collection of requests a scenario issues to implement its feature. |
| `<Outputs>` | A list of `<Output>` elements that define which fields to extract from the API response. |

:::note
If the built-in scenarios do not cover a requirement, you can add supplementary configuration by editing the template directly. See [Extended configurations](#extended-configurations).
:::

## Template property

The `<Information>` element's attributes describe the template as a whole.

| Attribute | Description |
| --- | --- |
| `Provider` | Template type. Fixed as `crm` or `helpdesk`. |
| `Name` | Template name. |
| `Key` | Unique identifier for the template. |
| `Logo` | Filename of the logo. |
| `Remark` | A description or note about the template. |
| `Version` | Template version, for example `1.0.0`. |
| `AuthType` | Authentication method: `none`, `basic`, `oauth2`, or `bearertoken`. |
| `MaxConcurrentRequest` | Maximum number of concurrent HTTP requests allowed to the CRM/Helpdesk. |
| `UserAssociation` | Whether user association is enabled. `0` disabled, `1` enabled. |
| `CallJournal` | Whether call journaling is enabled. `0` disabled, `1` enabled. |
| `CreateNewContact` | Whether automatic contact creation is enabled. `0` disabled, `1` enabled. |
| `CreateNewTicket` | Whether automatic ticket creation is enabled. `0` disabled, `1` enabled. |
| `ChatJournal` | Whether chat journaling is enabled. `0` disabled, `1` enabled. |

## Authentication scenario

This scenario defines how Cloud Voice authenticates to the CRM/Helpdesk.

```xml
<Scenario Id="AuthMethod" Type="AUTH">
  <Presets></Presets>
  <Parameters>
    <Parameter Name="AuthMethod" Value="oauth2"></Parameter>
    <Parameter Name="AuthEndPoint" Value="https://api.example.com/oauth/v2/auth?client_id={{.client_id}}"></Parameter>
    <Parameter Name="TokenEndPoint" Value="https://api.example.com/oauth/v2/token?client_id={{.client_id}}&amp;client_secret={{.client_secret}}"></Parameter>
    <Parameter Name="ContentType" Value="application/json"></Parameter>
    <Parameter Name="AdditionalQueryString"></Parameter>
    <Parameter Name="Scope" Value="contacts.read,contacts.write,calls.read,calls.write,user.read,user.write"></Parameter>
    <Parameter Name="CredentialType"></Parameter>
    <Parameter Name="Base64EncodedCredential"></Parameter>
    <Parameter Name="TokenRefreshInterval" Value="25"></Parameter>
    <Parameter Name="TokenRefreshBody" Value="grant_type=refresh_token&amp;refresh_token={{.refresh_token}}"></Parameter>
    <Parameter Name="TokenRefreshEndpointMethod" Value="post"></Parameter>
    <Parameter Name="TokenRefreshEndpoint" Value="https://api.example.com/oauth2/token"></Parameter>
    <Parameter Name="TokenRefreshContentType" Value="application/x-www-form-urlencoded"></Parameter>
    <Parameter Father="CustomFieldList" Name="client_id" Editor="password" Title="Client ID" Value="" IsDelete="0" IsRequired="1"></Parameter>
    <Parameter Father="CustomFieldList" Name="client_secret" Editor="password" Title="Client Secret" Value="" IsDelete="0" IsRequired="1"></Parameter>
    <Parameter Father="CustomFieldList" Name="application_id" Editor="string" Title="Application ID" Value="" IsDelete="0" IsRequired="1"></Parameter>
    <Parameter Father="CustomFieldList" Name="server_address" Editor="string" Title="Server Address" Value="" IsDelete="0" IsRequired="1"></Parameter>
    <Parameter Father="PopulateTemplateString" Name="Content-Type" Type="Header" Value="application/json" Description="The format of the request body"/>
    <Parameter Father="PopulateTemplateString" Name="Accept" Type="Header" Value="application/json" Description="The expected response data format from the server"/>
    <Parameter Father="PopulateTemplateString" Name="X-CSRF-Token" Type="Header" Value="f3e1a2b4c5d6e7f8g9h0" Description="Prevent Cross-Site Request Forgery (CSRF) attacks"/>
    <Parameter Father="PopulateTemplateString" Name="X-Client-Id" Type="Header" Value="{{.client_id}}" Description="for client identification"/>
    <Parameter Father="FollowUpList" Name="ffb425cb-565d-49cd-92be-3290d0ab5129" Type="FollowUpRequest" Value="" IsDelete="0">
      <Parameter Name="TriggeredEvent" Value="token_retrieved"></Parameter>
      <Parameter Name="RequestMethod" Value="post"></Parameter>
      <Parameter Name="Url" Value="https://api.example.com/v1/install/verify"></Parameter>
      <Parameter Name="Headers" Value="{&quot;Content-Type&quot;:&quot;application/json&quot;,&quot;X-Request-ID&quot;:&quot;550e8400-e29b-41d4-a716-446655440000&quot;,&quot;User-Agent&quot;:&quot;YourApp-Integration/1.0.0&quot;}"></Parameter>
      <Parameter Name="Body" Value="{&quot;app_id&quot;:&quot;your_unique_app_identifier&quot;,&quot;webhook_url&quot;:&quot;https://your-app.com/api/webhooks&quot;}"></Parameter>
      <Parameter Name="ResponseFieldPath" Value=".data.access_token, .tokens[0].value"></Parameter>
      <Parameter Name="TargetVariable" Value="token,refresh"></Parameter>
    </Parameter>
    <Parameter Name="AuthMode" Value="pkce"></Parameter>
    <Parameter Name="CodeChallengeMethod" Value="S256"></Parameter>
    <Parameter Name="EnableKeepalive" Value="1"></Parameter>
    <Parameter Name="KeepaliveInterval" Value="5"></Parameter>
  </Parameters>
  <Requests></Requests>
</Scenario>
```

### Scenario element

| Attribute | Description |
| --- | --- |
| `Id` | Scenario identifier. Fixed as `AuthMethod`. |
| `Type` | Scenario type. `AUTH`, the scenario performs authentication. |

### Parameter element

| Attribute | Description |
| --- | --- |
| `Name` | Name of the authentication setting (see [Authentication settings](#authentication-settings)). |
| `Value` | Value of the authentication setting. |
| `Father` | The parent parameter that groups related child parameters. The authentication scenario has three parent types: `CustomFieldList`, `PopulateTemplateString`, and `FollowUpList`. |

The three parent parameters act as containers that organize child parameters into setting groups:

- **`CustomFieldList`**, Defines the fields users fill in with their authentication credentials (Client ID, Client Secret, and so on) in the configuration UI.

  :::note
  Values captured in these custom fields are available to every later request in the template.
  :::

- **`PopulateTemplateString`**, Defines custom HTTP headers to attach to every predefined CRM/Helpdesk request (user association, contact synchronization, and so on).
- **`FollowUpList`**, Defines one or more automated requests that fire after a specific event, such as after a token is retrieved.

#### Parent parameter attributes

**`CustomFieldList`** (authentication credential inputs):

| Attribute | Description |
| --- | --- |
| `Name` | Variable name of the field, usable in the template. For example, `client_id` is referenced as `{{.client_id}}`. |
| `Editor` | Field type: `string` (plain text), `password` (masked input), or `list` (selectable options). |
| `Title` | Label shown above the field in the configuration UI. |
| `Value` | The predefined list of options. Available only when `Editor` is `list`. Separate options with commas, for example `option1,option2`. |
| `IsRequired` | Whether the field is mandatory: `0` optional, `1` required. Available only when `AuthMethod` is `oauth2`. |

**`PopulateTemplateString`** (custom HTTP headers):

| Attribute | Description |
| --- | --- |
| `Type` | Parameter type. Fixed as `Header`. |
| `Name` | Name of the custom header. |
| `Value` | Header value, a literal value or a variable. You can reference an authentication field variable, for example `{{.client_id}}`. |
| `Description` | A short note describing the header's purpose. |

**`FollowUpList`** (follow-up requests):

| Attribute | Description |
| --- | --- |
| `Type` | Parameter type. Fixed as `FollowUpRequest`. |
| `Name` | For the parent parameter, the system generates an ID automatically. For child parameters, the name of the follow-up request setting (see [Follow-up request settings](#follow-up-request-settings)). |
| `Value` | Value of the follow-up request setting. |

### Authentication settings

| Setting | Description |
| --- | --- |
| `AuthMethod` | Authentication method. `none`, no authentication, or only relevant variables (an API key, a webhook URL) are exchanged. `basic`, credentials such as a username/password or API key are base64-encoded and sent in a header on every request. `oauth2`, tokens grant access without sharing credentials; the header and other parameters (such as the access token) are obtained through specific API requests. `bearertoken`, every request carries a header of the form `Authorization: Bearer {{.AccessToken}}`, where `{{.AccessToken}}` is the token granted by the CRM/Helpdesk. |
| `AuthMode` | Authorization mode (OAuth2 only). `authorization_code`, the standard code flow; use it when the CRM/Helpdesk expects a `client_secret`. `pkce`, Authorization Code with PKCE; use it when PKCE is supported, for an extra layer of security. In PKCE mode Cloud Voice generates a `code_verifier`, hashes it with SHA256 and Base64URL-encodes it into a `code_challenge`, sends the challenge upfront, and later presents the original verifier during token exchange. The server hashes the submitted verifier and compares it to the stored challenge; a match proves the client holds the original verifier, which prevents interception attacks. |
| `AuthEndPoint` | Authorization URL to open to start the authorization process (OAuth2 only). |
| `TokenEndPoint` | API URL for obtaining the access token and refresh token (OAuth2 and bearer token only). |
| `ContentType` | Content type of the token retrieval request: `application/json` or `application/x-www-form-urlencoded`. |
| `CodeChallengeMethod` | How the `code_verifier` is transformed into the `code_challenge` (available only when `AuthMode` is `pkce`). `S256`, SHA256 hash + Base64URL encoding (recommended). `plain`, use the verifier directly, for systems that do not support SHA256. |
| `AdditionalQueryString` | Query variables to add when the CRM/Helpdesk authenticates with query parameters instead of a scope (OAuth2 only). |
| `Scope` | The scope of CRM/Helpdesk data Cloud Voice may access (OAuth2 only). |
| `CredentialType` | Credential type (Basic only): `username_password` or `api_key`. |
| `Base64EncodedCredential` | The combination format used to build the basic authentication string (Basic only), for example `{{.username}}:{{.password}}` or `{{.api_key}}`. |
| `TokenRefreshEndpointMethod` | HTTP method for the token refresh API: `get` or `post` (OAuth2 and bearer token only). |
| `TokenRefreshEndpoint` | API URL for refreshing the access token (OAuth2 and bearer token only). |
| `TokenRefreshContentType` | Content type of the refresh request: `application/json`, `application/x-www-form-urlencoded`, or `multipart/form-data` (OAuth2 and bearer token only). |
| `TokenRefreshInterval` | How often the token is refreshed automatically, in minutes (OAuth2 and bearer token only). |
| `TokenRefreshBody` | Request body for the refresh API (OAuth2 and bearer token only). |
| `EnableKeepalive` | Whether to keep the connection alive: `0` disabled, `1` enabled (keep-alive requests are sent at the configured interval). |
| `KeepaliveInterval` | Interval for keep-alive requests, in minutes. |

### Follow-up request settings

| Setting | Description |
| --- | --- |
| `TriggeredEvent` | The event that fires the request. `token_retrieved`, after an access token is retrieved. `token_refreshed`, after an access token is refreshed. |
| `RequestMethod` | HTTP method: `get` or `post`. |
| `Url` | Endpoint URL for the follow-up operation, for example `https://api.example.com/rest-services/login`. |
| `Headers` | Request headers in JSON. Use `{{.varname}}` for dynamic values, for example `{"Content-Type":"application/json", "X-Custom-Header": "{{.DynamicValue}}"}`. |
| `Body` | Request payload in JSON. Use `{{.varname}}` for dynamic values, for example `{"lastName":"{{.LastName}}","ownerId":"{{.Id}}","phone":"{{.BusinessNumber}}"}`. |
| `ResponseFieldPath` | JSON path(s) to extract from the response. Separate multiple paths with commas, for example `.data.access_token, .tokens[0].value`. |
| `TargetVariable` | Names of the system variables that store the extracted values. These can be existing or new custom variables and are stored globally for use across the integration. Separate multiple names with commas, for example `token,refresh`. Values are assigned in the same order as the paths in `ResponseFieldPath`. |

## User association scenario

This scenario retrieves the list of users from the CRM/Helpdesk.

```xml
<Scenario Id="UserAssociation" Type="REST">
  <Parameters></Parameters>
  <Requests>
    <Request Name="UserAssociation" Method="GET" ResponseType="application/json" RequestEncoding="" URLFormat="https://www.api.example.com/v1/users?type=ActiveUsers">
      <Parameters>
        <Parameter Name="PaginationEnabled" Value="0" />
        <Parameter Name="PaginationType" Value="" />
        <Parameter Name="VarPageName" Value="page" />
        <Parameter Name="VarPageValue" Value="1" />
        <Parameter Name="VarPageSizeName" Value="page_size" />
        <Parameter Name="VarPageSizeValue" Value="10" />
        <Parameter Name="VarOffsetName" Value="from" />
        <Parameter Name="VarOffsetValue" Value="1" />
        <Parameter Name="VarLimitName" Value="limit" />
        <Parameter Name="VarLimitValue" Value="10" />
        <Parameter Name="VarNextPagePath" Value="links.next" />
      </Parameters>
      <Outputs>
        <Output Name="UserUniqueId" Path="users.#.id" Type=""></Output>
        <Output Name="FirstName" Path="users.#.First_Name" Type=""></Output>
        <Output Name="LastName" Path="users.#.Last_Name" Type=""></Output>
        <Output Name="Email" Path="users.#.Email" Type=""></Output>
      </Outputs>
    </Request>
  </Requests>
</Scenario>
```

### Scenario element

| Attribute | Description |
| --- | --- |
| `Id` | Scenario identifier. Fixed as `UserAssociation`. |
| `Type` | Scenario type. `REST`, the scenario runs a REST API through an HTTP request. |

### Request element

| Attribute | Description |
| --- | --- |
| `Name` | Request name, used to identify the request within the scenario. Fixed as `UserAssociation`. |
| `Method` | HTTP method. Defaults to `GET`; change it if needed. |
| `ResponseType` | Expected response format, in JSON (`application/json`). |
| `RequestEncoding` | How the request is encoded. Empty in this scenario. |
| `URLFormat` | Request URL of the API endpoint. |

### Parameter element

The `<Parameter>` element sets pagination behavior with a `Name` (a pagination setting) and its `Value`.

| Setting | Description |
| --- | --- |
| `PaginationEnabled` | Whether pagination is enabled: `0` disable, `1` enable. |
| `PaginationType` | Pagination mode. `page_based`, by page number and page size. `offset_based`, by starting index and record limit. `link_based`, by following the next-page URL in the response. |
| `VarPageName` | Parameter name that specifies the page number (page-based only). |
| `VarPageValue` | Initial page number to query from (page-based only). |
| `VarPageSizeName` | Parameter name that specifies records per page (page-based only). |
| `VarPageSizeValue` | Maximum records to return per page (page-based only). |
| `VarOffsetName` | Parameter name that specifies the start position (offset-based only). |
| `VarOffsetValue` | Starting position, as the number of records to skip (offset-based only). For example, `1` starts at the first record; `100` starts at the 100th. |
| `VarLimitName` | Parameter name that specifies records per page (offset-based only). |
| `VarLimitValue` | Maximum records to return per page (offset-based only). |
| `VarNextPagePath` | JSON path (for example `links.next`) to the next-page link (link-based only). |

### Output element

| Attribute | Description |
| --- | --- |
| `Name` | Output variable name, the value to retrieve from the response. |
| `Path` | Location of the field in the response, using path syntax for nested data (for example `users.#.id`). |
| `Type` | Data type of the output variable. Fixed as `string`. |

The scenario retrieves these variables:

| Variable | Description |
| --- | --- |
| `UserUniqueId` | Unique ID of the CRM/Helpdesk user. |
| `FirstName` | User's first name. |
| `LastName` | User's last name. |
| `Email` | User's email. |

## Automatic contact synchronization scenario

This scenario searches for contacts in the CRM/Helpdesk. Its results drive contact search, automatic contact synchronization, and the call pop-up.

```xml
<Scenario Id="SyncContactAuto" Type="REST">
  <Presets></Presets>
  <Parameters>
    <Parameter Name="ContactUrlType" Value="retrieve_from_contact"></Parameter>
    <Parameter Name="URLFormat"></Parameter>
    <Parameter Name="ContactFieldForUri" Value="data.#.contactUrl"></Parameter>
    <Parameter Name="ContactsIdEnable" Value="1"></Parameter>
    <Parameter Name="FirstNameEnable" Value="1"></Parameter>
    <Parameter Name="BusinessNumberEnable" Value="1"></Parameter>
    <Parameter Name="CustomValueEnable" Value="0"></Parameter>
  </Parameters>
  <Requests>
    <Request Name="Contacts" Method="GET" ResponseType="application/json" RequestEncoding="" URLFormat="https://www.api.example.com/v1/Contacts/search?criteria=((Phone:equals:{{.Phone}})or(Home_Phone:equals:{{.Phone}})or(Mobile:equals:{{.Phone}})or(Asst_Phone:equals:{{.Phone}}))">
      <Parameters></Parameters>
      <Outputs>
        <Output Name="ContactsId" Path="data.0.id" Type=""></Output>
        <Output Name="FirstName" Path="data.0.First_Name" Type=""></Output>
        <Output Name="BusinessNumber" Path="data.0.Phone" Type=""></Output>
        ...
        <Output Name="CustomValue" Path="data.0.Owner" Type=""></Output>
      </Outputs>
    </Request>
  </Requests>
</Scenario>
```

### Scenario element

| Attribute | Description |
| --- | --- |
| `Id` | Scenario identifier. Fixed as `SyncContactAuto`. |
| `Type` | Scenario type. `REST`, the scenario runs a REST API through an HTTP request. |

### Parameter element

The `<Parameter>` element carries the scenario's configuration settings as `Name`/`Value` pairs.

| Setting | Description |
| --- | --- |
| `ContactUrlType` | How the contact URL for the call pop-up is obtained. `specify_url_format`, build the URL from a format string with variables. `retrieve_from_contact`, pull the URL directly from a field in the contact search response. |
| `URLFormat` | The expression for the contact URL. You can use variables captured during the [authentication process](#authentication-scenario), plus `ContactSyncType` (contact type, taken from the search request's name), `ContactId`, and `CustomValue` (both retrieved from this scenario's response). For example: `{{.crm_url}}/crm/{{.CustomValue}}/tab/{{Capitalize .ContactSyncType}}/{{.ContactId}}`. If the provided variables are not enough, define extra requests to retrieve what you need (see [Retrieve additional variables for global use](#retrieve-additional-variables-for-global-use)). |
| `ContactFieldForUri` | JSON path to the contact URL field in the response, for example `.data.#.contactUrl`. |
| `ContactsIdEnable` | Whether to retrieve the contact's ID. Set to `1` (required). |
| `FirstNameEnable` | Whether to retrieve the contact's first name. Set to `1` (required). |
| `BusinessNumberEnable` | Whether to retrieve the contact's business phone number: `0` no, `1` yes. At least one phone number is required. |
| `CustomValueEnable` | Whether to enable a custom variable that can be used to build the contact URL: `0` disable, `1` enable. |

The remaining fields are optional retrieval toggles. Each takes `0` (do not retrieve) or `1` (retrieve):

| Setting | Retrieves |
| --- | --- |
| `LastNameEnable` | Contact's last name |
| `CompanyEnable` | Contact's company |
| `EmailEnable` | Contact's email |
| `BusinessNumber2Enable` | Second business phone number |
| `BusinessFaxNumberEnable` | Business fax number |
| `MobileNumberEnable` | Mobile number |
| `MobileNumber2Enable` | Second mobile number |
| `HomeNumberEnable` | Home number |
| `HomeNumber2Enable` | Second home number |
| `HomeFaxNumberEnable` | Home fax number |
| `OtherNumberEnable` | Other number (not business or home) |
| `ZipCodeEnable` | Zip code |
| `StreetEnable` | Street |
| `CityEnable` | City |
| `StateEnable` | State/province |
| `CountryEnable` | Country |
| `RemarkEnable` | Remark |

### Request element

| Attribute | Description |
| --- | --- |
| `Name` | Request name. Set it to the actual name of the contact type being searched in the CRM/Helpdesk; it is exposed as the `ContactSyncType` variable. |
| `Method` | HTTP method. Defaults to `GET`; change it if needed. |
| `ResponseType` | Expected response format, in JSON (`application/json`). |
| `RequestEncoding` | How the request is encoded. Empty in this scenario. |
| `URLFormat` | Request URL of the API endpoint. |

### Output element

Each `<Output>` uses `Name`, `Path`, and `Type` (fixed as `string`), as described under [User association](#output-element).

:::note
The variable values retrieved for a call can be referenced across modules for the entire duration of that call, until it ends.
:::

<a id="contact-variables"></a>

| Variable | Description |
| --- | --- |
| `ContactsId` | **(Required)** Unique ID of the contact. |
| `FirstName` | **(Required)** Contact's first name. |
| `LastName` | Contact's last name. |
| `Company` | Contact's company. |
| `Email` | Contact's email. |
| `BusinessNumber` | Business phone number. At least one phone number is required. |
| `BusinessNumber2` | Second business phone number. |
| `BusinessFaxNumber` | Business fax number. |
| `MobileNumber` | Mobile number. |
| `MobileNumber2` | Second mobile number. |
| `HomeNumber` | Home number. |
| `HomeNumber2` | Second home number. |
| `HomeFaxNumber` | Home fax number. |
| `OtherNumber` | Other phone number. |
| `ZipCode` | Zip code. |
| `Street` | Street. |
| `City` | City. |
| `State` | State or province. |
| `Country` | Country. |
| `Remark` | Remark. |
| `CustomValue` | Custom variable used to build the contact URL. |

## Automatic contact creation scenario

This scenario creates a new contact in the CRM/Helpdesk when a caller's number does not match any existing contact.

```xml
<Scenario Id="CreateNewContact" Type="REST">
  <Parameters></Parameters>
  <Requests>
    <Request Name="Contacts" Method="POST" ResponseType="application/json" RequestEncoding="" URLFormat="https://www.api.example.com/v1/Contacts">
      <Parameters>
        <Parameter Name="Data" Type="Body" Value="{&quot;data&quot;: [{&quot;Last_Name&quot;:&quot;{{.LastName}}&quot;,&quot;First_Name&quot;:&quot;{{.FirstName}}&quot;,&quot;Phone&quot;:&quot;{{.BusinessNumber}}&quot;}]}"></Parameter>
      </Parameters>
      <Outputs></Outputs>
    </Request>
  </Requests>
</Scenario>
```

### Scenario element

| Attribute | Description |
| --- | --- |
| `Id` | Scenario identifier. Fixed as `CreateNewContact`. |
| `Type` | Scenario type. `REST`, the scenario runs a REST API through an HTTP request. |

### Request element

| Attribute | Description |
| --- | --- |
| `Name` | Request name. Set it to the actual name of the contact type to create in the CRM/Helpdesk. |
| `Method` | HTTP method. `POST` in this scenario. |
| `ResponseType` | Expected response format, in JSON (`application/json`). |
| `RequestEncoding` | How the request is encoded. Empty in this scenario. |
| `URLFormat` | Request URL of the API endpoint. |

### Parameter element

The `<Parameter>` nested inside `<Request>` defines the request body.

| Attribute | Description |
| --- | --- |
| `Name` | Parameter name. Fixed as `Data`. |
| `Type` | Parameter type. Fixed as `Body`. |
| `Value` | The parameters passed in the request body, inside a `data` structure. Values can come from Cloud Voice's predefined variables. |

:::note
The value must follow XML parameter rules. For example, to insert a line break, use the escape sequence `&#xA;`.
:::

Only the required variables appear below. For more, see [Retrieve additional variables for global use](#retrieve-additional-variables-for-global-use).

| Variable | Description |
| --- | --- |
| Variables from the `AuthMethod` scenario | Variables captured from the authentication credential inputs during authentication. |
| Target variables from follow-up requests | Values extracted from the responses of follow-up requests. |
| `{{.LastName}}` | Contact's last name. |
| `{{.FirstName}}` | Contact's first name. |
| `{{.BusinessNumber}}` | Contact's phone number. |

## Automatic ticket creation scenario (Helpdesk only)

This scenario creates a new ticket in the Helpdesk.

```xml
<Scenario Id="CreateNewTicket" Type="REST">
  <Presets></Presets>
  <Parameters>
    <Parameter Name="EnableSubject" Value="1"></Parameter>
    <Parameter Name="Subject" Value="{{.Communication_Type}} {{.Call_Status}} - from {{.Call_From}} to {{.Call_To}}"></Parameter>
    <Parameter Name="EnableDescription" Value="1"></Parameter>
    <Parameter Name="Description" Value="{{.Time}} {{.Communication_Type}} {{.Call_Status}} - from {{.Call_From}} to {{.Call_To}} {{.Talk_Duration}}"></Parameter>
  </Parameters>
  <Requests>
    <Request Name="CreateNewTicket" Method="POST" Weight="0" ResponseType="application/json" RequestEncoding="" URLFormat="https://{{.domain}}/api/v1/tickets">
      <Parameters>
        <Parameter Name="Data" Type="Body" Value="{&quot;subject&quot;:&quot;{{.Subject}}&quot;,&quot;contactId&quot;:&quot;{{.ContactId}}&quot;,&quot;phone&quot;:&quot;{{.ContactNumber}}&quot;,&quot;description&quot;:&quot;{{.Description}}&quot;}"></Parameter>
      </Parameters>
      <Outputs></Outputs>
    </Request>
  </Requests>
</Scenario>
```

### Scenario element

| Attribute | Description |
| --- | --- |
| `Id` | Scenario identifier. Fixed as `CreateNewTicket`. |
| `Type` | Scenario type. `REST`, the scenario runs a REST API through an HTTP request. |

### Parameter element

Configuration settings for the scenario, as `Name`/`Value` pairs:

| Setting | Description |
| --- | --- |
| `EnableSubject` | Whether the ticket subject is customizable: `0` disable, `1` enable. |
| `Subject` | Default subject value. Default: `{{.Communication_Type}} {{.Call_Status}} - from {{.Call_From}} to {{.Call_To}}`. See the [variable list](#ticket-variables) for supported variables. |
| `EnableDescription` | Whether the ticket description is customizable: `0` disable, `1` enable. |
| `Description` | Default description value. Default: `{{.Time}} {{.Communication_Type}} {{.Call_Status}} - from {{.Call_From}} to {{.Call_To}} {{.Talk_Duration}}`. See the [variable list](#ticket-variables) for supported variables. |

### Request element

| Attribute | Description |
| --- | --- |
| `Name` | Request name. Fixed as `CreateNewTicket`. |
| `Method` | HTTP method. `POST` in this scenario. |
| `ResponseType` | Expected response format, in JSON (`application/json`). |
| `RequestEncoding` | How the request is encoded. Empty in this scenario. |
| `URLFormat` | Request URL of the API endpoint. |

### Parameter element (request body)

The `<Parameter>` nested inside `<Request>` defines the request body, with `Name` fixed as `Data`, `Type` fixed as `Body`, and `Value` holding the body content built from predefined variables.

:::note
The value must follow XML parameter rules. For example, to insert a line break, use the escape sequence `&#xA;`.
:::

Only the required variables are listed. For more, see [Retrieve additional variables for global use](#retrieve-additional-variables-for-global-use).

<a id="ticket-variables"></a>

| Variable | Description |
| --- | --- |
| Variables from the `AuthMethod` scenario | Variables captured from the authentication credential inputs. |
| Target variables from follow-up requests | Values extracted from follow-up request responses. |
| `{{.Subject}}` | Ticket subject, taken from the `Subject` parameter. |
| `{{.Description}}` | Ticket description, taken from the `Description` parameter. |
| `{{.LinkedId}}` | Unique ID of the call. |
| `{{.Time}}` | Time the call was made or received (in the system's time format). |
| `{{.StartTimeUnix}}` | Unix timestamp of the call start time. |
| `{{.EndTimeUnix}}` | Unix timestamp of the call end time. |
| `{{.Call_From}}` | Name and number of the calling party. Format: `Caller's name <Caller's number>`. |
| `{{.CallerName}}` | Caller's name. |
| `{{.CallerNumber}}` | Caller's number. |
| `{{.CalleeName}}` | Callee's name. |
| `{{.CalleeNumber}}` | Callee's number. |
| `{{.CrmId}}` | Unique ID of the CRM/Helpdesk user associated with a Cloud Voice extension. |
| `{{.ExtensionFirstName}}` | Extension user's first name. |
| `{{.ExtensionLastName}}` | Extension user's last name. |
| `{{.ExtensionEmail}}` | Extension user's email. |
| `{{.ContactSyncType}}` | Contact type. |
| `{{.ContactNumber}}` | Contact's number. |
| `{{.ContactId}}` | Unique ID of a contact. |
| `{{.TicketId}}` | Unique ID of the ticket created from a call. To obtain it, add extra settings (see [Retrieve the ticket ID for further operations](#retrieve-the-ticket-id-for-further-operations)). |
| `{{.CallDuration}}` | Time between the call starting and ending. |
| `{{.Talk_Duration}}` | Time between the call being answered and ending, in `hh:mm:ss`. |
| `{{.Talk_Duration_Sec}}` | Time between the call being answered and ending, in seconds. |
| `{{.Communication_Type}}` | Call direction: `Inbound` or `Outbound`. |
| `{{.Call_Status}}` | Processing status: `Missed` (not answered) or `Completed` (connected and finished). |
| `{{.Call_Log_Status}}` | Call status: `Missed Call`, `Outgoing Call`, `Incoming Call`, or `Voicemail`. |
| `{{.CallDisposition}}` | Call disposition: `MISSED`, `VOICEMAIL`, `BUSY`, `ANSWERED`, or `NO ANSWER`. |

## Call journal scenario

This scenario logs the call activity of associated users to the CRM/Helpdesk.

```xml
<Scenario Id="CallJournal" Type="REST">
  <Presets></Presets>
  <Parameters>
    <Parameter Name="EnableSubject" Value="1"></Parameter>
    <Parameter Name="Subject" Value="Extension Call"></Parameter>
    <Parameter Name="EnableDescription" Value="1"></Parameter>
    <Parameter Name="Description" Value="Call: {{.Time}} {{.Call_Log_Status}} from {{.Call_From}} to {{.Call_To}} {{.Talk_Duration}}"></Parameter>
    <Parameter Name="EnablePlayCallRecording" Value="1"></Parameter>
    <Parameter Name="PlayCallRecording" Value="0"></Parameter>
    <Parameter Name="EnableForwardCallLogForAnsweredAgent" Value="0"></Parameter>
    <Parameter Name="ForwardCallLogForAnsweredAgent" Value="0"></Parameter>
  </Parameters>
  <Requests>
    <Request Name="CallJournal" Method="POST" Weight="0" ResponseType="application/json" RequestEncoding="" URLFormat="https://www.api.example.com/v2/Calls" RefreshTime="" IsDelete="0">
      <Parameters>
        <Parameter Name="Data" Type="Body" Value="{&#xA;  &#34;data&#34;: [&#xA;    {&#xA;      &#34;{{.Owner}}{{.WhoModule}}&#34;: {&#xA;        &#34;Description&#34;: &#34;{{.Description}}&#34;,&#xA;        &#34;Voice_Recording__s&#34;: &#34;{{.RecordPath}}&#34;,&#xA;        &#34;Call_Start_Time&#34;: &#34;{{TimeFormat .StartTimeUnix &#39;yyyy-MM-ddTHH:mm:ss-z&#39; &#39;1&#39;}}&#34;,&#xA;        &#34;Subject&#34;: &#34;{{.Subject}}&#34;,&#xA;        &#34;Call_Type&#34;: &#34;Inbound&#34;,&#xA;        &#34;Call_Result&#34;: &#34;{{.Call_Log_Status}}&#34;,&#xA;        &#34;Call_Duration&#34;: &#34;{{.Talk_Duration_Sec}}&#34;&#xA;      }&#xA;    }&#xA;  ]&#xA;}"></Parameter>
      </Parameters>
      <Outputs></Outputs>
    </Request>
    <Request Name="CallJournalUpdate" Method="PUT" Weight="0" ResponseType="application/json" RequestEncoding="" URLFormat="https://www.api.example.com/v2/Calls/{{.CallId}}" RefreshTime="" IsDelete="0">
      <Parameters>
        <Parameter Name="Data" Type="Body" Value="{&#xA;  &#34;data&#34;: [&#xA;    {&#xA;      &#34;{{.Owner}}{{.WhoModule}}&#34;: {&#xA;        &#34;Description&#34;: &#34;{{.Description}}&#34;,&#xA;        &#34;Voice_Recording__s&#34;: &#34;{{.RecordPath}}&#34;,&#xA;        &#34;Call_Start_Time&#34;: &#34;{{TimeFormat .StartTimeUnix &#39;yyyy-MM-ddTHH:mm:ss-z&#39; &#39;1&#39;}}&#34;,&#xA;        &#34;Subject&#34;: &#34;{{.Subject}}&#34;,&#xA;        &#34;Call_Type&#34;: &#34;Inbound&#34;,&#xA;        &#34;Call_Result&#34;: &#34;{{.Call_Log_Status}}&#34;,&#xA;        &#34;Call_Duration&#34;: &#34;{{.Talk_Duration_Sec}}&#34;,&#xA;        &#34;AI_Transcription&#34;: &#34;{{.AI_Transcription}}&#34;,&#xA;        &#34;AI_Summary&#34;: &#34;{{.AI_Summary}}&#34;,&#xA;        &#34;Call_Note&#34;: &#34;{{.Call_Note}}&#34;&#xA;      }&#xA;    }&#xA;  ]&#xA;}"></Parameter>
      </Parameters>
      <Outputs></Outputs>
    </Request>
  </Requests>
</Scenario>
```

### Scenario element

| Attribute | Description |
| --- | --- |
| `Id` | Scenario identifier. Fixed as `CallJournal`. |
| `Type` | Scenario type. `REST`, the scenario runs a REST API through an HTTP request. |

### Parameter element

Configuration settings for the scenario, as `Name`/`Value` pairs:

| Setting | Description |
| --- | --- |
| `EnableSubject` | Whether the call log subject is configurable in the integration: `0` disable, `1` enable. |
| `Subject` | Default subject value. Default: `Extension Call`. You can also use supported variables (see the [variable list](#call-variables)). |
| `EnableDescription` | Whether the call log description is configurable: `0` disable, `1` enable. |
| `Description` | Default description value. Default: `{{.Time}} {{.Communication_Type}} {{.Call_Status}} - from {{.Call_From}} to {{.Call_To}} {{.Talk_Duration}}`. See the [variable list](#call-variables). |
| `EnablePlayCallRecording` | Whether playing call recordings within the CRM/Helpdesk is configurable: `0` disable, `1` enable. |
| `PlayCallRecording` | Default state of the recording-playback option: `0` disable, `1` enable. |
| `EnableForwardCallLogForAnsweredAgent` | Whether the option to suppress missed-call logs for non-answering agents (on queue or ring group calls) is configurable in the integration. |
| `ForwardCallLogForAnsweredAgent` | Default state of that option. `0` disable. `1` enable, for queue and ring group calls, the log syncs only to the CRM/Helpdesk of the agent who answered, and missed-call logs for the same call are not synced to agents who did not answer. |

### Request element

| Attribute | Description |
| --- | --- |
| `Name` | Request name. `CallJournal` creates a new call log in the CRM/Helpdesk. `CallJournalUpdate` updates an existing call log with additional information. |
| `Method` | HTTP method: `POST` or `PUT`. |
| `ResponseType` | Expected response format, in JSON (`application/json`). |
| `RequestEncoding` | How the request is encoded. Empty in this scenario. |
| `URLFormat` | Request URL of the API endpoint. |

### Parameter element (request body)

The `<Parameter>` nested inside `<Request>` defines the request body, with `Name` fixed as `Data`, `Type` fixed as `Body`, and `Value` holding the body content built from predefined variables.

:::note
The value must follow XML parameter rules. For example, to insert a line break, use the escape sequence `&#xA;`.
:::

<a id="call-variables"></a>

The request body accepts every call variable listed for [Automatic ticket creation](#ticket-variables), plus the following recording and AI fields:

| Variable | Description |
| --- | --- |
| `{{.EnableCallRecording}}` | Whether call recording is enabled: `0` disabled, `1` enabled. |
| `{{.AI_Transcription}}` | AI-generated call transcript. |
| `{{.AI_Summary}}` | AI-generated call summary. |
| `{{.Call_Note}}` | Call note content. |

Only the required variables are documented here. For more, see [Retrieve additional variables for global use](#retrieve-additional-variables-for-global-use).

## Chat journal scenario

This scenario syncs the chat messages exchanged between associated users and contacts to the CRM/Helpdesk.

```xml
<Scenario Id="ChatJournal" Type="REST">
  <Presets></Presets>
  <Parameters>
    <Parameter Name="EnableSubject" Value="1"/>
    <Parameter Name="Subject" Value="PhoneSystem External Chat Session"/>
    <Parameter Name="EnableCreateType" Value="0"/>
    <Parameter Name="CreateType" Value=""/>
  </Parameters>
  <Requests>
    <Request Name="ChatJournalDefault" Method="POST" Weight="0" ResponseType="application/json" RequestEncoding="" URLFormat="https://www.api.example.com/crm/v7/Tasks" RefreshTime="" IsDelete="0">
      <Parameters>
        <Parameter Name="Data" Type="Body" Value="{ &quot;data&quot;: [ { &quot;Owner&quot;: { &quot;id&quot;: &quot;{{.OwnerId}}&quot; }, &quot;Who_Id&quot;: &quot;{{.ContactEntityId}}&quot;, &quot;Subject&quot;: &quot;{{.Subject}}&quot;, &quot;Due_Date&quot;: &quot;{{ TimeFormat .StartTimeUnix &quot;yyyy-MM-dd&quot; &quot;0&quot; }}&quot;, &quot;Closed_Time&quot;: &quot;{{ TimeFormat .EndTimeUnix &quot;yyyy-MM-ddTHH:mm:ss.000Zz&quot; &quot;0&quot; }}&quot;, &quot;Status&quot;: &quot;Completed&quot;, &quot;Priority&quot;: &quot;Normal&quot;, &quot;Description&quot;: &quot;Message Channel Type: {{.Channel_Display}}\n\n{{.Messages}}&quot; } ] }"/>
      </Parameters>
      <Outputs/>
    </Request>
  </Requests>
</Scenario>
```

### Scenario element

| Attribute | Description |
| --- | --- |
| `Id` | Scenario identifier. Fixed as `ChatJournal`. |
| `Type` | Scenario type. `REST`, the scenario runs a REST API through an HTTP request. |

### Parameter element

Configuration settings for the scenario, as `Name`/`Value` pairs:

| Setting | Description |
| --- | --- |
| `EnableSubject` | Whether the subject of the synced record is configurable: `0` disable, `1` enable. |
| `Subject` | Default subject value. Default: `PhoneSystem External Chat Session`. You can also use supported variables (see the [variable list](#chat-variables)). |
| `EnableCreateType` | Reserved field (not applicable). |
| `CreateType` | Reserved field (not applicable). |

### Request element

| Attribute | Description |
| --- | --- |
| `Name` | Request name. Fixed as `ChatJournalDefault`. |
| `Method` | HTTP method: `POST` or `PUT`. |
| `ResponseType` | Expected response format, in JSON (`application/json`). |
| `RequestEncoding` | How the request is encoded. Empty in this scenario. |
| `URLFormat` | Request URL of the API endpoint. |

### Parameter element (request body)

The `<Parameter>` nested inside `<Request>` defines the request body, with `Name` fixed as `Data`, `Type` fixed as `Body`, and `Value` holding the body content built from predefined variables.

:::note
The value must follow XML parameter rules. For example, to insert a line break, use the escape sequence `&#xA;`.
:::

Only the required variables are listed. For more, see [Retrieve additional variables for global use](#retrieve-additional-variables-for-global-use).

<a id="chat-variables"></a>

| Variable | Description |
| --- | --- |
| Variables from the `AuthMethod` scenario | Variables captured from the authentication credential inputs. |
| Target variables from follow-up requests | Values extracted from follow-up request responses. |
| `{{.ContactNumber}}` | Phone number of the CRM/Helpdesk contact. |
| `{{.ContactEmail}}` | Email address of the CRM/Helpdesk contact. |
| `{{.ContactName}}` | Name of the CRM/Helpdesk contact. |
| `{{.ContactEntityId}}` | Entity ID of the matched contact, lead, or account. |
| `{{.ContactEntityType}}` | Type of the matched entity (contact, lead, or account). |
| `{{.QueueName}}` | Name of the message queue, included when the chat is routed to a queue. |
| `{{.Messages}}` | The messages sent and received during the session, including time, senders, and content. |
| `{{.ExtensionNumber}}` | Extension number of the extension or agent who handled the messages or closed the session. If the system closes the session automatically, this is `PBX System`. |
| `{{.ExtensionFirstName}}` | First name of the extension or agent who handled the messages or closed the session. If the system closes it automatically, this is `PBX System`. |
| `{{.ExtensionLastName}}` | Last name of the extension or agent who handled the messages or closed the session. If the system closes it automatically, this is `PBX System`. |
| `{{.ExtensionEmail}}` | Email address of the extension or agent who handled the messages. |
| `{{.ChatDuration}}` | Chat session duration, in `hh:mm:ss`. To convert to total minutes, use `{{ToMinutes .ChatDuration}}`. |
| `{{.StartTimeUnix}}` | Unix timestamp (seconds) of the session start. Format it as a local time string with `{{ TimeFormat .StartTimeUnix "yyyy-MM-ddTHH:mm:ss.000Zz" "0" }}`, as UTC with `"1"` instead of `"0"`, or convert to milliseconds with `{{ToMillis .StartTimeUnix}}`. |
| `{{.EndTimeUnix}}` | Unix timestamp (seconds) of the session end. Format it as a local time string with `{{ TimeFormat .EndTimeUnix "yyyy-MM-ddTHH:mm:ss.000Zz" "0" }}`, as UTC with `"1"` instead of `"0"`, or convert to milliseconds with `{{TsSecToMilliSec .EndTimeUnix}}`. |

## Extended configurations

Beyond the scenarios you set on the configuration page, you can add custom configurations by editing the template directly.

:::note
Custom configurations in the template are preserved and are not overwritten by changes made through the Cloud Voice management portal.
:::

### Set custom request headers

To add custom request headers, add one or more parameters with `Type` set to `Header`. In the example below, an `X-Auth-Token` header carries the API key. `Father` (fixed as `PopulateTemplateString`) groups the related parameters, `Type` (fixed as `Header`) marks the parameter as an HTTP header, and `Name` and `Value` set the header. The request then includes `X-Auth-Token:{{.api_key}}`.

```xml
<Requests>
  <Request Name="contacts" Method="GET" ResponseType="application/json" URLFormat="https://api.example.com/contacts/search?number={{.Phone}}">
    <Parameters>
      <Parameter Father="PopulateTemplateString" Name="X-Auth-Token" Type="Header" Value="{{.api_key}}" />
    </Parameters>
    <Outputs>
      ...
    </Outputs>
  </Request>
</Requests>
```

### Identify token errors

In the `AuthMethod` scenario, add a `TokenInvalid` parameter to help distinguish a token problem from other errors. Set its `Value` to the token-related error code or specific content. If the HTTP status is not `200` and the response body contains that content, the error is recognized as **TokenInvalid**.

```xml
<Scenario Id="AuthMethod" Type="AUTH">
  <Presets />
  <Parameters>
    <Parameter Name="AuthMethod" Value="oauth2" />
    ...
    <Parameter Father="TokenErrorMap" Type="TokenInvalid" Name="TokenInvalid" Value="INVALID_TOKEN" />
    ...
  </Parameters>
  <Requests />
  <Responses />
</Scenario>
```

### Retrieve additional variables for global use

If you need variables beyond the built-in ones, for example common information you want to reuse globally, define a `GetGlobalInfo` scenario with the requests that retrieve those values.

When the integration completes or Cloud Voice starts, the requests inside `GetGlobalInfo` are sent to the CRM/Helpdesk and the values are stored in the `Output` elements. Each output's name maps directly to a variable name, making it available in other scenarios (except the authentication scenario). In the example below, `GetGlobalInfo` retrieves `DepartmentId` and `PortalName`.

```xml
<Scenario Id="GetGlobalInfo" Type="REST">
  <Presets />
  <Parameters />
  <Requests>
    <Request Name="GetDepartments" Method="GET" ResponseType="application/json" URLFormat="https://desk.example.{{.domain_suffix}}/api/v1/departments">
      <Parameters />
      <Outputs>
        <Output Name="DepartmentId" Path="data.#.id" />
      </Outputs>
    </Request>
    <Request Name="GetOrganizations" Method="GET" ResponseType="application/json" URLFormat="https://desk.example.{{.domain_suffix}}/api/v1/organizations">
      <Parameters />
      <Outputs>
        <Output Name="PortalName" Path="data.#(portalName!=&quot;&quot;).portalName" />
      </Outputs>
    </Request>
  </Requests>
</Scenario>
```

### Supplement contact query information

If the first contact query does not return everything you need, run a further query using the returned contact ID or other fields. In the example below, the initial contact-sync query does not return the phone numbers:

```xml
<Scenario Id="SyncContactAuto" Type="REST">
  <Presets />
  <Parameters>
    <Parameter Name="ContactUrlType" Value="specify_url_format" />
    ...
  </Parameters>
  <Requests>
    <Request Name="contacts" Method="GET" ResponseType="application/json" URLFormat="https://{{.subdomain}}.example.com/api/v2/users?query=phone:{{UrlEncode .Phone}}&amp;role[]=end-user">
      <Parameters />
      <Outputs Next="GetIdentities">
        <Output Name="ContactsId" Path="users.#.id" />
        <Output Name="FirstName" Path="users.#.name" />
        <Output Name="BusinessNumber" Path="users.#.phone" />
        ...
        <!-- The following phone number fields return empty. -->
        <Output Name="BusinessNumber2" Path=""></Output>
        <Output Name="BusinessFaxNumber" Path=""></Output>
        <Output Name="MobileNumber" Path=""></Output>
        <Output Name="MobileNumber2" Path=""></Output>
        <Output Name="HomeNumber" Path=""></Output>
        <Output Name="HomeNumber2" Path=""></Output>
        ...
      </Outputs>
    </Request>
  </Requests>
</Scenario>
```

To retrieve the missing numbers, chain scenarios:

1. **Add a `Next` attribute to the original scenario.** In the contact-sync scenario, add a `Next` attribute to the `<Outputs>` element of the initial query request. Its value is the name of the request you will define in the `Common` scenario, here, `GetIdentities`.

   ```xml
   <Outputs Next="GetIdentities">
   ```

2. **Create a `Common` scenario.** Create a scenario named `Common` with type `REST` (both are fixed), then add a request named `GetIdentities` that queries the extra contact information using `{{.ContactsId}}` from the initial request.

   ```xml
   <Scenario Id="Common" Type="REST">
     <Presets></Presets>
     <Parameters></Parameters>
     <Requests>
       <Request Name="GetIdentities" Method="GET" URLFormat="https://{{.subdomain}}.example.com/api/v2/users/{{.ContactsId}}/identities" ResponseType="application/json">
         <Parameters></Parameters>
         <Outputs>
           <Output Name="BusinessNumber2" Path="identities.#(type==&quot;phone_number&quot;)#|1.value"></Output>
           <Output Name="BusinessFaxNumber" Path="identities.#(type==&quot;phone_number&quot;)#|2.value"></Output>
           <Output Name="MobileNumber" Path="identities.#(type==&quot;phone_number&quot;)#|3.value"></Output>
           <Output Name="MobileNumber2" Path="identities.#(type==&quot;phone_number&quot;)#|4.value"></Output>
           <Output Name="HomeNumber" Path="identities.#(type==&quot;phone_number&quot;)#|5.value"></Output>
           <Output Name="HomeNumber2" Path="identities.#(type==&quot;phone_number&quot;)#|6.value"></Output>
           <Output Name="HomeFaxNumber" Path="identities.#(type==&quot;phone_number&quot;)#|7.value"></Output>
           <Output Name="OtherNumber" Path="identities.#(type==&quot;phone_number&quot;)#|8.value"></Output>
         </Outputs>
       </Request>
     </Requests>
   </Scenario>
   ```

   Because the request is referenced through the `Next` attribute of the original scenario, the variable from the initial query is passed to it. The request runs and backfills its `Outputs` into the initial response to complete the record.

### Retrieve the ticket ID for further operations

In a Helpdesk template, you can retrieve the ticket ID for later operations, such as updating the ticket or referencing it in the call journal. For example, when a ticket is created before the call (when the phone rings), it may be missing information you can fill in later using its `TicketId`.

```xml
<Scenario Id="CreateNewTicket" Type="REST">
  <Presets />
  <Parameters>
    <Parameter Name="EnableSubject" Value="1" />
    ...
    <Parameter Name="NeedSyncContact" Value="1" />
  </Parameters>
  <Requests>
    <Request Name="CreateNewTicket" Method="POST" ResponseType="application/json" URLFormat="https://{{.domain}}/api/v1/tickets">
      <Parameters>
        <Parameter Name="Data" Type="Body" Value="{&quot;departmentId&quot;:&quot;{{.DepartmentId}}&quot;,&quot;subject&quot;:&quot;{{.Subject}}&quot;,&quot;contactId&quot;:&quot;{{.ContactId}}&quot;,&quot;phone&quot;:&quot;{{.ContactNumber}}&quot;,&quot;description&quot;:&quot;{{.Description}}&quot;}" />
      </Parameters>
      <Outputs>
        <Output Name="TicketId" Path="id" />
      </Outputs>
    </Request>
    <Request Name="UpdateTicket" Method="POST" ResponseType="application/json" URLFormat="https://{{.domain}}/api/v1/tickets/{{.TicketId}}/comments">
      <Parameters>
        <Parameter Name="Data" Type="Body" Value="{&quot;isPublic&quot;:&quot;true&quot;,&quot;content&quot;:&quot;{{.Description}}&quot;}" />
      </Parameters>
      <Outputs />
    </Request>
  </Requests>
</Scenario>
```

1. **Retrieve the ticket ID.** In the `CreateNewTicket` scenario, add an `<Output>` element to extract the ID from the `CreateNewTicket` request's response. This stores the `TicketId` for later use.

   ```xml
   <Outputs>
     <Output Name="TicketId" Path="id" />
   </Outputs>
   ```

2. **Update the ticket.** Add a request that updates the ticket in the corresponding call record using the retrieved ID. The ticket is then completed with all necessary data after its initial creation.

   ```xml
   <Request Name="UpdateTicket" Method="POST" ResponseType="application/json" URLFormat="https://{{.domain}}/api/v1/tickets/{{.TicketId}}/comments">
     <Parameters>
       <Parameter Name="Data" Type="Body" Value="{&quot;isPublic&quot;:&quot;true&quot;,&quot;content&quot;:&quot;{{.Description}}&quot;}" />
     </Parameters>
     <Outputs />
   </Request>
   ```
