Add a CRM Integration Template
When the CRM you want to connect isn’t already available as a ready-made integration, you can define your own. A custom integration template describes how Cloud Voice authenticates with the CRM and which API requests it sends, letting the two systems exchange and synchronize data. This page walks through creating a template and filling in the settings your CRM requires.
Requirements
Section titled “Requirements”- Cloud Voice server
- Firmware: version 84.23.0.123 or later.
- Plan: Enterprise Plan (EP) or Ultimate Plan (UP).
- CRM: exposes a REST API.
You can add up to 10 custom CRM integration templates.
Before you start
Section titled “Before you start”- You are comfortable with basic coding and JSON.
- You have your CRM’s REST API documentation on hand and have gathered the following.
Authentication details
Identify the authentication method the CRM uses. Cloud Voice supports None, Basic, OAuth2, and Bearer Token. If the CRM uses OAuth2 or Bearer Token, collect these endpoints and their data specifications:
| Endpoint | Purpose |
|---|---|
| Authorization | The URL users are redirected to for sign-in and consent. |
| Get access token | The API request that returns an access token. |
| Refresh access token | Optional. The API request that returns a refresh token. |
API request details
Based on what the CRM can do and what you need, collect the request URLs and data specifications for the functions you plan to use:
| Function | Purpose |
|---|---|
| Search contacts | Request URLs that look up contacts in the CRM by specific criteria. |
| Get users | Optional. The request that returns the CRM’s user list. |
| Create contacts | Optional. The request that adds a new contact to the CRM. |
| Call journaling | Optional. The request that creates and/or updates call records in the CRM. |
| Chat journaling | Optional. The request that creates an object (such as a task) to hold synced chat data. |
Create the template
Section titled “Create the template”-
Sign in to the Cloud Voice web portal and open Integrations > CRM.
-
In the CRM list, click Custom. You are taken to the Template Management page.

-
Click Add.
-
In the pop-up, complete the template settings your CRM and use case call for. The sections that follow describe each area, in the order you’ll typically work through them:
- General settings
- User association (optional)
- Authentication method
- Request headers (optional)
- Follow-up requests (optional)
- Connection keepalive (optional)
- Contact search, synchronization, and call pop-up
- New contact creation (optional)
- Call journaling (optional)
- Chat journaling (optional)
-
Click Save to generate the template.
General settings
Section titled “General settings”In the General section, fill in the template basics.

- Logo: Upload an image for the CRM. It appears next to the CRM in the list on the Integrations page.
- CRM Name: The name of the CRM.
- Max Concurrent Request: The most simultaneous HTTP requests Cloud Voice may send to the CRM.
- Remark: Optional. A description shown on the Template Management page.
User association (optional)
Section titled “User association (optional)”In the User Association section, turn on and configure the ability to link CRM users to Cloud Voice extensions.

-
Turn on User Association.

-
In the Get User field, enter the CRM request URL that returns the list of CRM users.

For example:
https://www.api.example.com/v1/users?type=ActiveUsers -
In the Pagination Type list, choose the mode that matches your CRM. For modes that make repeated requests, a single sync runs at most 100 requests.
-
Disabled: Cloud Voice sends a single request with no pagination parameters. Use this when the API returns every record in one response or doesn’t paginate.
-
Page Number Pagination: Cloud Voice sends repeated requests based on page number and page size, incrementing the page number each time until all data is retrieved. Configure:

- Page Parameter Name: The parameter that carries the page number.
- Page Start Value: The first page number to request.
- Page Size Parameter Name: The parameter that sets records per page.
- Page Size Value: The maximum records returned per page.
-
Offset Pagination: Cloud Voice sends repeated requests based on a starting offset and a record limit, raising the offset by the limit each time until all data is retrieved. Configure:

