API Not updating data to clients

Status
Not open for further replies.

Triple

Customer
Joined
Aug 5, 2020
Messages
32
Reaction score
5
So i've implemented the 3CX CRM Rest API with our CRM system like described here: https://www.3cx.com/docs/crm-integration/ When i test the API using the Test function in the backend than everything works except for two things:

1. The API Test shows the message " CRM Integration is working OK but contact number does not exist. Check log for more info or try a different number." when it receives response from our CRM.
2. In the live situation the Phone Contact lookup works as far as data is given back to 3CX however i would expect that all client showing the number would get updated with the data Contact information retrieved from our CRM. But this doesn't happen.
3. If i call from the same number twice that the GET ~/api/search?Phone=[PhoneNumber] isn't fired from 3CX?

This is our template:

XML:
<?xml version="1.0"?>
<Crm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Country="US" Name="TripleCRM" Version="1">
  <Number Prefix="AsIs" MaxLength="[MaxLength]" />
  <Connection MaxConcurrentRequests="2" />
  <Parameters>
    <Parameter Name="ReportCallEnabled" Type="Boolean" Editor="String" Title="Enable Call Journaling" Default="False" />
    <Parameter Name="Subject" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Call Subject:" Default="3CX PhoneSystem Call" />
    <Parameter Name="InboundCallText" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Answered Inbound Call:" Default="[DateTime]: Answered incoming call from [Number] to [Agent] ([Duration])" />
    <Parameter Name="MissedCallText" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Missed Call:" Default="[DateTime]: Missed call from [Number] to [Agent]" />
    <Parameter Name="OutboundCallText" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Answered Outbound Call:" Default="[DateTime]: Answered outgoing call from [Agent] to [Number] ([Duration])" />
    <Parameter Name="NotAnsweredOutboundCallText" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Unanswered Outbound Call:" Default="[DateTime]: Unanswered outgoing call from [Agent] to [Number]" />
  </Parameters>
  <Authentication Type="No">
    <Value>[APIkey]:X</Value>
  </Authentication>
  <Scenarios>
    <Scenario Id="" Type="REST">
      <Request Url="http://192.168.0.133:3721/api/search?Phone=[Number]" MessagePasses="0" RequestEncoding="UrlEncoded" RequestType="Get" ResponseType="Json" />
      <Rules>
        <Rule Type="Any">contact_id</Rule>
      </Rules>
      <Variables>
        <Variable Name="ContactID" Path="contact_id">
          <Filter />
        </Variable>
        <Variable Name="FirstName" Path="contact_firstname">
          <Filter />
        </Variable>
        <Variable Name="LastName" Path="contact_lastname">
          <Filter />
        </Variable>
        <Variable Name="CompanyName" Path="contact.company">
          <Filter />
        </Variable>
        <Variable Name="PhoneBusiness" Path="contact_businessphone1">
          <Filter />
        </Variable>
        <Variable Name="PhoneBusiness2" Path="contact_businessphone2">
          <Filter />
        </Variable>
        <Variable Name="PhoneMobile" Path="contact_mobilephone1">
          <Filter />
        </Variable>
        <Variable Name="PhoneMobile2" Path="contact_mobilephone2">
          <Filter />
        </Variable>
      </Variables>
      <Outputs AllowEmpty="false">
        <Output Type="ContactID" Passes="0" Value="[ContactID]" />
        <Output Type="FirstName" Passes="0" Value="[FirstName]" />
        <Output Type="LastName" Passes="0" Value="[LastName]" />
        <Output Type="CompanyName" Passes="0" Value="[CompanyName]" />
        <Output Type="PhoneBusiness" Passes="0" Value="[PhoneBusiness]" />
        <Output Type="PhoneBusiness2" Passes="0" Value="[PhoneBusiness2]" />
        <Output Type="PhoneMobile" Passes="0" Value="[PhoneMobile]" />
        <Output Type="PhoneMobile2" Passes="0" Value="[PhoneMobile2]" />
        <Output Type="ContactUrl" Passes="0" Value="http://192.168.0.233/show?ContactID=123456" />
      </Outputs>
    </Scenario>
    <Scenario Id="ReportCall" Type="REST">
      <Request SkipIf="[ReportCallEnabled]!=True||[CallType]!=Inbound" Url="http://192.168.0.133:3721/api/createCall" MessagePasses="0" RequestContentType="application/json" RequestEncoding="Json" RequestType="Post" ResponseType="Json">
        <PostValues Key="">
          <Value Key="duration" Passes="1" Type="String">[Duration]</Value>
          <Value Key="phone" Passes="1" Type="String">[Number]</Value>
          <Value Key="agent" Passes="1" Type="String">[Agent]</Value>
        </PostValues>
      </Request>
      <Variables />
      <Outputs Next="ReportCallMissed" AllowEmpty="true" />
    </Scenario>
    <Scenario Id="ReportCallMissed" Type="REST">
      <Request SkipIf="[ReportCallEnabled]!=True||[CallType]!=Missed" Url="http://192.168.0.133:3721/api/createCall" MessagePasses="0" RequestContentType="application/json" RequestEncoding="Json" RequestType="Post" ResponseType="Json">
        <PostValues Key="">
          <Value Key="duration" Passes="1" Type="String">[Duration]</Value>
          <Value Key="phone" Passes="1" Type="String">[Number]</Value>
          <Value Key="agent" Passes="1" Type="String">[Agent]</Value>
        </PostValues>
      </Request>
      <Variables />
      <Outputs Next="ReportCallOutbound" AllowEmpty="true" />
    </Scenario>
    <Scenario Id="ReportCallOutbound" Type="REST">
      <Request SkipIf="[ReportCallEnabled]!=True||[CallType]!=Outbound" Url="http://192.168.0.133:3721/api/createCall" MessagePasses="0" RequestContentType="application/json" RequestEncoding="Json" RequestType="Post" ResponseType="Json">
        <PostValues Key="">
          <Value Key="duration" Passes="1" Type="String">[Duration]</Value>
          <Value Key="phone" Passes="1" Type="String">[Number]</Value>
          <Value Key="agent" Passes="1" Type="String">[Agent]</Value>
        </PostValues>
      </Request>
      <Variables />
      <Outputs Next="ReportCallNotanswered" AllowEmpty="true" />
    </Scenario>
    <Scenario Id="ReportCallNotanswered" Type="REST">
      <Request SkipIf="[ReportCallEnabled]!=True||[CallType]!=Notanswered" Url="http://192.168.0.133:3721/api/createCall" MessagePasses="0" RequestContentType="application/json" RequestEncoding="Json" RequestType="Post" ResponseType="Json">
        <PostValues Key="">
          <Value Key="duration" Passes="1" Type="String">[Duration]</Value>
          <Value Key="phone" Passes="1" Type="String">[Number]</Value>
          <Value Key="agent" Passes="1" Type="String">[Agent]</Value>
        </PostValues>
      </Request>
      <Variables />
      <Outputs AllowEmpty="false" />
    </Scenario>
  </Scenarios>
