Webhooks
Webhooks are an easy way to integrate Moveo.AI with your own system, to provide personalization or more complex interaction with your users. Moveo.AI sends information to your custom endpoint using simple HTTP POST calls whenever a webhook action is triggered within your dialog.
You can use a webhook to do one of the following types of things:
- Validate information that you collect from the user.
- Send requests to an external application. For example, you might check on the application status of a customer or access your inventory to see if a product is available for shipping.
- Trigger an SMS notification or OTP verification.
Verifying Origin
Each callback contains a signature on the JSON passed to the callback. The signature is HMAC with SHA256 that will use the webhook verification token as the key and the JSON as the value. The result is passed as HTTP Header X-Moveo-Signature
so the receiver can determine the origin of the message.
- NodeJS
- Python
import crypto from "crypto";
function encodeHMAC(data: crypto.BinaryLike, secret: string): string {
return crypto.createHmac("sha256", secret).update(data).digest("hex");
}
import hashlib
import hmac
def encode_hmac(verify_token: bytes, req_body: dict) -> str:
body_bytes = json.dumps(req_body).encode("utf-8")
return hmac.new(token, body_bytes, hashlib.sha256,).hexdigest()
Whitelisting IPs
We strongly discourage IP allow lists and encourage customers instead to verify the callbacks by using HMAC Signed Callbacks.
If you are restricting inbound traffic, you should allow the following IPs:
18.192.167.150
18.198.233.220
3.66.239.254
Receiving Calls
Whenever a webhook is triggered, Moveo.AI sends a payload of the following format (JSON) to your webhook URL.
Example
{
"channel": "web",
"session_id": "00d2ff33-706e-4a2c-8544-df6c9d0c1ecf",
"brain_id": "d3d08940-f0ef-42e0-993c-1bea065dcqwe",
"lang": "en",
"context": {
"total_months": 3,
"destination": "England",
"sys-unknown_counter": 0,
"sys-channel": "web",
"sys-user_message_counter": 1,
"total_expenses": 500
},
"input": {
"text": "Hello, my name is George and I would like to go for erasmus"
},
"intents": [
{
"intent": "erasmus",
"confidence": 0.89
}
],
"entities": [
{
"entity": "firstname",
"value": "George",
"start": 18,
"end": 36,
"confidence": 1,
"type": "user"
}
],
"tags": ["erasmus", "destination"],
"debug": {
"dialog_stack": [
{
"node_id": "35411a26-cff7-4fb3-a2e9-0e8e6ada048a",
"name": "greetings"
},
{
"node_id": "a85b10e8-e7f3-40df-9715-196c4eae5f14",
"name": "plan_erasmus"
}
]
}
}
In the case of receiving error HTTP codes 5xx
as a response to the POST calls, Moveo.AI will try to re-send the payload three times before giving up.
Reference
Outer Level
Property | Type | Description |
---|---|---|
channel | string | Channel name the message is coming from ("viber", "web" etc.) |
session_id | string | The ID representing the user that triggered the webhook call |
brain_id | string | The ID representing the brain for the webhook call |
verify_token | string | The verify token you specified in the webhook configuration |
context | Context | Context variables that have been collected for that user so far |
input | Input | The user input that triggered the dialog node |
intents | Intent | List of intents recognized, sorted by confidence |
entities | Entity | List of entities recognized in the user input |
debug | Debug | Information related to debugging the Moveo.AI dialog state |
Context
Context consists of key-value pairs with the keys representing context variables names and values capturing the user input.
Input
Property | Type | Description |
---|---|---|
text | string | The text that was typed by the user |
Intent
Property | Type | Description |
---|---|---|
intent | string | The intent name |
confidence | float | The confidence for that intent (between 0 and 1) |
Entity
Property | Type | Description |
---|---|---|
entity | string | The entity type |
value | string | The entity value from the user's input |
start | integer | Start index of the value within the user's text |
end | integer | End index of the value within the user's text |
confidence | float | Entity detection confidence |
type | string | Type of entity (ie. "user", "system" etc.) |
Debug/Dialog Stack
Property | Type | Description |
---|---|---|
node_id | string | The node id as defined in the dialog |
name | string | The node name as defined in the dialog |
Sending Replies
The webhook expects a JSON response with a specific structure. The response must be a JSON object containing either a context
dictionary or a responses
array, or both.
context
: An object containing key-value pairs for session-specific data.responses
: An array of response objects, each specifying a particular type of response.
Response Requirements:
- Expects a response in the same HTTP call.
- Expects a 200 response code from your server.
- Expects a response from your server within 8 seconds or less.
Context Object
The context
object is used to store session-specific data that can be passed between requests to maintain state.
Requirements:
- Must be a JSON object.
- Cannot include the following reserved keywords:
"global"
"channels"
Example:
{
"context": {
"selected_product": "apples",
"amount": "6"
}
}
Responses Array
The responses
array contains response objects that define how the Virtual Agent should respond to the user.
Requirements:
- Must be a JSON array.
- Each element must be a JSON object.
- Each response object must have a
"type"
field.
Supported Response Types:
"text"
"image"
"video"
"audio"
"file"
"event"
"carousel"
"webview"
"reset"
Response Object Types
1. Text Response
Used to send text messages, possibly with quick reply options.
Schema:
{
"type": "text",
"texts": [ "string" ],
"options": [ { ... } ] // optional
}
Fields:
type
(string): Must be"text"
.texts
(array of strings): The text messages to send.- Required.
options
(array of option objects): Quick reply options.- Optional.
- Minimum 1, maximum 10 options.
Option Object:
{
"text": "string",
"label": "string"
}
text
(string): The text sent back when the option is selected.- Required.
- Minimum length: 1 character.
label
(string): The display label for the option.- Required.
- Minimum length: 1 character.
- Maximum length: 64 characters.
Example:
{
"type": "text",
"texts": ["Hello! How can I assist you today?"],
"options": [
{
"text": "I need help",
"label": "Help"
},
{
"text": "Just browsing",
"label": "Browse"
}
]
}
2. Media Response
Used to send media files like images, videos, audio, or files.
Schema:
{
"type": "string",
"url": "string",
"name": "string", // optional
"size": integer // optional
}
Fields:
type
(string): One of"image"
,"video"
,"audio"
,"file"
.- Required.
url
(string): The URL of the media file.- Required.
- Must be a valid URI.
name
(string): The name of the file.- Optional.
size
(integer): The size of the file in bytes.- Optional.
Example:
{
"type": "image",
"url": "https://example.com/image.jpg",
"name": "Sample Image",
"size": 102400
}
3. Event Response
Used to trigger specific events in the conversation flow.
Schema:
{
"type": "event",
"trigger_node_id": "string"
}
Fields:
type
(string): Must be"event"
.- Required.
trigger_node_id
(string): The UUID of the node to trigger.- Required.
- Must match the UUID format.
Example:
{
"type": "event",
"trigger_node_id": "123e4567-e89b-12d3-a456-426614174000"
}
4. Carousel Response
Used to send a carousel of cards, each with media, title, subtitle, and buttons.
Schema:
{
"type": "carousel",
"cards": [ { ... } ],
"action_id": "string"
}
Fields:
type
(string): Must be"carousel"
.- Required.
cards
(array of card objects): The carousel cards.- Required.
- Minimum 1, maximum 6 cards.
action_id
(string): A UUID representing the action.- Required.
- Must match the UUID format.
Card Object:
{
"media": { ... },
"title": "string",
"subtitle": "string", // optional
"buttons": [ { ... } ], // optional
"default_action": { ... } // optional
}
Fields:
media
(object): The media associated with the card.- Required.
- Must include:
url
(string): Valid URI.type
(string):"image"
or"video"
.
title
(string): The title of the card.- Required.
- Minimum length: 1 character.
- Maximum length: 64 characters.
subtitle
(string): The subtitle of the card.- Optional.
- Maximum length: 100 characters.
buttons
(array of button objects): Interactive buttons.- Optional.
- Minimum 1, maximum 3 buttons.
default_action
(object): The default action when the card is tapped.- Optional.
- Must be one of the action types defined below.
Button Object:
Buttons can be of the following types:
- Postback Button:
{
"type": "postback",
"label": "string",
"value": "string"
} - URL Button:
{
"type": "url",
"label": "string",
"url": "string"
} - Webview Button:
{
"type": "webview",
"label": "string",
"url": "string",
"height": "string", // "tall", "compact", "full"
"trigger_node_id": "string" // optional
}
Default Action Object:
Same structure as the button object, but without the label
field for postback and URL types.
Example:
{
"type": "carousel",
"cards": [
{
"media": {
"url": "https://example.com/product1.jpg",
"type": "image"
},
"title": "Product 1",
"subtitle": "Description of product 1",
"buttons": [
{
"type": "postback",
"label": "Buy Now",
"value": "buy_product_1"
},
{
"type": "url",
"label": "Learn More",
"url": "https://example.com/product1"
}
],
"default_action": {
"type": "url",
"url": "https://example.com/product1"
}
}
],
"action_id": "123e4567-e89b-12d3-a456-426614174000"
}
5. Webview Response
Used to display a webview within the chat interface.
Schema:
{
"type": "webview",
"name": "string",
"label": "string",
"url": "string",
"height": "string", // "tall", "compact", "full"
"trigger_node_id": "string" // optional
}
Fields:
type
(string): Must be"webview"
.- Required.
name
(string): The name of the webview.- Required.
label
(string): The label for the webview.- Required.
url
(string): The URL to load in the webview.- Required.
- Must be a valid URI.
height
(string): The height of the webview.- Optional.
- Acceptable values:
"tall"
,"compact"
,"full"
.
trigger_node_id
(string): The UUID to trigger upon webview events.- Optional.
- Must match the UUID format.
Example:
{
"type": "webview",
"name": "Survey",
"label": "Visit our website",
"url": "https://example.com/",
"height": "full",
"trigger_node_id": "123e4567-e89b-12d3-a456-426614174000"
}
6. Reset Response
Used to reset the conversation or user context.
Schema:
{
"type": "reset"
}
Fields:
type
(string): Must be"reset"
.- Required.
Example
Full Response Example with Context and Multiple Responses
{
"context": {
"user": {
"language": "en"
}
},
"responses": [
{
"type": "text",
"texts": ["Welcome back! What would you like to do today?"],
"options": [
{
"text": "View Products",
"label": "Products"
},
{
"text": "Contact Support",
"label": "Support"
}
]
},
{
"type": "carousel",
"cards": [
{
"media": {
"url": "https://example.com/product1.jpg",
"type": "image"
},
"title": "Product 1",
"buttons": [
{
"type": "postback",
"label": "Buy Now",
"value": "buy_product_1"
}
]
},
{
"media": {
"url": "https://example.com/product2.jpg",
"type": "image"
},
"title": "Product 2",
"buttons": [
{
"type": "postback",
"label": "Buy Now",
"value": "buy_product_2"
}
]
}
]
}
],
"context": {
"total_expenses": 100
}
}
Reference
Outer Level
Property | Type | Description |
---|---|---|
responses | Responses | List of responses that Moveo should use to respond to the user |
context | dictionary | Key-value pairs that can be used to update user context variables |
Responses
Property | Type | Description |
---|---|---|
type | string | Integration type |
texts | string | List of texts that should be used to reply |
name | string | Media name |
url | string | URL to be used for url type |
size | string | Media size in bytes |
trigger_node_id | string | Node ID to be triggered for event type |
You cannot directly set the user
variable. Instead, if you want to return a field such as the user's name, use the following approach:
Instead of:
context: {
user: {
display_name: "John Doe";
}
}
Use:
context: {["user.display_name"]: "John Doe"}
Validation
You can use the Details section within from the Test functionality to debug any issues that Moveo might have encountered when displaying your webhook responses.
How to create your own webhook
You can find a comprehensive set of examples where webhooks are used here.