Author picture Anumadu Moses

Guide to Zendesk Webhooks Features and Best Practices

Published


Zendesk webhook is a system that notifies third-party apps when an event occurs on a Zendesk ticket. Zendesk webhook features allow third-party apps to easily set up and receive webhook data when an event is triggered for a new ticket created or updated.

In this article, we will explore Zendesk webhooks and discuss best practices for working with Zendesk webhooks.

Click here for a more general guide on working with your webhook endpoints.

Zendesk webhook features

FeatureDetails
Webhook configurationZendesk webhook API and Zendesk admin dashboard
Hashing algorithmSHA256 HMAC
Timeout10-second timeout
Retry logicRetry up to 3 times
Alert logicNot available
Manual retryNot available
Browsable logAvailable on the admin dashboard

Above are some of the essential features to know when dealing with Zendesk webhooks. If you are interested in learning more about the features and their behavior, we're releasing an extensive guide very soon!

What to know when working with Zendesk webhooks

Third-party apps can get notified when an event occurs on a ticket via the Zendesk webhook. For Zendesk to send webhook data, we must first subscribe to a webhook event that will trigger it. Zendesk webhook provides several events such as ticket create and update, or social media likes and shares, comments, and direct messages. You can check available Zendesk events from your Zendesk admin dashboard after creating an account.

A Zendesk webhook subscription can be created either through the admin dashboard or using the Zendesk webhook API. Let's take a look at how Zendesk webhook subscriptions can be created using these two methods.

Creating webhooks using the Zendesk admin dashboard

There are two steps to creating webhooks using the Zendesk admin dashboard.

  • From your admin dashboard, navigate through Apps and integrations > Webhooks and click on Create webhook.
  • Enter the webhook name and the URL that would receive the notification, and select the request method, format, and authentication.

For more details on creating a Zendesk webhook using the Zendesk dashboard, click here.

Zendesk API authentication

Creating webhooks using Zendesk's REST API

A webhook can be created by sending an HTTPS POST request to the webhook API endpoint. The request body includes the endpoint, which is the URL of the third party that receives webhook data, and the request format specifies the notification payload. It can be a JSON or XML format and webhook API only supports conditional_ticket_events for subscriptions. The body also includes the webhook name and status.

{
  "webhook": {
    "endpoint": "{webhook_url}",
    "http_method": "POST",
    "name": "{webhook name}",
    "request_format": "json",
    "status": "active",
    "subscriptions": [
      "conditional_ticket_events"
    ]
  }
}

For more details on creating a Zendesk webhook using the Zendesk REST API, click here.

Webhook Headers

Webhook HTTP headers are important. They are useful when developing because they enable the webhook to send important information to the client app easily. An example of this can be seen in how Zendesk webhook uses HTTP headers to identify and verifies a request using x-zendesk-webhook-signature and x-zendesk-webhook-signature-timestamp. The following are HTTP headers included in a Zendesk webhook request:

  • x-zendesk-account-id: This header provides the account ID.
  • x-zendesk-webhook-id: This is the unique ID of the webhook. This header is important when debugging a failed webhook.
  • x-zendesk-webhook-invocation-id: This header is a unique identifier for a specific invocation (attempt). You can query invocations that were made in the last 7 days.
  • x-zendesk-webhook-signature: The HMAC header is a base64 encoded string that is used to verify a webhook notification.
  • x-zendesk-webhook-signature-timestamp: This header shows the timestamp of the signature verication in the following format 2021-03-25T05:09:27Z.

Zendesk webhooks retry logic

If the server receiving the request returns an error with an HTTP status code of 409, Zendesk automatically retries the webhook invocation up to three times.

If the application returns a 429 error or a 503 error, Zendesk will retry the webhook invocation only if your request contains a retry-after header with a value that is 60 seconds lesser than the time the request was received. Your webhook will not be deactivated due to a number of successive failed requests.

Zendesk assigns a unique ID for each webhook connection invoked. You can get more details about any failed webhook invocation by using the invocation unique ID. This can come in handy when debugging. To see details, make a GET with the invocation unique ID to this route /api/v2/webhooks/{webhook_id}/invocations/{invocation_id}/attempts

Best practices when working with Zendesk webhooks

Local troubleshooting and testing

Testing your Zendesk webhook is critical to verify that your application receives the expected webhook data and that it can handle the incoming data effectively. If Zendesk webhook sends a ticket id as an integer, it is recommended to store it as an integer rather than to use another datatype in order to avoid performance issues.

To ensure that your webhook performs accurately, you need to test your Zendesk webhook endpoint to ensure the following:

