Help Buddy Docs

Webhooks

Capture and send Help Buddy events to any external URL

Premium Feature

Webhooks require the Custom tier and are managed by server Admins or the owner.

Overview

Outbound webhooks enable Help Buddy to send real-time updates (ticket open, message posting, SLA violation, etc) using HTTP.

This feature requires a Custom Buddy and Manage Server permissions in this guild.

How it works

  1. You create one or more endpoints (a URL + the events it should receive).
  2. When a subscribed event fires, Help Buddy renders your message body and POSTs it to the endpoint.
  3. Each request is signed so you can verify it genuinely came from Help Buddy.
  4. Failed deliveries are retried with exponential backoff; every attempt is visible in the delivery log.

Creating an endpoint

  1. Open Developers → Webhooks and click Add endpoint.
  2. Give it a name and paste the Payload URL that will receive events.
  3. Pick a format preset (Discord, Slack, Google Chat, Microsoft Teams, or Other/Raw).
  4. Check the events you want delivered.
  5. Optionally customize the message body, add custom headers, and use the live preview.
  6. Save. The signing secret is shown once on creation, copy it now.

Events

Subscribe an endpoint to any combination of these events:

GroupEventFires when
Ticket lifecycleticket.createdA new ticket is opened
ticket.claimedA staff member claims / is assigned a ticket
ticket.closedA ticket is closed
ticket.deletedA ticket is deleted (from the bot or the dashboard)
Messagesticket.messageA staff or user message is posted in a ticket
SLAsla.first_response_breachedThe first-response SLA deadline is exceeded
sla.subsequent_breachedA subsequent-response SLA deadline is exceeded
CSATcsat.submittedA ticket creator submits a satisfaction rating
Reportsreport.generatedA scheduled report has been generated
Configpanel.updatedA ticket panel is created or updated
category.updatedA ticket category is created or updated
subscription.changedThe guild subscription tier or status changes (admin panel)

Payload format

If you leave the message body blank (the Other (Raw) preset), Help Buddy sends a standard JSON envelope. The event-specific fields live under data:

{
  "id": "evt_1042",
  "event": "ticket.created",
  "created": 1751500000,
  "guild_id": "123456789012345678",
  "data": {
    "ticket_id": "998877665544332211",
    "ticket_name": "ticket-0042",
    "category": "billing",
    "tier": "custom",
    "creator": "ada",
    "creator_id": "223344556677889900"
  }
}

Every request also carries these headers:

HeaderValue
X-HelpBuddy-EventThe event name, e.g. ticket.created
X-HelpBuddy-DeliveryUnique delivery id (also the retry key)
X-HelpBuddy-SignatureHMAC signature, format t=<timestamp>,v1=<hex>

Placeholders

Anywhere in a message body you can use {token} placeholders. They are replaced with real values at delivery time. An unknown token is left untouched so a typo is easy to spot. These are all the available placeholders:

Always availableMeaning
{id}Unique delivery id (e.g. evt_1234)
{event}The raw event name, e.g. ticket.created
{event_title}Human-friendly event name, e.g. Ticket Created
{created}Unix timestamp (seconds) of delivery
{guild_id}The Discord server id
Ticket eventsMeaning
{ticket_id}The ticket channel/thread id
{ticket_name}The ticket channel name
{ticket_url}Deep link to the ticket in Discord
{category}The ticket category / type
{tier}The tier the ticket was opened under
{creator}The ticket opener display name (on create)
{creator_id}The ticket opener user id
{assigned_to}Assigned staff user id (claim/close)
ticket.messageMeaning
{message_content}The message text
{message_author}Author username
{message_author_id}Author user id
{message_role}"staff" or "user"
{message_id}The Discord message id
SLA eventsMeaning
{sla_type}"first_response" or "subsequent_response"
{sla_deadline}The configured deadline, e.g. "30 minutes"
csat.submittedMeaning
{rating}The rating: "up", "neutral", or "down"
{comment}The optional free-text comment (empty if none)
{source}Where the rating came from: "discord" or "email"
{staff}The handling staff user id (empty if unclaimed)
Config eventsMeaning
{panel_id}panel.updated: the panel id
{panel_name}panel.updated: the panel name
{category_key}category.updated: the category key
{category_label}category.updated: the category label
{status}subscription.changed: the subscription status
{processor}subscription.changed: the payment processor