</Crm>
 
Did some more comparison with other XML templates and i adjusted my but it still makes no difference. This is the XML i got so far:


XML:
<?xml version="1.0"?>
<Crm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Country="US" Name="TripleCRM2" Version="1">
  <Number Prefix="AsIs" MaxLength="[MaxLength]" />
  <Connection MaxConcurrentRequests="15" />
  <Parameters>
    <Parameter Name="ReportCallEnabled" Type="Boolean" Editor="String" Title="Enable Call Journaling" Default="True" />
    <Parameter Name="Subject" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Call Subject:" Default="3CX PhoneSystem Call" />
    <Parameter Name="InboundCallText" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Answered Inbound Call:" Default="[DateTime]: Answered incoming call from [Number] to [Agent] ([Duration])" />
    <Parameter Name="MissedCallText" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Missed Call:" Default="[DateTime]: Missed call from [Number] to [Agent]" />
    <Parameter Name="OutboundCallText" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Answered Outbound Call:" Default="[DateTime]: Answered outgoing call from [Agent] to [Number] ([Duration])" />
    <Parameter Name="NotAnsweredOutboundCallText" Type="String" Parent="ReportCallEnabled" Editor="String" Title="Unanswered Outbound Call:" Default="[DateTime]: Unanswered outgoing call from [Agent] to [Number]" />
  </Parameters>
  <Authentication Type="No" />
  <Scenarios>
    <Scenario Id="" Type="REST">
      <Request Url="http://192.168.0.133:3721/api/search?Phone=[Number]" MessagePasses="0" RequestEncoding="UrlEncoded" RequestType="Get" ResponseType="Json" />
      <Rules>
        <Rule Type="Any">id</Rule>
      </Rules>
      <Variables>
        <Variable Name="ContactID" Path="id">
          <Filter />
        </Variable>
        <Variable Name="FirstName" Path="firstname">
          <Filter />
        </Variable>
        <Variable Name="LastName" Path="lastname">
          <Filter />
        </Variable>
        <Variable Name="CompanyName" Path="company">
          <Filter />
        </Variable>
        <Variable Name="Email" Path="email">
          <Filter />
        </Variable>
        <Variable Name="PhoneBusiness" Path="businessphone">
          <Filter />
        </Variable>
        <Variable Name="PhoneMobile" Path="phonemobile">
          <Filter />
        </Variable>
        <Variable Name="ContactUrl" Path="url">
          <Filter />
        </Variable>
      </Variables>
      <Outputs AllowEmpty="false">
        <Output Type="ContactID" Passes="0" Value="[ContactID]" />
        <Output Type="FirstName" Passes="0" Value="[FirstName]" />
        <Output Type="LastName" Passes="0" Value="[LastName]" />
        <Output Type="CompanyName" Passes="0" Value="[CompanyName]" />
        <Output Type="Email" Passes="0" Value="[Email]" />
        <Output Type="PhoneBusiness" Passes="0" Value="[PhoneBusiness]" />
        <Output Type="PhoneMobile" Passes="0" Value="[PhoneMobile]" />
        <Output Type="ContactUrl" Passes="0" Value="[ContactUrl]" />
      </Outputs>
    </Scenario>
    <Scenario Id="ReportCall" Type="REST">
      <Request SkipIf="[ReportCallEnabled]!=True||[CallType]!=Inbound" Url="http://192.168.0.133:3721/api/createCall" MessagePasses="0" RequestContentType="application/json" RequestEncoding="Json" RequestType="Post" ResponseType="Json">
        <PostValues Key="">
          <Value Key="duration" Passes="1" Type="String">[Duration]</Value>
          <Value Key="phone" Passes="1" Type="String">[Number]</Value>
          <Value Key="agent" Passes="1" Type="String">[Agent]</Value>
        </PostValues>
      </Request>
      <Variables />
      <Outputs Next="ReportCallMissed" AllowEmpty="true" />
    </Scenario>
    <Scenario Id="ReportCallMissed" Type="REST">
      <Request SkipIf="[ReportCallEnabled]!=True||[CallType]!=Missed" Url="http://192.168.0.133:3721/api/createCall" MessagePasses="0" RequestContentType="application/json" RequestEncoding="Json" RequestType="Post" ResponseType="Json">
        <PostValues Key="">
          <Value Key="duration" Passes="1" Type="String">[Duration]</Value>
          <Value Key="phone" Passes="1" Type="String">[Number]</Value>
          <Value Key="agent" Passes="1" Type="String">[Agent]</Value>
        </PostValues>
      </Request>
      <Variables />
      <Outputs Next="ReportCallOutbound" AllowEmpty="true" />
    </Scenario>
    <Scenario Id="ReportCallOutbound" Type="REST">
      <Request SkipIf="[ReportCallEnabled]!=True||[CallType]!=Outbound" Url="http://192.168.0.133:3721/api/createCall" MessagePasses="0" RequestContentType="application/json" RequestEncoding="Json" RequestType="Post" ResponseType="Json">
        <PostValues Key="">
          <Value Key="duration" Passes="1" Type="String">[Duration]</Value>
          <Value Key="phone" Passes="1" Type="String">[Number]</Value>
          <Value Key="agent" Passes="1" Type="String">[Agent]</Value>
        </PostValues>
      </Request>
      <Variables />
      <Outputs Next="ReportCallNotanswered" AllowEmpty="true" />
    </Scenario>
    <Scenario Id="ReportCallNotanswered" Type="REST">
      <Request SkipIf="[ReportCallEnabled]!=True||[CallType]!=Notanswered" Url="http://192.168.0.133:3721/api/createCall" MessagePasses="0" RequestContentType="application/json" RequestEncoding="Json" RequestType="Post" ResponseType="Json">
        <PostValues Key="">
          <Value Key="duration" Passes="1" Type="String">[Duration]</Value>
          <Value Key="phone" Passes="1" Type="String">[Number]</Value>
          <Value Key="agent" Passes="1" Type="String">[Agent]</Value>
        </PostValues>
      </Request>
      <Variables />
      <Outputs AllowEmpty="false" />
    </Scenario>
  </Scenarios>
