Webhooks
With webhooks you are able to get notified when something happens in Trengo without having to poll the API.
Introduction
Webhooks are useful in a broad range of situations. When an event in Trengo occures, such as a new message or a new voice call, Trengo will perform an HTTP request to the URL you provide. Based on the payload of the request, you can determine which action you need to perform.
Configuration
Request payload
The payload of each webhook depends on the type of the event. Use this list to see what payload we will POST to your URL.
INBOUND
Param | Description |
---|---|
message_id | Message ID |
ticket_id | Ticket ID |
contact_id | Contact ID |
message | Message content |
contact_name | Contact name |
contact_email | Contact email (if present) |
contact_identifier | Contact phone (if present) |
channel_id | Channel ID |
OUTBOUND
Param | Description |
---|---|
message_id | Message ID |
ticket_id | Ticket ID |
message | Message content |
user_id | User ID |
user_name | User name |
user_email | User email |
contact_id | Contact ID |
contact_name | Contact name |
contact_email | Contact email (if present) |
contact_identifier | Contact phone (if present) |
channel_id | Channel ID |
NOTE
Param | Description |
---|---|
message_id | Message ID |
ticket_id | Ticket ID |
message | Message content |
user_id | User ID |
user_name | User name |
user_email | User email |
TICKET_LABEL_ADDED
Param | Description |
---|---|
ticket_id | Ticket ID |
label_id | Label ID |
label_name | Label name |
TICKET_LABEL_DELETED
Param | Description |
---|---|
ticket_id | Ticket ID |
label_id | Label ID |
label_name | Label name |
TICKET_ASSIGNED
Param | Description |
---|---|
ticket_id | Ticket ID |
user_id | User ID |
user_name | User name |
user_email | User email |
team_id | Team ID |
team_name | Team name |
assigned_to | TEAM or USER |
TICKET_CLOSED
Param | Description |
---|---|
ticket_id | ticket_id |
TICKET_REOPENED
Param | Description |
---|---|
ticket_id | ticket_id |
status | OPEN or ASSIGNED |
TICKET_MARKED_AS_SPAM
Param | Description |
---|---|
ticket_id | Ticket ID |
TICKET_UNMARKED_AS_SPAM
Param | Description |
---|---|
ticket_id | Ticket ID |
VOICE_CALL_STARTED
Param | Description |
---|---|
channel_id | Channel ID |
ticket_id | Ticket ID |
contact_id | Contact ID |
direction | INBOUND / OUTBOUND |
from | Origination phone number |
to | Destination phone number |
user_id | User ID |
user_name | User name |
user_email | User email |
VOICE_CALL_ENDED
Param | Description |
---|---|
channel_id | Channel ID |
ticket_id | Ticket ID |
contact_id | Contact ID |
direction | INBOUND / OUTBOUND |
from | Origination phone number |
to | Destination phone number |
user_id | User ID |
user_name | User name |
user_email | User email |
duration | Duration in seconds |
VOICE_CALL_RECORDED
Param | Description |
---|---|
channel_id | Channel ID |
ticket_id | Ticket ID |
contact_id | Contact ID |
direction | INBOUND / OUTBOUND |
from | Origination phone number |
to | Destination phone number |
user_id | User ID |
user_name | User name |
user_email | User email |
duration | Duration in seconds |
recording_url | Recording URL (when enabled) |
VOICE_CALL_MISSED
Param | Description |
---|---|
channel_id | Channel ID |
ticket_id | Ticket ID |
contact_id | Contact ID |
from | Origination phone number |
to | Destination phone number |
duration | Duration in seconds |
recording_url | Recording URL (when enabled) |
failure_reason | List of available reasons: NO_BALANCE , OUTSIDE_BUSINESS_HOURS , FULL_QUEUE , QUEUE_TIME_EXCEEDED , NO_AGENTS_AVAILABLE |
VOICE_CALL_ROUTE_NUMBER
Param | Description |
---|---|
channel_id | Channel ID |
ticket_id | Ticket ID |
contact_id | Contact ID |
ivr_menu_route_number_id | IVR menu route number ID |
ivr_menu_id | IVR menu ID |
action | Route action |
trigger | Route number |
team_id | Route to team ID |
target_ivr_menu_id | Route to target IVR menu ID |
phone_number | Route to phone number |
Verifying payload
We recommend verifying the webhook signature to make sure the data received is coming from Trengo.
The Trengo-Signature
header is sent with every webhook, it consists of a timestamp and hash concatenated together with a ;
in between.
Example signature: 1569508124;1298b36aefaeb7e0e93073744b954266515b69304b3dfe044cbf7203525061f4
The hash is a lowercase hexadecimal SHA256 HMAC digest of the timestamp, a .
and the request's body. It uses your signing secret as key.
Compare the hash part of the signature to verify the webhook's authenticity.
<?php
$payload = @file_get_contents('php://input'); // The request's body
$signature = $_SERVER['HTTP_TRENGO_SIGNATURE']; // The Trengo-Signature header value
$signingSecret = 'my-secret'; // Your signing secret
// verify the signature
if (verify($payload, $signature, $signingSecret)) {
echo 'Valid signature.';
} else {
echo 'Invalid signature';
}
/**
* @param $payload
* @param $signature
* @param $signingSecret
* @return bool
*/
function verify($payload, $signature, $signingSecret) {
list($timestamp, $hash) = explode(';', $signature);
return hash_equals(hash_hmac('sha256', $timestamp . '.' . $payload, $signingSecret), $hash);
}
var express = require('express');
var CryptoJS = require('crypto-js');
// start the express server
var app = express();
app.listen();
// parse the URLEncoded body and save the raw body to req.rawBody
app.use(
express.urlencoded({
verify: function (req, res, buf) {
req.rawBody = buf;
},
inflate: true,
type: "application/x-www-form-urlencoded"
})
);
// listen for POST requests to '/my-endpoint'
app.post('/my-endpoint', function(req, res) {
// replace with your signing secret, found in Trengo
var signingSecret = 'my-secret';
// get signature header
var signature = req.header('Trengo-Signature');
// get raw request body
var payload = req.rawBody;
// verify the signature
if (verify(payload, signature, signingSecret)) {
res.send('Valid signature');
// the parsed body is available at req.body
console.log(req.body);
} else {
res.send('Invalid signature');
}
});
// the function to verify the trengo-signature
function verify(payload, signature, signingSecret) {
// split the timestamp from the hash
var signatureParts = signature.split(';');
var timestamp = signatureParts[0];
var hash = signatureParts[1];
// get the raw digest bytes
var raw = CryptoJS.HmacSHA256(timestamp + '.' + payload, signingSecret);
// encode the raw bytes as hexadecimal digits
var hex = raw.toString(CryptoJS.enc.hex);
// and make the hexadecimal digits lowercase
var lowerCase = hex.toLowerCase();
// compare the result to the hash from the signature header
return lowerCase === hash;
}
You can deploy a working example on Heroku to instantly test it out for free.
The repository is available here: https://github.com/rleroi/trengo-webhook-example-node
Updated 2 months ago