ECE Messaging API & Webhook Server

  • Add an 'External App' 'Authentication'
    • Partition → Integration → External Apps → Authentication
      • Add → Name, Description, Type (General), Authentication Type (Basic or OAuth 2.0)
        • select 'Configuration' tab
        • For Basic Auth - just enter username / password.
        • For Oauth2.0 - enter the necessary fields.
  • Register a new Application
    • Partition → Integration → External Apps → Register Applications
      • In General Tab, enter 'Name', Application Type → Chat
      • In Callback URL enter
        • the URL of your webhook server (this comes from ECE Data Server), e.g. https://mywebhookserver/webhook1
        • callback format (JSON or XML)
        • Callback error notification email
        • Authentication (Select from dropdown - the application auth you created in the above step)
        • After Saving - Copy and save the Client Key and Client Secret
          • This is used by the API to login to ECE to retrieve the Bearer token - see example below.
          • The API uses Basic Auth and the client key is the username, and client secret is the password.
  • Add Messaging Adapter
    • Select the Relevant Department (where the entry points are).
      • Select Apps → Messaging Adaptors → 'New'
        • Select New
          • Enter Name, Description, the Registered App (created above)and assign the Entry Points to be allowed to be used with this 'messaging adaptor'.
          • Note custom messages can also be uploaded here
  • Login and get bearer token using basic auth of client key and secret (this lasts 24 hours)
  • Get the relevant Entrypoint and find its LastModifed Date
  • Start Conversation - Conversation and Activity ID returned - store the Conversation ID!
    • Set - email address of customer
    • Set - Entry point ID
    • Set - Entry point last modified date
    • Set - Enable start / end typing to be sent to webhook server if you want it (not enabled by default)
    • Retrieve in the response the Conversation ID and Activity ID
  • Send Message
    • Uses the Conversation ID
  • Receive messages via Webhook server (all agents responses sent to webhook server) - note we can also send & receive the start and end typing notifications (if enabled when we start the conversation).
  • End Conversation (HTTP PUT)
    • Conversation ID is in the URL

Reference: https://pubhub.devnetcloud.com/media/enterprise-chat-and-email/docs/guides/interaction-api-developer-guide/d7/d75/classclientapplications_1_1pages_1_1asyncmessaging_1_1_authenticate_page.html#

The authentication scheme used by this API. This API only supports “Basic” authentication scheme. Hence, the value must be “Basic ” followed by the base64 encoded string comprising of client key + colon + client secret. To elaborate, the value must be “Basic <base64 encoded value of <client_key>:<client_secret»”

Convert the client key and the client secret from the Registered App in ECE into Base 64. Example:

  • Client Key = ABCD
  • Client Secret = 01234
  • ABCD:01234 → QUJDRDowMTIzNA==

i.e. this is just Basic Auth - the username is the Client Key and the Password is the Client Secret.

HTTP Method: POST Authorization: Basic [Base 64 value of client key and secret - (see above)] Content-Type: application/x-www-form-urlencoded Accept: application/json Url-encode: grant_type=client_credentials

Example:

curl --location 'https://ece-webserver.mydomain.com/system/ws/v19/clientapplications/authentication/oauth2/token' \
--header 'Authorization: Basic QUJDRDowMTIzNA==' \
--header 'Accept: application/json' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials'

You should get a response with the Bearer token and when it will expire (24 hours).

Example HTTP Response

statusCode: 200 OK

{"access_token":"5a0f0bc4-dc21-44c8-a50b-b12bad7ae41e","expires_in":86400,"token_type":"Bearer"}

We need to get the Entrypoint - to find the lastModified Date of the EntryPoint ID. Which will be returned in along with other details.

This can be cached so there is no need to check the EntryPoint ID config, before starting every conversation, but if caching you should handle the error and re-retrieve the latest lastModified data again, if you get a 409 Conflict returned when starting a conversation.

curl --location 'https://ece-webserver.mydomain.com/system/ws/v19/clientapplications/messaging/configuration?entrypoint=1001' \
--header 'Authorization: Bearer 5a0f0bc4-dc21-44c8-a50b-b12bad7ae41e' \
--header 'Accept: application/json' \

Example HTTP Response

statusCode: 200 OK

