Ticketing Webhooks
Webhooks enable your applications to receive real-time notifications when events occur in your ticketing and issue tracking systems. This eliminates the need for polling and ensures your systems stay synchronized with ticket updates, status changes, and comments across all integrated platforms.
Unizo normalizes webhook events from Jira, ServiceNow, Zendesk, GitHub Issues, and other ticketing providers into a consistent format. This means you write your webhook handler once and it works with all supported platforms.
To set up webhooks for your integration, visit the Unizo Console Webhooks section for step-by-step configuration guide.
Supported Event Types
These are the event types currently supported by Unizo's Ticketing webhooks. The list keeps growing as we add support for more events across different platforms.
Event Type | Description | Trigger Conditions |
---|---|---|
ticket:created | A new ticket has been created | Ticket creation via UI, API, email, or automation |
ticket:updated | Ticket information has been modified | Title, description, status, priority, or assignee changes |
ticket:deleted | A ticket has been deleted | Ticket deletion or permanent removal |
Webhook Security
All webhooks from Unizo include security headers to verify authenticity:
Headers
Header | Description |
---|---|
x-unizo-event-type | The type of event that triggered the webhook |
x-unizo-signature | HMAC SHA-256 signature for request validation |
x-unizo-timestamp | Unix timestamp when the event was sent |
x-unizo-delivery-id | Unique identifier for this webhook delivery |
Signature Verification
Verify the authenticity of incoming webhooks using HMAC SHA-256:
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}
Ticket Events
Ticket Created
ticket:created
• Single endpoint:
https://api.yourapp.com/webhooks/unizo
- Route all events to one handler• Category-based endpoints:
https://api.yourapp.com/webhooks/unizo/ticketing
- Route by category (ticketing, ticketing, etc.) for microservices architectureHeaders
Name | Type | Required | Description |
---|---|---|---|
x-unizo-event-type | string | Yes | Event type: ticket:created |
x-unizo-signature | string | Yes | HMAC SHA-256 signature |
Request Body Schema
Property | Type | Required | Description |
---|---|---|---|
type | string | Yes | Event type identifier |
version | string | Yes | Webhook payload version |
contentType | string | Yes | Branch name/identifier |
collection | string | Yes | Collection name |
collection.id | string | Yes | Collection ID |
collection.name | string | Yes | Collection Display Name |
organization | string | Yes | Organization name |
organization.id | string | Yes | Organization ID |
organization.name | string | Yes | Organization Display Name |
ticket | string | Yes | Ticket Name |
ticket.id | string | Yes | Ticket Id |
ticket.state | string | No | Ticket key or number |
ticket.summary | string | Yes | Ticket title or summary |
ticket.createdDateTime | string | No | Ticket Creation Timestamp |
integration | string | Yes | Integration Name |
integration.type | string | No | Integration type |
integration.id | string | Yes | Integration id |
integration.name | string | Yes | Integration Display Name |
Example Payload
{"type": "ticket:created","version": "1.0.0","contentType": "application/json","collection": {"id": "169133028","name": "GH-DemoOrg411"},"organization": {"id": "797087929","name": "DemoRepo1"},"ticket": {"id": "78","state": "open","summary": "New issue","createdDateTime": "May 5, 2025 2:50 PM","createdBy": "Shruthi089"},"integration": {"type": "TICKETING","id": "13348832-e545-4b33-aa32-51ad1b92afdf","name": "Gi_Secu_1746456420866"}}
Response
200 OK | Webhook processed successfully |
400 Bad Request | Invalid webhook payload |
401 Unauthorized | Invalid or missing signature |
Ticket Updated
ticket:updated
• Single endpoint:
https://api.yourapp.com/webhooks/unizo
- Route all events to one handler• Category-based endpoints:
https://api.yourapp.com/webhooks/unizo/scm
- Route by category (scm, ticketing, etc.) for microservices architectureHeaders
Name | Type | Required | Description |
---|---|---|---|
x-unizo-event-type | string | Yes | Event type: ticket:created |
x-unizo-signature | string | Yes | HMAC SHA-256 signature |
Request Body Schema
Property | Type | Required | Description |
---|---|---|---|
type | string | Yes | Event type identifier |
version | string | Yes | Webhook payload version |
contentType | string | Yes | Branch name/identifier |
collection | string | Yes | Collection name |
collection.id | string | Yes | Collection ID |
collection.name | string | Yes | Collection Display Name |
organization | string | Yes | Organization name |
organization.id | string | Yes | Organization ID |
organization.name | string | Yes | Organization Display Name |
ticket | string | Yes | Ticket Name |
ticket.id | string | Yes | Ticket Id |
ticket.state | string | No | Ticket key or number |
ticket.summary | string | Yes | Ticket title or summary |
ticket.createdDateTime | string | No | Ticket Creation Timestamp |
ticket.changeLog | string | Yes | Ticket Change Log |
ticket.changeLog.updatedDateTime | string | Yes | Ticket Change Log Updated Timestamp |
ticket.changeLog.items | string | Yes | Ticket Change Log Items |
integration | string | Yes | Integration Name |
integration.type | string | No | Integration type |
integration.id | string | Yes | Integration id |
integration.name | string | Yes | Integration Display Name |
Example Payload
{"type": "ticket:updated","version": "1.0.0","contentType": "application/json","collection": {"id": "169133028","name": "GH-DemoOrg411"},"organization": {"id": "797087929","name": "DemoRepo1"},"ticket": {"id": "78","state": "open","summary": "New issue123","createdDateTime": "May 5, 2025 2:50 PM","changeLog": {"updatedDateTime": "May 5, 2025 2:50 PM","items": [{"field": "body","fieldId": "body","from": ""},{"field": "title","fieldId": "title","from": "New issue"}]}}}
Response
200 OK | Webhook processed successfully |
400 Bad Request | Invalid webhook payload |
401 Unauthorized | Invalid or missing signature |
Ticket Deleted
ticket:deleted
• Single endpoint:
https://api.yourapp.com/webhooks/unizo
- Route all events to one handler• Category-based endpoints:
https://api.yourapp.com/webhooks/unizo/scm
- Route by category (scm, ticketing, etc.) for microservices architectureHeaders
Name | Type | Required | Description |
---|---|---|---|
x-unizo-event-type | string | Yes | Event type: ticket:created |
x-unizo-signature | string | Yes | HMAC SHA-256 signature |
Request Body Schema
Property | Type | Required | Description |
---|---|---|---|
type | string | Yes | Event type identifier |
version | string | Yes | Webhook payload version |
contentType | string | Yes | Branch name/identifier |
collection | string | Yes | Collection name |
collection.id | string | Yes | Collection ID |
collection.name | string | Yes | Collection Display Name |
organization | string | Yes | Organization name |
organization.id | string | Yes | Organization ID |
organization.name | string | Yes | Organization Display Name |
ticket | string | Yes | Ticket Name |
ticket.id | string | Yes | Ticket Id |
ticket.state | string | No | Ticket key or number |
ticket.summary | string | Yes | Ticket title or summary |
ticket.createdDateTime | string | No | Ticket Creation Timestamp |
integration | string | Yes | Integration Name |
integration.type | string | No | Integration type |
integration.id | string | Yes | Integration id |
integration.name | string | Yes | Integration Display Name |
Example Payload
{"type": "ticket:deleted","version": "1.0.0","contentType": "application/json","collection": {"id": "169133028","name": "GH-DemoOrg411"},"organization": {"id": "797087929","name": "DemoRepo1"},"ticket": {"id": "78","state": "open","summary": "New issue123","createdDateTime": "May 5, 2025 2:50 PM"},"integration": {"type": "TICKETING","id": "13348832-e545-4b33-aa32-51ad1b92afdf","name": "Gi_Secu_1746456420866"}}
Response
200 OK | Webhook processed successfully |
400 Bad Request | Invalid webhook payload |
401 Unauthorized | Invalid or missing signature |
Webhook Delivery & Retries
Unizo implements automatic retry logic for failed webhook deliveries:
- Initial Delivery: Immediate
- First Retry: After 1 minute
- Second Retry: After 5 minutes
- Third Retry: After 15 minutes
- Final Retry: After 1 hour
Webhooks are considered failed if:
- Your endpoint returns a non-2xx status code
- Connection timeout (30 seconds)
- SSL/TLS errors
Best Practices
1. Idempotency
Idempotent Webhook Handler
async function handleWebhook(request) {
const deliveryId = request.headers['x-unizo-delivery-id'];
// Check if already processed
if (await isProcessed(deliveryId)) {
return { status: 200, message: 'Already processed' };
}
// Process webhook
await processWebhook(request.body);
// Mark as processed
await markProcessed(deliveryId);
return { status: 200 };
}
2. Async Processing
Asynchronous Processing
app.post('/webhooks/ticketing', (req, res) => {
// Validate signature
if (!verifySignature(req)) {
return res.status(401).send('Invalid signature');
}
// Queue for processing
ticketQueue.add(req.body);
// Return immediately
res.status(200).send('OK');
});
3. Error Handling
Comprehensive Error Handling
async function processWebhook(payload) {
try {
switch (payload.type) {
case 'ticket:created':
await handleTicketCreated(payload);
break;
case 'ticket:status_changed':
await handleStatusChange(payload);
break;
case 'ticket:comment_added':
await handleNewComment(payload);
break;
default:
logger.warn(`Unknown webhook type: ${payload.type}`);
}
} catch (error) {
logger.error('Webhook processing failed', {
error: error.message,
payload,
stack: error.stack
});
throw error;
}
}
Need Help?
For webhook-related support:
- Contact support at support@unizo.ai