Webhooks
Webhooks let you receive real-time HTTP POST notifications when events occur in your project. Configure webhook endpoints in the dashboard under Project → Webhooks.
Available events
| Event | Fired when |
|---|---|
ticket.created | A new ticket is submitted (via portal, API, or SDK) |
ticket.resolved | A ticket is marked as resolved |
message.received | A new message is added to a ticket |
Payload format
Each webhook delivery sends a JSON POST request with the following structure:
{
"event": "ticket.created",
"timestamp": "2025-01-15T10:30:00.000Z",
"data": {
"ticket": {
"id": "uuid",
"number": 42,
"subject": "Can't reset password",
"status": "open",
"priority": "high"
},
"customer": {
"email": "user@example.com",
"name": "Jane Smith"
}
}
}Headers
Every webhook delivery includes these headers:
| Header | Description |
|---|---|
Content-Type | Always application/json |
X-Helmdesk-Event | The event type (e.g. ticket.created) |
X-Helmdesk-Signature | HMAC-SHA256 signature of the request body |
Verifying signatures
Every delivery is signed with your webhook secret using HMAC-SHA256. Always verify the signature to ensure the request came from Helmdesk.
import { createHmac } from 'crypto'
function verifyWebhookSignature(
body: string,
signature: string,
secret: string
): boolean {
const expected = createHmac('sha256', secret)
.update(body)
.digest('hex')
return signature === expected
}
// Express / Next.js API route example
export async function POST(req: Request) {
const body = await req.text()
const signature = req.headers.get('x-helmdesk-signature') ?? ''
if (!verifyWebhookSignature(body, signature, WEBHOOK_SECRET)) {
return new Response('Invalid signature', { status: 401 })
}
const payload = JSON.parse(body)
switch (payload.event) {
case 'ticket.created':
// Handle new ticket
break
case 'ticket.resolved':
// Handle resolved ticket
break
case 'message.received':
// Handle new message
break
}
return new Response('OK', { status: 200 })
}Slack integration
Enable Slack format when creating a webhook to receive payloads formatted as Slack Block Kit messages. Point the webhook URL at a Slack incoming webhook to get formatted notifications in your channel.
// Slack-formatted payload example
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*New Ticket Created*\n> *Subject:* Can't reset password\n> *#42*\n> *Customer:* user@example.com\n> *Priority:* high"
}
}
]
}Delivery behavior
- • Webhooks are delivered asynchronously (fire-and-forget) and do not block API responses
- • Deliveries time out after 5 seconds
- • All deliveries (successes and failures) are logged and visible in the dashboard
- • Use the Test button in the dashboard to send a sample delivery to your endpoint