{
    "entryPointConfiguration": [
        {
            "entryPoint": {
                "id": 1001
            },
            "lastModified": {
                "date": "2023-06-16T10:25:13.000Z"
            },
            "maskingConfiguration": {
                "patterns": {
                    "pattern": [
                        {
                            "name": "Visa Credit Card 16 Digits",
                            "maskingCharacter": "*",
                            "javascriptRegularExpression": "4(((\\r)?\\n){0,2}[0-9]){15}|4(((\\r)?\\n){0,2}[0-9]){3}(((\\r)?\\n){0,2}[-](((\\r)?\\n){0,2}[0-9]){4}){3}|4(((\\r)?\\n){0,2}[0-9]){3}(((((\\r)?\\n){1,2}[ ?])|([ ?]((\\r)?\\n){1,2})|([ ?]|((\\r)?\\n){1,2}))[0-9](((\\r)?\\n){0,2}[0-9]){3}){3}",
                            "javaRegularExpression": "4(((\\r)?\\n){0,2}[0-9]){15}|4(((\\r)?\\n){0,2}[0-9]){3}(((\\r)?\\n){0,2}[-](((\\r)?\\n){0,2}[0-9]){4}){3}|4(((\\r)?\\n){0,2}[0-9]){3}(((((\\r)?\\n){1,2}[ ?])|([ ?]((\\r)?\\n){1,2})|([ ?]|((\\r)?\\n){1,2}))[0-9](((\\r)?\\n){0,2}[0-9]){3}){3}",
                            "numOfCharsToUnmaskFromLeft": 0,
                            "numOfCharsToUnmaskFromRight": 0,
                            "applyLuhnAlgorithm": false
                        },
                        {
                            "name": "MasterCard Credit Cards",
                            "maskingCharacter": "*",
                            "javascriptRegularExpression": "5((\\r)?\\n){0,2}[1-5](((\\r)?\\n){0,2}[0-9]){14}|5((\\r)?\\n){0,2}[1-5](((\\r)?\\n){0,2}[0-9]){2}(((\\r)?\\n){0,2}[-](((\\r)?\\n){0,2}[0-9]){4}){3}|5((\\r)?\\n){0,2}[1-5](((\\r)?\\n){0,2}[0-9]){2}(((((\\r)?\\n){1,2}[ ?])|([ ?]((\\r)?\\n){1,2})|([ ?]|((\\r)?\\n){1,2}))([0-9]((\\r)?\\n){0,2}){3}[0-9]){3}",
                            "javaRegularExpression": "5((\\r)?\\n){0,2}[1-5](((\\r)?\\n){0,2}[0-9]){14}|5((\\r)?\\n){0,2}[1-5](((\\r)?\\n){0,2}[0-9]){2}(((\\r)?\\n){0,2}[-](((\\r)?\\n){0,2}[0-9]){4}){3}|5((\\r)?\\n){0,2}[1-5](((\\r)?\\n){0,2}[0-9]){2}(((((\\r)?\\n){1,2}[ ?])|([ ?]((\\r)?\\n){1,2})|([ ?]|((\\r)?\\n){1,2}))([0-9]((\\r)?\\n){0,2}){3}[0-9]){3}",
                            "numOfCharsToUnmaskFromLeft": 0,
                            "numOfCharsToUnmaskFromRight": 0,
                            "applyLuhnAlgorithm": false
                        }
                    ]
                },
                "enableOffRecordMessages": false
            },
            "attachmentPolicies": {
                "restrictionType": {
                    "value": "block_specific"
                },
                "fileExtensions": ".csv",
                "chatPolicy": {
                    "isEnabled": true,
                    "attachmentSize": 3
                }
            }
        }
    ]
}

Start the Conversation with the relevant EntryPoint ID, the last modified date of the entry point ID (see get EntryPoint details above) and the email address of the customer.

Note - we can also request to enable Typing notification (which is NOT enabled by default). To do so, include the variable sendTypingNotification in the URL and setting it to yes, and the webhook server will receive notification when the agent starts and stops typing.

Note when enabled - if the agent presses a key, the a start notification will be sent (see below for examples), once they stop typing it will wait about 5 seconds before sending a stop notification.

This can then be used to show or hide a “Agent is typing…” notification

The below also gives an example of setting a custom attribute - which in this the attribute name is: “activity_test_string1” The string supports only certain characters as documented below- note an example of a character which is NOT supported is the “+” symbol.