</Crm>

and then the received response:

Started scenario with empty id
Request text: http://192.168.0.133:3721/api/search?Phone=551234
Response text:
JSON:
{
  "contact": {
    "id": 156,
    "firstname": "API",
    "lastname": "Test",
    "company": "HelloWorld",
    "businessphone": "551234",
    "phonemobile": "551234",
    "email": "[email protected]"
  }
}
Response finished
Finished scenario with empty id
 
Last edited:
Change all the path for fields to "contact.<field>" as well as the rule to "contact.id".

Contact is the root object of your JSON. You have to specify it.
 
  • Like
Reactions: edossantos
2. In the live situation the Phone Contact lookup works as far as data is given back to 3CX however i would expect that all client showing the number would get updated with the data Contact information retrieved from our CRM. But this doesn't happen.
Do you mean that the caller name is not shown in some devices? Usually, this is the case for the first call from a contact, when not using the 3CX Web Client. However, if you use the Web Client, the contact details should be visible even for the first call. This is because the call is sent to the phone before getting back the result, and we can't change it afterwards. But from the Web Client we can do this update.

3. If i call from the same number twice that the GET ~/api/search?Phone=[PhoneNumber] isn't fired from 3CX?
This is the expected behaviour, as there is a 10 minutes cache. So the second call during these 10 minutes will get the contact details from cache, instead of doing the lookup in the CRM.
 
  • Like
