DigiReply offers multiple ways to create tickets, each designed for different use cases. All ticket creation methods trigger webhooks, allowing you to receive real-time updates in your systems.
Use Case: Internal project management and team collaboration
Use Case: Customer support automation and interactive ticket creation
Use Case: Direct ticket submission from external sources
Use Case: Integrated ticket submission on your website
DigiReply's ticket webhook system enables real-time integration with your ticketing system by sending notifications about ticket-related events. This allows you to track and respond to ticket activities, automate workflows, and maintain synchronized ticket data across your systems.
The ticket webhook system supports four main event types, each providing specific information about ticket activities:
ticket.created
Triggered when a new ticket is created in the system.
Property | Type | Description |
---|---|---|
ticket_id |
string | Unique identifier for the ticket |
ticket_number |
string | Human-readable ticket number (e.g., TIC-20240321-1234) |
subject |
string | Ticket subject/title |
description |
string | Detailed ticket description |
status |
string | Initial ticket status (typically "open") |
priority |
string | Ticket priority level |
created_by |
string | Username of ticket creator |
created_by_email |
string | Email address of ticket creator (for submissions via public forms where user does not have membership) |
project_name |
string | Name of the project the ticket belongs to |
{
"event": "ticket.created",
"secret_key": "your_webhook_secret",
"data": {
"ticket_id": "123",
"ticket_number": "TIC-20240321-1234",
"subject": "Technical Issue",
"description": "Need help with integration",
"status": "open",
"priority": "medium",
"created_by": "john_doe",
"created_by_email": "john@example.com",
"project": "My Project"
}
}
ticket.updated
Triggered when an existing ticket is modified.
Property | Type | Description |
---|---|---|
ticket_id |
string | Identifier of the updated ticket |
status |
string | New ticket status |
priority |
string | New priority level |
updated_by |
string | Username of the user who made the update |
changes |
object | Object containing before/after values of changed fields |
project_name |
string | Project name |
{
"event": "ticket.updated",
"secret_key": "your_webhook_secret",
"data": {
"ticket_id": "123",
"status": "in_progress",
"priority": "high",
"updated_by": "jane_smith",
"changes": {
"status": ["open", "in_progress"],
"priority": ["medium", "high"]
},
"project": "My Project"
}
}
ticket.deleted
Triggered when a ticket is deleted from the system.
Property | Type | Description |
---|---|---|
ticket_id |
string | Identifier of the deleted ticket |
deleted_by |
string | Username of the user who deleted the ticket |
project_name |
string | Project name |
{
"event": "ticket.deleted",
"secret_key": "your_webhook_secret",
"data": {
"ticket_id": "123",
"deleted_by": "admin_user",
"project": "My Project"
}
}
ticket.response.added
Triggered when a response is added to an existing ticket.
Property | Type | Description |
---|---|---|
ticket_id |
string | Identifier of the ticket |
response_by |
string | Username of the response author |
response_text |
string | Content of the response |
is_private |
boolean | Whether the response is private |
project_name |
string | Project name |
{
"event": "ticket.response.added",
"secret_key": "your_webhook_secret",
"data": {
"ticket_id": "123",
"response_by": "support_agent",
"response_text": "Here's the solution to your issue...",
"is_private": false,
"project": "My Project"
}
}
ticket-webhook.php
in your web server directory.config/database.php
.https://your-domain.com/ticket-webhook.php
).ticket.created
, ticket.updated
, etc.).Below is a production-ready implementation of a ticket webhook handler that processes all ticket events and logs them to a file:
<?php
require_once 'config/database.php';
// Set response header to JSON
header('Content-Type: application/json');
// Enable error logging
ini_set('log_errors', 1);
ini_set('error_log', 'ticket_webhook_error.log');
// Your webhook secret key from the webhook settings panel
$webhook_secret = 'PASTE_YOUR_SECRET_KEY_HERE'; // User should paste their secret key here
// Read the JSON payload
$input = file_get_contents('php://input');
error_log("Received webhook data: " . $input); // Debug log
$payload = json_decode($input, true);
if (!$payload) {
http_response_code(400);
echo json_encode(['error' => 'Invalid JSON payload']);
exit;
}
// Debug what we received
error_log("Decoded payload: " . print_r($payload, true));
// Simple secret key verification
if (!isset($payload['secret_key']) || $payload['secret_key'] !== $webhook_secret) {
http_response_code(401);
echo json_encode(['error' => 'Invalid secret key']);
exit;
}
// Get the event type
$event = $payload['event'] ?? 'unknown';
// Write to tickets.txt file
$log_entry = [
'timestamp' => date('Y-m-d H:i:s'),
'event' => $event,
'data' => []
];
switch ($event) {
case 'ticket.created':
$log_entry['data'] = [
'ticket_id' => $payload['data']['ticket_id'] ?? null,
'ticket_number' => $payload['data']['ticket_number'] ?? null,
'project_name' => $payload['data']['project'] ?? null,
'priority' => $payload['data']['priority'] ?? null,
'status' => $payload['data']['status'] ?? null,
'created_by' => $payload['data']['created_by'] ?? null,
'created_by_email' => $payload['data']['created_by_email'] ?? null,
'subject' => $payload['data']['subject'] ?? null,
'description' => $payload['data']['description'] ?? null
];
break;
case 'ticket.updated':
$log_entry['data'] = [
'ticket_id' => $payload['data']['ticket_id'] ?? null,
'status' => $payload['data']['status'] ?? null,
'priority' => $payload['data']['priority'] ?? null,
'updated_by' => $payload['data']['updated_by'] ?? null,
'changes' => $payload['data']['changes'] ?? [],
'project_name' => $payload['data']['project'] ?? null
];
break;
case 'ticket.deleted':
$log_entry['data'] = [
'ticket_id' => $payload['data']['ticket_id'] ?? null,
'deleted_by' => $payload['data']['deleted_by'] ?? null,
'project_name' => $payload['data']['project'] ?? null
];
break;
case 'ticket.response.added':
$log_entry['data'] = [
'ticket_id' => $payload['data']['ticket_id'] ?? null,
'response_by' => $payload['data']['response_by'] ?? null,
'response_text' => $payload['data']['response_text'] ?? null,
'is_private' => $payload['data']['is_private'] ?? false,
'project_name' => $payload['data']['project'] ?? null
];
break;
}
$log_line = json_encode($log_entry) . PHP_EOL;
error_log("Writing to tickets.txt: " . $log_line); // Debug log
file_put_contents('tickets.txt', $log_line, FILE_APPEND | LOCK_EX);
// Send success response
echo json_encode([
'success' => true,
'message' => 'Event logged successfully'
]);
You can test your webhook implementation using cURL commands. Here are examples for each event type:
curl -X POST https://your-domain.com/ticket-webhook.php \
-H "Content-Type: application/json" \
-d '{
"event": "ticket.created",
"secret_key": "your_webhook_secret",
"data": {
"ticket_id": "123",
"ticket_number": "TIC-20240321-1234",
"subject": "Test Ticket",
"description": "Testing webhook integration",
"status": "open",
"priority": "medium",
"created_by": "test_user",
"project": "Test Project"
}
}'
{
"success": true,
"message": "Event logged successfully"
}
Centralizing ticket logging from different sources (web forms and chatbots) provides several key benefits:
Below is a complete implementation example for handling chatbot-generated tickets while maintaining consistency with web-generated tickets:
<?php
require_once 'config/database.php'; // Include database connection
// webhook.php
// 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'] : '';
if ($event_type !== 'on_ticket_created') {
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 on_ticket_created event
if ($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.";
}
// Respond with success
http_response_code(200);
echo json_encode($response);
?>
tickets.txt
for new log entriesticket_webhook_error.log
for any errorsIf you need assistance with ticket webhooks:
Last Updated: April 26, 2025