curl --location 'https://ece-webserver.mydomain.com/system/ws/v19/clientapplications/messaging/conversation/start?searchContactOnAttribute=email.emailAddress&sendTypingNotification=yes' \
--header 'Authorization: Bearer 5a0f0bc4-dc21-44c8-a50b-b12bad7ae41e' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Accept-Language: en-US' \
--data-raw '{
  "entryPointConfiguration": {
    "entryPoint": {
      "id": "1001"
    },
    "lastModified": {
      "date": "2023-06-16T10:25:13.000Z"
    }
  },
  "activity": {
    "subject":"Hello this is a summary - max of 255 characters",
    "customAttributes": {
        "customAttribute": [
            {
                "attribName":"activity_test_string1",
                "attribValues":{
                    "attribValue":[
                        {
                            "value":"Test String Value"
                        }
                    ]
                }
            }
        ]
    },        
    "payload": {
        "chat": {
            "clientInfo": {
                "referrerName": "TestReferrerName",
                "referrerUrl": "https://orourke.tv/chat/"
            }
        }
    },
    "customer": {
      "type": {
        "value": "individual"
      },
      "contacts": {
        "contact": [
          {
            "firstName": "Charlie",
            "lastName": "Cheeze",
            "email": [
              {
                "emailAddress": "[email protected]"
              }
            ]
          }
        ]
      }
    }
  }
}'

Example HTTP Response

statusCode: 200 OK

Note - this response includes the conversation id - although it just calls it “id” in the response, which is included in responses in sent to the webhook server and is also used in the Send Message API.

{
    "activity": {
        "case": {
            "id": 4329
        },
        "id": 4329
    },
    "id": "645ac530-7520-4daa-b95c-8e8cad6fcda7"
}

An example of an error response - if the Entry Point Modified Date was incorrect:

HTTP Status Code: 409

Body:

{
    "code": "409-100",
    "developerMessage": "Last modified date provided in the request body for the following  do not match : conversation.entryPointConfiguration."
}

The agent will respond to the chat - and these responses will be sent to the configured webhook server. To authenticate the responses - we can use OAuth or Basic Authentication.

Below is an example of the initial response sent by the system when the agent replied back with “Hello”. Note - how the Conversation ID matches the above - which we got as a response to the Start Conversation API Request.

As you can see from the below examples - we can see if the responses sent are from the agent OR from the system. e.g. when an agent is assigned to the chat, the ECE sends a message with

  • “sender”:{“type”:“system”}
    • “type”:{“value”:“assigned”}
    • and other relevant information (agent screen name for example).

When an agent completes the chat, ECE sends a system from

  • “sender”:{“type”:“system”}
    • “type”:{“value”:“complete”} etc.

When an agent sends a message to the customer, it uses

  • “sender”:{“type”: “user”,”user“}
    • “type”:{“value”:“text/html”},

with the content containing the message, e.g. “content”: “Hello”.

See below example for actual examples and some of the other details it also sends along with above.

{
"message":
    [
        {
        "content": "You are now chatting with Banana Man",
        "conversation":
            {
            "id": "02945e5e-d5a5-48c6-96f6-969c1c32d125"
            },
        "id": "7860514302",
        "sender":
            {
            "type": "system"
            },
        "timeStamp": 1736780710000,
        "type":
            {
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                },
            "value": "assigned"
            }
        },
        {
        "content": "Hello",
        "conversation":
            {
            "id": "02945e5e-d5a5-48c6-96f6-969c1c32d125"
            },
        "id": "6554364198",
        "sender":
            {
            "type": "user",
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                }
            },
        "timeStamp": 1736780853000,
        "type":
            {
            "value": "text/html"
            }
        }
    ]
}
{
"content": "Hello",
"conversation":
    {
    "id": "02945e5e-d5a5-48c6-96f6-969c1c32d125"
    },
"id": "6554364198",
"sender":
    {
    "type": "user",
    "user":
        {
        "name": "eir support1",
        "screenName": "Banana Man"
        }
    },
"timeStamp": 1736780853000,
"type":
    {
    "value": "text/html"
    }
}

An example from wireshark of a similar response to above is below - so you can see the Basic Auth and format of the message (which as per Content-Type is in JSON).

