WhosOn Backend API

Introduction

The WhosOn Backend API enables developers and system integrators to access completed WhosOn Chats as self-contained JSON objects via the WhosOn Server 'Chat Archiving' feature. Once the Chat Archiving feature is enabled, the WhosOn Server will output chat JSON objects automatically as chats complete. The chat JSON can then be used to integrate with other applications, to provide custom reporting, or simply as a secure archive.

Chat Archiving

The WhosOn Server archives completed chats as self-contained JSON documents. Chats are archived as they complete.

Chats can be archived to:

  1. A Microsoft Azure Cosmos Database.
  2. A Webhook of your choice.
  3. A local folder on the WhosOn Server file system.

Any chats that change after being archived (eg: following a missed-chat response) will be updated.

Any chats specifically deleted by Admins using the client will be removed.

All chats are archived, including missed chats and Bot-Taken chats.

Chats deleted from the local database as part of the WhosOn Server daily database maintenance will not be removed from the archive.

Archiving Frequency

The WhosOn Server performs chat archiving once per minute. New chats completed or updated since the last archive run will be archived.

Enabling Chat Archiving

Chat Archiving is enabled using the WhosOn Service Manager.

Chat Archiving can be enabled server-wide for all monitored sites, or on a site-by-site basis.

WhosOn Server-Wide

Using the WhosOn Service Manager, go to: Server Settings - Chat Archiving tab.

Type Notes
Cosmos To enable Cosmos Archiving enable the Enable Azure Cosmos DB Archiving Of Chats setting. You must then enter your End Point URL and Key. You must setup an Azure Cosmos DB on your Azure Account prior to this. Important: Ensure you add the WhosOn Server IP to the Cosmos firewall.
Webhook To enable Webhook Archiving enable the Enable External Archiving Of Chats option. You must then enter the URL. This is the URL that will receive the JSON via HTTP Posts.
Folder To enable local folder saving, enter or select the local path to save the JSON files to.

Note: You can enable any or all of these options.

Note: Cosmos Keys are stored encrypted in the WhosOn Local Settings.

Site Specific

To enable Chat Archiving for a specific site go to: Sites - Monitored Site - Chat Archiving tab.

You can then use the same options as above.

Note: The site specific archiving options will override any server-wide settings.

Archiving Types

Azure Cosmos

Azure Cosmos DB is a fully managed database service with turnkey global distribution and transparent multi-master replication. With single-digit millisecond read and write latencies at the 99th percentile, automatic and elastic scaling of throughput and storage worldwide, 99.999-per cent high availability, and five well-defined consistency choices – all backed by industry-leading comprehensive SLAs.

Cosmos data is encrypted at rest by default.

The WhosOn Server creates a Cosmos Database for each WhosOn Site against the Azure end-point specified (using the site domain name as the database name).

A chats collection is created within the database. Once Archiving is enabled against a site then all previous chats will be archived (regardless of their age).

The Cosmos Site database will be removed if the site is deleted from WhosOn.

For more information about Azure Cosmos DB go to: https://azure.microsoft.com/en-us/services/cosmos-db/

Webhook

Chats can also be sent to your own custom webhook. The WhosOn Server will make a HTTP post to the URL specified. The post is in application/json format.

The WhosOn Server also adds the following headers to the post request:

Header Value
X-WhosOn-Server The external address of the WhosOn Server.
X-WhosOn-Registered The registered name assigned to the WhosOn Server.
X-WhosOn-Domain The site domain name for the accompanying chat.
X-WhosOn-SiteKey The numeric site key for the site.
X-WhosOn-ChatUID The chat uid.

Local Folder

Individual JSON files will be saved to the specified local folder. The filenames will be {chatuid}.json. If an existing chat is updated then the existing file will be overwritten. It is safe to delete the files at any time.

Chat Archiving Use Cases

Integration

The Archive can be used to integrate chat data with other applications. Using Azure Cosmos you can create Azure functions that trigger automatically when new chat documents are added. Azure functions can be used to automate integration tasks easily.

Reporting

You can create your own reports and dashboards that query the archive. This would execute independently from the WhosOn Server and therefore not affect server performance. A number of 3rd party reporting solutions are already available that work with Azure Cosmos DB, including Microsoft Power BI, Qlik Sense. Cosmos DB provides a SQL API allowing data to be queried using any development tool.

Performance

Once archiving is enabled it is then possible to remove chats from the local WhosOn SQL database faster. For example, chats could be removed after 3 months instead of 3 years. This improves the performance and storage requirements of the local database.

