Back to User Guide

Webhooks

Receive real-time notifications when events occur in Relay.

What Are Webhooks?

Webhooks are HTTP callbacks that notify your server when events happen:

  • No polling required
  • Real-time updates
  • Efficient integration

How Webhooks Work

  1. You register a webhook URL
  2. Select which events to receive
  3. When event occurs, Relay sends POST request
  4. Your server processes the request
  5. Return 200 OK to acknowledge

Setting Up Webhooks

Create a Webhook

  1. Go to Dashboard → Integrations → Webhooks
  2. Click + Add Webhook
  3. Enter webhook URL
  4. Select events to subscribe
  5. Save

Webhook URL Requirements

  • Must be HTTPS
  • Publicly accessible
  • Responds within 30 seconds
  • Returns 2xx status code

Available Events

Ticket Events

EventDescription
ticket.createdNew ticket created
ticket.updatedTicket fields changed
ticket.status_changedStatus changed
ticket.assignedAssignee changed
ticket.deletedTicket deleted

Message Events

EventDescription
message.createdNew message added
message.customer_replyCustomer replied
message.agent_replyAgent replied

Customer Events

EventDescription
customer.createdNew customer
customer.updatedCustomer updated

SLA Events

EventDescription
sla.warningSLA approaching deadline
sla.breachedSLA breached

Webhook Payload

Request Format

POST /your-webhook-url
Content-Type: application/json
X-Relay-Signature: sha256=...
X-Relay-Event: ticket.created
X-Relay-Delivery: webhook_delivery_123

Payload Structure

{
  "id": "evt_123456",
  "event": "ticket.created",
  "created_at": "2025-01-15T10:30:00Z",
  "data": {
    "ticket": {
      "id": "tkt_789",
      "subject": "Help needed",
      "status": "open",
      "priority": "medium",
      "customer": {
        "id": "cust_456",
        "email": "user@example.com"
      }
    }
  }
}

Event-Specific Data

Each event includes relevant data:

ticket.created:

{
  "event": "ticket.created",
  "data": {
    "ticket": { ... }
  }
}

message.created:

{
  "event": "message.created",
  "data": {
    "message": { ... },
    "ticket": { ... }
  }
}

Verifying Webhooks

Signature Verification

Verify requests are from Relay using signatures.

How It Works

  1. Relay signs payload with your webhook secret
  2. Signature sent in X-Relay-Signature header
  3. You verify signature matches

Verification Code

Node.js:

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return `sha256=${expected}` === signature;
}

Python:

import hmac
import hashlib

def verify_signature(payload, signature, secret):
    expected = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()

    return f"sha256={expected}" == signature

Webhook Secret

Find your webhook secret in webhook settings. Keep it secure!


Handling Webhooks

Basic Handler

app.post('/webhook', (req, res) => {
  const event = req.body.event;
  const data = req.body.data;

  switch (event) {
    case 'ticket.created':
      handleNewTicket(data.ticket);
      break;
    case 'message.created':
      handleNewMessage(data.message);
      break;
  }

  res.status(200).send('OK');
});

Best Practices

  1. Respond quickly: Return 200 immediately
  2. Process async: Queue for background processing
  3. Handle duplicates: Same event may send twice
  4. Log everything: For debugging

Idempotency

Handle duplicate deliveries:

const processedEvents = new Set();

app.post('/webhook', (req, res) => {
  const eventId = req.body.id;

  if (processedEvents.has(eventId)) {
    return res.status(200).send('Already processed');
  }

  processedEvents.add(eventId);
  // Process event...

  res.status(200).send('OK');
});

Retry Policy

Automatic Retries

If your endpoint fails, Relay retries:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
68 hours

Failure Conditions

Retries on:

  • Connection timeout
  • 5xx server errors
  • Connection refused

No Retry

Won't retry on:

  • 2xx success
  • 4xx client errors (except 429)

Testing Webhooks

Send Test Event

  1. Go to webhook settings
  2. Click Send Test
  3. Select event type
  4. View response

Local Development

Use tunneling tools:

  • ngrok
  • Cloudflare Tunnel
  • localtunnel

Example with ngrok:

ngrok http 3000
# Use generated URL as webhook endpoint

Webhook Logs

View delivery history:

  1. Go to webhook settings
  2. Click on webhook
  3. View recent deliveries
  4. See payload and response

Troubleshooting

Webhook Not Firing

  • Verify webhook is enabled
  • Check event is subscribed
  • Confirm URL is accessible

Signature Mismatch

  • Check secret is correct
  • Ensure using raw body (not parsed JSON)
  • Verify encoding

Timeout Errors

  • Respond within 30 seconds
  • Process async if slow
  • Check server performance

Repeated Retries

  • Return 200 status code
  • Check server errors
  • Verify endpoint logic

Managing Webhooks

Disable Temporarily

  1. Edit webhook
  2. Toggle "Enabled" off
  3. Events queue (limited)
  4. Re-enable when ready

Delete Webhook

  1. Go to webhook settings
  2. Click webhook
  3. Delete
  4. Events stop immediately

Update URL

  1. Create new webhook with new URL
  2. Verify it works
  3. Delete old webhook

← Authentication | REST API →