POST /webhook1 HTTP/1.1
Authorization: Basic TXlXZWJob29rVXNlcm5hbWU6TXlXZWJob29rUGFzc3dvcmQ=
Content-Type: application/json
Content-Length: 2370
Host: my-node-red-server.mydomain.com:1880
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.14 (Java/11.0.17)
Accept-Encoding: gzip,deflate
 
{
"message":
    [
        {
        "content": "You are now chatting with Banana Man",
        "conversation":
            {
            "id": "fb517e44-7b0a-492a-9be4-cfebcbae2012"
            },
        "id": "3109817384",
        "sender":
            {
            "type": "system"
            },
        "timeStamp": 1734457852000,
        "type":
            {
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                },
            "value": "assigned"
            }
        },
        {
        "content": "hi",
        "conversation":
            {
            "id": "fb517e44-7b0a-492a-9be4-cfebcbae2012"
            },
        "id": "5278750286",
        "sender":
            {
            "type": "user",
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                }
            },
        "timeStamp": 1734457861000,
        "type":
            {
            "value": "text/html"
            }
        },
        {
        "content": "hi",
        "conversation":
            {
            "id": "fb517e44-7b0a-492a-9be4-cfebcbae2012"
            },
        "id": "3468974654",
        "sender":
            {
            "type": "user",
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                }
            },
        "timeStamp": 1734458071000,
        "type":
            {
            "value": "text/html"
            }
        },
        {
        "content": "Banana Man has ended the chat",
        "conversation":
            {
            "id": "fb517e44-7b0a-492a-9be4-cfebcbae2012"
            },
        "id": "5981744797",
        "sender":
            {
            "type": "system"
            },
        "timeStamp": 1734462234000,
        "type":
            {
            "value": "complete"
            }
        },
        {
        "content": "You are now chatting with Banana Man",
        "conversation":
            {
            "id": "92554d9a-0266-425f-b2c6-fe39f4535d9f"
            },
        "id": "9972824079",
        "sender":
            {
            "type": "system"
            },
        "timeStamp": 1734462258000,
        "type":
            {
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                },
            "value": "assigned"
            }
        },
        {
        "content": "hi",
        "conversation":
            {
            "id": "92554d9a-0266-425f-b2c6-fe39f4535d9f"
            },
        "id": "5167610718",
        "sender":
            {
            "type": "user",
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                }
            },
        "timeStamp": 1734462262000,
        "type":
            {
            "value": "text/html"
            }
        },
        {
        "content": "hello",
        "conversation":
            {
            "id": "92554d9a-0266-425f-b2c6-fe39f4535d9f"
            },
        "id": "8371467370",
        "sender":
            {
            "type": "user",
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                }
            },
        "timeStamp": 1734462286000,
        "type":
            {
            "value": "text/html"
            }
        },
        {
        "content": "asdadas",
        "conversation":
            {
            "id": "92554d9a-0266-425f-b2c6-fe39f4535d9f"
            },
        "id": "9160441015",
        "sender":
            {
            "type": "user",
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                }
            },
        "timeStamp": 1734462287000,
        "type":
            {
            "value": "text/html"
            }
        },
        {
        "content": "asdasdasd",
        "conversation":
            {
            "id": "92554d9a-0266-425f-b2c6-fe39f4535d9f"
            },
        "id": "8430369050",
        "sender":
            {
            "type": "user",
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                }
            },
        "timeStamp": 1734462288000,
        "type":
            {
            "value": "text/html"
            }
        },
        {
        "content": "Banana Man has ended the chat",
        "conversation":
            {
            "id": "92554d9a-0266-425f-b2c6-fe39f4535d9f"
            },
        "id": "7738939127",
        "sender":
            {
            "type": "system"
            },
        "timeStamp": 1734462290000,
        "type":
            {
            "value": "complete"
            }
        }
    ]
}

ECE Webserver will return a 204 No Content to a successful Send Message request.

curl --location 'https://ece-webserver.mydomain.com/system/ws/v19/clientapplications/messaging/sendmessage' \
--header 'Authorization: Bearer 5a0f0bc4-dc21-44c8-a50b-b12bad7ae41e' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Accept-Language: en-US' \
--data '{ 
   "conversation":{ 
      "id":"02945e5e-d5a5-48c6-96f6-969c1c32d125"
   },
   "type":{ 
      "value":"text/html"
   },
  "content":"Hi, This is <b>Gerry Berry</b>. I want to discuss bananas and the offer &#x1F600;"
}'

