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
- You register a webhook URL
- Select which events to receive
- When event occurs, Relay sends POST request
- Your server processes the request
- Return 200 OK to acknowledge
Setting Up Webhooks
Create a Webhook
- Go to Dashboard → Integrations → Webhooks
- Click + Add Webhook
- Enter webhook URL
- Select events to subscribe
- Save
Webhook URL Requirements
- Must be HTTPS
- Publicly accessible
- Responds within 30 seconds
- Returns 2xx status code
Available Events
Ticket Events
| Event | Description |
|---|---|
ticket.created | New ticket created |
ticket.updated | Ticket fields changed |
ticket.status_changed | Status changed |
ticket.assigned | Assignee changed |
ticket.deleted | Ticket deleted |
Message Events
| Event | Description |
|---|---|
message.created | New message added |
message.customer_reply | Customer replied |
message.agent_reply | Agent replied |
Customer Events
| Event | Description |
|---|---|
customer.created | New customer |
customer.updated | Customer updated |
SLA Events
| Event | Description |
|---|---|
sla.warning | SLA approaching deadline |
sla.breached | SLA 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
- Relay signs payload with your webhook secret
- Signature sent in
X-Relay-Signatureheader - 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
- Respond quickly: Return 200 immediately
- Process async: Queue for background processing
- Handle duplicates: Same event may send twice
- 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:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 | 8 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
- Go to webhook settings
- Click Send Test
- Select event type
- 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:
- Go to webhook settings
- Click on webhook
- View recent deliveries
- 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
- Edit webhook
- Toggle "Enabled" off
- Events queue (limited)
- Re-enable when ready
Delete Webhook
- Go to webhook settings
- Click webhook
- Delete
- Events stop immediately
Update URL
- Create new webhook with new URL
- Verify it works
- Delete old webhook