Skip to content

Developer guide · Webhooks

Zapier, Make and n8n via webhooks

Hushdesk sends a signed JSON POST when a ticket is created, the customer replies or a ticket is closed. Point it at Zapier, Make, n8n or your own server and build anything those tools can reach.

Ticket events Hushdesk sends

Every event goes to the same URL. Read the event field, or the X-Hushdesk-Event header, to decide what to do.

EventFires whenTypical use
ticket.createdA new ticket arrives on any channel: email, live chat or a form. It is sent after your rules have run, so the tags and priority they set are in the payload.Add a row to a sheet, create a CRM contact, page someone for VIP customers.
customer.repliedThe customer writes again on a ticket that already exists, by email or in chat.Reopen a task in your project tool, notify the account owner.
ticket.closedAn agent closes a ticket, with Send and close or by changing its status to closed.Log the resolution, send a follow-up from your email tool, update a dashboard.
pingSent once when you click Connect. Your endpoint must answer with a 2xx status, or nothing is saved.Nothing to do: just return 200 or 204.

Want something to happen inside Hushdesk instead, such as tagging or assigning? That is what automation rules are for. Want a ping in a chat channel? The Slack integration needs no tool in between.

Webhook request format

Each event is one HTTPS POST with a JSON body and these headers:

Content-Type
application/json
User-Agent
Hushdesk-Webhooks/1
X-Hushdesk-Event
ticket.created, customer.replied, ticket.closed or ping
X-Hushdesk-Signature
sha256= followed by the hex HMAC-SHA256 of the raw body, keyed with your signing secret

Example webhook payload

All three ticket events share this shape. The ping sent on connect is just { "event": "ping", "at": "2026-10-06T09:40:03.004Z" }

POST /your-endpoint · X-Hushdesk-Event: ticket.created
{
  "event": "ticket.created",
  "at": "2026-10-06T09:41:12.381Z",
  "workspace_id": "6f1c2a9e-4b7d-4e0a-9c1f-2d8e5a7b3c10",
  "ticket": {
    "id": "c0a8012e-5d3b-4f6a-8e21-9b7c4d2e1f05",
    "subject": "Where is my order #1042?",
    "status": "open",
    "channel": "email",
    "priority": 0,
    "tags": ["order-status"],
    "url": "https://…/app/inbox?c=c0a8012e-5d3b-4f6a-8e21-9b7c4d2e1f05",
    "customer": { "email": "ana@example.com", "name": "Ana Reyes" },
    "last_message": "Hi, my order #1042 still says processing. When will it ship?"
  }
}

Field reference

FieldTypeMeaning
eventstringticket.created, customer.replied or ticket.closed
atstringWhen the event was sent, ISO 8601 in UTC
workspace_idstringYour Hushdesk workspace
ticket.idstringThe ticket’s id (a UUID)
ticket.subjectstring | nullThe subject line; can be null for some chats
ticket.statusstringopen, pending, snoozed, closed or spam
ticket.channelstringWhere it came from, for example email, chat or form
ticket.prioritynumber-1 low, 0 normal, 1 high, 2 urgent
ticket.tagsstring[]Tags on the ticket at the time of the event
ticket.urlstringOpens the ticket in Hushdesk (sign-in required)
ticket.customerobjectemail and name; either can be null
ticket.last_messagestringThe customer’s latest message, up to 2,000 characters

Verify the webhook signature (HMAC-SHA256)

  1. 1Read the raw request body as bytes, before any JSON parsing. Re-serialised JSON will not match.
  2. 2Compute HMAC-SHA256 of those bytes with your signing secret as the key, and write it as lowercase hex.
  3. 3Put sha256= in front and compare it with the X-Hushdesk-Signature header using a constant-time comparison.
  4. 4Reject the request with 401 if it does not match. Otherwise answer 2xx quickly and process the event.
Node.js (Express)
import crypto from 'node:crypto';
import express from 'express';

const app = express();
const SECRET = process.env.HUSHDESK_WEBHOOK_SECRET;