The type value which can be sent are:

  • assigned: Chat assigned to an agent
  • text/plain: Text message from the end user.
  • text/html: Html message from the end user.
  • startTyping: End user started typing a message.
  • endTyping: End user stopped typing a message.
  • enableOffRecordMessages: End user has enabled “offRecord” messages. When this is enabled, the messages sent by the end user will not be masked by the application. Such messages will not be persisted.
  • disableOffRecordMessages: End user has disabled “offRecord” messages. When this is disabled, the messages sent by the end user will be masked by the application, based on the configured masking rules.
  • acceptAttachment: End user accepted the attachment.
  • rejectAttachment: End user rejected the attachment.
  • uploadAttachment: End user uploaded an attachment.
  • error: Details of error occurred while sending message from webhook to customer.
  • delivered: The message was delivered to the end user.
  • read: End user read the message.
  • geolocation: Geographical location of end user. One of coordinate, address or url must be provided.

End the Message using PUT, no Body. Note - The URL contains the conversation ID.

A successful End Message request will receive a statusCode of 204 No Content

curl --location --request PUT 'https://ece-webserver.mydomain.com/system/ws/v19/clientapplications/messaging/conversation/02945e5e-d5a5-48c6-96f6-969c1c32d125/end' \
--header 'Authorization: Bearer 5a0f0bc4-dc21-44c8-a50b-b12bad7ae41e' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Accept-Language: en-US' \

So that you receive notification (to the webhook web server), when the agent starts and stop typing, when sending the Start Conversation request, include the variable sendTypingNotification and set it to yes in the URL as per below example. This is disabled by default.

Once an agent starts to type - the startTyping Notification is sent. Once an agent stops typing it waits about 5 seconds, before sending an endTyping notification (i.e. in case the agent starts to type again).

https://{{ece-web-server}}/system/ws/v19/clientapplications/messaging/conversation/start?searchContactOnAttribute=email.emailAddress&sendTypingNotification=yes

Example of a Start Typing Notification

POST /webhook1 HTTP/1.1
Authorization: Basic TXlXZWJob29rVXNlcm5hbWU6TXlXZWJob29rUGFzc3dvcmQ=
Content-Type: application/json
Content-Length: 233
Host: webhook-server.mydomain.com:1880
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.14 (Java/11.0.17)
Accept-Encoding: gzip,deflate
 
{
"message":
    [
        {
        "conversation":
            {
            "id": "03d9f1fd-16ac-4f0f-8260-5352f4a4b293"
            },
        "id": "3463141276",
        "sender":
            {
            "type": "user",
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                }
            },
        "timeStamp": 1742919891000,
        "type":
            {
            "value": "startTyping"
            }
        }
    ]
}

Example of an End Typing Notification

POST /webhook1 HTTP/1.1
Authorization: Basic TXlXZWJob29rVXNlcm5hbWU6TXlXZWJob29rUGFzc3dvcmQ=
Content-Type: application/json
Content-Length: 231
Host: webhook-server.mydomain.com:1880
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.14 (Java/11.0.17)
Accept-Encoding: gzip,deflate
 
{
"message":
    [
        {
        "conversation":
            {
            "id": "03d9f1fd-16ac-4f0f-8260-5352f4a4b293"
            },
        "id": "5104121778",
        "sender":
            {
            "type": "user",
            "user":
                {
                "name": "eir support1",
                "screenName": "Banana Man"
                }
            },
        "timeStamp": 1742919901000,
        "type":
            {
            "value": "endTyping"
            }
        }
    ]
}

Use the SendMessage API and send a value of 'startTyping' or 'endTyping' as per below examples. Note with the Send Message API - you should receive a 204 response (Success - No Content)

Example of an Start Typing Notification

{ 
   "conversation":{ 
      "id":"03d9f1fd-16ac-4f0f-8260-5352f4a4b293"
   },
   "type":{ 
      "value":"startTyping"
   }
}

Example of an End Typing Notification

{ 
   "conversation":{ 
      "id":"03d9f1fd-16ac-4f0f-8260-5352f4a4b293"
   },
   "type":{ 
      "value":"endTyping"
   }
}
  • vendors/cisco/uc/ece/messaging-api.txt
  • Last modified: 2025/10/20 08:16
  • by gerardorourke