{ticket_url} is generated automatically for any ticket event. Tokens that do not apply to a given event resolve to an empty string.

Message customization

Each endpoint has a Use the same message for all events toggle:

  • On - one shared body template is used for every subscribed event.
  • Off - you author a separate body per event; events you leave blank fall back to the default envelope.

The signature is always computed over the final rendered body, so custom shapes still verify correctly. You can also set a custom Content-Type and add arbitrary request headers (for example anAuthorization header your receiver requires).

Platform setup

A preset seeds a starter body shaped for that platform's incoming webhook. You can edit it freely afterward. Presets are offered in this order: Discord, Slack, Google Chat, Microsoft Teams, Other (Raw).

Discord

  1. In Discord, open the target channel and choose Edit Channel → Integrations → Webhooks → New Webhook (requires the Manage Webhooks permission).
  2. Click Copy Webhook URL.
  3. In the dashboard, add an endpoint, paste that URL, choose your events, and select the Discord preset.

A Discord webhook only accepts Discord's own JSON shape, so the Discord preset is what makes events render as messages. Discord ignores the signature header, which is expected.

Slack

  1. Create (or open) a Slack app, enable Incoming Webhooks, and choose Add New Webhook to Workspace.
  2. Pick the destination channel and copy the generated URL.
  3. Add an endpoint, paste the URL, choose your events, and select the Slack preset.

Google Chat

  1. In the Google Chat space, open Apps & integrations → Manage webhooks.
  2. Add a webhook, give it a name, and copy the URL.
  3. Add an endpoint, paste the URL, choose your events, and select the Google Chat preset.

Microsoft Teams

  1. In the channel, choose … → Connectors → Incoming Webhook → Configure, name it, and copy the URL.
  2. Add an endpoint, paste the URL, choose your events, and select the Microsoft Teams preset.

Microsoft is migrating Teams from classic Office 365 connectors to Power Automate Workflows, which expect an Adaptive Card body instead of a MessageCard. If your tenant uses Workflows, create a "Post to a channel when a webhook request is received" flow and use the Other (Raw)preset with an Adaptive Card body.

Verifying the signature

Compute an HMAC-SHA256 over `${timestamp}.${rawBody}` using your endpoint's signing secret and compare it to the v1 value in the X-HelpBuddy-Signature header. Always use the raw request body (not a re-serialized object).

Node.js

const crypto = require('crypto');

function verify(rawBody, signatureHeader, secret) {
  const parts = Object.fromEntries(
    signatureHeader.split(',').map(p => p.split('='))
  ); // { t, v1 }
  const expected = crypto
    .createHmac('sha256', secret)
    .update(parts.t + '.' + rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected), Buffer.from(parts.v1)
  );
}

Python

import hmac, hashlib

def verify(raw_body: str, signature_header: str, secret: str) -> bool:
    parts = dict(p.split('=') for p in signature_header.split(','))
    expected = hmac.new(
        secret.encode(), f"{parts['t']}.{raw_body}".encode(), hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, parts['v1'])

You may also reject requests whose t timestamp is far from the current time to guard against replays.

Retries and failures

A delivery succeeds on any 2xx response within 10 seconds. Otherwise it is retried on this schedule: 1m, 5m, 30m, 2h, 6h. After 6 failed attempts the delivery is marked dead. An endpoint that accumulates 15 consecutive dead deliveries is automatically disabled; re-enable it from the dashboard once your receiver is healthy. Every attempt, status code, and error is shown in Recent deliveries.

Testing

Use the Send test event button (the paper-plane icon) on any endpoint to queue a synthetic test.ping delivery. It is delivered within about 10 seconds and appears in the delivery log. A free service like webhook.site is handy for inspecting the exact payload and headers.