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.

An example webhook client in Node.js is available here: https://github.com/rleroi/trengo-webhook-example-node

Deploy to Heroku

Configuration

Webhooks can be configured via Settings > Apps & Integrations > Webhooks. You may also programmatically set a webhook via the Rest API. The list below describes the available webhook types and triggers.

Type

Triggers

INBOUND

When an inbound message is received

OUTBOUND

When an outbound message is sent

NOTE

When an internal message is created

TICKET_LABEL_ADDED

When a label is added to a ticket

TICKET_LABEL_DELETED

When a label is removed from a ticket

TICKET_ASSIGNED

When a ticket is assigned to an agent

TICKET_CLOSED

When a ticket is closed

TICKET_REOPENED

When a ticket is reopened

TICKET_MARKED_AS_SPAM

When a ticket is marked as spam

TICKET_UNMARKED_AS_SPAM

When a ticket is unmarked as spam

VOICE_CALL_STARTED

When a voice call has started

VOICE_CALL_ENDED

When a voice call has ended

VOICE_CALL_RECORDED

When a voice call has been recorded

VOICE_CALL_MISSED

When a voice call is missed

VOICE_CALL_ROUTE_NUMBER

When an IVR action is sent

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)


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.

Deploy to Heroku

The repository is available here: https://github.com/rleroi/trengo-webhook-example-node


Did this page help you?