Compliance

The Azure Cosmos Database provides a trusted, secure, globally distributed database service. To help customers meet their own compliance obligations across regulated industries and markets worldwide, Azure maintains the largest compliance portfolio in the industry in terms of both breadth (total number of offerings) and depth (number of customer-facing services in assessment scope).

See: https://docs.microsoft.com/en-us/azure/cosmos-db/compliance for more information.

Chat JSON Format

Regardless of the Archiving method (Cosmos, Webhook or Local Folder) the WhosOn Server produces the same chat JSON. Each JSON document is self-contained with all the information about the chat, including: visitor details, contact information, geo-ip, transcript lines, wrapup, pre & post-chat survey values.

  • The id is the unique Chat Uid.
  • The Site contains the Domain and site Name of the monitored site in WhosOn assigned to the chat.
  • The Visitor object contains info about the WhosOn Visitor associated with the chat.
  • The Visitor.ContactRecord contains the current visitor contact info.
  • The Visitor.GeoIP object contains the Geo-IP data assigned to the visitor's IP address.
  • The Operators list contains all operators that have chatted to the visitor.
  • The Transcript list contains all chat lines. Lines with IsServerMessage=True will be log messages added by the server and the OperatorName will be the server registered user.
  • The TelephoneCalls list contains any Twilio callbacks made during the chat.
{
     "id": "51xc78h4p2",
     "Site": {
         "Domain": "www.mycompany.com",
         "Name": "My Company Inc"
     },
     "Visitor": {
         "Name": "John",
         "CompanyName": "Visitor Company",
         "IPAddress": "195.62.193.194",
         "DNS": "19419362195.visitorcompany.com",
         "Page": "chat.aspx",
         "EntryAlert": "Google (All Other Visitors)",
         "EmailAddress": "johndoe@visitorcompany.com",
         "PhoneNumber": "+44123456789",
         "VisitNumber": 62,
         "VisitDate": "2019-06-10T13:47:26.263",
         "FirstPage": "chat.aspx",
         "PageViews": 1,
         "Referer": "https://www.google.com",
         "OperatingSystem": "Windows 10",
         "Browser": "Chrome 75",
         "Prospect": false,
         "Customer": false,
         "GeoIP": {
             "IPAddress": "195.62.193.194",
             "IsProxy": false,
             "IsSatellite": false,
             "PostCode": "ST1",
             "Latitude": 53.0278,
             "Longitude": -2.1658,
             "Radius": 20,
             "ISP": "Internet Central Limited",
             "CountryISO": "GB",
             "CountryName": "United Kingdom",
             "City": "Stoke-on-Trent",
             "MetroCode": "",
             "Organization": "Visitor Company",
             "RegionName": "",
             "RegionISO": ""
         },
         "GeoIPLocation": {
             "type": "Point",
             "coordinates": [
                 53.0278,
                 -2.1658
             ]
         },
         "Language": "en",
         "ContactRecord": {
             "Name": "John",
             "EmailAddress": "johndoe@visitorcompany.com",
             "PhoneNumber": "+44123456789",
             "CompanyName": "Visitor Company",
             "Street": "",
             "City": "",
             "ZIP": "",
             "Country": "",
             "WebAddress": "",
             "CRMID": "",
             "Notes": ""
         }
     },
     "Operators": [
        {
            "Name": "Jane Doe",
            "Department": "Management",
            "Skills": "Sales,Support",
            "EmailAddress": "jane@mycompany.com",
            "PhoneNumber": "sip:110@sip.mycompany.com",
            "IsBot": false
        }
     ],
     "Started": "2019-06-10T13:47:38.317",
     "Finished": "2019-06-10T13:50:03.753",
     "Invited": false,
     "Taken": true,
     "RequestedDepartment": "",
     "RequestedUserName": null,
     "RequestedSkills": [
         "Sales"
     ],
     "RequestedTranslation": false,
     "RequestedCallBack": false,
     "RequestedCallBackOn": "0001-01-01T00:00:00",
     "WaitedForSeconds": 4,
     "ChattedForSeconds": 145,
     "PreChatSurvey": [
        {
            "FieldName": "Company",
            "FieldValue": "Visitor Company"
        }
     ],
     "PostChatSurvey": [
         {
            "FieldName": "Rating",
            "FieldValue": "5"
         },
         {
            "FieldName": "transEmail",
            "FieldValue": ""
         }
     ],
     "Transcript": [
         {
            "Number": 1,
            "Dated": "2019-06-10T13:47:33.377",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": true,
            "OperatorName": "My Company Inc",
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "Please wait. An operator will be with you shortly."
         },
         {
            "Number": 2,
            "Dated": "2019-06-10T13:47:38.347",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": true,
            "OperatorName": null,
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "[OP] Operator Jane Doe picked up session. (John)"
         },
         {
            "Number": 3,
            "Dated": "2019-06-10T13:47:40.51",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": false,
            "OperatorName": "Jane Doe",
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "Good Afternoon John. My name is Jane Doe how can I help you?"
         },
         {
            "Number": 4,
            "Dated": "2019-06-10T13:47:51.227",
            "IsLink": false,
            "IsVisitor": true,
            "IsOperator": false,
            "IsServerMessage": false,
            "OperatorName": null,
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "Hello. I need a price for WhosOn"
         },
         {
            "Number": 5,
            "Dated": "2019-06-10T13:48:45.103",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": false,
            "OperatorName": "Jane Doe",
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "Ok. How many users?"
         },
         {
            "Number": 6,
            "Dated": "2019-06-10T13:48:54.073",
            "IsLink": false,
            "IsVisitor": true,
            "IsOperator": false,
            "IsServerMessage": false,
            "OperatorName": null,
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "5"
         },
         {
            "Number": 7,
            "Dated": "2019-06-10T13:49:02.787",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": false,
            "OperatorName": "Jane Doe",
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "Is this hosted or installable?"
         },
         {
            "Number": 8,
            "Dated": "2019-06-10T13:49:05.95",
            "IsLink": false,
            "IsVisitor": true,
            "IsOperator": false,
            "IsServerMessage": false,
            "OperatorName": null,
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "Hosted"
         },
         {
            "Number": 9,
            "Dated": "2019-06-10T13:49:12.283",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": false,
            "OperatorName": "Jane Doe",
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "What is your email address?"
         },
         {
            "Number": 10,
            "Dated": "2019-06-10T13:49:25.927",
            "IsLink": false,
            "IsVisitor": true,
            "IsOperator": false,
            "IsServerMessage": false,
            "OperatorName": null,
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "johndoe@visitorcompany.com"
         },
         {
            "Number": 11,
            "Dated": "2019-06-10T13:49:36.073",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": false,
            "OperatorName": "Jane Doe",
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "Ok I will email you a quotation now"
         },
         {
            "Number": 12,
            "Dated": "2019-06-10T13:49:43.967",
            "IsLink": false,
            "IsVisitor": true,
            "IsOperator": false,
            "IsServerMessage": false,
            "OperatorName": null,
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "thank you."
         },
         {
            "Number": 13,
            "Dated": "2019-06-10T13:49:56.387",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": false,
            "OperatorName": "Jane Doe",
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "No problem. Bye for now"
         },
         {
            "Number": 14,
            "Dated": "2019-06-10T13:50:03.737",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": true,
            "OperatorName": null,
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "[OC] Operator Jane Doe forced closed session."
         },
         {
            "Number": 15,
            "Dated": "2019-06-10T13:50:04.087",
            "IsLink": false,
            "IsVisitor": false,
            "IsOperator": true,
            "IsServerMessage": true,
            "OperatorName": null,
            "Translated": "",
            "FileName": null,
            "FileURL": null,
            "Text": "[VC] Visitor closed session."
         },
     ],
     "TelephoneCalls": [
         {
            "CalledBy": {
                "Name": "Jane Doe",
                "Department": "Management",
                "Skills": "Sales,Support",
                "EmailAddress": "jane@mycompany.com",
                "PhoneNumber": "sip:110@sip.mycompany.com",
                "IsBot": false
         },
         "FromNumber": "sip:110@sip.mycompany.com",
         "ToNumber": "+44123456789",
         "CallStarted": "2019-06-10T13:50:03.737",
         "Duration": 0,
         "Status": "",
         "RecordingURL": ""
        }
     ],
     "Rating": 5,
     "SentimentScore": 100,
     "WrapUpValue": "Quote",
     "Tags": [
         "Sales",
         "Quotation"
     ],
     "Missed": false,
     "MissedResponded": false,
     "MissedRespondedBy": null,
     "MissedRespondedDate": "0001-01-01T00:00:00",
     "Summary": "I need a price for whoson.",
     "LeftMessageMessage": ""
 }

(c) Parker Software 2019 https://www.whoson.com