Available Events

Event Name
Event Code (X-Desk-Event)
Payload
Ticket Created
ticket.created
Ticket
Ticket Deleted
ticket.deleted
ID Only
Ticket Note
ticket.note
Thread
Agent Reply
ticket.agent.reply
Thread
Customer Reply
ticket.customer.reply
Thread
Ticket Assigned
ticket.assigned
Ticket Assigned
Ticket Unassigned
ticket.unassigned
Ticket Assigned
Ticket Priority
ticket.priority
Ticket Priority
Ticket Merged
ticket.merged
Ticket Merged
Ticket Moved
ticket.moved
Ticket Moved
Thread Edited
thread.edited
Thread
Thread Deleted
thread.deleted
ID Only
Customer Created
customer.created
Customer
Customer Edited
customer.edited
Customer
Customer Deleted
customer.deleted
ID Only
Agent Created
agent.created
Agent
Agent Edited
agent.edited
Agent
Agent Deleted
agent.deleted
ID Only
Inbox Created
inbox.created
Inbox
Inbox Edited
inbox.edited
Inbox
Inbox Deleted
inbox.deleted
ID Only

Payloads

Below are example payloads sent, see the Available Events table for which payload is sent for which events.

When given eventCreatorId is the id of the agent that caused this event.

ID Only

The id property is dependent on the event, e.g for ticket.deleted it is the tickets id and customer.deleted the customers.

{
    "id": 1
}

Ticket

{
  "ticket": {
    "updatedAt": "2016-06-06T09:14:36.426741207+01:00",
    "createdAt": "2016-06-06T09:14:36.426741207+01:00",
    "state": "active",
    "threads": [
      {
        "updatedAt": "2016-06-06T09:14:36.429692802+01:00",
        "createdAt": "2016-06-06T09:14:36.429692802+01:00",
        "threadType": {
          "name": "message",
          "id": 1
        },
        "customer": {
          "linkedinURL": "",
          "googlePlusURL": "",
          "twitterURL": "",
          "facebookURL": "",
          "address": "",
          "mobile": "",
          "phone": "",
          "jobTitle": "",
          "company": "",
          "avatarURL": "https:\/\/digitalcrew.teamwork.com\/desk\/images\/avatars\/animals\/cat.png",
          "email": "joe@bloggs.com",
          "lastName": "Bloggs",
          "firstName": "Joe",
          "id": 1
        },
        "body": "I tried to do this and it didn't work...",
        "ticketId": 1,
        "id": 1
      },
      {
        "updatedAt": "2016-06-06T09:14:36.430863412+01:00",
        "createdAt": "2016-06-06T09:14:36.430863412+01:00",
        "threadType": {
          "name": "message",
          "id": 1
        },
        "agent": {
          "avatarURL": "https:\/\/digitalcrew.teamwork.com\/desk\/images\/avatars\/animals\/sheep.png",
          "lastName": "Agent",
          "firstName": "Jane",
          "id": 1
        },
        "body": "Have you tried doing...",
        "ticketId": 1,
        "id": 2
      },
      {
        "updatedAt": "2016-06-06T09:14:36.433186639+01:00",
        "createdAt": "2016-06-06T09:14:36.433186639+01:00",
        "threadType": {
          "name": "note",
          "id": 3
        },
        "agent": {
          "avatarURL": "https:\/\/digitalcrew.teamwork.com\/desk\/images\/avatars\/animals\/sheep.png",
          "lastName": "Agent",
          "firstName": "Jane",
          "id": 1
        },
        "body": "This is a private note",
        "ticketId": 1,
        "id": 3
      }
    ],
    "type": {
      "name": "Problem",
      "id": 1
    },
    "priority": {
      "sortOrder": 0,
      "color": "",
      "name": "Low",
      "id": 1
    },
    "status": {
      "color": "#44d335",
      "code": "active",
      "name": "Active",
      "id": 1
    },
    "tags": [
      {
        "color": "",
        "name": "needs-help",
        "id": 1
      },
      {
        "color": "",
        "name": "hard-fix",
        "id": 2
      }
    ],
    "files": null,
    "agent": {
      "avatarURL": "https:\/\/digitalcrew.teamwork.com\/desk\/images\/avatars\/animals\/sheep.png",
      "lastName": "Agent",
      "firstName": "Jane",
      "id": 1
    },
    "customer": {
      "linkedinURL": "",
      "googlePlusURL": "",
      "twitterURL": "",
      "facebookURL": "",
      "address": "",
      "mobile": "",
      "phone": "",
      "jobTitle": "",
      "company": "",
      "avatarURL": "https:\/\/digitalcrew.teamwork.com\/desk\/images\/avatars\/animals\/cat.png",
      "email": "joe@bloggs.com",
      "lastName": "Bloggs",
      "firstName": "Joe",
      "id": 1
    },
    "subject": "Help!",
    "id": 1
  },
  "inbox": {
    "state": "active",
    "name": "Support",
    "id": 1
  }
}

Ticket Assigned

On ticket.unassigned the agent property will not be given.

{
    "agent": {
        "avatarURL": "https://digitalcrew.teamwork.com/desk/images/avatars/animals/sheep.png",
        "firstName": "Jane",
        "id": 1,
        "lastName": "Agent"
    },
    "eventCreatorId": 1,
    "id": 1
}

Ticket Priority

{
    "eventCreatorId": 1,
    "id": 1,
    "priority": {
        "color": "",
        "id": 1,
        "name": "Low",
        "sortOrder": 0
    }
}

Ticket Merged

