API
Webhooks
Receive real-time event notifications from Trunx via webhooks.
Overview
Trunx webhooks deliver real-time notifications to your application when events occur — SMS delivery, call completion, campaign progress, and more.
Register a Webhook
curl -X POST https://api.trunx.io/api/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/trunx",
"events": ["sms.*", "voice.*"]
}'Response:
{
"id": "whk_abc123",
"url": "https://your-app.com/webhooks/trunx",
"events": ["sms.*", "voice.*"],
"secret": "whsec_aBcDeFgHiJkLmNoPqRsTuVwXyZ..."
}Save the secret — it's only shown once and is used to verify webhook signatures.
Glob Patterns
The events array supports glob patterns:
| Pattern | Matches |
|---|---|
* | All events |
sms.* | All SMS events |
voice.* | All voice events |
campaign.* | All campaign events |
sms.delivered | Only SMS delivered events |
List Webhooks
curl https://api.trunx.io/api/webhooks \
-H "Authorization: Bearer YOUR_API_KEY"Response:
{
"webhooks": [
{
"id": "whk_abc123",
"url": "https://your-app.com/webhooks/trunx",
"events": ["sms.*", "voice.*"],
"active": true,
"createdAt": "2025-01-01T00:00:00.000Z"
}
]
}Delete a Webhook
curl -X DELETE https://api.trunx.io/api/webhooks/whk_abc123 \
-H "Authorization: Bearer YOUR_API_KEY"Delivery Logs
curl https://api.trunx.io/api/webhooks/whk_abc123/logs?limit=20 \
-H "Authorization: Bearer YOUR_API_KEY"Response:
{
"logs": [
{
"id": "log_123",
"eventType": "sms.delivered",
"status": "delivered",
"attempts": 1,
"responseCode": 200,
"createdAt": "2025-01-01T12:00:00.000Z"
}
]
}Event Types
| Event | Description |
|---|---|
sms.sent | SMS sent to carrier |
sms.delivered | SMS delivered to recipient |
sms.failed | SMS delivery failed |
sms.received | Inbound SMS received |
voice.initiated | Outbound call initiated |
voice.ai.initiated | AI voice call initiated |
voice.inbound | Inbound call received |
voice.answered | Call answered |
voice.completed | Call completed |
voice.ai.completed | AI call completed |
voice.failed | Call failed |
voice.amd | AMD detection result |
campaign.call.initiated | Campaign call started |
campaign.call.human_connected | Human answered campaign call |
campaign.call.voicemail | Campaign call reached voicemail |
campaign.call.failed | Campaign call failed |
campaign.stats.updated | Campaign stats refreshed |
campaign.paused.no_dids | Campaign paused — no healthy DIDs |
Payload Format
{
"channel": "sms",
"eventType": "sms.delivered",
"payload": {
"id": "msg_xyz789",
"from": "+15551234567",
"to": "+15559876543",
"status": "delivered"
},
"customerId": "cust_123",
"timestamp": "2025-01-01T12:00:00.000Z"
}Verifying Signatures
Every webhook includes an X-Trunx-Signature header containing an HMAC-SHA256 signature of the raw request body, using your webhook secret.
JavaScript:
import crypto from "crypto";
function verifyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler:
app.post("/webhooks/trunx", (req, res) => {
const signature = req.headers["x-trunx-signature"];
const isValid = verifyWebhook(req.rawBody, signature, WEBHOOK_SECRET);
if (!isValid) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = req.body;
console.log(`Received: ${event.eventType}`, event.payload);
res.status(200).json({ received: true });
});Python:
import hmac
import hashlib
def verify_webhook(raw_body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(), raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)Retry Policy
Failed deliveries retry with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 30 seconds |
| 3 | 2 minutes |
| 4 | 10 minutes |
| 5 | 1 hour |
After 5 failed attempts, the delivery is marked as failed.
SSE Alternative
For real-time streaming without webhooks, use Server-Sent Events. SSE supports channel filtering and Last-Event-ID replay.