Webhooks
Receive events as they happen and verify their signature.
Webhooks POST a JSON event to your URL when something happens. Create endpoints in Tixxy at Organisation > Settings > Webhooks or through the API (webhooks:manage).
Events
| Type | Sent when |
|---|---|
order.created | An order was placed: in the shop, by hand, by import or through the API |
order.paid | An order on invoice was marked as paid |
order.cancelled | An order was cancelled |
order.refunded | A refund of an order was completed |
ticket.checked_in | A ticket was scanned at the entrance |
ticket.invalidated | A ticket was made invalid |
event.created | An event was created |
event.updated | The name, dates, sale period or location of an event changed |
Payload
{
"id": "whevt_01J...",
"object": "event",
"type": "order.created",
"created": "2026-10-01T12:00:00Z",
"livemode": true,
"data": {
"object": { "id": "ord_01J...", "object": "order" }
}
}data.object is the same object the matching GET endpoint returns. Personal data is only included when the endpoint was set up to receive it.
Verify the signature
Every request carries a Tixxy-Signature header:
Tixxy-Signature: t=1790000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bdCompute an HMAC-SHA256 of {t}.{raw request body} with your endpoint's signing secret and compare it with v1. Reject requests where t is more than five minutes old.
import crypto from 'node:crypto';
export function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map((part) => part.split('=')));
const expected = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Delivery
- Answer with any 2xx status within 10 seconds. Do the real work afterwards, for example on a queue.
- Failed deliveries are retried for about a day with increasing delays.
- An endpoint that keeps failing for three days is switched off; its owners get an email.
- The same event can arrive more than once. Store
idand skip events you already processed. - Redirects are not followed, and endpoints must be public HTTPS URLs.