Skip to main content

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​

EventDescription
ticket.createdNew ticket created
ticket.updatedTicket fields changed
ticket.assignedTicket assigned to agent
ticket.resolvedTicket marked resolved
ticket.comment.addedNew comment on ticket

Call Events​

EventDescription
call.startedCall initiated
call.answeredCall answered
call.completedCall ended
call.transferredCall transferred
call.recording.readyRecording available

Agent Events​

EventDescription
agent.status_changedStatus update
agent.logged_inAgent signed in
agent.logged_outAgent signed out

User Events​

EventDescription
user.createdNew user added
user.updatedUser profile changed
user.deletedUser removed

Billing Events​

EventDescription
subscription.createdNew subscription
subscription.updatedSubscription plan changed
subscription.canceledSubscription canceled
payment.succeededPayment processed
payment.failedPayment failed
invoice.paidInvoice payment received
invoice.failedInvoice payment failed

CRM Events​

EventDescription
crm.account.createdAccount created
crm.account.updatedAccount modified
crm.account.deletedAccount deleted
crm.contact.createdContact created
crm.contact.updatedContact modified
crm.contact.deletedContact deleted
crm.contact.lead_convertedLead converted to opportunity/customer

Engagement Events​

EventDescription
engagement.createdNew engagement started
engagement.closedEngagement ended
engagement.escalatedEngagement escalated

Survey Events​

EventDescription
survey.response.completedSurvey response submitted
survey.response.updatedSurvey response modified

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:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
68 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​

Best Practices​

  1. Respond fast - Return 2xx within 30 seconds
  2. Process async - Queue events for background processing
  3. Be idempotent - Handle duplicate deliveries
  4. Verify signatures - Always validate authenticity
  5. Monitor failures - Alert on repeated failures
  6. Use HTTPS - Only accept secure connections