DigiReply's webhook system allows you to integrate your chatbot with external applications by receiving real-time notifications about key events. Webhooks are HTTP callbacks that send POST requests to your specified URL when events occur, such as receiving a message or a live chat request. This enables you to build custom workflows, automate processes, and enhance your chatbot's functionality.
DigiReply supports the following webhook events. Each event includes a JSON payload with relevant data, sent as a POST request to your registered webhook URL.
on_message_received
Triggered when a user sends a message to the chatbot.
Payload:
{
"event_type": "on_message_received",
"bot_id": 21,
"visitor_id": "v_76f4v2c3e13",
"message": "Hello, I need help with billing.",
"type": "text",
"intent": "billing_inquiry",
"timestamp": "2025-04-26T10:30:45Z"
}
Use Cases:
on_ticket_created
Triggered when a ticket is created through the chatbot (e.g., for a support request).
Payload:
{
"event_type": "on_ticket_created",
"bot_id": 21,
"visitor_id": "v_76f4v2c3e13",
"ticket_number": "TICKET123",
"ticket_data": {
"name": "John Doe",
"email": "john@example.com",
"description": "Billing issue"
},
"timestamp": "2025-04-26T10:32:10Z"
}
Use Cases:
on_live_chat_requested
Triggered when a user requests a live chat session (e.g., by typing "live chat").
Payload:
{
"event_type": "on_live_chat_requested",
"bot_id": 21,
"visitor_id": "v_76f4v2c3e13",
"session_status": "pending",
"message": "I need live support",
"request_time": "2025-04-26T10:32:10Z"
}
Use Cases:
before_response_sent
Triggered before the chatbot sends a response, allowing modification or skipping of the response.
Payload:
{
"event_type": "before_response_sent",
"bot_id": 21,
"visitor_id": "v_76f4v2c3e13",
"response": {
"response": "Original response",
"type": "text"
},
"message": "Test message",
"source_type": "bot",
"intent": "webhook",
"timestamp": "2025-04-26T10:40:15Z"
}
Use Cases:
Follow these steps to configure and use webhooks with DigiReply.
https://yourserver.com/webhook
).Authorization
token for your webhook.Your server must handle POST requests from DigiReply's webhook system. Here's how to set it up:
Authorization
header in every webhook request (e.g., Authorization: Bearer your_token
).event
type and other data.200 OK
response to acknowledge receipt.message_received
event.Authorization
header is validated and the payload is parsed correctly.Below is a sample PHP script to handle DigiReply webhooks. It processes four event types: on_message_received
, on_ticket_created
, on_live_chat_requested
, and before_response_sent
. The script validates the Authorization header, logs event details to separate files, and provides custom responses based on event types and intents.
{
"event_type": "on_ticket_created",
"bot_id": "21",
"visitor_id": "v_76f4v2c3e13",
"ticket_number": "TIC-20250507-5320",
"ticket_data": {
"name": "John Doe",
"email": "john@example.com",
"description": "Need help with integration"
}
}
{
"status": "success",
"action": "override_response",
"response": "Ticket TIC-20250507-5320 has been created successfully."
}
{
"timestamp": "2025-05-07 00:46:01",
"event": "ticket.created",
"source": "chatbot",
"data": {
"ticket_number": "TIC-20250507-5320",
"project_name": "Default Project",
"priority": "medium",
"status": "open",
"created_by": "John Doe",
"created_by_email": "john@example.com",
"subject": "Support Ticket from John Doe",
"description": "Need help with integration",
"bot_id": "21",
"visitor_id": "v_76f4v2c3e13"
}
}
<?php
require_once 'config/database.php'; // Include database connection
// Secret token for basic authentication
define('WEBHOOK_SECRET', 'PASTE_YOUR_SECRET_KEY_HERE');
// Set response header to JSON
header('Content-Type: application/json');
// Enable error logging
ini_set('log_errors', 1);
ini_set('error_log', 'webhook_error.log');
// Verify the Authorization header
$headers = getallheaders();
$auth_header = isset($headers['Authorization']) ? $headers['Authorization'] : '';
if ($auth_header !== 'Bearer ' . WEBHOOK_SECRET) {
error_log("Unauthorized access attempt: auth_header='$auth_header'");
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
// Read the JSON payload
$input = file_get_contents('php://input');
$payload = json_decode($input, true);
if (!$payload) {
error_log("Invalid JSON payload: input='$input'");
http_response_code(400);
echo json_encode(['error' => 'Invalid JSON payload']);
exit;
}
// Determine event_type
$event_type = isset($payload['event_type']) ? $payload['event_type'] : '';
$valid_event_types = ['on_message_received', 'on_ticket_created', 'on_live_chat_requested', 'before_response_sent'];
error_log("Processing webhook with event_type='$event_type', payload=" . json_encode($payload));
if (!in_array($event_type, $valid_event_types)) {
error_log("Invalid event type: event_type='$event_type', payload=" . json_encode($payload));
http_response_code(400);
echo json_encode(['error' => 'Invalid event type']);
exit;
}
// Initialize response
$response = ['status' => 'success'];
// Handle event types
if ($event_type === 'on_message_received') {
// Log message details
$log_entry = [
'timestamp' => date('Y-m-d H:i:s'),
'event_type' => $event_type,
'bot_id' => $payload['bot_id'] ?? 'unknown',
'visitor_id' => $payload['visitor_id'] ?? 'unknown',
'message' => $payload['message'] ?? 'no message',
'type' => $payload['type'] ?? 'unknown',
'intent' => $payload['intent'] ?? 'none'
];
$log_file = 'webhook_log.txt';
error_log("Writing to webhook_log.txt: " . json_encode($log_entry));
if (!is_writable($log_file) && !touch($log_file)) {
error_log("Cannot write to webhook_log.txt: file is not writable");
}
if (!file_put_contents(
$log_file,
json_encode($log_entry, JSON_PRETTY_PRINT) . PHP_EOL,
FILE_APPEND | LOCK_EX
)) {
error_log("Failed to write to webhook_log.txt");
}
// Intent-specific response
if (isset($payload['intent']) && $payload['intent'] === 'greeting.hello') {
$response['action'] = 'override_response';
$response['response'] = 'Welcome! How can I assist you today?';
}
} elseif ($event_type === 'on_ticket_created') {
// Validate required fields
if (!isset($payload['ticket_number']) || !isset($payload['bot_id']) || !isset($payload['visitor_id'])) {
error_log("Missing required fields for on_ticket_created: payload=" . json_encode($payload));
http_response_code(400);
echo json_encode(['error' => 'Missing required fields']);
exit;
}
try {
// Get project name from bot_id
$stmt = $pdo->prepare("
SELECT p.name as project_name
FROM bots b
JOIN projects p ON b.project_id = p.id
WHERE b.id = ?
");
$stmt->execute([$payload['bot_id']]);
$project = $stmt->fetch(PDO::FETCH_ASSOC);
// Create standardized log entry
$log_entry = [
'timestamp' => date('Y-m-d H:i:s'),
'event' => 'ticket.created',
'source' => 'chatbot',
'data' => [
'ticket_number' => $payload['ticket_number'],
'project_name' => $project['project_name'] ?? 'Unknown Project',
'priority' => 'medium', // Default priority for chatbot tickets
'status' => 'open',
'created_by' => $payload['ticket_data']['name'] ?? 'Unknown',
'created_by_email' => $payload['ticket_data']['email'] ?? 'Unknown',
'subject' => isset($payload['ticket_data']['name']) ?
"Support Ticket from " . $payload['ticket_data']['name'] :
"Support Ticket",
'description' => $payload['ticket_data']['description'] ?? '',
'bot_id' => $payload['bot_id'],
'visitor_id' => $payload['visitor_id']
]
];
$log_file = 'tickets.txt';
error_log("Writing standardized format to tickets.txt: " . json_encode($log_entry));
if (!is_writable($log_file) && !touch($log_file)) {
error_log("Cannot write to tickets.txt: file is not writable");
}
if (!file_put_contents(
$log_file,
json_encode($log_entry) . PHP_EOL,
FILE_APPEND | LOCK_EX
)) {
error_log("Failed to write to tickets.txt");
}
} catch (Exception $e) {
error_log("Error processing ticket webhook: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Internal server error']);
exit;
}
// Override response for ticket creation
$response['action'] = 'override_response';
$response['response'] = "Ticket {$payload['ticket_number']} has been created successfully.";
} elseif ($event_type === 'on_live_chat_requested') {
// Validate required fields
if (!isset($payload['bot_id']) || !isset($payload['visitor_id'])) {
error_log("Missing required fields for on_live_chat_requested: payload=" . json_encode($payload));
http_response_code(400);
echo json_encode(['error' => 'Missing required fields']);
exit;
}
// Log live chat request details
$log_entry = [
'timestamp' => date('Y-m-d H:i:s'),
'event_type' => $event_type,
'bot_id' => $payload['bot_id'],
'visitor_id' => $payload['visitor_id'],
'session_status' => $payload['session_status'] ?? 'unknown',
'message' => $payload['message'] ?? 'no message',
'request_time' => $payload['request_time'] ?? 'unknown'
];
$log_file = 'live_chat_log.txt';
error_log("Writing to live_chat_log.txt: " . json_encode($log_entry));
if (!is_writable($log_file) && !touch($log_file)) {
error_log("Cannot write to live_chat_log.txt: file is not writable");
}
if (!file_put_contents(
$log_file,
json_encode($log_entry, JSON_PRETTY_PRINT) . PHP_EOL,
FILE_APPEND | LOCK_EX
)) {
error_log("Failed to write to live_chat_log.txt");
}
// Override response for live chat request
$response['action'] = 'override_response';
$response['response'] = 'Your live chat request has been received. An agent will assist you shortly.';
} elseif ($event_type === 'before_response_sent') {
// Validate required fields
if (!isset($payload['bot_id']) || !isset($payload['visitor_id']) || !isset($payload['response'])) {
error_log("Missing required fields for before_response_sent: payload=" . json_encode($payload));
http_response_code(400);
echo json_encode(['error' => 'Missing required fields']);
exit;
}
// Log response details
$log_entry = [
'timestamp' => date('Y-m-d H:i:s'),
'event_type' => $event_type,
'bot_id' => $payload['bot_id'],
'visitor_id' => $payload['visitor_id'],
'response' => $payload['response'],
'message' => $payload['message'] ?? 'no message',
'source_type' => $payload['source_type'] ?? 'unknown'
];
$log_file = 'response_log.txt';
error_log("Writing to response_log.txt: " . json_encode($log_entry));
if (!is_writable($log_file) && !touch($log_file)) {
error_log("Cannot write to response_log.txt: file is not writable");
}
if (!file_put_contents(
$log_file,
json_encode($log_entry, JSON_PRETTY_PRINT) . PHP_EOL,
FILE_APPEND | LOCK_EX
)) {
error_log("Failed to write to response_log.txt");
}
// Overwrite response based on conditions
$modified_response = $payload['response'];
// Example 1: Change response for a specific intent
if (isset($payload['intent']) && $payload['intent'] === 'webhook') {
$modified_response['response'] = 'This is a webhook test.';
$modified_response['source_type'] = 'webhook';
$response['action'] = 'override_response';
$response['response'] = $modified_response;
}
// Example 2: Skip error responses
if ($modified_response['type'] === 'error') {
$response['action'] = 'skip';
}
}
// Respond with success
http_response_code(200);
echo json_encode($response);
?>
You can test your webhook implementation using tools like cURL or Postman. Here are examples for testing different event types:
curl -X POST https://your-domain.com/webhook.php \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_type": "on_ticket_created",
"bot_id": "21",
"visitor_id": "v_123456",
"ticket_number": "TIC-20250507-5320",
"ticket_data": {
"name": "John Doe",
"email": "john@example.com",
"description": "Need help with integration"
}
}'
Expected Response:
{
"status": "success",
"action": "override_response",
"response": "Ticket TIC-20250507-5320 has been created successfully."
}
curl -X POST https://your-domain.com/webhook.php \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_type": "on_message_received",
"bot_id": "21",
"visitor_id": "v_123456",
"message": "Hello!",
"intent": "greeting.hello"
}'
Expected Response:
{
"status": "success",
"action": "override_response",
"response": "Welcome! How can I assist you today?"
}
curl -X POST https://your-domain.com/webhook.php \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_type": "on_live_chat_requested",
"bot_id": "21",
"visitor_id": "v_123456",
"session_status": "pending",
"message": "I need live support"
}'
Expected Response:
{
"status": "success",
"action": "override_response",
"response": "Your live chat request has been received. An agent will assist you shortly."
}
Here are some common patterns for extending the webhook functionality:
You can override bot responses based on specific conditions:
if ($event_type === 'before_response_sent') {
// Override response for specific intents
if (isset($payload['intent']) && $payload['intent'] === 'custom.intent') {
$response['action'] = 'override_response';
$response['response'] = 'This is a custom response.';
}
}
Add additional context to your log entries:
$log_entry = [
'timestamp' => date('Y-m-d H:i:s'),
'event_type' => $event_type,
'environment' => getenv('APP_ENV'),
'client_ip' => $_SERVER['REMOTE_ADDR'],
'data' => [
// Your event-specific data
]
];
file_put_contents('webhook_log.txt', json_encode($log_entry) . PHP_EOL, FILE_APPEND | LOCK_EX);
Implement comprehensive error handling:
try {
// Your webhook logic here
} catch (PDOException $e) {
error_log("Database error: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Database error occurred']);
exit;
} catch (Exception $e) {
error_log("General error: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Internal server error']);
exit;
}
Always validate input data and implement proper error handling to prevent security vulnerabilities and ensure reliable operation of your webhook endpoint.
Authorization
header to ensure requests come from DigiReply.message
, feedback
) to prevent injection attacks. In PHP, use htmlspecialchars()
or a library like voku/anti-xss
.visitor_id
and timestamp
.Authorization
failures or payload issues.If you need help with webhooks or any other feature, contact our support team:
Last Updated: April 26, 2025