Reactions: Evolute IT
Change all the path for fields to "contact.<field>" as well as the rule to "contact.id".

Contact is the root object of your JSON. You have to specify it.

Is that still needed if i change it to:
JSON:
{
    "id": 156,
    "firstname": "API",
    "lastname": "Test",
    "company": "HelloWorld",
    "businessphone": "551234",
    "phonemobile": "551234",
    "email": "[email protected]"
}


Do you mean that the caller name is not shown in some devices? Usually, this is the case for the first call from a contact, when not using the 3CX Web Client. However, if you use the Web Client, the contact details should be visible even for the first call. This is because the call is sent to the phone before getting back the result, and we can't change it afterwards. But from the Web Client we can do this update.
Yes, for example: We all use the 3CX Webclient extension in Chromium Edge. Our contact from our CRM aren't synced to the 3CX internal Phonebook. When a customer calls then we receive GET ~/api/search?Phone=[PhoneNumber] and we return all the contact information from our CRM. What i then would expect is with that information 3CX would update all 3CX Webclients (chromium edge extension) with the retrieved contact information. However this doesn't happen. Side question but when a contact-information is retrieved is it then possible for 3CX to add it to it's internal PhoneBook?

This is the expected behaviour, as there is a 10 minutes cache. So the second call during these 10 minutes will get the contact details from cache, instead of doing the lookup in the CRM.