// Keep the raw body: the signature covers the exact bytes Hushdesk sent.
app.post('/helpdesk-events', express.raw({ type: 'application/json' }), (req, res) => {
  const expected = 'sha256=' + crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
  const received = req.get('X-Hushdesk-Signature') ?? '';
  const ok = received.length === expected.length && crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
  if (!ok) return res.status(401).end();

  const event = JSON.parse(req.body.toString('utf8'));
  res.status(204).end(); // answer within 5 seconds, then do the slow work
  // …hand `event` to your own queue or job runner here
});

app.listen(3000);
Python (Flask)
import hashlib, hmac, os
from flask import Flask, abort, request

app = Flask(__name__)
SECRET = os.environ["HUSHDESK_WEBHOOK_SECRET"].encode()

@app.post("/helpdesk-events")
def helpdesk_events():
    body = request.get_data()  # raw bytes, before any JSON parsing
    expected = "sha256=" + hmac.new(SECRET, body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, request.headers.get("X-Hushdesk-Signature", "")):
        abort(401)
    event = request.get_json()
    if event["event"] == "ticket.closed":
        pass  # your code here
    return "", 204
PHP
<?php
$secret   = getenv('HUSHDESK_WEBHOOK_SECRET');
$body     = file_get_contents('php://input'); // raw body
$expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
$received = $_SERVER['HTTP_X_HUSHDESK_SIGNATURE'] ?? '';

if (!hash_equals($expected, $received)) {
    http_response_code(401);
    exit;
}

$event = json_decode($body, true);
http_response_code(204);

Delivery rules and limits

  • Public https only

    The URL must use https and resolve to a public address. Private and internal network addresses are refused, and checked again at every delivery.

  • 5-second window

    Any 2xx answer within five seconds counts as delivered. Redirects are not followed, so a 3xx is a failure.

  • One attempt per event

    Deliveries are not retried today. The last delivery, delivered or failed with its status, is shown on the Webhooks card in Settings, Apps.

  • Your secret, encrypted

    The signing secret must be at least 16 characters. It is encrypted at rest and never shown again; to rotate it, connect again with a new one.

  • Tested before saving

    Connect sends the ping event first. If your endpoint does not answer 2xx, nothing is saved and you see why.

  • Admins only, audited

    Only owners and admins can connect or disconnect webhooks, and both are written to the audit log.

Recipes for Zapier, Make and n8n

Each tool gives you a webhook URL; Hushdesk posts to it. Pick the one your team already uses.

Zapier

Log every closed ticket to Google Sheets

  1. 1Create a Zap. For the trigger choose Webhooks by Zapier, then Catch Hook, and copy the webhook URL it gives you.
  2. 2In Hushdesk open Settings, Apps, Webhooks. Paste the URL, add a signing secret of at least 16 characters, and click Connect.
  3. 3Close a test ticket in Hushdesk, then click Test trigger in Zapier so it picks up a real ticket.closed event with every field.
  4. 4Add a Filter step: only continue if event exactly matches ticket.closed.
  5. 5Add Google Sheets, Create Spreadsheet Row, and map ticket subject, customer email, tags and the time.

Webhooks by Zapier is one of Zapier’s premium apps, so it needs a paid Zapier plan. To check the signature in Zapier, use Catch Raw Hook and a Code by Zapier step.

Zapier webhook docs

Make

Send urgent tickets to your CRM

  1. 1Create a scenario. Add the Webhooks module, choose Custom webhook, click Add, name it, and copy the address.
  2. 2Paste it in Hushdesk under Settings, Apps, Webhooks with a signing secret, and click Connect.
  3. 3In Make, click Redetermine data structure, then create a test ticket in Hushdesk so Make learns the fields.
  4. 4Add a filter after the webhook: event equals ticket.created and ticket priority equals 2.
  5. 5Add your CRM module (HubSpot, Pipedrive or any HTTP API) and map the customer and the ticket URL.

Make’s advanced webhook settings can pass the raw body and request headers to the scenario if you want to check the signature there.

Make webhook docs

n8n

Run your own workflow, self-hosted

  1. 1Add a Webhook node. Set the method to POST and give it a path such as hushdesk.
  2. 2Copy the Production URL (the Test URL only listens while the editor is open) and activate the workflow.
  3. 3Paste the URL in Hushdesk under Settings, Apps, Webhooks with a signing secret, and click Connect.
  4. 4Turn on the Webhook node’s Raw Body option, compute an HMAC (SHA256, hex) of it with the Crypto node, and compare it with the x-hushdesk-signature header in an IF node.
  5. 5Branch on the event field with a Switch node and build each path.

Self-hosted n8n works too, as long as Hushdesk can reach it on a public https address.

n8n webhook docs

Wire up your first event

Start free, open Settings, Apps, Webhooks, and send the ping to your endpoint.

Read next

FAQ

Webhooks for Zapier, Make and n8n: questions and answers

How do I connect Hushdesk to Zapier?

Start a Zap with the Webhooks by Zapier trigger and choose Catch Hook, then copy its URL. In Hushdesk, open Settings, Apps, Webhooks, paste the URL with a signing secret and click Connect. Create or close a test ticket so Zapier sees a real event, then add your actions.

Does Hushdesk have its own Zapier app?

Not yet. Hushdesk connects to Zapier through Webhooks by Zapier, which receives the same ticket events a dedicated app would: ticket created, customer replied and ticket closed. The same webhook works with Make, n8n and your own server, so you are not tied to one automation tool.

Which events can Hushdesk send to Zapier, Make or n8n?

Hushdesk sends three ticket events: ticket.created when a new ticket arrives on any channel, customer.replied when the customer writes again, and ticket.closed when an agent closes it. A ping event is sent once when you connect. Every event goes to the same URL, so branch on the event field.

How do I verify a Hushdesk webhook signature?

Compute an HMAC-SHA256 of the raw request body using your signing secret, write it as lowercase hex, put sha256= in front, and compare it with the X-Hushdesk-Signature header using a constant-time comparison. Use the raw bytes before any JSON parsing, because re-serialising the JSON changes the signature.

Which header carries the Hushdesk webhook signature?

The signature is in the X-Hushdesk-Signature header, in the form sha256= followed by a hex HMAC-SHA256 of the body. The X-Hushdesk-Event header repeats the event name, and the User-Agent is Hushdesk-Webhooks/1, which helps when you filter logs or firewall rules on your side.

What happens if my webhook endpoint is down?

Hushdesk makes one delivery attempt per event and does not retry it today. The result, delivered or failed with the status code, is shown on the Webhooks card in Settings, Apps. Keep your endpoint fast and reliable, or point it at Zapier, Make or n8n, which receive the event for you.

How quickly must my webhook endpoint respond?

Within 5 seconds. Hushdesk waits up to five seconds for an answer, and any 2xx status counts as delivered. Redirects are not followed, so a 301 or 302 counts as a failure. Return 200 or 204 straight away and do slow work, such as calling other APIs, afterwards in a queue.

Can Hushdesk send webhooks to an http or localhost address?

No. The endpoint must use https and resolve to a public address. Hushdesk refuses private and internal network addresses, and checks again at every delivery in case the host’s DNS changed after you saved it. For local testing, expose your server through an https tunnel or use an automation tool’s webhook URL.

Can webhooks create or update tickets in Hushdesk?

No. Hushdesk webhooks are outgoing only: they tell other tools what happened to a ticket. To change tickets automatically inside Hushdesk, such as tagging, assigning or setting priority, use automation rules, which run on the same events and act on the ticket directly.

Is the Hushdesk webhooks integration secure?

Yes. Every request is signed with your secret so you can reject anything that did not come from Hushdesk. The secret must be at least 16 characters, is encrypted at rest and is never shown again. Only owners and admins can connect webhooks, and every change is written to the audit log.