Webhooks
    enterprise+ plan

    Receive real-time HTTP notifications when events happen on your Giveawayz platform. Webhooks let you automate workflows, sync data with external systems, and react instantly to ticket purchases, draw results, and more.

    Setting Up a Webhook

    Open Webhook settings

    From your dashboard, navigate to Settings > Webhooks.

    Add an endpoint

    Click Add Endpoint and enter the URL where you want to receive webhook events. This must be a publicly accessible HTTPS URL.

    Select events

    Choose which events you want to subscribe to. You can select individual events or subscribe to all events.

    Copy your signing secret

    A unique signing secret is generated for your endpoint. Copy it immediately and store it securely -- you will need it to verify webhook signatures.

    Events

    The following events are available. Each event fires at a specific moment in the competition lifecycle.

    | Event | Description | When It Fires | |-------|-------------|---------------| | order.created | A new order has been placed | When a customer submits an order at checkout | | order.paid | Payment has been confirmed | When Stripe confirms the payment was successful | | order.refunded | An order has been refunded | When an admin processes a full or partial refund | | competition.published | A competition has gone live | When a competition is published from the wizard or dashboard | | competition.completed | A competition has ended | When a competition reaches its end date or is ended early | | draw.completed | A draw has been executed | When winners are selected (scheduled, flash, or manual draw) | | ticket.purchased | A ticket has been issued | When individual tickets are assigned after a successful payment |

    Payload Format

    All webhook payloads are sent as JSON via a POST request to your endpoint. Every payload follows this structure:

    {
      "event": "order.paid",
      "timestamp": "2026-02-28T14:30:00Z",
      "data": {
        "id": "ord_1a2b3c4d",
        "competitionId": "comp_8f3k2j1m",
        "customerEmail": "jane@example.com",
        "ticketCount": 3,
        "amount": 8.97,
        "status": "paid"
      }
    }
    
    • event -- The event type string (e.g. order.paid)
    • timestamp -- ISO 8601 timestamp of when the event occurred
    • data -- The event-specific payload containing the relevant resource data

    Example Payloads

    draw.completed:

    {
      "event": "draw.completed",
      "timestamp": "2026-03-16T18:00:05Z",
      "data": {
        "competitionId": "comp_8f3k2j1m",
        "competitionTitle": "Win a PS5 Pro Bundle",
        "drawType": "scheduled",
        "winners": [
          {
            "ticketNumber": 247,
            "customerEmail": "lucky@example.com"
          }
        ],
        "totalEntrants": 312,
        "seed": "a1b2c3d4e5f6..."
      }
    }
    

    competition.published:

    {
      "event": "competition.published",
      "timestamp": "2026-02-20T12:00:00Z",
      "data": {
        "id": "comp_9a4b5c6d",
        "title": "£1,000 Cash Giveaway",
        "ticketPrice": 1.50,
        "maxTickets": 1000,
        "startDate": "2026-02-20T12:00:00Z",
        "endDate": "2026-03-20T12:00:00Z",
        "drawType": "flash"
      }
    }
    

    Signature Verification

    Every webhook request includes an X-Giveawayz-Signature header containing an HMAC-SHA256 signature of the request body. You should always verify this signature to confirm the request genuinely came from Giveawayz.

    How Verification Works

    1. Giveawayz computes an HMAC-SHA256 hash of the raw request body using your endpoint's signing secret
    2. The hex-encoded hash is sent in the X-Giveawayz-Signature header
    3. Your server computes the same hash and compares them using a timing-safe comparison

    Node.js Verification Example

    const crypto = require('crypto');
    
    function verifyWebhook(payload, signature, secret) {
      const expected = crypto
        .createHmac('sha256', secret)
        .update(payload)
        .digest('hex');
      return crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(expected)
      );
    }
    
    // Usage in an Express route
    app.post('/webhooks/giveawayz', (req, res) => {
      const signature = req.headers['x-giveawayz-signature'];
      const isValid = verifyWebhook(req.rawBody, signature, process.env.WEBHOOK_SECRET);
    
      if (!isValid) {
        return res.status(401).send('Invalid signature');
      }
    
      const { event, data } = req.body;
    
      switch (event) {
        case 'order.paid':
          // Handle paid order
          break;
        case 'draw.completed':
          // Handle draw completion
          break;
      }
    
      res.status(200).send('OK');
    });
    

    Retry Policy

    If your endpoint does not respond with a 2xx status code (or does not respond within 30 seconds), Giveawayz will retry the delivery with exponential backoff:

    | Attempt | Delay After Failure | |---------|-------------------| | 1st retry | 1 minute | | 2nd retry | 5 minutes | | 3rd retry | 30 minutes |

    After 3 failed retries, the event is marked as failed. You can view failed deliveries and manually retry them from the Settings > Webhooks page in your dashboard.

    Testing Webhooks

    During development, you likely will not have a publicly accessible HTTPS URL. Here are two approaches for testing:

    Using webhook.site

    1. Go to webhook.site and copy the unique URL provided
    2. Add this URL as a webhook endpoint in your dashboard
    3. Trigger events (e.g. create a test order) and inspect the payloads on webhook.site

    Using ngrok

    1. Install ngrok and run ngrok http 3000 (or whichever port your server runs on)
    2. Copy the HTTPS forwarding URL (e.g. https://abc123.ngrok.io)
    3. Add https://abc123.ngrok.io/webhooks/giveawayz as your webhook endpoint
    4. Trigger events and inspect the requests hitting your local server
    • API Reference — Query data programmatically instead of waiting for events
    • Custom Domains — Use your own domain for a fully branded integration
    • Team Management — Only Admin role members can manage webhooks
    • Pricing Plans — Webhooks are available on the Enterprise plan