Skip to main content

Webhooks

Real-time event notifications for your integrations

How Webhooks Work

Unizo webhooks deliver real-time notifications when events occur in your connected integrations. Events are normalized across providers, so you write your webhook handler once and it works with all integrations.

1

Event Occurs

An event happens in a connected integration

2

Event Captured

Unizo receives the event from the provider

3

Normalization

Event data is normalized to unified schema

4

Webhook Delivery

HTTP POST request sent to your endpoint

5

Your Processing

Your application handles the normalized event

Available Webhook Events

Quick Start

1. Create a Webhook Endpoint

First, create an endpoint in your application to receive webhook events:

// Express.js example
app.post('/webhooks/unizo', (req, res) => {
  const signature = req.headers['x-unizo-signature'];
  const event = req.body;
  
  // Verify webhook signature
  if (!verifyWebhookSignature(signature, req.rawBody)) {
    return res.status(401).send('Unauthorized');
  }
  
  // Handle the event
  switch (event.type) {
    case 'pull_request.opened':
      handlePullRequestOpened(event.data);
      break;
    case 'ticket.created':
      handleTicketCreated(event.data);
      break;
    // ... handle other events
  }
  
  res.status(200).send('OK');
});

2. Register Your Webhook

Webhooks are registered under integrations. First, you need an integration ID:

# Register a webhook for an integration
curl -X POST https://api.unizo.ai/api/v1/integrations/{integrationId}/watches \
  -H "apiKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/unizo",
    "events": ["pull_request.*", "ticket.*"]
  }'

3. Verify Webhook Signatures

Always verify webhook signatures to ensure requests are from Unizo:

const crypto = require('crypto');

function verifyWebhookSignature(signature, payload) {
  const secret = process.env.UNIZO_WEBHOOK_SECRET;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

Unified Webhook Payload

Standard Fields

id - Unique event identifier
type - Event type (e.g., pull_request.opened)
created - ISO 8601 timestamp
integration - Source integration details

Normalized Data

The data field contains provider-specific information normalized to a consistent schema:

  • Common fields across all providers
  • Consistent naming conventions
  • Standardized date formats
  • Unified status values

Example Payload

{
  "id": "evt_1234567890",
  "type": "pull_request.opened",
  "created": "2024-01-15T10:30:00Z",
  "integration": {
    "id": "int_github_123",
    "provider": "github",
    "name": "My GitHub Integration"
  },
  "data": {
    // Normalized fields work across GitHub, GitLab, Bitbucket
    "id": "pr_456",
    "number": 123,
    "title": "Add new feature",
    "description": "This PR adds...",
    "status": "open",  // Normalized: open, closed, merged
    "repository": {
      "id": "repo_789",
      "name": "my-repo",
      "full_name": "org/my-repo"
    },
    "author": {
      "id": "user_321",
      "username": "johndoe",
      "email": "john@example.com"
    }
  }
}

Best Practices

Security & Reliability

  • Verify webhook signatures for request authenticity
  • HTTPS endpoints required for secure data transmission
  • Implement idempotent handlers for event replay safety
  • Acknowledge quickly with 2xx, process asynchronously

Need Help?

For webhook-related support:

Contact support at support@unizo.ai