Webhooks are the way to have ThriveDesk call a script on your server when one or more events have happened, enabling you to react however you like. Webhooks can be thought of as event listeners or push notifications.

Available Events:

Available Events:

Each request body uses the object format linked in the table below. All webhooks use the v1 payload
Event Name Event Type
Conversation created conversation.created
Conversation assigned conversation.assigned
Note added to conversation conversation.note.added
User replies to conversation conversation.agent.replied
Customer replies to conversation conversation.contact.replied
Conversation status updated conversation.status.updated
Conversation Tags added/updated conversation.tags.updated
Conversation moved conversation.moved

Response:

A sample response body has been demonstrated here:

{
  "eventType": "conversation.tags.updated",
  "data": {
    "type": "conversation",
    "id": "dea1fca0-6529-43fd-91df-044afbf2a1d4",
    "ticketId": 26,
    "subject": "Duis aute irure dolor in reprehenderit in voluptate velit",
    "excerpt": "Cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat...",
    "status": "Active",
    "priority": "Normal",
    "active": true,
    "createdAt": "2021-06-29T13:04:05.000000Z",
    "tags": [
      "Beatae",
      "Consequuntur",
      "Cumque"
    ],
    "inbox": {
      "id": "f86385ff-9ce5-456a-a207-0bbf4ec59c0e",
      "name": "Dev",
      "inboxAddress": "example@app.thrivedesk.email",
      "connectedEmailAddress": "example@mail.com"
    },
    "cc": [
      "examplecc@mail.com"
    ],
    "bcc": [
      "examplebcc@mail.com"
    ],
    "assignedTo": {
      "id": "050cbdb6-a973-40df-a5dd-b7f72c993055",
      "firstName": "Assigned",
      "lastName": "Example",
      "email": "exampleassigned@mail.com"
    },
    "contact": {
      "id": "925298d4-a7d9-4d6b-8a01-10b2dea439aa",
      "name": "example",
      "email": "example@mail.com",
      "avatar": null
    },
    "hasAttachment": false,
    "hasInlineAttachment": false,
    "threadsCount": 3,
    "threads": [
      {
        "id": "967b48b3-32d7-4d63-81cc-4f6d04d879b1",
        "type": "Email",
        "status": "Active",
        "direction": "Outbound",
        "htmlBody": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut...",
        "textBody": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut...",
        "createdAt": "2021-06-29T13:04:05.000000Z",
        "updatedAt": "2021-06-29T13:04:05.000000Z",
        "viewedAt": null
      },
      {
        "id": "e84aea7e-65ee-4b5a-a8d0-4f216192847e",
        "type": "Email",
        "status": "Active",
        "direction": "Outbound",
        "htmlBody": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea...",
        "textBody": null,
        "createdAt": "2021-06-29T13:04:46.000000Z",
        "updatedAt": "2021-06-29T13:04:46.000000Z",
        "viewedAt": null
      },
      {
        "id": "ce7946ae-86c4-4891-af2a-485d984a6a74",
        "type": "Note",
        "status": "Active",
        "direction": null,
        "htmlBody": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla...",
        "textBody": null,
        "createdAt": "2021-06-29T13:04:59.000000Z",
        "updatedAt": "2021-06-29T13:04:59.000000Z",
        "viewedAt": null
      }
    ]
  }
}

Response fields (Conversation):

Path Type Description
eventType String Type of the event, one of the available events
type String Type of the data, ex: conversation
data Object Main response body
id String Unique identifier
ticketId Integer Unique ticket identifier
subject String Conversation subject
excerpt String Conversation excerpt
status String Conversation status, one of:
Active
Pending
Closed
priority String Conversation priority, one of:
High
Normal
Low
active Boolean Conversation active status
createdAt String UTC time when the conversation was created
tags Array List of tags, with the following fields:
name
inbox Object Inbox information of the conversation, with the following fields:
id
name
inboxAddress
connectedEmailAddress
cc Array List of emails that are cc’d
bcc Array List of emails that are bcc’d
assignedTo Object Who the conversation is assigned to, with the following fields:
id
firstName
lastName
email
contactInfo Object An object containing the contact information associate with the conversation with the following fields:
id
name
email
avatar
hasAttachment Boolean Conversation contain attachment or not
hasInlineAttachment Boolean Conversation contains inline attachment or not
isDraft Boolean Is conversation drafted or not
threadsCount Integer Number of threads the conversation has
threads Array List of threads, with the following fields:
id
type (Email, Note, Draft)
status
Direction (Inbound, Outbound )
htmlBody
textBody
createdAt
updatedAt
viewedAt

Headers:

Each webhook includes one ThriveDesk header:

Verifying:

Webhooks can be verified as coming from ThriveDesk by calculating a digital signature. Each webhook request contains an X-TD-SIGNATURE header, generated using the given secret key, along with the JSON encoded payload data (only the data field of response data) sent in the request.

To verify if the request came from ThriveDesk, compute the HMAC hash and compare it to the header value sent in the request. If the computed signatures match, you can be sure the request was sent from ThriveDesk.

Signatures are calculated based on the raw request body passed to your servers by ThriveDesk. This means that if non-ASCII characters are contained in the payload, you will need to calculate the signature based on the escaped, transliterated string passed to you by ThriveDesk. We recommend this as best practice in general, even for those primarily working with ASCII data.

PHP

function isFromThriveDesk($data, $signature, $secret_key) {
    $calculate = base64_encode(hash_hmac('sha1', json_encode($data), $secret_key, true));

    return $signature == $calculate;
}

/**
 * $request->get('data')
 * 
 * only the data field of request body
 */ 
if (isFromThriveDesk($request->get('data'), $signature, $secret_key)) { 
	// do something
}

Node JS

const crypto = require('crypto');

/**
 * request.body.data
 *
 * only the data field of reqeust body
 */
if (isFromThriveDesk(request.body.data, signature, secret_key)) {
    // do something
}

let isFromThriveDesk = (data, signature, secret_key) => {
    return signature === crypto
        .createHmac('SHA1', secret_key)
        .update(JSON.stringify(data))
        .digest('base64');
}

Responses:

Anything returned to the body of the response will be discarded. In order to know the webhook was successful, an HTTP status code between 200 and 299 must be returned.

A status code of 410 will cause the webhook to get deactivated/deleted.

Any status codes other than something between 200 and 299 or 410 is a failure of some kind. If the event fails several times, it is discarded.