During project development, we cannot test the Zendesk webhook because the webhook cannot send data to a local development environment. A webhook can only send data to a publicly accessible URL. To tunnel your Zendesk webhook requests to your local environment, we can use tools like Hookdeck CLI.

Decouple webhook processing to avoid timeouts

When webhook requests are sent to the third-party applications from Zendesk, Zendesk waits for 10 seconds to get a response. Whenever Zendesk sends a webhook request, Zendesk will wait for 10 seconds to get a response from the third-party application.

If Zendesk cannot get a response within the waiting period, it will return a timeout. As a best practice, your application has to be able to process Zendesk webhooks fast to avoid webhook failure. A timeout error will result if your application takes more than 10 seconds to process Zendesk webhook data.

Asynchronous processing of webhook requests is one of the best practices to prevent time-out errors when working with webhook.

You can also decouple the webhook logic by ensuring that you are queuing your webhook request and processing them one at a time and also implementing a good retry mechanism for the failed requests.

One more thing you can do to prevent timeout errors is to ensure that your webhook endpoint doesn't make requests to third-party apps because this can increase the request time to more than 10 seconds and eventually throw a timeout error.

Verifying incoming webhooks

Zendesk let you verify and ensure that every webhook received in your application comes from the right source. Since webhook URLs are accessible publicly, this may expose your application to a lot of vulnerabilities. To avoid this, we need to verify that every webhook data received comes from the Zendesk webhook and not from another source.

Zendesk webhook requests contain two headers, X-Zendesk-Webhook-Signature and  X-Zendesk-Webhook-Signature-Timestamp that can be used to verify if the request is from Zendesk or not.

To verify the signature, create the same SHA256 HMAC signature (HMACSHA256(TIMESTAMP + BODY)) and compare it to X-Zendesk-Webhook-Signature and the X-Zendesk-Webhook-Signature-Timestamp sent along with the webhook payload to make sure they match. If they match, then you can be sure that the webhook came from Zendesk. If they don't, it may be a request from another source.

The code below shows how a signature can be verified using Node.js and Express:

const express = require("express");
const crypto = require("crypto");
require("body-parser-xml")(express);

// Signing secret from webhook itself
const SIGNING_SECRET = "dGhpc19zZWNyZXRfaXNfZm9yX3Rlc3Rpbmdfb25seQ==";

// Always sha256
const SIGNING_SECRET_ALGORITHM = "sha256";

const PORT = 3000;

const app = express();

function isValidSignature(signature, body, timestamp) {
  let hmac = crypto.createHmac(SIGNING_SECRET_ALGORITHM, SIGNING_SECRET);
  let sig = hmac.update(timestamp + body).digest("base64");

  return (
    Buffer.compare(
      Buffer.from(signature),
      Buffer.from(sig.toString("base64")),
    ) === 0
  );
}

function storeRawBody(req, res, buf) {
  if (buf && buf.length) {
    req.rawBody = buf.toString("utf8");
  }
}

// Use middleware to store raw request body depending on request format
app.use(
  express.json({
    verify: storeRawBody,
  }),
);
app.use(express.urlencoded({ verify: storeRawBody, extended: true }));
app.use(express.xml({ verify: storeRawBody }));

app.post("/hook", (req, res) => {
  // Fields from the webhook request, this will change every time
  const signature = req.headers["x-zendesk-webhook-signature"];
  const timestamp = req.headers["x-zendesk-webhook-signature-timestamp"];
  const body = req.rawBody;

  console.log(
    isValidSignature(signature, body, timestamp)
      ? "HMAC signature is valid"
      : "HMAC signature is invalid",
  );
  res.status(200).send("Success");
});

app.listen(PORT, () => console.log(`🚀 Server running on port ${PORT}`));

For more information on how you can enhance your webhook security, check out our security checklist.

Idempotency avoiding duplicates impacting data integrity

The next best practice we'll look at is idempotency. Idempotency helps to avoid processing webhooks more than once. For example, when some of your Twitter friends send you a direct message, your application is ready to send a custom message to the user once it receives a notification of the ticket via webhook. You can avoid sending the user duplicate messages. To avoid webhook duplicates, validate the received webhook data with the ticket ID.

When a new ticket is created, Zendesk will generate a unique ID for it. This ticket ID can be sent along with the webhook payload. Ticket ID is not included in the webhook payload by default, so you’ll need to add it to the payload during your webhook setup.

Once you include the ticket ID in the payload, you can track webhooks data that has already been processed and skip them to avoid duplicating them. For more detail on webhook data integrity, check out this article here.

CONCLUSION

Zendesk webhook simplifies the process of receiving Zendesk event data to your application.

In this article, we discussed Zendesk webhooks features, what to know when working with them, and best practices. We hope this information will help you build your integrations.

Happy coding!