CRM Template XML Description
- Introduction
- The XML Template Format
- Number Element
- Connection Element
- Parameters Element
- Authentication Element
- Scenarios Element
- Request element
- Query element
- Command element
- Rules
- Variables
- Variable
- Outputs
- Outputs for each type of scenario
- Scenarios returning contact information
- Authentication Scenario
- OAuth Response Scenario
- Chained scenario
- Creating OAuth2 authentication flow
- Expressions
- Variables
- Predefined Variables
- String Concatenation
- Method Invocation
- Condition Evaluation
- Call Journaling
- Chat Journaling
- Lookup from a CFD application
- Debugging
- See Also
Introduction
This document describes the format of the XML template used for the CRM integration, and also provides a description of how the engine executes according to the settings defined in the template. Finally, we explain how we can easily debug a template.
The XML Template Format
<Crm> is the root element of the XML template and contains:
- Name (string) - Name of the template. It is shown to the user to identify the CRM.
- Version (integer) - Template version for updates.
- Country (string) - The country to which the template applies, this is not used at the moment, however it is a mandatory attribute.
- SupportsEmojis (boolean) - Indicates whether the CRM supports emojis when storing the chat conversation in the CRM. If this is false, emojis will be removed from the chat messages before sending them to the CRM. If the attribute is not specified, a default “false” value is used.
The <Crm> element contains the following child elements:
- Number
- Connection
- Parameters
- Authentication
- Scenarios
Number Element
This element is used to format the received caller number in the way that the CRM expects it. The resulting number will be used for contact matching. It has the following attributes:
Prefix (Enum) - describes what to do with the caller number prefix:
- AsIs - do not modify prefix: +,00 ⇒ +,00
- Off - exclude prefix: +,00 ⇒ X
- Plus - use ‘plus’ sign: +,00 ⇒ +
- Zeros - use zeros as prefix: +,00 ⇒ 00
MaxLength (Number Expression) - Maximum number of digits to keep in the phone number.
For example, if MaxLength=6, the phone number will be converted taking only the last 6 digits:
+123456789 ⇒ 456789.
If the expression is empty, the number is not changed.
You can use the variable [MaxLength] here to take the value configured in the 3CX Console > Contacts > Options.
Connection Element
This element describes connection-specific options for the CRM. It has the following attributes:
MaxConcurrentRequests (integer) - Specifies how many simultaneous requests can be sent to the CRM. A request is considered a number lookup for a single call. Please note that many queries for the same call (different scenarios to query for example for contacts, leads or accounts), are counted as one.
Parameters Element
This element contains a collection of children <Parameter> elements, which are variables that can be configured by the user from the 3CX Admin Console. Each child <Parameter> element has the following attributes:
- Name (string) - Name of the parameter. The parameter value can be obtained providing its name in square brackets. For example: [SomeParameter]
- Type (enum) - The type of the parameter. There are 7 types available at the moment:
- String - represents a string
- Password - represents a string hidden in a user interface
- Boolean - represents a checkbox
- Integer - represents an integer number
- Double - represents a floating point number
- DateTime - represents a date and time
- OAuth - represents a button to trigger the OAuth authorization flow
- Title (string) - Caption to show in the 3CX Admin Console for this parameter.
- Default (String Expression) - The default value for the parameter.
- Parent (string) - This is the name of a parent parameter to group children parameters into a box in the configuration UI. If the text provided here is not a parameter name, the box grouping all children parameters will have the label taken from this attribute.
- Editor (enum) - The type of editor to use to enter text. Possible values are String, which lets you enter up to 100 characters, and Sql which lets you enter up to 1000 characters.
- RequestUrl (String Expression) - The URL that needs to be opened to start the OAuth authentication flow, only valid when the parameter type is OAuth.
- RequestUrlParameters (String Expression) - OAuth parameters which will be concatenated with RequestUrl when the parameter type is OAuth.
- ResponseScenario (string) - The ID of the scenario that should be executed to get the refresh token returned by the OAuth server, only valid when the parameter type is OAuth.
Example (see Parameters node in Zoho template):
Authentication Element
This element defines the authentication method used by the CRM. There are three options at the moment:
- No authentication: Type="No" This option is used when there is no authentication, or the CRM uses a custom authentication mechanism, for example some parameters in the query string.
- Basic authentication: Type="Basic" In this case every HTTP request sent to the CRM will include the Authorization header, encoded according to the basic authentication protocol, using the value taken from the <Value> child element.
- Scenario authentication: Type="Scenario" With this type of authentication it is possible to describe complex authentication scenarios, including OAuth. The idea is to invoke a scenario to get the header and/or other parameters that we need to use for requests (for example, OAuth access token), the token expiration, etc. using specific requests to the CRM.
Please note that not only Outputs but all Variables captured or declared within the authentication scenario are accessible for subsequent requests.
Scenarios Element
This element describes the different scenarios to be used when interacting with the CRM. For example, a scenario might describe an authentication flow, another scenario might describe how to query for contacts, how to create a new contact, how to report a call, etc. This element contains a collection of <Scenario> children elements.
A Scenario is the main unit of data processing, and works as follows:
- It performs an HTTP request, or database query to the CRM.
- It splits and filters the results according to rules and the response data (JSON or XML).
- For each result, it fills variables taken from the response data and provides an output or calls an inner scenario recursively by id.
The Scenario element has an attribute named Id (string) which contains a unique identifier for each scenario or an empty string. Some Ids have a special meaning:
- When the Id is empty, the scenario is used for contact lookup using a phone number.
- When the Id starts with “LookupByEmail”, the scenario is used for contact lookup using an email address.
- When the Id starts with “SearchContacts”, the scenario is used to search for contacts in the CRM using free text, i.e. search on first name, last name, company name, phone numbers or email addresses.
- The Id “ReportCall” is used for call journaling. When the call ends, this scenario will be executed.
- The Id “ReportChat” is used for chat journaling. When the chat is dealt with, this scenario will be executed.
- The Id “CreateContactRecordFromClient” is used to automatically create a new contact record in the CRM when it’s requested by a 3CX client.
- The following Ids are used to perform contact lookup from a CFD app: “LookupFromCFD_Contacts_LookupNumber”, “LookupFromCFD_Contacts_LookupID”, “LookupFromCFD_Contacts_LookupFreeQuery”, “LookupFromCFD_Leads_LookupNumber”, “LookupFromCFD_Leads_LookupID”, “LookupFromCFD_Leads_LookupFreeQuery”, “LookupFromCFD_Accounts_LookupNumber”, “LookupFromCFD_Accounts_LookupID”, “LookupFromCFD_Accounts_LookupFreeQuery”.
- Any other Id can be used for specific purposes, invoking children scenarios from one of the standard scenario types. For example, the lookup scenario with an empty Id, could just return a contact id, and then another scenario is required to get the contact details.
Also, the Scenario element defines the scenario type using the “Type” attribute, which can be defined as:
- “REST”: the scenario will execute a REST API using an HTTP request.
- “SQLDatabase”: the scenario is to execute an SQL Database query. The supported SQL databases are MySQL, PostgreSQL and Microsoft SQL Server.
- “NoSQLDatabase”: the scenario is to execute a No SQL Database command. The only supported NoSQL database is MongoDB.
Finally, the Scenario element has the “EntityId” and “EntityOrder” attributes, for defining the lookup order when a template contains more than one lookup scenario. The “EntityId” attribute defines the entity to search, for example Contacts, Leads or Accounts. The “EntityOrder” attribute usually takes the value from a parameter, so the user can set the lookup order. The parameter should be a list with comma-separated values, and each value defining the order with the entities separated by a slash. Consider this parameter definition example:
<Parameter Parent="General Configuration" Name="LookupOrder" Type="List" ListValues="Contacts/Leads/Accounts,Contacts/Accounts/Leads,Leads/Accounts/Contacts,Leads/Contacts/Accounts,Accounts/Contacts/Leads,Accounts/Leads/Contacts" Title="Contact Lookup Order:" Default="Contacts/Leads/Accounts" />
The Scenario node has these children elements: Request, Query, Command, Rules, Variables and Outputs.
Request element
This child element is mandatory when the scenario type is REST (default value), as the scenario must perform an HTTP request. The Request element has the following attributes:
- SkipIf (Boolean Expression) - If the expression evaluates to true, then the request is skipped. This means that all variables for this scenario will be set to empty, and the output will be provided only if its AllowEmpty attribute is set to true.
- Url (String Expression) - URL to invoke when the scenario is executed.
- RequestType (enum) - The HTTP request method: Get - for GET requests. Post - for POST requests.
- RequestContentType (String) - The Content Type to use for the HTTP request.
- RequestEncoding (enum) - The encoding used for POST request. Valid values are: Json, UrlEncoded. When Json is selected you can build advanced Json objects by using children nodes <Object/>, <Array/> and <Value/>, inside the element <PostValues>. Please see an example in the Zoho template, scenario CreateCall.
- Message (String Expression) - The text to use as HTTP Content for the POST request.
Not applicable for Get requests. Optionally this can be set using a child <PostValues> element as explained in the RequestEncoding attribute. Please note that this attribute should not be set if the <PostValues> child element is defined. - ResponseType (enum) - The type of response expected. Valid values are: Json and Xml.
When the RequestType is Post, a collection of key-value pairs can be defined as children elements. In this case, the request will look as follows:
The Request element can also have a Headers child element. The headers specified here will be sent in the HTTP request. This element will have a set of children <Value> elements, as follows:
Query element
This child element is mandatory when the scenario type is SQLDatabase, as the scenario must execute an SQL query. The Query element has the following attributes:
- SkipIf (Boolean Expression) - If the expression evaluates to true, then the query is skipped. This means that all variables for this scenario will be set to empty, and the output will be provided only if its AllowEmpty attribute is set to true.
- DatabaseType (enum) - the type of database on which the query will be executed. This could be MySQL, MsSQL or PostgreSQL.
- ConnectionString (String Expression) - the connection string to use to connect to the database.
- StatementPasses (Integer) - the number of times the Statement expression needs to be evaluated. The default value is 1, but it might need to be a higher value if nested expressions are used. For example, if the Statement uses a parameter, and the parameter value uses another parameter, then the value should be set to 2.
- Statement (String Expression) - the SQL statement to execute on the database. This expression will be recursively evaluated the number of times specified in StatementPasses.
Command element
This child element is mandatory when the scenario type is NoSQLDatabase, as the scenario must execute a No SQL command. The Command element has the following attributes:
- SkipIf (Boolean Expression) - If the expression evaluates to true, then the command is skipped. This means that all variables for this scenario will be set to empty, and the output will be provided only if its AllowEmpty attribute is set to true.
- DatabaseType (enum) - the type of database on which the command will be executed. This must be MongoDB.
- ConnectionString (String Expression) - the connection string to use to connect to the database.
- Database (String Expression) - the name of the database to use.
- Collection (String Expression) - the name of the collection to use.
- CommandType (enum) - the type of command to execute. This could be Filter or Insert.
- CommandPasses (Integer) - the number of times the Command expression needs to be evaluated. The default value is 1, but it might need to be a higher value if nested expressions are used. For example, if the Command uses a parameter, and the parameter value uses another parameter, then the value should be set to 2.
- Command (String Expression) - the command to execute on the database. This expression will be recursively evaluated the number of times specified in CommandPasses.
- CommandData - a different way to specify the command. In some cases it is preferable to specify the command using nested XML elements. These elements will be automatically converted to JSON when the command is executed. The <CommandData> element is a child of the <Command> element, and can include nested <Object/>, <Array/> or <Value/> elements inside. See the MongoDB sample for more details about this.
Rules
This element is used to analyze the response returned by the server. The response can be JSON, XML or plain text, and is automatically converted to a tree-view structure. Each node of the structure can be one of 3 types:
- An array of elements: unnamed set of similar elements.
- An element with named properties.
- The value itself: when the node is a leaf of the tree, it is a value of an elementary type.
We need to perform 2 tasks when processing this response tree:
- Identify the root element for each contact returned by the server.
- Optionally filter the contacts that we need.
A scenario might have one or more children <Rules> elements. Also, each <Rules> element can have one or more children <Rule> elements. The returned data (JSON, XML or Plain Text) is processed according to these rules, and each record will pass the filter if:
- At least one <Rule> element from a <Rules> element passes the filter (<Rule> elements are evaluated with an OR condition).
- AND every <Rules> element passes the filter, according to the previous bullet point (<Rules> elements are evaluated with an AND condition).
The value inside the child <Rule> element is the path to the matching element in the response data tree, and the attributes of this element are the following:
- Type (enum) - Matching rule type, which can be one of the following:
- Any - if the rule is used to determine contact’s root in the response data tree without filtration.
- Number - if the rule should match the data element (provided by the path) to the phone number.
- Equals - if the rule should match the data element (provided by the path) to the value specified in the attribute Ethalon.
- Ethalon (String Expression) - Expression to use when Type=Equals. The rule passes if the string representation of Ethalon matches the data element content.
This is an example of a JSON response returned by a CRM:
The path is an expression to point to a specific node in the response tree. This expression is a string which concatenates node names separated by dots. The path expression points to the value of the selected element, so if the path points to a leaf, the elementary value is returned, and if it points to an array, the array of elements is returned.
In the above JSON example we can see that:
- The path “result” points to the array of contacts.
- The path “result.lastName” points to the 2 leaves with values “Bravo” and “Lecter”.
- The path “result.communicationItems.type.name” points to the 4 leaves with values: “Direct”, “Email”, “Cell” and “Direct”.
Let’s see how different <Rule> elements work. Consider the following rule:
This rule will return every record which has a firstName property in the result node. There are 2 records that pass this rule, and therefore will be converted into contacts: one for “Johnny Bravo” and one for “Hannibal Lecter”.
If we change the rule as follows:
..this will result in a single record for “Hannibal Lecter”.
By comparison, using the following rule:
..will match 4 records, 3 for “Johnny Bravo” and 1 for “Hannibal Lecter”.
If we change the rules as follows:
..the first rule will filter the 3 “Phone” records (direct phone and cell phone for Johnny Bravo, and direct phone for Hannibal Lecter). And the second filter will restrict the result to the numbers that match the caller number. So, for example, if we’re looking for the number “987654”, only one record for “Johnny Bravo” will pass through the filters. And if we’re looking for the number “123456” with MaxLength=6, two records will pass through the filters, one for “Johnny Bravo” with number “123456”’ and one for “Hannibal Lecter” with number “+1123456”.
Variables
After applying the rules to the data returned by the server, we need to fill variables with the parts of the data we need. We can define as many variables as we need.
A scenario can only have one child <Variables> element. And this element might have as many children <Variable> elements as we need. The value inside the child <Variable> element is the path to the matching element in the response data tree, and the attributes of this element are the following:
- Name (string) - Name of the variable.
- Path (string) - The path to the matching element in the response data tree. This can also be specified as the element value.
- LookupValue (string) - when this attribute is set, the lookup is inverted, and the variable will be assigned with the key of the path that contains the specified value. For example, if the response tree is “result.phones.1234567890=work”, the path is set to “result.phones” and LookupValue=”work”, then the value “1234567890” will be assigned to the variable.
If there are arrays on the path from the root of the tree to the root of the contact, the instance for this specific contact will be selected. But if there are arrays on the path from the root of the contact to the final leaf, and no variable filtering is applied, an exception will be thrown.
Continuing with the JSON response from the example above, let’s assume that we have the following rule to filter the contact root:
In this case we can easily create variables to get the first name, the last name and the company name:
However, this does not work for phone numbers and email, because that information is stored in arrays, and it’s not possible to define which leaf of the path “result.communicationItems.value” needs to be taken for the email and each phone number type. We need to use variable filtering to disambiguate in this case.
Variable
Each variable can provide a filter to eliminate the ambiguity of multiple leaves from an array, selecting only the one we need for each case. The variable filter is based on the same principle as the general Rules, but it contains only one set of rules, and filters an array of records from the root of the contact to the final leaf.
From our example, we can see that the contact “Johnny Bravo” has three communication Items: 2 phones and 1 email. To get this information into variables, we can apply the following filters:
Each variable has the same path but different filters, so the engine reads the proper value for each variable.
Outputs
After filling the variables with the values taken from the data returned by the server, we need to complete the output of the scenario, that means the result of all this processing. To do this, we use the <Outputs> element. There are 2 different types of outputs:
- To provide output values: this stops the scenario chain processing. In this case the <Outputs> element has as many children <Output> elements as we need, one for each output value.
- To run another (chained) scenario: in this case the Next attribute is set to the Id of the following scenario, and the output will be provided by the next scenario instead of this.
The scenario providing output values can do it in 2 cases:
- When there is at least one record that matches the scenario rules.
- When the AllowEmpty attribute is set to true.
The attributes of the <Outputs> element are the following:
- Next (string) - Id of the following scenario to execute, if any.
- AllowEmpty (bool) - When true, the scenario provides an output even when there is no record that matches the scenario rules, or when the whole request has been skipped. In this case the output will have an empty value for all values.
This is useful if you want to skip some intermediate scenario in a chain, due to some reason. For example, you need one request to get the main contact data (first name, last name, company id, etc.) and a second chained request to get the company name by its id. If the contact is not associated with a company, the second request will return no records. In this case, if AllowEmpty is not specified, it will not return any information from this contact, and that is incorrect as the contact is still valid.
When the <Outputs> element provides output values, it contains children <Output> elements. Each child <Output> element has the following attributes:
- Type (string) - The type of the output value. See section Output for each type of scenario for more details.
- Passes (integer) - The number of times the Value expression needs to be evaluated. In some cases, the Value is set to a parameter which is also an expression, and evaluating the Value only once is not enough. In those cases a greater value is needed here, usually 2. The default value is 1.
- Value (string Expression) - The expression to create the value to output.
For example, the following output sets the result for a contact lookup, using expressions to include variables:
Outputs for each type of scenario
There are 4 types of scenarios:
Scenarios returning contact information
The following scenarios will return contact information:
- Contact lookup by phone number, which does not have an Id.
- Contact lookup by email scenarios, which start with the prefix “LookupByEmail”.
- Search contacts scenarios, which start with the prefix “SearchContacts”.
- Contact creation scenario, which has the Id “CreateContactRecordFromClient”.
It’s possible to have many scenarios of these types for a single template. In case of having more than one scenario, they will be executed one after the other, in the same order as they are placed in the template, and the result will be concatenated. The order can be adjusted in runtime using the lookup ordering technique explained above.
The output types for this scenario are the following: (All are string Expression)
- FirstName - First name of the contact
- LastName - Last name of the contact
- Email - Email of the contact
- CompanyName - Company name of the contact
- ContactUrl - URL of the contact in the CRM - this is mandatory, as it’s the identifier of the contact in 3CX
- PhoneMobile - Mobile phone of the contact
- PhoneMobile2 - Additional mobile phone of the contact
- PhoneHome - Home phone of the contact
- PhoneHome2 - Additional home phone of the contact
- PhoneBusiness - Business phone of the contact
- PhoneBusiness2 - Additional business phone of the contact
- PhoneOther - Other phone of the contact
- FaxBusiness - Business fax of the contact
- FaxHome - Home fax of the contact
- Pager - Pager of the contact
- PhotoUrl - Url to the photo of the contact
- EntityId - The ID of the matched entity (contact, lead or account) which will be accessible during call and chat journaling
- EntityType - The type of the matched entity (contact, lead or account) which will be accessible during call and chat journaling
IMPORTANT: For a record to be considered a valid match, the template must return the following outputs:
- ContactUrl: as mentioned above, this is mandatory and should be unique for each contact.
- FirstName, LastName or CompanyName: one of these outputs must have a value.
- PhoneMobile, PhoneMobile2, PhoneHome, PhoneHome2, PhoneBusiness, PhoneBusiness2, PhoneOther, FaxBusiness, FaxHome, or Pager: when running a lookup by phone number, one of these outputs must have the value set to the phone number being searched.
- Email: when running a lookup by email, this value must be set to the email being searched.
Authentication Scenario
Only one authentication scenario is allowed per template. This scenario is triggered from the Authentication section, matching the Id to the Value specified there.
The Authentication Scenario is invoked in the following cases:
- On the first query to the CRM.
- When the token expires, or the token expiration is not specified and the last invocation to the authentication scenario was made more than 1 hour ago.
The output types for this scenario are the following:
- Bearer (string Expression) - If provided, the Bearer value to use in the Authentication header for each request sent.
- BearerExpiration (integer Expression) - Timeout in seconds for bearer expiration. The Authentication Scenario will not be invoked again until this timeout expires. We recommend setting this parameter one minute less than your real expiration timeout to avoid expiration errors.
- HeaderName (string Expression) - If provided, name of custom request header to use on each request to the CRM.
- HeaderValue (string Expression) - If provided, value of custom request header to use on each request to the CRM.
Note: at least one header should be provided: Bearer or HeaderName/HeaderValue.
OAuth Response Scenario
When the template uses OAuth2 authentication, there must be a parameter of type OAuth. In this case, the 3CX Admin Console will show an Authorize button. When the user clicks on that button, a new tab will be opened, showing the Authorization page of the CRM. Once the user grants access to the CRM data to 3CX, the CRM redirects the browser tab to a 3CX page, providing an authorization code. This code is then used by the admin console to generate the Refresh Token. This final processing is done executing the OAuth Response Scenario. Please check the Zoho template for more details about this.
The output types for this scenario are the following:
- Result (string Expression) - this is the refresh token obtained by this scenario.
Chained scenario
Any of the previous types of scenarios can invoke a chained scenario to complete the task. In that case, a chained scenario is configured as output, and that scenario will provide the actual output. The chained scenario is executed for each result returned by the Rules filters. For example, this output invokes a chained scenario with Id “GetContactId”:
<Outputs Next="GetContactId"/>
A chained scenario has access to every variable set in a parent scenario.
The scenario execution chain ends in two cases:
- The last scenario is reached and outputs are set.
- The scenario’s request produces an empty response (or there are no records that pass the filter) and the AllowEmpty attribute for the output is set to false.
Creating OAuth2 authentication flow
For a complete example see the Zoho template.
- Get ClientId and ClientSecret from your CRM provider.
- Allow 3CX Phone System OAuth2 URL in your CRM provider. It should be set to (for example) “https://my-pbx.example.com:5001/api/oauth2crm”
- Create a Parameter with type OAuth inside the Parameters section. This will be used to get authorization code. In RequestUrl and RequestUrlParameters attributes you can use other Parameter values. RequestUrlParameters will be automatically urlencoded while RequestUrl will remain intact. Please consult your CRM provider on how to build parameters for getting the authorization code. It’s mandatory to pass the special parameters [State] and [RedirectUri]. You can pass [State] separately (see Zoho) or concatenate it with [RedirectUri]. Usually at least client_id and redirect_url parameters are mandatory.
- Create a response scenario which will be used to get the refresh token and set its name to the ResponseScenario attribute. Please consult your CRM provider on how to get the refresh token. Usually this is a POST Json request and at least client_id and client_secret parameters are mandatory.
- Create the Authentication node with Type=”Scenario” and create a scenario to get the access token. Please consult your CRM provider on how to get the access token. Usually this is a POST Json request and at least refresh_token, client_id and client_secret parameters are mandatory.
Expressions
The expressions engine allows us to build values using:
- Variables
- String concatenation
- Method invocation
- Condition evaluation
When building an expression containing string literals and variables, in case you need to use some specific characters in your string literal, you will need to escape them, as they have special meaning for the expression. These characters are:
- The opening square bracket [ which needs to be replaced by {{.
- The closing square bracket ] which needs to be replaced by }}.
- The quotation mark " which needs to be replaced by ^^.
Variables
To get a variable value, everywhere except when invoking an SQL query, use the variable name between square brackets: [SomeVariable]
For SQL queries, variable values are obtained using named parameters instead, using the @ character prefix, for example: @SomeVariable.
Variables are obtained from:
- Predefined variables
- Input parameters
- Scenario variables
Predefined Variables
Each type of scenario has some predefined variables you can use.
The following variables are predefined for the contact lookup by number scenarios, and can be used at any time:
- Number (string) - Phone number to search modified according to the Number element.
- CallDirection (string) - The call direction during contact lookup, it can be “Inbound” or “Outbound”.
- MaxLength (integer) - Number of digits to match (counted from right to left).
- FoundRecordCount (integer) - Total number of contacts returned. It is determined when the matching scenario chain has finished.
The following variables are predefined for the contact lookup by email scenarios, and can be used at any time:
- Email (string) - The email to search.
- FoundRecordCount (integer) - Total number of contacts returned. It is determined when the matching scenario chain has finished.
The following variables are predefined for the search contacts scenarios, and can be used at any time:
- SearchText (string) - The text to search.
- FoundRecordCount (integer) - Total number of contacts returned. It is determined when the matching scenario chain has finished.
The following variables are predefined for the contact creation scenario, and can be used at any time:
- FirstName (string) - The first name of the contact to create.
- LastName (string) - The last name of the contact to create.
- Number (string) - The number of the contact to create (might be empty when only the email is provided).
- Email (string) - The email of the contact to create (might be empty when only the phone number is provided).
- Company (string) - The name of the company for the contact to create.
The following variables are predefined for the report call scenario, and can be used at any time:
- CallType (string) - The type of call, it can be “Inbound”, “Outbound”, “Missed”, or “Notanswered”.
- Number (string) - The external contact number (the number dialed for outbound calls or the caller number for inbound calls).
- CallDirection (string) - The call direction, it can be “Inbound” or “Outbound”.
- Name (string) - The name of the matched contact.
- EntityId (string) - The ID of the matched entity (contact, lead or account).
- EntityType (string) - The type of the matched entity (contact, lead or account).
- QueueExtension (string) - The extension number of the queue or ring group, only when the call arrives to the agent through a queue or ring group.
- Agent (string) - The extension number of the agent handling the call.
- AgentFirstName (string) - The first name of the agent handling the call.
- AgentLastName (string) - The last name of the agent handling the call.
- AgentEmail (string) - The email of the agent handling the call.
- Duration (string) - The duration of the call in “hh:mm:ss” format.
- DurationTimespan (TimeSpan) - The duration of the call as a TimeSpan object, which can be formatted as the user wants. For example, it can be converted to a string representing the total number of minutes, using the expression [[[DurationTimespan].get_TotalMinutes()].ToString("F0")]
- DateTime (string) - The start date & time of the call, in the local time zone, formatted using the local culture from the 3CX server.
- CallStartTimeLocal (DateTime) - The start date & time of the call, in the local time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[CallStartTimeLocal].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- CallStartTimeUTC (DateTime) - The start date & time of the call, in UTC time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[CallStartTimeUTC].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- CallEstablishedTimeLocal (DateTime) - The date & time in which the call was established, in the local time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[CallEstablishedTimeLocal].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- CallEstablishedTimeUTC (DateTime) - The date & time in which the call was established, in UTC time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[CallEstablishedTimeUTC].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- CallEndTimeLocal (DateTime) - The end date & time of the call, in the local time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[CallEndTimeLocal].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- CallEndTimeUTC (DateTime) - The end date & time of the call, in UTC time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[CallEndTimeUTC].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- CallStartTimeLocalMillis (integer) - The start date & time of the call, in the local time zone, expressed as milliseconds since epoch (aka unix time).
- CallStartTimeUTCMillis (integer) - The start date & time of the call, in UTC time zone, expressed as milliseconds since epoch (aka unix time).
- CallEstablishedTimeLocalMillis (integer) - The date & time in which the call was established, in the local time zone, expressed as milliseconds since epoch (aka unix time).
- CallEstablishedTimeUTCMillis (integer) - The date & time in which the call was established, in UTC time zone, expressed as milliseconds since epoch (aka unix time).
- CallEndTimeLocalMillis (integer) - The end date & time of the call, in the local time zone, expressed as milliseconds since epoch (aka unix time).
- CallEndTimeUTCMillis (integer) - The end date & time of the call, in UTC time zone, expressed as milliseconds since epoch (aka unix time).
The following variables are predefined for the report chat scenario, and can be used at any time:
- Number (string) - The external contact number (only available when this is a chat through SMS).
- Email (string) - The external contact email address (only available when this is a chat through Live Chat).
- Name (string) - The name of the matched contact.
- EntityId (string) - The ID of the matched entity (contact, lead or account).
- EntityType (string) - The type of the matched entity (contact, lead or account).
- QueueExtension (string) - The extension number of the queue, only when the chat arrives to the agent through a queue.
- ChatMessages (string) - The messages sent and received during the chat session.
- Agent (string) - The extension number of the agent handling the chat.
- AgentFirstName (string) - The first name of the agent handling the chat.
- AgentLastName (string) - The last name of the agent handling the chat.
- AgentEmail (string) - The email of the agent handling the chat.
- Duration (string) - The duration of the chat session in “hh:mm:ss” format.
- DurationTimespan (TimeSpan) - The duration of the chat session as a TimeSpan object, which can be formatted as the user wants. For example, it can be converted to a string representing the total number of minutes, using the expression [[[DurationTimespan].get_TotalMinutes()].ToString("F0")]
- DateTime (string) - The start date & time of the chat session, in the local time zone, formatted using the local culture from the 3CX server.
- ChatStartTimeLocal (DateTime) - The start date & time of the chat session, in the local time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[ChatStartTimeLocal].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- ChatStartTimeUTC (DateTime) - The start date & time of the chat session, in UTC time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[ChatStartTimeUTC].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- ChatEndTimeLocal (DateTime) - The end date & time of the chat session, in the local time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[ChatEndTimeLocal].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- ChatEndTimeUTC (DateTime) - The end date & time of the chat session, in UTC time zone, as a DateTime object, which can be formatted as the user wants. For example, it can be converted to string using the expression [[ChatEndTimeUTC].ToString("yyyy-MM-ddTHH:mm:ssZ")]
- ChatStartTimeLocalMillis (integer) - The start date & time of the chat session, in the local time zone, expressed as milliseconds since epoch (aka unix time).
- ChatStartTimeUTCMillis (integer) - The start date & time of the chat session, in UTC time zone, expressed as milliseconds since epoch (aka unix time).
- ChatEndTimeLocalMillis (integer) - The end date & time of the chat session, in the local time zone, expressed as milliseconds since epoch (aka unix time).
- ChatEndTimeUTCMillis (integer) - The end date & time of the chat session, in UTC time zone, expressed as milliseconds since epoch (aka unix time).
The following variables are predefined for the Lookup from CFD scenarios, and can be used at any time:
- Number (string) - Phone number to search as received from the CFD app when Lookup Type is “Entity Number”.
- EntityID (string) - The ID of the entity (contact, lead or account) to search as received from the CFD app when Lookup Type is “Entity ID”.
- Query (string) - The query to use when searching in the CRM, as received from the CFD app when Lookup Type is “Custom Query”.
String Concatenation
By default, the expression engine will concatenate the strings found in an expression. For example, if an expression contains variables and string literals:
<Authentication Type="Basic">
<Value>[CompanyName]+[PublicKey]:[PrivateKey]</Value>
</Authentication>
The value will be the result of concatenating the value of the variable [CompanyName], then the “+” string literal, then the value of the variable [PublicKey], then the “:” string literal, and finally the value of the variable [PrivateKey].
Another example to build the URL for a request:
<RequestUrl="[Domain]/rest/v10/Contacts?filter{{0}}{{phone_mobile}}{{$ends}}=[Number]&fields=id,first_name,last_name,phone_mobile,email,accounts" ResponseType="Json"/>
...where, [Domain] is an input parameter, and [Number] is the predefined variable containing the phone number to search. The remaining text is considered string literal, and will be concatenated with the values of these variables.
To leave the string concatenation mode and enter the methods invocation and condition evaluation modes, you need to put the expression content inside square brackets, as shown in the following sections.
Method Invocation
You can invoke any supported method on the value of a variable using this syntax:
[[Variable].MethodName(param1;param2;...paramN)]
For example, to replace a “+” with the string “%2B” to perform URL encoding on the number to search, we can use the following expression:
[[Number].Replace("+","%2B")]
Another example, if we want to format the start date and time of the call during the Report Call scenario, we can use:
[[CallStartTimeUTC].ToString("yyyy-MM-dd")]
In the first example, [Number] is a C# string, so any method from the System.String class can be used. In the second example, [CallStartTimeUTC] is a C# DateTime object, so any method from the System.DateTime class can be used.
Condition Evaluation
The engine supports the following operators:
- == (bool) - Compares two strings and returns true if they are equal
- != (bool) - Compares two strings and returns true if they are not equal.
- > (bool) - Compares two IComparable objects, and returns true if the first is greater than the second.
- || (bool) - Conditional OR.
- && (bool) - Conditional AND.
- + (integer float string) - Returns the addition of two objects, according to their type.
- - (integer float) - Returns the subtraction of two objects, according to their type.
- IIf(cond,res1,res2) - Returns res1 when cond is true, otherwise returns res2.
Example: https://[IIf([IsCloud]==true,"api-","")][Domain]...
In this case, when the variable [IsCloud] is true, the string value “api-” will be added to the value of the [Domain] variable, to create the proper URL. Please note the square brackets that act around the “IIf” operator.
Call Journaling
3CX Phone System supports reporting external calls to CRM. To support call journaling, you just need to create a scenario with the reserved name “ReportCall”. This scenario doesn’t return any data, so you should not provide <Rules/>, <Variables/> and <Outputs/> nodes. Only a <Request>, <Query> or <Command> element is required, according to the type of scenario.
Check the CRM templates provided by 3CX to see Call Journaling examples.
Chat Journaling
3CX Phone System supports reporting chats to the CRM. To support chat journaling, you just need to create a scenario with the reserved name “ReportChat”. This scenario doesn’t return any data, so you should not provide <Rules/>, <Variables/> and <Outputs/> nodes. Only a <Request>, <Query> or <Command> element is required, according to the type of scenario.
Check the CRM templates provided by 3CX to see Chat Journaling examples.
Lookup from a CFD application
3CX Phone System supports searching contacts in the CRM from a CFD app. To support this, you just need to create a scenario with one or more of the following reserved names:
- “LookupFromCFD_Contacts_LookupNumber”
- “LookupFromCFD_Contacts_LookupID”
- “LookupFromCFD_Contacts_LookupFreeQuery”
- “LookupFromCFD_Leads_LookupNumber”
- “LookupFromCFD_Leads_LookupID”
- “LookupFromCFD_Leads_LookupFreeQuery”
- “LookupFromCFD_Accounts_LookupNumber”
- “LookupFromCFD_Accounts_LookupID”
- “LookupFromCFD_Accounts_LookupFreeQuery”
These scenarios will return the entire JSON or XML received from the CRM, to the CFD application. No output must be included in this scenario.
Check the CRM templates provided by 3CX to see Lookup from CFD scenarios examples.
Debugging
The 3CX System Service is responsible for executing the server side CRM engine, for every inbound and outbound call in the system. This service loads the templates during startup, and keeps them in memory as long as the process is running. Therefore, any change to a template requires the 3CX service to be restarted, for the changes to be applied.
In order to debug a template without making real calls, use the Test button in the 3CX Console > Settings > CRM Integration page.
See Also
- Integrating a CRM using the CRM Integration Wizard
- Bitrix24 CRM Integration
- ConnectWise CRM Integration
- Freshdesk Integration
- Jetpack CRM Integration
- Zendesk CRM Integration
- Microsoft SQL Server, MySQL, PostgreSQL Database Integration
Last Updated
This document was last updated on 22 May 2024