{
    "eventCreatorId": 1,
    "id": 1,
    "mergedToTicketId": 200
}

Ticket Moved

{
    "eventCreatorId": 1,
    "id": 1,
    "newInboxId": 2,
    "oldInboxId": 1
}

Thread

Example agent message thread:

{
    "thread": {
        "agent": {
            "avatarURL": "https://digitalcrew.teamwork.com/desk/images/avatars/animals/sheep.png",
            "firstName": "Jane",
            "id": 1,
            "lastName": "Agent"
        },
        "body": "Have you tried doing...",
        "createdAt": "2016-04-28T09:35:11.197304718+01:00",
        "id": 2,
        "threadType": {
            "id": 1,
            "name": "message"
        },
        "ticketId": 1,
        "updatedAt": "2016-04-28T09:35:11.197304718+01:00"
    }
}

Example customer message thread:

{
    "thread": {
        "body": "I tried to do this and it didn't work...",
        "createdAt": "2016-04-28T09:35:11.196119068+01:00",
        "customer": {
            "address": "",
            "avatarURL": "https://digitalcrew.teamwork.com/desk/images/avatars/animals/cat.png",
            "company": "",
            "email": "joe@bloggs.com",
            "facebookURL": "",
            "firstName": "Joe",
            "googlePlusURL": "",
            "id": 1,
            "jobTitle": "",
            "lastName": "Bloggs",
            "linkedinURL": "",
            "mobile": "",
            "phone": "",
            "twitterURL": ""
        },
        "id": 1,
        "threadType": {
            "id": 1,
            "name": "message"
        },
        "ticketId": 1,
        "updatedAt": "2016-04-28T09:35:11.196119068+01:00"
    }
}

Example note thread:

{
    "thread": {
        "agent": {
            "avatarURL": "https://digitalcrew.teamwork.com/desk/images/avatars/animals/sheep.png",
            "firstName": "Jane",
            "id": 1,
            "lastName": "Agent"
        },
        "body": "This is a private note",
        "createdAt": "2016-04-28T09:56:12.568495585+01:00",
        "id": 3,
        "threadType": {
            "id": 3,
            "name": "note"
        },
        "ticketId": 1,
        "updatedAt": "2016-04-28T09:56:12.568495585+01:00"
    }
}

Customer

{
    "customer": {
        "address": "",
        "avatarURL": "https://digitalcrew.teamwork.com/desk/images/avatars/animals/cat.png",
        "company": "",
        "email": "joe@bloggs.com",
        "facebookURL": "",
        "firstName": "Joe",
        "googlePlusURL": "",
        "id": 1,
        "jobTitle": "",
        "lastName": "Bloggs",
        "linkedinURL": "",
        "mobile": "",
        "phone": "",
        "twitterURL": ""
    }
}

Agent

{
    "agent": {
        "avatarURL": "https://digitalcrew.teamwork.com/desk/images/avatars/animals/sheep.png",
        "firstName": "Jane",
        "id": 1,
        "lastName": "Agent"
    }
}

Inbox

{
    "inbox": {
        "id": 1,
        "name": "Support",
        "state": "active"
    }
}

Headers

Webhooks include the following headers:

  • X-Desk-Event: The event name of the webhook, e.g ticket.created
  • X-Desk-Signature: The signature generated by Teamwork Desk using your Secret Token for you to determine if the request is genuine.
  • X-Desk-Delivery: The delivery UUID, this is listed in the Recent Deliveries section of your webhook.
  • User-Agent: The version of the webhooks service used to make this request is included in this header.

Verifying

So you can verify that the request comes from Teamwork Desk we include the X-Desk-Signature header. This header includes the HMAC-SHA256 hex encoded signature of the request which was computed using your Secret Token in your webhook settings.

To verify the request you should compute the HMAC hash and compare it against the X-Desk-Signature header, if they match then you know the request was sent from Teamwork Desk. See the examples for a demonstration of this.

Responses

Responses with a status code other than 200 will be considered as a failure, failures will be reattempted 3 times before permanent failure. After multiple permanent failures we will disable your webhook.

Reattempt #
Delay (mins)
1
1
2
5
3
10

Examples

Go

package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

const secretToken = "bea1ffc4e56d5056b6e0c7ee24b47b5"

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != "POST" {
            http.Error(w, "", http.StatusBadRequest)
            return
        }

        b, err := ioutil.ReadAll(r.Body)
        if err != nil {
            http.Error(w, "", http.StatusInternalServerError)
            return
        }

        if !validSignature(r.Header.Get("X-Desk-Signature"), b) {
            http.Error(w, "", http.StatusBadRequest)
            return
        }

        fmt.Println("Verified Teamwork Desk Webhook:")
        for h, v := range r.Header {
            fmt.Printf("%s: %s\n", h, v[0])
        }
        fmt.Println("-------------------")
        fmt.Println(string(b))
    })

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func validSignature(sig string, body []byte) bool {
    mac := hmac.New(sha256.New, []byte(secretToken))
    mac.Write(body)
    return sig == hex.EncodeToString(mac.Sum(nil))
}

PHP

<?php

define('SECERT_TOKEN', 'bea1ffc4e56d5056b6e0c7ee24b47b5');

$body = file_get_contents('php://input');
$sig = hash_hmac('sha256', $body, SECERT_TOKEN, false);
if ($sig !== $_SERVER['HTTP_X_DESK_SIGNATURE']) {
    error_log('Bad signature');
    http_response_code(400);
    exit;
}

error_log('Verified Teamwork Desk Webhook Event: ' . $_SERVER['HTTP_X_DESK_EVENT']);
error_log($body);