Skip to main content

Webhooks

Receive real-time HTTP POST notifications when events happen in your schedules.

Pro plan required

Overview

Webhooks let you receive automatic POST notifications to your server when key events occur, such as ticket sales, event changes, or check-ins. Instead of polling the API, your application is notified in real time.

Each webhook delivery includes an HMAC-SHA256 signature so you can verify the payload came from Event Schedule. Delivery logs are available in your account settings for debugging.

Setup

  1. Go to Settings in the admin panel and select the Webhooks section.
  2. Enter your endpoint URL (must be HTTPS in production).
  3. Select which event types you want to receive.
  4. Click Add Webhook. Your signing secret will be displayed once. Copy and store it securely.
  5. Use the Test button to send a test ping and verify your endpoint responds with a 2xx status.

Event Types

Event Description
sale.createdA new ticket sale is created (status: unpaid)
sale.paidA sale is confirmed as paid (Stripe, Invoice Ninja, manual, or free)
sale.refundedA sale is refunded
sale.cancelledA sale is cancelled
event.createdA new event is created
event.updatedAn event is updated
event.deletedAn event is deleted
ticket.scannedA ticket QR code is scanned at check-in
feedback.submittedAn attendee submits feedback for an event

Payload Format

All webhook payloads are JSON with this structure:

{
  "event": "sale.paid",
  "timestamp": "2026-03-01T12:00:00+00:00",
  "data": {
    "id": "abc123",
    "event_id": "def456",
    "event_name": "Summer Concert",
    "name": "Jane Doe",
    "email": "[email protected]",
    "status": "paid",
    "payment_amount": 25.00,
    "tickets": [
      { "ticket_id": "ghi789", "quantity": 2, "price": 12.50, "type": "General" }
    ]
  }
}

The data object matches the corresponding API response format. Sale webhooks include the same fields as the Sales API , and event webhooks match the Events API.

Request Headers

Header Description
X-Webhook-SignatureHMAC-SHA256 signature: sha256=<hex>
X-Webhook-EventThe event type (e.g. sale.paid)
X-Webhook-TimestampISO 8601 timestamp of when the webhook was sent
Content-Typeapplication/json
User-AgentEventSchedule-Webhook/1.0

Signature Verification

Every webhook includes an X-Webhook-Signature header containing an HMAC-SHA256 hash of the raw request body, signed with your webhook secret. Always verify this signature before processing the payload.

PHP

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';

$expected = 'sha256=' . hash_hmac('sha256', $payload, $webhookSecret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

$data = json_decode($payload, true);

Node.js

const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = 'sha256=' +
    crypto.createHmac('sha256', secret).update(body).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected), Buffer.from(signature)
  );
}

Python

import hmac, hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    expected = 'sha256=' + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Best Practices

  • Respond quickly. Return a 2xx status within 5 seconds. Do heavy processing asynchronously after acknowledging receipt.
  • Verify signatures. Always validate the X-Webhook-Signature header before processing any webhook payload.
  • Handle duplicates. Use the data.id field as an idempotency key. In rare cases, the same event may be delivered more than once.
  • Use HTTPS. Always use an HTTPS endpoint to protect webhook payloads in transit.
  • Monitor deliveries. Check the delivery log in your Webhook settings to debug failed deliveries and verify payloads.

Testing

Use the Test button in your webhook settings to send a test payload. The test event uses the type webhook.test with an empty data object:

{
  "event": "webhook.test",
  "timestamp": "2026-03-01T12:00:00+00:00",
  "data": {}
}

See Also