Webhooks Guide
Webhooks let TicketNation notify your server in real time when important events happen — orders placed via your affiliate links, payments confirmed, commissions earned. Instead of polling our API, your server receives an HTTP POST request the moment an event occurs.
Overview
| Property | Value |
|---|---|
| Method | POST |
| Format | JSON body |
| Signature Header | X-TN-Signature |
| Expected Response | HTTP 200 (any 2xx accepted) |
| Timeout | 10 seconds |
| Retry Attempts | 3 (on non-2xx or timeout) |
Setting Up Your Webhook
- Log in to the Partner Dashboard
- Navigate to Settings → Webhooks
- Enter your publicly accessible HTTPS endpoint URL
- Select the events you want to receive
- Click Save Webhook
- Use Send Test Event to verify your endpoint is receiving payloads correctly
Your endpoint must be reachable from the internet. Local addresses (
localhost,127.0.0.1) will not work in production. Use a tool like ngrok for local development testing.
Webhook Events
order.created
Fired when a new order is placed via your affiliate link. The order is in PENDING status — payment has not yet been confirmed.
Use this to: Log new order activity, update your own dashboards.
{
"id": "evt_8f3b2a1c4d",
"event": "order.created",
"isTest": false,
"timestamp": "2025-04-15T08:30:00.000Z",
"data": {
"orderId": "ord_x9k2m7n4p",
"amount": 1500,
"currency": "PHP",
"status": "PENDING"
}
}
order.completed
Fired when payment is confirmed and tickets have been issued to the buyer.
Use this to: Trigger commission tracking, send custom confirmation emails, update CRM records.
{
"id": "evt_9c4d3b2e1f",
"event": "order.completed",
"isTest": false,
"timestamp": "2025-04-15T08:35:00.000Z",
"data": {
"orderId": "ord_x9k2m7n4p",
"amount": 1500,
"currency": "PHP",
"status": "COMPLETED"
}
}
order.failed
Fired when a payment attempt fails, is declined, or expires without payment.
Use this to: Alert your team, remove pending order from your system.
{
"id": "evt_2a1b3c4d5e",
"event": "order.failed",
"isTest": false,
"timestamp": "2025-04-15T08:40:00.000Z",
"data": {
"orderId": "ord_x9k2m7n4p",
"amount": 1500,
"currency": "PHP",
"status": "FAILED",
"reason": "Payment declined"
}
}
commission.earned
Fired when a commission is calculated and recorded for your account. This fires after order.completed once commission rules are applied.
Use this to: Update your internal earnings records, trigger payout reports.
{
"id": "evt_5f6g7h8i9j",
"event": "commission.earned",
"isTest": false,
"timestamp": "2025-04-15T08:36:00.000Z",
"data": {
"commissionId": "comm_7r8s9t0u",
"amount": 150,
"currency": "PHP",
"orderId": "ord_x9k2m7n4p"
}
}
Payload Structure
Every webhook payload follows the same top-level structure:
| Field | Type | Description |
|---|---|---|
id | string | Unique delivery ID for this webhook event |
event | string | Event type (e.g. order.completed) |
isTest | boolean | true when sent via "Send Test Event" in the dashboard |
timestamp | string | ISO 8601 UTC timestamp of when the event occurred |
data | object | Event-specific payload (see each event above) |
Signature Verification
Every webhook request includes an X-TN-Signature header. Always verify this signature before processing the payload to ensure the request genuinely came from TicketNation.
The signature is an HMAC-SHA256 hash of the raw request body, using your webhook secret as the key. Your secret is available in the Partner Dashboard under Settings → Webhooks.
Verification Example (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(rawBody, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(rawBody, 'utf8')
.digest('hex');
// Use timingSafeEqual to prevent timing attacks
const sigBuffer = Buffer.from(signature);
const expectedBuffer = Buffer.from(expectedSignature);
if (sigBuffer.length !== expectedBuffer.length) return false;
return crypto.timingSafeEqual(sigBuffer, expectedBuffer);
}
// Express.js example
app.post('/webhooks/ticketnation', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-tn-signature'];
const secret = process.env.TN_WEBHOOK_SECRET;
if (!verifyWebhookSignature(req.body, signature, secret)) {
return res.status(401).send('Invalid signature');
}
const payload = JSON.parse(req.body);
switch (payload.event) {
case 'order.completed':
// Handle completed order
break;
case 'commission.earned':
// Record commission
break;
}
// Respond quickly — process async if needed
res.status(200).send('OK');
});
Important: Use
express.raw()(notexpress.json()) to receive the raw request body. The signature is computed from the raw bytes — parsing JSON first will break verification.
Retry Logic
If your endpoint returns a non-2xx status code or times out (>10 seconds), TicketNation will retry the delivery:
| Attempt | Delay After Previous |
|---|---|
| 1st retry | 30 seconds |
| 2nd retry | 5 minutes |
| 3rd retry | 50 minutes |
After 3 failed retries the delivery is marked as failed. You can manually retry failed deliveries from the Delivery History tab in the Partner Dashboard.
Testing
Use the Send Test Event button in the Partner Dashboard (Settings → Webhooks) to send a sample payload with isTest: true to your endpoint. This lets you verify your endpoint is reachable and your parsing logic is correct without waiting for real orders.
You can also use the Delivery History table to inspect every delivery attempt, view the exact payload sent, and see your server's response status.
Security Best Practices
- Always verify the
X-TN-Signatureheader. Reject requests with invalid or missing signatures. - Use HTTPS. Never configure a plaintext
http://endpoint for production webhooks. - Respond quickly. Return
200 OKwithin 10 seconds. If processing takes longer, queue the job and respond immediately. - Be idempotent. The same event may be delivered more than once on retries. Use the
idfield to detect and deduplicate duplicate deliveries. - Rotate your secret periodically. Use the Regenerate Secret button in the dashboard and update your server configuration.
Need Help?
- Developer Support: developers@ticketnation.ph
- API Documentation: API Overview
- Partner Dashboard: Settings → Webhooks