Thanks for confirming that. What will it do when no information is returned the first time but the CRM gets updated in the meantime?
 
Little update: Managed to get it all working now. Though i was wondering if you get get the Agent Contact Name from the 3CX. Now you only have [Agent]. we've added all info to the contact list in 3CX
 
Is that still needed if i change it to:
JSON:
{
"id": 156,
"firstname": "API",
"lastname": "Test",
"company": "HelloWorld",
"businessphone": "551234",
"phonemobile": "551234",
"email": "[email protected]"
}
No, it wouldn't be needed but I'd keep the main "contact" object. It makes the API cleaner.

What i then would expect is with that information 3CX would update all 3CX Webclients (chromium edge extension) with the retrieved contact information. However this doesn't happen.
If the number is matched to a CRM contact, they should appear in the Webclient/Windows app. HOWEVER, you MUST have a Contact URL variable (even if it's just basically the contact ID). 3CX uses that to link contacts in the phonebook and call journaling.

Side question but when a contact-information is retrieved is it then possible for 3CX to add it to it's internal PhoneBook?
As said above, if you have a Contact URL set (necessary), yes it will save it to the phonebook and update the entry on future calls. Note that there's a 10min cache between request so if you update right after a call and then redial, it won't appear.

Thanks for confirming that. What will it do when no information is returned the first time but the CRM gets updated in the meantime?
As above, the cache is 10min. Outside of that, the service asks the API on every call (if query is set to always). It would update infos and the Webclient would have it show up. Also, starting the 2nd call, deskphones would get it too.

Though i was wondering if you get get the Agent Contact Name from the 3CX. Now you only have [Agent]. we've added all info to the contact list in 3CX
No, unfortunately, only the agent extension. You can look at Salesforce CRM template, they do a lookup on the User object to get the related agent by its extension. This way, the call log is assigned to the contact and the agent correctly.
 
  • Like
Reactions: edossantos
Thanks! I all got it working now. Was wondering though if you can pass with the GET ~/api/search?Phone=[PhoneNumber] command also to which number the incomming call is? We have 10+ phonenumbers connected to our 3CX so it would be usefull to see who is calling to which number.
 
Thanks! I all got it working now. Was wondering though if you can pass with the GET ~/api/search?Phone=[PhoneNumber] command also to which number the incomming call is? We have 10+ phonenumbers connected to our 3CX so it would be usefull to see who is calling to which number.
No you can't. Only incoming CID.
 
Alright, thanks!
 
I'm struggling with the contact URL. Because our CRM system has no Web ContactUrl available so our CRM <> 3CX plugin/middleware acts as a REST webserver. No problem their but is it necessary to fill in the URL and if so what should be returned? Because what i noticed that when i create an contact URL and response to it when requested from 3CX with the JSON used earlier bij the CRM Lookup from 3CX, then a browser always popups with the URL of the contact. This is not the desired behaviour.
 
I'm struggling with the contact URL. Because our CRM system has no Web ContactUrl available so our CRM <> 3CX plugin/middleware acts as a REST webserver. No problem their but is it necessary to fill in the URL and if so what should be returned? Because what i noticed that when i create an contact URL and response to it when requested from 3CX with the JSON used earlier bij the CRM Lookup from 3CX, then a browser always popups with the URL of the contact. This is not the desired behaviour.
You need to return a different URL for each contact, because this is treated as the primary key. Otherwise the integration will not work. You can turn off the popup from the Web Client > Settings > Integration.
 
  • Like
Reactions: Evolute IT
Alright, that seems to does the trick! Is there also a document available where this settings for the Webclient contact popup is stored so i can apply it to all clients?

Other question; So i understand that in the CRM Lookup API the DID(To which number is being called) is not available but the Agent is, so i can do some magic on that but when i add it the the Phone Search URL like below that the GET doens't get triggered anymore.

Rich (BB code):
GET ~/api/search?Phone=[Number]&amp;Agent=[Agent]
 
Alright, that seems to does the trick! Is there also a document available where this settings for the Webclient contact popup is stored so i can apply it to all clients?
I'm not sure to understand what you mean. Can you please elaborate a bit more on what you need to do? The contact details are only available in the Web Client and the Chrome Extension. No other client will get this information.

Other question; So i understand that in the CRM Lookup API the DID(To which number is being called) is not available but the Agent is, so i can do some magic on that but when i add it the the Phone Search URL like below that the GET doens't get triggered anymore.
During contact lookup, only the caller number is available in the [Number] variable. The agent is only available during call journaling. Here you have the details of the variables you have in each scenario:
https://www.3cx.com/docs/server-side-crm-template-xml-description/#h.vcivldjsa1lz
 
  • Like
Reactions: Evolute IT
I'm not sure to understand what you mean. Can you please elaborate a bit more on what you need to do? The contact details are only available in the Web Client and the Chrome Extension. No other client will get this information.
Sorry for that, i meant to say that where does the Web Client store it's local user settings? Is that in windows registry or in file? In this way i can turn off the setting "Contact Popup" under Web Client > Settings > Integration for all Web clients we have.


During contact lookup, only the caller number is available in the [Number] variable. The agent is only available during call journaling. Here you have the details of the variables you have in each scenario:
https://www.3cx.com/docs/server-side-crm-template-xml-description/#h.vcivldjsa1lz

Hmm that's to bad. How would one detect what incoming number is calling? The reason i ask is because we have several different phone numbers that our customers can call but not all numbers need to do a Contact Lookup.
 
Sorry for that, i meant to say that where does the Web Client store it's local user settings? Is that in windows registry or in file? In this way i can turn off the setting "Contact Popup" under Web Client > Settings > Integration for all Web clients we have.
No, this is stored in the 3CX configuration in the server, there is no supported way of changing all of them at once.

Hmm that's to bad. How would one detect what incoming number is calling? The reason i ask is because we have several different phone numbers that our customers can call but not all numbers need to do a Contact Lookup.
Contact lookup is triggered for all the calls that arrive to 3CX through an external line. Unfortunately there is no way to filter this as you need.
 
  • Like
Reactions: Evolute IT
No, this is stored in the 3CX configuration in the server, there is no supported way of changing all of them at once.

Under which tab can i find/adjust this?

Contact lookup is triggered for all the calls that arrive to 3CX through an external line. Unfortunately there is no way to filter this as you need.

Alright, that's to bad. Just a thought but let's say i don't use the CRM Integration instead i use the Call Flow Designer to first detect which number is being called and then will use the CRM Lookup object to get the information from our CRM? And for the Call journal, we are only intrested in Inbound call so a Flow like Call Inbound ended, POST call information to CRM.

Could something like these two conditions be made with the Call Flow Designer?
 
Alright, that's to bad. Just a thought but let's say i don't use the CRM Integration instead i use the Call Flow Designer to first detect which number is being called and then will use the CRM Lookup object to get the information from our CRM? And for the Call journal, we are only intrested in Inbound call so a Flow like Call Inbound ended, POST call information to CRM.

Could something like these two conditions be made with the Call Flow Designer?
You can't do this from a CFD app, because the app would be executed before the call is sent to the extension. Once the app transfers the call to the next endpoint (a queue or extension), it doesn't know about it anymore.

Maybe what you can do is parsing the generated CDRs using a custom program, and report to your CRM only the calls in which you are interested.
 
Status
Not open for further replies.

Latest Posts

Forum statistics

Threads
112,325
Messages
591,898
Members
165,477
Latest member
Mueller