Webhook Integration Guide
Set up webhooks to receive real-time notifications when events occur in Semaswift.
Setting Up Webhooks
Create a Webhook Endpoint
First, create an endpoint in your application to receive webhook events:
// Express.js example
const express = require('express');
const crypto = require('crypto');
app.post('/webhooks/semaswift', express.raw({type: 'application/json'}), (req, res) => {
// Verify webhook signature
const signature = req.headers['x-semaswift-signature'];
const timestamp = req.headers['x-semaswift-timestamp'];
const expectedSig = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(`${timestamp}.${req.body}`)
.digest('hex');
if (signature !== expectedSig) {
return res.status(401).send('Invalid signature');
}
// Parse and handle event
const event = JSON.parse(req.body);
console.log('Received event:', event.type);
// Respond quickly
res.status(200).send('OK');
// Process async
processEvent(event);
});
Register Webhook in Semaswift
POST /api/v1/webhooks
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
{
"url": "https://your-app.com/webhooks/semaswift",
"events": [
"ticket.created",
"ticket.updated",
"call.completed",
"agent.status_changed"
],
"secret": "whsec_your_secret_key",
"description": "Production webhook"
}
Webhook Payload Structure
{
"id": "evt_abc123",
"type": "ticket.created",
"api_version": "2024-01",
"created_at": "2024-01-15T10:30:00Z",
"organization_id": "org_789",
"data": {
"object": {
"id": "tkt_123",
"subject": "Help needed",
"status": "new",
"priority": "high"
}
},
"previous_attributes": null
}
Event Categories
Ticket Events
| Event | Description |
|---|---|
ticket.created | New ticket created |
ticket.updated | Ticket fields changed |
ticket.assigned | Ticket assigned to agent |
ticket.resolved | Ticket marked resolved |
ticket.comment.added | New comment on ticket |
Call Events
| Event | Description |
|---|---|
call.started | Call initiated |
call.answered | Call answered |
call.completed | Call ended |
call.transferred | Call transferred |
call.recording.ready | Recording available |
Agent Events
| Event | Description |
|---|---|
agent.status_changed | Status update |
agent.logged_in | Agent signed in |
agent.logged_out | Agent signed out |
User Events
| Event | Description |
|---|---|
user.created | New user added |
user.updated | User profile changed |
user.deleted | User removed |
Billing Events
| Event | Description |
|---|---|
subscription.created | New subscription |
invoice.paid | Invoice payment received |
invoice.failed | Payment failed |
Signature Verification
Always verify webhook signatures to ensure authenticity:
import hmac
import hashlib
import time
def verify_webhook(payload: bytes, signature: str, timestamp: str, secret: str) -> bool:
# Check timestamp is recent (within 5 minutes)
if abs(time.time() - int(timestamp)) > 300:
return False
# Compute expected signature
signed_payload = f"{timestamp}.{payload.decode()}"
expected = hmac.new(
secret.encode(),
signed_payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
func verifyWebhook(payload []byte, signature, timestamp, secret string) bool {
// Check timestamp
ts, _ := strconv.ParseInt(timestamp, 10, 64)
if time.Now().Unix()-ts > 300 {
return false
}
// Compute signature
signedPayload := fmt.Sprintf("%s.%s", timestamp, string(payload))
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(signedPayload))
expected := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(signature), []byte(expected))
}
Managing Webhooks
List Webhooks
GET /api/v1/webhooks
Update Webhook
PATCH /api/v1/webhooks/{webhook_id}
{
"events": ["ticket.created", "ticket.updated"],
"enabled": true
}
Delete Webhook
DELETE /api/v1/webhooks/{webhook_id}
View Delivery History
GET /api/v1/webhooks/{webhook_id}/deliveries
Retry Failed Delivery
POST /api/v1/webhooks/{webhook_id}/deliveries/{delivery_id}/retry
Retry Policy
Failed deliveries are retried with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 | 8 hours |
After 6 failures, the webhook is disabled.
Testing
Send Test Event
POST /api/v1/webhooks/{webhook_id}/test
{
"event_type": "ticket.created"
}
Use Webhook Debugging Tools
- ngrok - Expose local server
- webhook.site - Inspect payloads
Best Practices
- Respond fast - Return 2xx within 30 seconds
- Process async - Queue events for background processing
- Be idempotent - Handle duplicate deliveries
- Verify signatures - Always validate authenticity
- Monitor failures - Alert on repeated failures
- Use HTTPS - Only accept secure connections