- Offset Parameter Name: The parameter that sets the starting offset.
- Offset Value: Where retrieval begins.
1starts at the first record;100starts at the 100th. - Limit Parameter Name: The parameter that sets records per page.
- Limit Value: The maximum records returned per page.
-
Link Pagination: Cloud Voice follows the “next page” URL in each response until no more pages remain. In Next Page Link Path, enter the JSON path to that URL, for example
links.next.
-
-
In User Field Mapping, map the CRM’s response fields to the Cloud Voice fields by entering a JSON path (for example,
data.#(key=="value").field) for each.
Cloud Voice field Description User Unique ID The user’s unique ID, for example users.#.id.First Name The user’s first name, shown in the CRM user list, for example users.#.First_Name.Last Name The user’s last name, shown in the CRM user list, for example users.#.Last_Name.Email The user’s email, shown in the CRM user list and usable to match CRM users to extensions automatically, for example users.#.Email.
Set the authentication method
Section titled “Set the authentication method”In Request Configuration > Authentication Method, pick the method your CRM expects: None, Basic, OAuth2, or Bearer Token.
Several methods let you add custom fields that appear as inputs on the integration page, so whoever activates the integration can supply the details it needs. Values that users type into these fields are stored as global variables and can be referenced anywhere in the template. Each custom field has the following settings:
| Setting | Description |
|---|---|
| Type | The field type: Text Input for plain text, Password Input for masked sensitive values, or Dropdown List to choose from preset options. |
| Name | The variable name used to reference the field elsewhere in the template. |
| Title | The label shown above the input. |
| Dropdown Options | For a Dropdown List, the available options, separated by commas (for example, option1,option2). |
Use this when the CRM needs no authentication, or only needs certain values for the integration such as an API key or a webhook URL for real-time delivery.

- In the Authentication Method list, select None.
- Optionally, click Add to create custom fields for the details users must provide.
Every request to the CRM carries an Authorization: Basic {{.basic_string}} header, where {{.basic_string}} is the Base64-encoded username and password or API key supplied during setup.

- In the Authentication Method list, select Basic.
- In the Credential Type list, select Username and Password or API Key, matching what the CRM requires.
- Set up the fields users fill in for their credentials, and add custom fields if needed (up to 5 fields total).
- In Base64 Encoded Credential, define how the credential variables combine to build the
basic_string, for example{{.username}}:{{.password}}or{{.api_key}}.
OAuth2
Section titled “OAuth2”This method uses tokens to grant access without sharing credentials, obtaining the token and related values through specific requests to the CRM. Both the Standard Authorization Code flow and the Authorization Code with PKCE (Proof Key for Code Exchange) flow are supported.
-
Set the method and authorization mode.

-
In the Authentication Method list, select OAuth2.
-
In the Authorization Mode list, choose a mode:
Mode Description Standard Authorization Code Requires a client_secret. Use it when the CRM expects aclient_secret.Authorization Code (PKCE) Makes client_secretoptional and adds a layer of security. Cloud Voice generates acode_verifier, derives acode_challengefrom it (SHA256 hashed and Base64URL encoded), and sends the challenge upfront. It keeps thecode_verifierand presents it during token exchange; the server re-derives the challenge and compares. A match proves the same client is exchanging the code, which blocks interception attacks.
-
-
Set up the fields users fill in for their credentials.

-
Configure the OAuth2 authorization settings.

Setting Description Authorization Endpoint The CRM authorization URL users are redirected to during setup, for example https://www.api.example.com/auth/v2/authorize?client_id={{.client_id}}.Token Endpoint The CRM request URL that returns the access token and refresh token, for example https://www.api.example.com/oauth/v2/token?client_id={{.client_id}}&client_secret={{.client_secret}}.Content Type The content type of the token retrieval request. PKCE Verification Method How the code_verifierbecomes thecode_challenge. Available only when Authorization Mode is Authorization Code (PKCE). S256 hashes with SHA256 and encodes with Base64URL (recommended); Plain uses thecode_verifieras-is for CRMs without SHA256 support.Scope Optional. The CRM data Cloud Voice may access, with multiple scopes separated by commas, for example contacts.read,contacts.write,calls.read,calls.write,user.read,user.write.Additional Query String Optional. When the CRM authenticates with query parameters instead of a scope, add them here, for example client_id={{.client_id}}&redirect_uri={{.redirect_uri}}. -
Optionally, configure token refresh.

Setting Description Token Refresh Request Method The HTTP method for the refresh request. Token Refresh Endpoint The request URL that refreshes the access token. Token Refresh Content Type The content type of the refresh request. Token Refresh Time (min) How often, in minutes, to refresh the token automatically. 0disables automatic refresh; leaving it blank refreshes every 25 minutes.Token Refresh Request Body The body of the refresh request.
Bearer Token
Section titled “Bearer Token”Every request to the CRM carries an Authorization: Bearer {{.AccessToken}} header, where {{.AccessToken}} is a token granted by the CRM (typically through an authorization process such as OAuth2).
-
In the Authentication Method list, select Bearer Token.

-
Set up the fields users fill in for their credentials, and add custom fields if needed (up to 10 fields).

-
Configure token retrieval to match the API.

Setting Description Token Endpoint The CRM request URL that returns an access token, for example https://www.api.example.com/oauth/v2/token?client_id={{.client_id}}&client_secret={{.client_secret}}&grant_type=client_credentials. The returned token is stored in{{.AccessToken}}.Content Type The content type of the token retrieval request. -
Optionally, configure token refresh using the same fields described under OAuth2.

Request headers (optional)
Section titled “Request headers (optional)”Add custom HTTP headers that Cloud Voice includes in its predefined CRM sync requests (user association, contact sync, and so on).

-
In Request Configuration > Headers, click Add.
-
Configure the header.
Setting Description Name The header name, such as Content-TypeorAccept.Value The header value, either literal or a variable. Variables defined for the authentication method work here too; for example, reference a client_idvariable as{{.client_id}}.Description A short note on what the header is for.
Follow-up requests (optional)
Section titled “Follow-up requests (optional)”If your integration needs extra operations after certain predefined requests finish, add follow-up requests. Each one fires automatically when its specified operation succeeds, and you can pull values out of its response into global variables for reuse elsewhere.

-
In Request Configuration > Follow-up Requests, click Add.
-
Configure the request.
Setting Description Triggered Event The event that fires this follow-up request. Request Method The HTTP method for the request. URL The endpoint URL, for example https://api.example.com/rest-services/login.Headers The request headers as a JSON object, with {{.varname}}for dynamic values, for example{"Content-Type":"application/json", "X-Custom-Header": "{{.DynamicValue}}"}.Request Body The request payload as a JSON object, with {{.varname}}for dynamic values, for example{"lastName":"{{.LastName}}","ownerId":"{{.Id}}","phone":"{{.BusinessNumber}}"}.Response Field Path The JSON path(s) to extract from the response, separated by commas, for example .data.access_token, .tokens[0].value.Target Variable Name The variable(s) that store the extracted values, either existing or new, separated by commas (for example, token,refresh). Variables receive values in the same order as the paths in Response Field Path. Stored values are global and reusable throughout the integration.
Connection keepalive (optional)
Section titled “Connection keepalive (optional)”Keep the connection from dropping after a network timeout or a period of inactivity. When enabled, Cloud Voice sends keep-alive requests at the interval you set to check the connection and confirm authentication is still valid.

- Turn on Connection Keepalive.
- In Keepalive Interval (minutes), set how often the keep-alive request is sent.
Contact search, synchronization, and call pop-up
Section titled “Contact search, synchronization, and call pop-up”In the Synchronize Contacts Automatically section, define the contact types users can pick from and the requests that look those contacts up. These settings power contact search, automatic contact synchronization, and the call pop-up.
-
Add a contact type and its lookup request.

-
Contact Type: A name such as
Contacts. It appears as an option for automatic contact synchronization when users configure the integration. -
Contact Match Query URL: The CRM request URL that searches for contacts by criteria. You can use these variables in the criteria:
- Values users entered during authentication.
- Target variables extracted from follow-up requests.
{{.Phone}}: the number on an inbound or outbound call, or the number a user types when searching.
For example:
https://www.api.example.com/crm/v1/Contacts/search?criteria=((Phone:equals:{{.Phone}})or(Home_Phone:equals:{{.Phone}})or(Mobile:equals:{{.Phone}})or(Asst_Phone:equals:{{.Phone}}))
-
-
Set the call pop-up URL with one of the following methods.
Specify URL Format
Build the URL yourself from an expression, using variables to fill it in dynamically.

-
In the Contact Popup URL list, select Specify URL Format.
-
In URL Format, enter the expression. The following variables draw their values from the contact search results:
- Values users entered during authentication.
- Target variables extracted from follow-up requests.
{{.ContactSyncType}}: the contact type.{{.ContactId}}: the contact ID.{{.CustomValue}}: a field mapped in Contact Field Mapping.
For example:
{{.crm_url}}/crm/{{.CustomValue}}/tab/{{Capitalize .ContactSyncType}}/{{.ContactId}}
Retrieve from Contact Fields
Read the URL straight from a field in the contact search response.

- In the Contact Popup URL list, select Retrieve from Contact Fields.
- In Contact Field for URL, enter the JSON path to the field, for example
data.#.contactUrl.
-
-
In Contact Field Mapping, map the CRM’s response fields to the Cloud Voice fields with a JSON path (for example,
data.#(key=="value").field).-
Map the required fields.

- Contact ID: the ID of the found contact, for example
data.0.id. - First Name: the first name of the found contact, for example
data.0.First_Name.
- Contact ID: the ID of the found contact, for example
-
Enable and map any other fields you need. You must enable and map at least one phone number.

-
If no existing field gives you the value you need, enable and map the response field to Custom Value, then reference it as
{{.CustomValue}}.
-
New contact creation (optional)
Section titled “New contact creation (optional)”To create a new CRM contact when a caller’s number matches nothing in the CRM, turn on and configure Create New Contact.

- Turn on Create New Contact.
- Add the contact types users can choose from when configuring the integration.
-
Contact Type: The type of contact, for example
Contacts. -
Contact Creation URL (POST): The CRM request URL that creates a contact, for example
https://www.api.example.com/crm/v1/Contacts. -
Contact Creation Request Body: The request body (JSON) that carries the contact details. You can use these variables:
- Values users entered during authentication.
- Target variables extracted from follow-up requests.
{{.LastName}}: required. The contact’s last name.{{.FirstName}}: required. The contact’s first name.{{.BusinessNumber}}: required. The contact’s phone number.
For example:
{"data": [{"Last_Name": "{{.LastName}}","First_Name": "{{.FirstName}}","Phone": "{{.BusinessNumber}}"}]}
-
Call journaling (optional)
Section titled “Call journaling (optional)”To log call activity and details into the CRM automatically, turn on and configure Call Journal.

-
Turn on Call Journal.
-
Configure the request that creates a call log.
-
Create Call Journal URL: The CRM request URL that creates a call log, for example
https://www.api.example.com/v2/Calls. -
Create Call Log Request Method: POST or PUT.
-
Call Journal Creation Request Body: The request body (JSON) carrying the call details. For the variables you can use, see the call-journal variables in the XML reference. For example:
{"data": [{"{{.Owner}}{{.WhoModule}}": {"Description": "{{.Description}}","Voice_Recording__s": "{{.RecordPath}}","Call_Start_Time": "{{TimeFormat .StartTimeUnix 'yyyy-MM-ddTHH:mm:ss-z' '1'}}","Subject": "{{.Subject}}","Call_Type": "Inbound","Call_Result": "{{.Call_Log_Status}}","Call_Duration": "{{.Talk_Duration_Sec}}"}}]}
-
-
Optionally, configure the request that updates an existing call log with more information.
-
Update Call Journal URL: The CRM request URL that updates a call log, for example
https://www.api.example.com/v2/Calls/{{.CallId}}. -
Update Call Log Request Method: POST or PUT.
-
Call Journal Update Request Body: The request body (JSON) carrying the call details. For example:
{"data": [{"{{.Owner}}{{.WhoModule}}": {"Description": "{{.Description}}","Voice_Recording__s": "{{.RecordPath}}","Call_Start_Time": "{{TimeFormat .StartTimeUnix 'yyyy-MM-ddTHH:mm:ss-z' '1'}}","Subject": "{{.Subject}}","Call_Type": "Inbound","Call_Result": "{{.Call_Log_Status}}","Call_Duration": "{{.Talk_Duration_Sec}}","AI_Transcription": "{{.AI_Transcription}}","AI_Summary": "{{.AI_Summary}}","Call_Note": "{{.Call_Note}}"}}]}
-
-
Optionally, choose which call-journal options appear in the integration. Select an option’s checkbox to expose it, and set its default value.
Option Description Subject Lets the integration set a default subject for all synced call logs. Description Lets the integration set the details of synced call logs, for example Call: {{.Time}} {{.Call_Log_Status}} from {{.Call_From}} to {{.Call_To}} {{.Talk_Duration}}.Play Call Recording Lets the integration control whether call recordings can be played back within the CRM. Disable Display Missed Call Records in Unanswered Agents Lets the integration sync queue and ring group call logs only to the CRM of the agent who answered, keeping missed-call logs for the same call out of the CRM of agents who didn’t.
Chat journaling (optional)
Section titled “Chat journaling (optional)”To sync chat messages with CRM contacts into the CRM automatically, turn on and configure Chat Journal.

-
Turn on Chat Journal.
-
Configure the request that stores chat messages.
-
Create Chat Journal URL (POST): The CRM request URL that creates an object to hold chat messages, for example
https://www.api.example.com/v2/Tasks. -
Chat Journal Creation Request Body: The request body (JSON) carrying the chat details. For the variables you can use, see the chat-journal variables in the XML reference. For example:
{"data": [{"Owner": {"id": "{{.OwnerId}}"},"Who_Id": "{{.ContactEntityId}}","Subject": "{{.Subject}}","Due_Date": "{{ TimeFormat .StartTimeUnix "yyyy-MM-dd" "0" }}","Closed_Time": "{{ TimeFormat .EndTimeUnix "yyyy-MM-ddTHH:mm:ss.000Zz" "0" }}","Status": "Completed","Priority": "Normal","Description": "Message Channel Type: {{.Channel_Display}}\n\n{{.Messages}}"}]}
-
-
Optionally, in the Subject section, decide whether users can customize the subject of the synced record.
- Select the checkbox to expose the Subject field in the integration.
- Set its default value.