Skip to main content

Incident Management Webhooks

Webhook Configuration

To set up webhooks for your integration, visit the Unizo Console Webhooks section for step-by-step configuration guide.

Overview

Unizo's Incident Management API provides webhooks to notify your application when important incident events occur across your integrated incident management platforms. These real-time notifications enable you to build automated incident response workflows, maintain synchronized incident tracking, and ensure timely response to critical issues.

Our platform normalizes webhook events from various incident management providers (PagerDuty, Opsgenie, ServiceNow, etc.) into a consistent format, making it easy to handle incident events regardless of the underlying platform.

Supported Event Types

Event TypeDescriptionTrigger Conditions
incident:createdEvent broadcast when an incident has been createdNew incident created
incident:deleted Event broadcast when an incident is deletedNew incident created

Incident Created

incident:created

Triggered when a new incident is created in your incident management system through manual creation, alerts, or API calls.
POSThttps://api.yourapp.com/webhooks/unizo/scm
Best Practice: Use a dedicated webhook endpoint that can handle multiple event types. You have two architectural options:
• 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 architecture
Headers
NameTypeRequiredDescription
x-unizo-event-typestringYesThe type of event that was triggered
x-unizo-signaturestringYesHMAC SHA-256 signature
Request Body Schema
PropertyTypeRequiredDescription
typestringYesEvent type identifier
versionstringYesWebhook payload version
contentTypestringYesBranch name/identifier
incidentstringYesIncident Name
incident.idstringYesIncident ID
incident.statestringYesCurrent Incident Status
incident.summarystringYesIncident Urgency
incident.servicestringYesIncident Priority
incident.createdDateTimestringYesIncident Timestamp
incident.createdBystringYesIncident Creator
integration.typestringYesIntegration type
integration.idstringYesIntegration ID
integration.namestringYesIntegration display name
Example Payload
{
"type": "incident:created",
"version": "1.0.0",
"contentType": "application/json",
"incident": {
"id": "01FAFUGR0FD645M4W6KNR6522O",
"state": "triggered",
"summary": "incident 4",
"service": "TheService",
"createdDateTime": "December 13, 2024 10:26 AM",
"createdBy": "Unz .io"
},
"integration": {
"type": "INCIDENT",
"id": "906e3a3c-e317-4114-8cd5-38bfacbf02a3",
"name": "Pa_Secu_1734085262512"
}
}
Response
200 OKWebhook processed successfully
400 Bad RequestInvalid webhook payload
401 UnauthorizedInvalid or missing signature

Incident Deleted

incident:deleted

Triggered when an incident is deleted, indicating it has been permanently removed from the system or no longer requires tracking
POSThttps://api.yourapp.com/webhooks/unizo/scm
Best Practice: Use a dedicated webhook endpoint that can handle multiple event types. You have two architectural options:
• 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 architecture
Headers
NameTypeRequiredDescription
x-unizo-event-typestringYesThe type of event that was triggered
x-unizo-signaturestringYesHMAC SHA-256 signature
Request Body Schema
PropertyTypeRequiredDescription
typestringYesEvent type identifier
versionstringYesWebhook payload version
contentTypestringYesBranch name/identifier
incidentstringYesIncident Name
incident.idstringYesIncident ID
incident.statestringYesCurrent Incident Status
incident.summarystringYesIncident Urgency
incident.servicestringYesIncident Priority
incident.createdDateTimestringYesIncident Timestamp
incident.createdBystringYesIncident Creator
integration.typestringYesIntegration type
integration.idstringYesIntegration ID
integration.namestringYesIntegration display name
Example Payload
{
"type": "incident:deleted",
"version": "1.0.0",
"contentType": "application/json",
"incident": {
"id": "01FAFUHLEXIZAAJW1QP6090VNJ",
"state": "resolved",
"summary": "incident 4",
"service": "TheService",
"createdDateTime": "December 13, 2024 10:26 AM",
"createdBy": "Unz .io"
},
"integration": {
"type": "INCIDENT",
"id": "906e3a3c-e317-4114-8cd5-38bfacbf02a3",
"name": "Pa_Secu_1734085262512"
}
}
Response
200 OKWebhook processed successfully
400 Bad RequestInvalid webhook payload
401 UnauthorizedInvalid or missing signature

Webhook Delivery & Retries

