Create an event notification
This tutorial walks you through creating an event notification
that triggers when a chatbot conversation expires. Using a streaming platform's customer support as an example use case, we will configure an event notification to send conversation details to an external webhook when a user session ends due to inactivity.Scenario
Imagine a streaming service where users can chat with a support bot to resolve issues. If a conversation remains inactive for too long, it expires. When this happens, we want to send the conversation details (including user ID, session history, and metadata) to a CRM system to follow up with the user. However, we will only process conversations that include the context.tags
field with a value of success
, ensuring we ignore incomplete or unresolved interactions.
Step 1: Handling the event notification
Your external system needs to process incoming webhook requests when a conversation expires. Below is a Node.js Express server that listens for event notifications, filtering out unresolved conversations and only processing those marked as successful.
const express = require("express");
const bodyParser = require("body-parser");
const crypto = require("crypto");
const app = express();
const port = process.env.PORT || 3000;
const SECRET = "mySuperSecretKey123!";
// Middleware to handle duplicate requests
app.use((req, res, next) => {
const reqId = req.headers["X-Request-Id"];
if (!shouldProcessRequest(reqId)) {
console.log("Ignoring duplicate request");
return res.status(200).send("Ignored");
}
next();
});
app.use(bodyParser.json());
app.post("/webhook/chat_expired", (req, res) => {
const headers = req.headers;
const body = req.body;
console.log("Received chat expiration webhook:", body);
// Validate HMAC signature
const signature = headers["x-moveo-signature"];
const expectedSignature = calculateSignature(JSON.stringify(body), SECRET);
if (signature !== expectedSignature) {
console.error("Invalid signature!");
return res.status(401).send("Unauthorized");
}
// Check if the conversation was successfully completed
const conversationTags = body.events[0]?.session?.context?.tags || [];
if (!conversationTags.includes("success")) {
console.log("Ignoring incomplete or unresolved conversation.");
return res.status(200).send("Ignored");
}
console.log("Signature valid. Processing expired chat...");
console.log(`Account ID: ${body.account_id}`);
console.log(`Event Type: ${body.event_type}`);
res.status(200).send("Webhook received successfully");
});
function calculateSignature(body, secret) {
const hmac = crypto.createHmac("sha256", secret);
hmac.update(body);
return hmac.digest("hex");
}
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
});
Step 2: Navigate to event notifications
- Go to Deploy → Developer Tools → Event Notifications.
- Click Create Event.
Step 3: Fill in the event notification details
1. Name
Give the event a recognizable name:
Chat Expired - Notify CRM
2. Event
Select the event that will trigger the notification. For this example, we will use dialog:expired
event. This event fires when a conversation remains inactive for a set threshold
3. URL
Provide the webhook URL where the conversation data will be sent:
https://api.crmplatform.com/webhook/chat_expired
4. Secret
Set a secret key to sign the request body and validate incoming notifications:
mySuperSecretKey123!
5. SSL Verification
Enable SSL verification for secure communication.
✅ Enable SSL Verification
Click Save to create the event notification.
Step 4: Updating or deleting an event notification
- To update an event notification, go to Deploy → Developer Tools → Event Notifications, select the event, and modify the fields.
- To delete an event notification, click Delete on the event in the list.
You can also enable or disable the endpoint by clicking the toggle button on the event notification. So you can disable the event notification if you want to stop sending events to the webhook URL without deleting the webhook URL.

Example Payload for dialog:expired
Below is an example payload sent when a conversation expires. Notice that the context.tags
array contains success
, meaning the conversation was completed successfully.
{
"account_id": "b8a3e9eb-b0ba-4185-850c-fd449cbc2008",
"event_type": "dialog:expired",
"events": [
{
"session": {
"context": {
"user": {
"display_name": "John Doe",
"user_id": "123456789",
"email": "john.doe@example.com"
},
"tags": ["success"]
},
"history": [
{
"author_id": "123456789",
"author_type": "user",
"responses": [
{ "text": "I need help with billing", "type": "text" }
],
"timestamp": 1742304104215
},
{
"author_id": "bot123",
"author_type": "brain",
"responses": [
{ "text": "Sure! What seems to be the issue?", "type": "text" }
],
"timestamp": 1742304106737
}
],
"session_id": "916bac5e-8325-4860-8a41-cfa818b260e3",
"source": {
"channel": "web"
}
},
"timestamp": 1742304407521
}
],
"request_id": "6ca38741-f0ce-43d2-9ba6-99894ed18208",
"timestamp": 1742304407801
}
Conclusion
By following this tutorial, you have successfully created an event notification that triggers when a chatbot conversation expires. This setup ensures that only successfully completed conversations are logged in an external system, enabling your support team to take meaningful action while ignoring incomplete interactions.