Огляд
Отримуйте події TicketWave як підписані HTTP-запити у власній програмі.
Webhooks
Вебхук — це HTTP-запит, який TicketWave надсилає вам. Щоразу, коли у вашому сервері щось відбувається — відкривається тікет, учасника додають до чорного списку — TicketWave надсилає POST із JSON-тілом на URL, який належить вам.
У цьому й різниця з Log Channels: log channels записують embed у Discord для людей, а вебхуки передають сирі події у ваш код.
Вебхуки — це преміумна функція. Без преміуму кінцеві точки не можна створювати, і жодні події не доставляються.
Create an Endpoint
Open the endpoints page
Server dashboard → Webhooks → Endpoints.
Add an endpoint
Click Add Endpoint and fill in two fields:
| Field | Description |
|---|---|
| Endpoint URL | The https:// URL that receives the requests |
| Event Types | Which events this endpoint should receive |
An endpoint only receives the types you tick. Selecting none is not allowed — pick at least one.
Copy the signing secret
TicketWave generates a signing secret (whsec_…) the moment the endpoint is created. Open the endpoints list, reveal it with the eye icon and copy it into your application's configuration.
Treat the secret like a password. Anyone who has it can forge requests that pass your signature check. Keep it in an environment variable, never in your repository.
Send a test event
Use the Send test event button (the paper plane) on the endpoint row. It delivers a real, fully signed request with "test": true in the payload, so you can confirm your receiver works before a real ticket depends on it.
The result shows up in the Webhooks history like any other delivery.
Endpoint Requirements
| Requirement | Detail |
|---|---|
| Scheme | https:// only — http:// is rejected |
| Host | Must be publicly resolvable. Private, loopback, link-local and CGNAT addresses are refused |
| Response | Any 2xx status counts as success |
| Timeout | You have 10 seconds to respond |
| Redirects | Not followed. A 3xx counts as a failure |
| Limit | Up to 5 endpoints per server |
The host check happens both when you save the endpoint and before every single delivery, so a domain that later starts resolving to an internal address stops being delivered to.
The Request
Every delivery is a POST with a JSON body.
Headers
| Header | Example | Meaning |
|---|---|---|
Content-Type | application/json | Always JSON |
User-Agent | TicketWave-Webhooks/1.0.5 | The bot version that sent it |
X-TicketWave-Event | ticket.created | The event type |
X-TicketWave-Delivery | wh_3f2a… | Unique id for this delivery |
X-TicketWave-Timestamp | 1786224191 | Unix seconds, part of the signature |
X-TicketWave-Signature | sha256=9f86d0… | HMAC of the request |
Body
Every payload uses the same envelope. Only data differs per event type:
{
"event": "ticket.created",
"timestamp": "2026-08-26T08:23:11.000Z",
"guild_id": "123456789012345678",
"data": {
"ticket_id": "ticket-1042",
"ticket_num_id": 1042,
"channel_id": "998877665544332211",
"category": "🤖 Support",
"user": { "id": "987654321098765432", "username": "Luna" },
"created_at": "2026-08-26T08:23:11.000Z"
}
}See the Event Reference for the data object of every type.
Verifying the Signature
Anyone who discovers your endpoint URL can send it a POST request. The signature is how you tell a real TicketWave delivery from a forged one.
Always verify. An unverified endpoint that creates or closes things in your system is an open door.
How the signature is built
TicketWave joins the timestamp and the raw request body with a dot, and runs HMAC-SHA256 over the result using your endpoint secret:
signed_payload = X-TicketWave-Timestamp + "." + raw_request_body
signature = HMAC_SHA256(signed_payload, your_endpoint_secret)The header carries that digest hex-encoded and prefixed: sha256=<digest>.
What your receiver must do
Read the raw body. Verify against the exact bytes you received. If your framework parses JSON first and you re-serialise it, key order or spacing may change and the digest will not match.
Recompute the HMAC over timestamp + "." + rawBody with your secret.
Compare in constant time (crypto.timingSafeEqual in Node). A plain === leaks timing information.
Check the timestamp is recent — five minutes of tolerance is a good default. The timestamp is inside the signed payload, so an attacker cannot replay an old request with a fresh timestamp.
A complete implementation is on the Example Server page.
Retries
A delivery that fails is retried automatically.
| Attempts | 3 (the first try plus 2 retries) |
| Backoff | 1 second, then 5 seconds |
| Retried on | Network errors, timeouts, 408, 429 and any 5xx |
| Not retried on | Every other 4xx — those mean your endpoint rejected the request on purpose |
Because of retries your endpoint can receive the same event twice. Use X-TicketWave-Delivery as an idempotency key: remember the ids you have processed and ignore repeats.
Deliveries are not ordered. If two tickets are created at the same moment, the requests can arrive in either order — use the timestamp field in the body if order matters to you.
Delivery History
The dashboard's Webhooks page lists every delivery with its status, response code, duration and number of attempts. Open a row to see the exact request payload that was sent and the response your server returned.
Failed deliveries can be re-sent from the detail page with Retry Webhook. It sends the original payload again to the same endpoint and records a new delivery.
The history is kept for 30 days, then cleaned up automatically.
Troubleshooting
| Problem | Fix |
|---|---|
| The endpoint cannot be saved | The URL must be https:// and resolve to a public address |
| Everything shows as failed with no response code | The request never reached you — timeout, DNS failure or connection refused |
| Signature never matches | You are hashing the parsed body instead of the raw bytes, or forgot the timestamp + "." prefix |
| Deliveries stop after a while | Check whether your host started returning 4xx — those are not retried |
| An event never arrives | The endpoint is not subscribed to that type, or the server lost premium |
| Duplicate events | Expected on retries — deduplicate on X-TicketWave-Delivery |
Next Steps
- Event Reference (Every event and its payload)
- Example Server (A runnable Express receiver)
- Log Channels (The same events, but posted into Discord)
How is this guide?