Unizo implements a robust delivery system with automatic retries to ensure your webhooks are delivered reliably:

  • Timeout: 30 seconds per delivery attempt
  • Retry Schedule: 5 attempts with exponential backoff
    • Attempt 1: Immediate
    • Attempt 2: 1 minute delay
    • Attempt 3: 5 minutes delay
    • Attempt 4: 30 minutes delay
    • Attempt 5: 2 hours delay
  • Success Criteria: HTTP status codes 200-299
  • Failure Handling: After 5 failed attempts, the webhook is marked as failed

Best Practices

1. Idempotency

Always implement idempotent webhook handlers using the x-unizo-delivery-id header:

Idempotent Webhook Handler

// Example: Handling webhooks idempotently
app.post('/webhooks/incidents', async (req, res) => {
const deliveryId = req.headers['x-unizo-delivery-id'];

// Check if we've already processed this delivery
const existingDelivery = await db.webhookDeliveries.findOne({ 
  deliveryId 
});

if (existingDelivery) {
  console.log(`Duplicate delivery detected: ${deliveryId}`);
  return res.status(200).json({ 
    status: 'already_processed' 
  });
}

// Process the webhook
try {
  await processIncidentEvent(req.body);
  
  // Record the delivery
  await db.webhookDeliveries.create({
    deliveryId,
    processedAt: new Date()
  });
  
  res.status(200).json({ status: 'success' });
} catch (error) {
  console.error('Webhook processing failed:', error);
  res.status(500).json({ status: 'error' });
}
});

2. Incident Response Automation

Automate incident response workflows based on webhook events:

Automated Incident Response

// Example: Automated incident response
app.post('/webhooks/incidents', async (req, res) => {
const { type, data } = req.body;

// Acknowledge receipt immediately
res.status(200).json({ status: 'received' });

switch (type) {
  case 'incident:created':
    // Auto-assign based on service
    if (data.incident.priority === 'P1') {
      await notificationService.pageOnCall({
        service: data.incident.service.name,
        urgency: 'high',
        message: `P1: ${data.incident.title}`
      });
      
      // Create war room
      await collaborationApi.createChannel({
        name: `inc-${data.incident.id}`,
        topic: data.incident.title,
        members: ['@oncall', '@incident-commander']
      });
      
      // Start status page incident
      await statusPageApi.createIncident({
        name: data.incident.title,
        status: 'investigating',
        affected_components: [data.incident.service.id]
      });
    }
    break;
    
  case 'incident:resolved':
    // Update related systems
    await Promise.all([
      // Close war room
      collaborationApi.archiveChannel(`inc-${data.incident.id}`),
      
      // Update status page
      statusPageApi.resolveIncident(data.incident.id),
      
      // Generate post-mortem template
      documentationApi.createPostMortem({
        incidentId: data.incident.id,
        duration: data.duration,
        responders: await getIncidentResponders(data.incident.id)
      })
    ]);
    break;
}
});

3. Metrics and Analytics

Track incident metrics for continuous improvement:

Incident Metrics Tracking

// Example: Track incident metrics
app.post('/webhooks/incidents', async (req, res) => {
const { type, data } = req.body;

// Store metrics
const metrics = {
  timestamp: new Date(),
  eventType: type,
  incidentId: data.incident?.id,
  service: data.incident?.service?.name,
  priority: data.incident?.priority
};

switch (type) {
  case 'incident:acknowledged':
    metrics.timeToAcknowledge = data.time_to_acknowledge;
    metrics.responder = data.acknowledged_by.email;
    break;
    
  case 'incident:resolved':
    metrics.timeToResolve = data.time_to_resolve;
    metrics.totalDuration = data.duration;
    break;
    
  case 'priority:changed':
    metrics.priorityEscalation = 
      data.priority_change.current > data.priority_change.previous;
    break;
}

// Store in time-series database
await metricsDb.incidents.create(metrics);

// Calculate SLO compliance
if (type === 'incident:resolved') {
  const sloTarget = getSLOTarget(data.incident.priority);
  const sloMet = data.duration <= sloTarget;
  
  await metricsDb.sloCompliance.create({
    incidentId: data.incident.id,
    priority: data.incident.priority,
    target: sloTarget,
    actual: data.duration,
    met: sloMet
  });
}

res.status(200).json({ status: 'tracked' });
});

Need Help?

For webhook-related support: