Modules
Send signed ticket events from Clarify to your own HTTPS endpoint, so your systems react in real time.

The Webhook integration sends a request to your own web address every time something happens to a ticket — a ticket is created, closed, reopened, assigned, escalated, rated, and more. Your system receives the event and can do whatever you like with it: log it, sync it to a CRM, post it somewhere, or kick off an automation.

You need somewhere to receive the events — a URL your team controls. Everything on the Clarify side is point-and-click, and it costs no feature token.

A webhook is a one-way notification: Clarify → your endpoint. Clarify sends events to you; it does not read anything back. You find it under Integrations → Webhook in the dashboard.

How it works

When a selected event happens, Clarify sends an HTTPS POST to your URL with the event and the ticket in the body. Every request is signed with your secret, so your server can confirm it came from Clarify and was not altered on the way. Clarify tries up to three times (10 seconds each, with a short pause between attempts) before giving up on a delivery.

Requests are sent through Clarify's delivery relay, so do not filter by IP address — verify the signature instead.

Destination

url
text
The web address Clarify sends events to. Required. Must start with https:// — plain http:// is not accepted.
secret
secret
A signing secret shared between Clarify and your server, at least 8 characters. Required at setup. Click Generate to get a strong random secret, copy it and store it where your endpoint reads it from. It is encrypted at rest and never shown back to you; when editing later, leave the field blank to keep the current secret, or generate a new one to replace it — then update your endpoint too.

Events

trigger
checkbox
Only selected events are sent. Default: Ticket created and Ticket closed.
  • Ticket created — A new ticket has been opened.
  • Ticket reopened — A closed ticket was opened again.
  • Ticket closed — A ticket was marked as resolved.
  • Agent assigned — An agent was assigned to a ticket.
  • Agent unassigned — An agent was removed from a ticket.
  • Member added — Someone was added to a ticket.
  • Member removed — Someone was removed from a ticket.
  • Ticket rated — The customer left a rating.
  • Ticket escalated — A ticket was moved to another support tier.

The X-Clarify-Event header and event.type in the body carry the event name: created, opened, closed, assigned, unassigned, added, removed, rated, escalated.

Custom headers

headers
keyvalue
Extra HTTP headers sent with every request, as name/value pairs — for example an Authorization: Bearer … header your endpoint expects. Optional. Your headers are added after Clarify's own, so a header with the same name overrides it.

What a request looks like

POST /hooks/clarify HTTP/1.1
Content-Type: application/json
X-Clarify-Event: closed
X-Clarify-Timestamp: 1758000000
X-Clarify-Signature: sha256=3f7a…
{
  "event": {
    "type": "closed",
    "timestamp": 1758000000000,
    "serverId": "123456789012345678",
    "ticketId": "…",
    "executor": { "id": "…", "username": "alex", "avatarUrl": "…" }
  },
  "ticket": { "…": "the full ticket record — participants, messages, inputs, assignees, routing" },
  "review": null
}
  • event.timestamp is in milliseconds; the X-Clarify-Timestamp header is in seconds.
  • ticket is the complete ticket as Clarify stores it, including its messages and the answers to its inputs. Treat your endpoint as confidential as the tickets themselves.
  • review holds the customer's rating and comment once the ticket has been rated, on every later event too; before that it is null.

Verifying the signature

Clarify signs "<X-Clarify-Timestamp>.<raw request body>" with HMAC-SHA256 using your secret and sends the hex digest as X-Clarify-Signature: sha256=…. Recreate it and compare:

import { createHmac, timingSafeEqual } from 'node:crypto'

function verify(rawBody, headers, secret) {
  const expected = 'sha256=' + createHmac('sha256', secret)
    .update(`${headers['x-clarify-timestamp']}.${rawBody}`)
    .digest('hex')
  const given = headers['x-clarify-signature'] ?? ''
  return given.length === expected.length && timingSafeEqual(Buffer.from(given), Buffer.from(expected))
}

Use the raw body bytes, not a re-serialised object. Reject requests whose timestamp is far from now if you want protection against replays.

Turning it on and testing

Set it Active

Use the Active / Inactive toggle on the Webhook page. While inactive, Clarify keeps your settings and sends nothing — handy for pausing during maintenance.

Send a test

Send test fires a sample request at your URL right away — a small fake ticket with the first event you selected — and shows the HTTP status and how long it took. The page also remembers the outcome of the last real delivery so you can see whether events are getting through.

A non-2xx status or a timeout means your endpoint did not accept the request. Check that the URL is public, that any required custom headers are set, and that your verification uses the exact secret you saved. See Troubleshooting if it persists.

Feedback

Where the rated event comes from.

Data connectors

Pull data from your own systems into a ticket, rather than pushing events out.

Security overview

How your secrets are encrypted and what data leaves Discord.

All integrations

Payment providers and GitHub, connected to your tickets.