---
title: "Ticket Fairy Order Webhooks | Full Order Payload Reference"
description: "Get the whole order at your own URL each time it changes: buyer, tickets, tables, add-ons, money and answers. Payload fields, signature checks and an example."
canonical: "https://www.ticketfairy.com/developers/webhooks"
---

# Ticket Fairy Order Webhooks | Full Order Payload Reference

Ticket Fairy developer documentation

# Receive every order as it changes

Ticket Fairy sends the whole order to your URL each time it changes: the buyer, the event, every ticket, table and add-on, the money and the checkout answers. Use it to keep your CRM, access control or reporting up to date without polling.

  [Set up a webhook](#setup) [See an example payload](#example)

This page describes the full order format. For the event API and the agent protocols, read the [Ticket Fairy developer documentation](https://www.ticketfairy.com/developers).

     Get an example payload

```
$ curl 'https://www.ticketfairy.com/api/v1/webhooks/notification/example?type=order&format=full_order'
```

No key, no sign-in. The response is JSON.

## When you get a delivery

You get a delivery with the whole order when one of these things happens:

- An order is paid. You get one delivery, after the last ticket in the order becomes valid.
- A buyer makes the first payment on a payment plan, and again when they pay the last instalment.
- A buyer adds an add-on to an order they already placed.
- A ticket holder changes their details.
- A ticket is transferred to somebody else.
- A ticket is listed for resale, or is sold on resale.
- A ticket is refunded or cancelled.
- A ticket is checked in, if the event has check-in sync switched on. See the questions at the end of this page.

## Set up a webhook

A webhook can cover one brand, one tour or one event. A brand webhook covers every event of that brand.

### In the dashboard

1. Open the brand, tour or event in your Ticket Fairy dashboard.
2. Go to the **Webhooks** page.
3. Add a webhook, enter your URL and choose the **Full order** format.

### With the subscription API

Generate a webhook API key in [your account settings](https://manage.ticketfairy.com/account). Send it as a Bearer token to `POST https://www.ticketfairy.com/api/v1/webhooks/subscription`. Set `criteria` to `brand`, `tour` or `event`, and `criteria_id` to its ID. Set `format` to `full_order`. `source` is a short name for your application, in letters, numbers, dashes and underscores. `headers` are sent with every delivery.

### Addresses you need

    Subscription endpoint, POST to subscribe and DELETE to unsubscribe

```
https://www.ticketfairy.com/api/v1/webhooks/subscription
```

    Example payload, GET

```
https://www.ticketfairy.com/api/v1/webhooks/notification/example?type=order&format=full_order
```

    Missed orders, GET with a Personal Access Token

```
https://www.theticketfairy.com/api/events/{event_id}/relationships/orders
```

    This documentation

```
https://www.ticketfairy.com/developers/webhooks
```

    Subscribe

```
$ curl -X POST 'https://www.ticketfairy.com/api/v1/webhooks/subscription' \
  -H 'Authorization: Bearer YOUR_WEBHOOK_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "order",
    "method": "post",
    "url": "https://example.com/ticket-fairy/orders",
    "criteria": "event",
    "criteria_id": "12345",
    "headers": {"X-Api-Key": "your-own-secret"},
    "params": {},
    "format": "full_order",
    "source": "my-crm"
  }'
```

The response is `201 Created` with the webhook's `id`. Keep it. To remove the webhook, send a `DELETE` request with that ID. The response is `204 No Content`.

   Unsubscribe

```
$ curl -X DELETE 'https://www.ticketfairy.com/api/v1/webhooks/subscription/WEBHOOK_ID' \
  -H 'Authorization: Bearer YOUR_WEBHOOK_API_KEY'
```

## Delivery and security

Each delivery is an HTTPS `POST` to your URL with a JSON body.

### Headers

- `Content-Type: application/json`
- `X-Signature`, if the event has a signing secret. It is the HMAC-SHA256 of the raw request body, made with the signing secret, as lower-case hex.
- The custom headers you set on the webhook.

### Your response

- Any 2xx status tells Ticket Fairy that you received the delivery.
- Respond quickly, then process the order. Put it on your own queue first.
- `410 Gone` removes the webhook. Ticket Fairy sends no more deliveries to it.
- Ticket Fairy does not send a failed delivery again. To catch up after a failure, read the answer to [What happens if my endpoint is down?](#questions)

### Check the signature

Calculate the HMAC-SHA256 of the raw body with your signing secret. Compare it with `X-Signature` in constant time. Use the bytes you received, not JSON you parsed and encoded again, because a new encoding changes the signature.

#### Node.js

   Node.js with Express

```
const crypto = require('crypto')
const express = require('express')

const app = express()
const secret = process.env.TICKET_FAIRY_SIGNING_SECRET

// Read the raw body. The signature is made from the exact bytes you receive.
app.post('/ticket-fairy/orders', express.raw({ type: 'application/json' }), (req, res) => {
  const expected = crypto.createHmac('sha256', secret).update(req.body).digest('hex')
  const received = Buffer.from(req.get('X-Signature') || '', 'utf8')

  if (received.length !== expected.length || !crypto.timingSafeEqual(received, Buffer.from(expected, 'utf8'))) {
    return res.sendStatus(401)
  }

  const order = JSON.parse(req.body.toString('utf8'))
  saveForLater(order) // Put the order on your own queue.
  res.sendStatus(200)
})
```

#### Python

   Python with Flask

```
import hashlib
import hmac
import json
import os

from flask import Flask, request

app = Flask(__name__)
secret = os.environ["TICKET_FAIRY_SIGNING_SECRET"].encode()


@app.post("/ticket-fairy/orders")
def receive_order():
    raw_body = request.get_data()  # The exact bytes you received.
    expected = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()

    if not hmac.compare_digest(expected, request.headers.get("X-Signature", "")):
        return "", 401

    order = json.loads(raw_body)
    save_for_later(order)  # Put the order on your own queue.
    return "", 200
```

#### PHP

   PHP

```
<?php

$secret = getenv('TICKET_FAIRY_SIGNING_SECRET');
$rawBody = file_get_contents('php://input'); // The exact bytes you received.
$expected = hash_hmac('sha256', $rawBody, $secret);

if (!hash_equals($expected, $_SERVER['HTTP_X_SIGNATURE'] ?? '')) {
    http_response_code(401);
    exit;
}

$order = json_decode($rawBody, true);
saveForLater($order); // Put the order on your own queue.
http_response_code(200);
```

## Payload

Field names are in snake\_case. Every amount is an integer in the smallest unit of the currency, for example cents, or whole yen for JPY. A field with no value is null. No field is left out.

### Top-level fields

| Field | Type | What it holds |
| --- | --- | --- |
| `format` | string | Always `full_order`. |
| `format_version` | string | The version of this format. Today it is `1.0`. |
| `notification_type` | string | Always `order`. |
| `sequence` | integer | The time Ticket Fairy built this delivery, in microseconds since 1 January 1970 UTC. A delivery with a higher number carries the same or newer order. |
| `order_id` | integer | The order ID in Ticket Fairy. Use it as the key for the order in your system. |
| `order_hash` | string | The order hash, a second reference to the same order. |
| `customer_id` | integer | The buyer's Ticket Fairy ID. |
| `order_status` | string | The status of the order, in lower case, for example `paid`. See [Status values](#status). |
| `order_date` | string | The order date, in ISO 8601 format and UTC, for example `2026-10-14T19:02:11Z`. |
| `deleted_at` | string or null | When the order was deleted, in ISO 8601 format and UTC. Null if the order is not deleted. |
| `currency` | string | The ISO 4217 currency code in upper case, for example `USD`. Every amount in the payload is in this currency. |
| `total` | integer | The order total. See [Totals](#totals) for how it adds up. |
| `totals` | object | The amounts that make up the total, and what is paid, due and refunded. See [Totals](#totals). |
| `promo_code` | string or null | The promo code the buyer used on the order. |
| `is_comp` | boolean | True if the order is a complimentary order. |
| `purchaser` | object | The buyer. See [Purchaser](#purchaser). |
| `event` | object | The event. See [Event](#event). |
| `tickets` | array | Every ticket in the order, including cancelled and refunded tickets. See [Tickets](#tickets-fields). |
| `tables` | array | One entry for each table booking in the order. Empty if there is none. See [Tables](#tables-fields). |
| `add_ons` | array | The add-ons in the order. Empty if there is none. See [Add-ons](#add-ons-fields). |
| `answers` | array | The buyer's answers to the order questions at checkout. See [Answers](#answers-fields). |
| `ticket_count` | integer | The number of tickets in the order. |
| `active_ticket_count` | integer | The number of active tickets in the order. |
| `cancelled_ticket_count` | integer | The number of cancelled or refunded tickets in the order. |

### Totals

For most orders, `total` is `subtotal` plus `tax`. For a table booking, `total` also includes the balance the buyer pays at the venue, and `amount_outstanding` shows that balance. A refund lowers `total` and `subtotal` by the refunded amount, and `amount_paid` stays the same. Every field in `totals` is an integer.

| Field | What it holds |
| --- | --- |
| `subtotal` | Tickets, tables and add-ons, after the discount and before tax. It includes any booking fees the buyer paid. |
| `discount` | The promo code discount. It is already taken off the subtotal, so do not subtract it again. |
| `tax` | The tax charged on top of the subtotal. |
| `amount_paid` | What the buyer paid so far. A refund does not lower it: amount\_refunded shows the refunds. It is lower than the total on a payment plan and on a table booking with a deposit. An instalment between the first and the last does not send a delivery, so this value updates with the next change to the order. A card hold that has not been charged yet counts as not paid. |
| `amount_outstanding` | What the buyer still has to pay. For a table booking, this is the balance due at the venue. It is 0 once the order, or the table, is refunded or cancelled. |
| `amount_refunded` | What was refunded to date, on the order, its tickets and their add-ons. |

### Purchaser

| Field | Type | What it holds |
| --- | --- | --- |
| `first_name, last_name` | string or null | The buyer's name. |
| `email` | string or null | The buyer's email address. |
| `phone` | string or null | The buyer's phone number. |
| `date_of_birth` | string or null | The buyer's date of birth, as `YYYY-MM-DD`. |
| `address` | object | The billing address: `street`, `city`, `state`, `postcode` and `country`. `country` is the ISO 3166-1 alpha-2 code, for example `US`. |
| `marketing_opt_in` | boolean | True if the buyer agreed to receive marketing email from the brand of this event at this `email`. It is false when the buyer checked out with an email other than their account email. |

### Event

| Field | Type | What it holds |
| --- | --- | --- |
| `event_id` | integer | The event ID in Ticket Fairy. |
| `event_name` | string | The name of the event. |
| `start_date_time, end_date_time` | string or null | When the event starts and ends, in the event's local time, as `YYYY-MM-DD HH:MM:SS`. |
| `timezone` | string or null | The IANA timezone of the event, for example `America/Los_Angeles`. |
| `venue` | object | The venue: `name`, `city`, `state` and `country`. |

## Tickets, tables and add-ons

`tickets` lists every ticket in the order. `tables` lists the table bookings, and `add_ons` lists the add-ons.

### Ticket categories and ticket types

A ticket type is a ticket the buyer can buy at a price, for example "GA Early Bird" or "GA Final Release". A ticket category groups ticket types, for example "General Admission" or "VIP". Use the category to count tickets by kind of access across all releases. The category is null if the organiser did not put the ticket type in a category.

### Tickets

| Field | Type | What it holds |
| --- | --- | --- |
| `ticket_id` | integer | The ticket ID in Ticket Fairy. Use it as the key for the ticket in your system. |
| `lookup_code` | string | The ticket code, in upper case. |
| `barcode` | string | The value in the ticket's QR code. If the event uses barcodes from a partner, it is that barcode. |
| `access_status` | string | `ok` if the holder can enter, or `invalid` if not. See [Who can enter](#access-status). |
| `status` | string | The status of the ticket, for example `valid` or `checked in`. See [Status values](#status). |
| `cancellation_reason` | string or null | Why the ticket was cancelled. |
| `ticket_category_id` | integer or null | The ticket category. Null if the organiser did not put the ticket type in a category. |
| `ticket_category_name` | string or null | The name of the ticket category, for example `VIP`. |
| `ticket_type_id` | integer | The ticket type. |
| `ticket_type_name` | string | The name of the ticket type, for example `VIP Early Bird`. |
| `price` | integer or null | The price the buyer paid for this ticket, after the discount and without tax. It includes any product extras charged with the ticket. It is 0 for a guest ticket on a table, because the table carries the price. It is null for a refunded ticket, and `amount_refunded` in [Totals](#totals) shows the refund. |
| `promo_code` | string or null | The promo code on the order. Every ticket in the order has the same value. |
| `seat` | object or null | The seat, with one field: `label`, the seat as it is printed on the ticket, for example `Block A, seat F12` or `Table 4`. Null for general admission. |
| `table_id` | integer or null | The table booking this ticket belongs to. It matches `table_id` in `tables`. |
| `holder` | object | The ticket holder: `first_name`, `last_name`, `email`, `phone`, `date_of_birth`, `age_at_event`, `postcode`, `city` and `country`. If the holder did not give a name, email or phone, you get the buyer's. `postcode`, `city` and `country` come from the buyer's billing address. |
| `tags` | array of strings | The tags on the ticket type. |
| `answers` | array | The holder's answers to the ticket questions. See [Answers](#answers-fields). |
| `notes` | string or null | Notes on the ticket. |

### Tables

A table booking has one entry here. Each guest on the table has a ticket in `tickets`, with the same `table_id` and a `price` of 0. The table entry carries the price.

| Field | Type | What it holds |
| --- | --- | --- |
| `table_id` | integer | The table booking. Each guest ticket on the table has the same `table_id`. |
| `ticket_category_id, ticket_category_name` | integer, string or null | The ticket category of the table. |
| `ticket_type_id, ticket_type_name` | integer, string | The ticket type of the table. |
| `guests_count` | integer | The number of guests on the table. |
| `price` | integer | The full price of the table. |
| `deposit_paid` | integer | The deposit the buyer paid at checkout. |
| `remaining` | integer | The balance the buyer still has to pay at the venue. It drops to 0 when the venue records the payment, and when the table is refunded or cancelled. |
| `status` | string or null | The status of the guest tickets on the table. |
| `ticket_ids` | array of integers | The guest tickets on the table. |

### Add-ons

| Field | Type | What it holds |
| --- | --- | --- |
| `add_on_line_id` | integer | The add-on purchase. A ticket add-on has one entry for each ticket it belongs to, and those entries have the same `add_on_line_id`. Use `add_on_line_id` and `ticket_id` together as the key. |
| `add_on_id` | integer | The add-on product. |
| `name` | string | The name of the add-on, for example `Parking pass`. |
| `group_name` | string or null | The add-on group, for example `Parking`. |
| `ticket_id` | integer or null | The ticket this add-on belongs to. Null for an add-on on the whole order. |
| `quantity` | integer | How many were bought. A ticket add-on entry is always 1. |
| `price` | integer | The price of one. |
| `total` | integer | The price multiplied by the quantity. |
| `status` | string | The status of the add-on, for example `active`. See [Status values](#status). |
| `barcode` | string | The code to scan when the buyer collects the add-on. |
| `answers` | array | The answers to the add-on questions. See [Answers](#answers-fields). |

### Answers

The order, each ticket and each ticket add-on have an `answers` list with the buyer's answers to the organiser's questions.

| Field | Type | What it holds |
| --- | --- | --- |
| `name` | string | The organiser's name for the question. It does not change when the organiser edits the question text, so use it as the key. |
| `question` | string | The question the buyer saw. If there is no question text, it is the same as `name`. |
| `answer` | string or null | The answer. |

## Example payload

Maya bought two General Admission tickets at 65.00 USD and one VIP ticket at 120.00 USD, with the promo code SUMMER10 for 10% off tickets. She also bought a parking pass for the order and a T-shirt for her own ticket, and paid 8% tax.

    POST body, application/json

```
{
    "format": "full_order",
    "format_version": "1.0",
    "notification_type": "order",
    "sequence": 1792004531482917,
    "order_id": 4815162,
    "order_hash": "9c1e5f0a7b3d",
    "customer_id": 90210,
    "order_status": "paid",
    "order_date": "2026-10-14T19:02:11Z",
    "deleted_at": null,
    "currency": "USD",
    "total": 30240,
    "totals": {
        "subtotal": 28000,
        "discount": 2500,
        "tax": 2240,
        "amount_paid": 30240,
        "amount_outstanding": 0,
        "amount_refunded": 0
    },
    "promo_code": "SUMMER10",
    "is_comp": false,
    "purchaser": {
        "first_name": "Maya",
        "last_name": "Chen",
        "email": "maya@example.com",
        "phone": "+12135550143",
        "date_of_birth": "1994-03-08",
        "address": {
            "street": "120 S Main St",
            "city": "Los Angeles",
            "state": "California",
            "postcode": "90012",
            "country": "US"
        },
        "marketing_opt_in": true
    },
    "event": {
        "event_id": 12345,
        "event_name": "Sunset Festival",
        "start_date_time": "2026-11-21 14:00:00",
        "end_date_time": "2026-11-21 23:00:00",
        "timezone": "America/Los_Angeles",
        "venue": {
            "name": "Beach Park",
            "city": "Los Angeles",
            "state": "California",
            "country": "United States"
        }
    },
    "tickets": [
        {
            "ticket_id": 7001,
            "lookup_code": "K7Q2XA9M",
            "barcode": "TFK7Q2XA9M",
            "access_status": "ok",
            "status": "valid",
            "cancellation_reason": null,
            "ticket_category_id": 301,
            "ticket_category_name": "General Admission",
            "ticket_type_id": 1101,
            "ticket_type_name": "GA Early Bird",
            "price": 5850,
            "promo_code": "SUMMER10",
            "seat": null,
            "table_id": null,
            "holder": {
                "first_name": "Maya",
                "last_name": "Chen",
                "email": "maya@example.com",
                "phone": null,
                "date_of_birth": "1994-03-08",
                "age_at_event": 32,
                "postcode": "90012",
                "city": "Los Angeles",
                "country": "US"
            },
            "tags": [],
            "answers": [],
            "notes": null
        },
        {
            "ticket_id": 7002,
            "lookup_code": "P4W8ZD3N",
            "barcode": "TFP4W8ZD3N",
            "access_status": "ok",
            "status": "valid",
            "cancellation_reason": null,
            "ticket_category_id": 301,
            "ticket_category_name": "General Admission",
            "ticket_type_id": 1101,
            "ticket_type_name": "GA Early Bird",
            "price": 5850,
            "promo_code": "SUMMER10",
            "seat": null,
            "table_id": null,
            "holder": {
                "first_name": "Sam",
                "last_name": "Ortiz",
                "email": "sam@example.com",
                "phone": null,
                "date_of_birth": "1995-07-19",
                "age_at_event": 31,
                "postcode": "90012",
                "city": "Los Angeles",
                "country": "US"
            },
            "tags": [],
            "answers": [],
            "notes": null
        },
        {
            "ticket_id": 7003,
            "lookup_code": "R2H6LC5T",
            "barcode": "TFR2H6LC5T",
            "access_status": "ok",
            "status": "valid",
            "cancellation_reason": null,
            "ticket_category_id": 302,
            "ticket_category_name": "VIP",
            "ticket_type_id": 1201,
            "ticket_type_name": "VIP Early Bird",
            "price": 10800,
            "promo_code": "SUMMER10",
            "seat": {
                "label": "Block A, seat F12"
            },
            "table_id": null,
            "holder": {
                "first_name": "Jordan",
                "last_name": "Lee",
                "email": "jordan@example.com",
                "phone": null,
                "date_of_birth": "1990-12-02",
                "age_at_event": 35,
                "postcode": "90012",
                "city": "Los Angeles",
                "country": "US"
            },
            "tags": [
                "vip"
            ],
            "answers": [],
            "notes": null
        }
    ],
    "tables": [],
    "add_ons": [
        {
            "add_on_line_id": 9001,
            "add_on_id": 501,
            "name": "Parking pass",
            "group_name": "Parking",
            "price": 2500,
            "ticket_id": null,
            "quantity": 1,
            "total": 2500,
            "status": "active",
            "barcode": "a8f31c7e02d4",
            "answers": []
        },
        {
            "add_on_line_id": 9002,
            "add_on_id": 502,
            "name": "Festival T-shirt",
            "group_name": "Merchandise",
            "price": 3000,
            "ticket_id": 7001,
            "quantity": 1,
            "total": 3000,
            "status": "active",
            "barcode": "d40b9e6a1f27",
            "answers": [
                {
                    "name": "tshirt_size",
                    "question": "T-shirt size",
                    "answer": "M"
                }
            ]
        }
    ],
    "answers": [
        {
            "name": "heard_about_us",
            "question": "How did you hear about this event?",
            "answer": "Instagram"
        }
    ],
    "ticket_count": 3,
    "active_ticket_count": 3,
    "cancelled_ticket_count": 0
}
```

### How the totals add up

- Tickets: 5850 + 5850 + 10800 = 22500, after 2500 off with SUMMER10.
- Add-ons: 2500 for the parking pass and 3000 for the T-shirt.
- `subtotal`: 22500 + 2500 + 3000 = 28000.
- `tax`: 8% of 28000 = 2240.
- `total`: 28000 + 2240 = 30240, which is 302.40 USD.

## Status values

Status values are lower-case words. More values can appear, so handle a value you do not know safely.

### Order status

`paid`, `payment plan`, `partially refunded`, `freefund`, `refunded`, `cancelled`, `pending`, `pending for oxxo`, `pending 3rd party payment`, `need id verification`, `frozen`.

### Ticket status

These ticket statuses let the holder in, if the order is paid, partially refunded or freefund: `valid`, `checked in`, `for sale`.

These ticket statuses never let the holder in. A transferred or swapped ticket is the old ticket: the new holder gets a new ticket with its own `ticket_id` and barcode. `payment plan`, `sale in progress`, `partially refunded`, `transferred`, `swapped`, `sold`, `refunded`, `cancelled`, `unpaid`, `frozen`.

### Add-on status

`active`, `refunded`, `cancelled`, `transferred`, `for sale`, `sold`, `checked in`, `unpaid`. Accept an add-on only if its status is `active`.

### Who can enter

`access_status` is `ok` only if both of these are true:

- The ticket status is one that lets the holder in.
- The order status is `paid`, `partially refunded` or `freefund`.

In every other case it is `invalid`. A ticket on a payment plan is `invalid` until the buyer pays the last instalment.

## Store orders in your own system

Follow these steps to keep your copy of each order correct.

1. Check the signature first, if you set a signing secret. Reject the request if it does not match.
2. Respond quickly with a 2xx status. Put the order on your own queue and do the work after you respond.
3. Use `order_id` as the key for the order and `ticket_id` as the key for each ticket. Each delivery holds the whole order, so replace your copy of the order, its tickets, tables and add-ons with what you receive.
4. Keep the `sequence` you stored with each order. If a delivery has a lower `sequence` than the one you stored, ignore it.
5. Read every amount as an integer in the smallest unit of `currency`. 5850 in USD is 58.50. JPY has no smaller unit, so 5850 in JPY is 5,850 yen. KWD has three decimal places, so 5850 in KWD is 5.850.
6. Let a ticket holder in only when `access_status` is `ok`. Do not calculate it yourself from the status.
7. `access_status` says whether the ticket is valid for entry. It stays `ok` after the ticket is scanned, so record each scan yourself and refuse a second entry unless the event allows re-entry.
8. If `deleted_at` has a value, the order was deleted. Mark it as deleted in your system. Deleting an order does not send a delivery by itself, so a later delivery for that order is the first to show it.
9. Treat a status value you do not know as one that does not let the holder in. Ignore fields you do not know.

## Questions about order webhooks

### How do I tell a new order from an update?

Every delivery has the same shape. If you have no order with that `order_id`, it is a new order. If you have one, it is an update, and the delivery replaces your copy.

### Can I get the same order more than once?

Yes. One order can change several times, and you get a delivery for each change. If you subscribe the same URL to a brand and to one of its events, you get each delivery twice. Store orders by `order_id` and compare `sequence`, so a second copy does no harm.

### Can deliveries arrive out of order?

Yes. The order in which deliveries arrive is not guaranteed. Compare `sequence` with the value you stored for that order. Keep the delivery if its `sequence` is higher, and ignore it if it is lower. Every delivery gets its own `sequence`, even when two changes happen in the same second.

### What happens if my endpoint is down?

Ticket Fairy does not send a delivery again. To get the orders you missed, request `GET https://www.theticketfairy.com/api/events/{event_id}/relationships/orders` with a [Personal Access Token](https://manage.ticketfairy.com/account) as a Bearer token. Add `paid=1`, `refunded=1` or `pending=1` to get only the orders with that status. To get Freefund orders, add `freefund=1`. A deleted order is not in the list. Always add `page` and `limit`, for example `page=1&limit=100`, and request the next page until a page has fewer orders than `limit`. Without them, the API returns every order of the event in one response. Your role on the event must let you see its orders. This API returns orders in the dashboard format, not in the full order format.

### Which value do I scan at the door?

Scan the ticket's `barcode`. It is the value in the QR code on the ticket. Let the holder in only if `access_status` is `ok` and you have not already let that barcode in. For an add-on, scan the add-on's `barcode` and accept it only if its `status` is `active`.

### Why is a ticket on a payment plan invalid?

A ticket on a payment plan does not let the holder in until the buyer pays the last instalment. When they do, the order becomes paid, its tickets become valid, and you get a new delivery with `access_status` set to `ok`.

### Can I add the buyer to my mailing list?

Only if `purchaser.marketing_opt_in` is true. It shows whether the buyer agreed to marketing email from the brand of this event.

### Do I get a delivery when a ticket is checked in?

Only if the event has check-in sync switched on. To switch it on, email [support@theticketfairy.com](mailto:support@theticketfairy.com) with the event name.

### How do I get a signing secret?

The signing secret belongs to the event. To set one, email [support@theticketfairy.com](mailto:support@theticketfairy.com) with the event name. When an event has a signing secret, the delivery does not send some of the custom headers you set, including `Authorization`, `Cookie` and `Host`. Check `X-Signature` to confirm that the delivery came from Ticket Fairy, not an `Authorization` header.

### Can I get the delivery as GET, PUT or PATCH?

No. The full order format is always sent as a `POST` with a JSON body, whatever method you choose.

### How do I test my endpoint?

Request `https://www.ticketfairy.com/api/v1/webhooks/notification/example?type=order&format=full_order`. It returns an example full order payload with no credential. Send it to your endpoint to check that your code reads it.

### How do I stop the deliveries?

Remove the webhook on the Webhooks page in your dashboard, or send `DELETE /api/v1/webhooks/subscription/{id}`. You can also respond to a delivery with `410 Gone`. Ticket Fairy then removes that webhook and sends no more deliveries to it.

Ticket Fairy in full: [ticketing platform for event organisers](https://www.ticketfairy.com/event-ticketing/), with the features, pricing and support behind this page.

## Further Reading

  [**Best Event Ticketing Software Compared**](https://www.ticketfairy.com/blog/the-best-event-ticketing-software-of-2023-price-and-feature-comparison) [**Early Bird & Tiered Pricing Strategies**](https://www.ticketfairy.com/blog/tiered-pricing-and-early-bird-strategies-for-festivals) [**Using Ticketing Data to Improve Your Events**](https://www.ticketfairy.com/blog/how-to-use-ticketing-data-and-analytics-to-improve-your-festival)

## Questions about webhooks?

Email [support@theticketfairy.com](mailto:support@theticketfairy.com) with the webhook ID, the host name it sends to, the order ID and the response your endpoint sent. Leave out the rest of the address, because it can hold an access key.

  [Read the developer documentation](https://www.ticketfairy.com/developers) [Create a free account](https://manage.ticketfairy.com/welcome)

---

This page is on Ticket Fairy, a ticketing, marketing and operations platform for live events and the venues that host them: festivals, club nights, concerts, conferences and tours, and night clubs, beach clubs and concert venues. It grows revenue with fan rewards that turn an audience into a sales channel, and runs the money side with payments and payouts, Vault business banking, and working capital advanced against ticket sales. [How Ticket Fairy ticketing works](https://www.ticketfairy.com/event-ticketing) · [Ticket Fairy for AI assistants](https://www.ticketfairy.com/llms.txt)
