# Webhooks

Webhooks allow data to be passed to an external system in real time. We have existing tutorials for how to use Webhooks with Zapier to connect to [Mailchimp](https://help.tito.io/en/articles/5676064-can-i-integrate-tito-with-mailchimp), [Slack](http://help.tito.io/en/articles/12008575-how-to-automatically-post-tito-registrations-to-slack-via-zapier), and [Zoom](http://help.tito.io/en/articles/4173884-how-can-i-integrate-tito-with-zoom). Let us know if there's a specific tutorial you'd love us to create!

You can specify a Webhook in the **Webhook Endpoints** tab in the **Settings** section of your event.

Webhooks will `POST` a `JSON` payload to the endpoint you specify, with a `X-Webhook-Name` header. This will be either:

`checkin.created`
Fired when an attendee is checked-in via one of the Tito apps (web, iOS or Android).

`checkin.deleted`
Fired when an attendee check-in is deleted via one of the Tito apps (web, iOS or Android).

`ticket.created`
Fired when tickets are created immediately after a registration is confirmed. Tickets can be unassigned, incomplete or complete at this stage depending on whether it is a single or multiple ticket registration or whether the ticket has required fields or not.

`ticket.completed`
Fired when all required fields like name, email, etc and required questions have been answered.

`ticket.reassigned`
Fired specifically when a ticket is reassigned to someone else.

`ticket.updated`
Fired anytime ticket details are changed, including changes to the email address.

`ticket.unsnoozed`
Fired when a “snoozed” ticket is assigned to someone. When people register tickets but do not want to or can’t assign them straight away they can be “snoozed”.

`ticket.unvoided`
Fired when a voided ticket is returned to a valid state.

`ticket.voided`
Fired when a ticket is changed to a voided state. Free tickets that are cancelled by the attendee will also cause this webhook to fire.

`registration.updated`
Fired when the registration is updated in the Tito admin area or via the API.

`registration.finished`
Fired as soon as the registration is confirmed, e.g when payment is complete.

`registration.completed`
Fired when all tickets on a registration have either been assigned or “snoozed”.

`registration.cancelled`
Fired when the registration is cancelled in the Tito admin area or via the API. Free tickets that are cancelled by the attendee will also cause this webhook to fire.

In addition, there are two more webhooks if you have our [pay-by-invoice feature](https://help.tito.io/en/articles/1994952-can-attendees-pay-by-invoice) enabled:

`registration.marked_as_paid`
Fired when a pay-by-invoice registration is marked as paid in Tito.

`registration.marked_as_unpaid`
Fired when a pay-by-invoice registration is marked as unpaid in Tito (for instance, if you accidentally marked an invoice as paid).

## Basic ticket payload

The payload will look something like this for a basic ticket:

```
{
  "id": 795,
  "event": {
    "id": 64,
    "title": "AwesomeConf ?",
    "url": "https://heroku.tito.io/paulca/awesomeconf",
    "account_slug": "paulca",
    "slug": "awesomeconf",
    "currency": "EUR",
    "start_date": "2020-12-01",
    "end_date": null
  },
  "name": "Peter Winter",
  "first_name": "Peter",
  "last_name": "Winter",
  "email": "winter@example.com",
  "phone_number": null,
  "company_name": "Peter Winter",
  "reference": "1i5nfwf2t",
  "price": "1.00",
  "tax": "0.19",
  "price_less_tax": "0.81",
  "slug": "1i5nfwf2t24",
  "state_name": "incomplete",
  "gender": "male",
  "release_price": "1.00",
  "discount_code_used": "",
  "total_paid": "1.00",
  "total_paid_less_tax": "0.81",
  "updated_at": "2017-08-27T13:07:47.000Z",
  "url": "https://heroku.tito.io/tickets/1i5nfwf2t24",
  "admin_url": "https://heroku.tito.io/paulca/awesomeconf/admin/tickets/1i5nfwf2t24",
  "release_title": "AwesomeConf ticket",
  "release_slug": "31az2uvoh4",
  "release_id": 90,
  "release": {
    "id": 90,
    "title": "AwesomeConf ticket",
    "slug": "31az2uvoh4",
    "metadata": null
  },
  "custom": null,
  "registration_id": "bdtyap3hguq",
  "registration_slug": "bdtyap3hguq",
  "metadata": null,
  "answers": [
    {
      "question": {
        "title": "Phone Number",
        "description": "",
        "id": 200
      },
      "response": "555-555-0199@example.com",
      "humanized_response": "555-555-0199@example.com"
    },
    {
      "question": {
        "title": "Session 1 – Second Choice",
        "description": "",
        "id": 1293
      },
      "response": "One",
      "humanized_response": "One"
    },
    {
      "question": {
        "title": "Session 1 - First Choice",
        "description": "",
        "id": 1292
      },
      "response": "555-555-0199@example.com",
      "humanized_response": "555-555-0199@example.com"
    },
    {
      "question": {
        "title": "Country",
        "description": "",
        "id": 1005357
      },
      "response": "AU",
      "humanized_response": "AU"
    },
    {
      "question": {
        "title": "Session 1 — Third Choice",
        "description": "",
        "id": 1295
      },
      "response": "One",
      "humanized_response": "One"
    },
    {
      "question": {
        "title": "T-Shirt Size",
        "description": "",
        "id": 1009604
      },
      "response": "Women's S",
      "humanized_response": "Women's S"
    }
  ],
  "responses": {
    "phone-number": "555-555-0199@example.com",
    "session-1-second-choice": "One",
    "session-1-first-choice": "555-555-0199@example.com",
    "country": "AU",
    "session-1-third-choice": "One",
    "t-shirt-size": "Women's S"
  },
  "upgrade_ids": [

  ],
  "registration": {
    "url": "https://heroku.tito.io/registrations/bdtyap3hguq",
    "admin_url": "https://heroku.tito.io/paulca/awesomeconf/admin/registrations/bdtyap3hguq",
    "total": "1.00",
    "currency": "EUR",
    "payment_reference": null,
    "source": null,
    "name": "Paul Campbell",
    "email": "funconf@gmail.com",
    "receipt": {
      "total": "1.00",
      "tax": "0.19",
      "payment_provider": "Unknown",
      "paid": true,
      "receipt_lines": [
        {
          "total": "1.00",
          "quantity": 1,
          "tax": "0.19"
        }
      ]
    }
  }
}
```

## Payload with responses to questions

If the ticket has answers to questions, it will look a bit like this:

```
{
  "id": 1052678,
  "event": {
    "id": 64,
    "title": "AwesomeConf ?",
    "url": "https://heroku.tito.io/paulca/awesomeconf",
    "account_slug": "paulca",
    "slug": "awesomeconf",
    "currency": "EUR",
    "start_date": "2020-12-01",
    "end_date": null
  },
  "name": "Peter Winter",
  "first_name": "Peter",
  "last_name": "Winter",
  "email": "winter@example.com",
  "phone_number": null,
  "company_name": "Peter Winter",
  "reference": "A8FV-3",
  "price": "1.00",
  "tax": "0.19",
  "price_less_tax": "0.81",
  "slug": "pGZ3De1X3wLslG7yQwO7QFg",
  "state_name": "incomplete",
  "gender": "male",
  "release_price": "1.00",
  "discount_code_used": "",
  "total_paid": "1.00",
  "total_paid_less_tax": "0.81",
  "updated_at": "2017-08-27T13:07:50.000Z",
  "url": "https://heroku.tito.io/tickets/pGZ3De1X3wLslG7yQwO7QFg",
  "admin_url": "https://heroku.tito.io/paulca/awesomeconf/admin/tickets/pGZ3De1X3wLslG7yQwO7QFg",
  "release_title": "AwesomeConf ticket",
  "release_slug": "31az2uvoh4",
  "release_id": 90,
  "release": {
    "id": 90,
    "title": "AwesomeConf ticket",
    "slug": "31az2uvoh4",
    "metadata": null
  },
  "custom": null,
  "registration_id": "pbidGD4FWx7r47py0dYdDeg",
  "registration_slug": "pbidGD4FWx7r47py0dYdDeg",
  "metadata": null,
  "answers": [
    {
      "question": {
        "title": "Phone Number",
        "description": "",
        "id": 200
      },
      "response": "12345",
      "humanized_response": "12345"
    },
    {
      "question": {
        "title": "Session 1 – Second Choice",
        "description": "",
        "id": 1293
      },
      "response": "One",
      "humanized_response": "One"
    },
    {
      "question": {
        "title": "Country",
        "description": "",
        "id": 1005357
      },
      "response": "AU",
      "humanized_response": "AU"
    },
    {
      "question": {
        "title": "Session 1 - First Choice",
        "description": "",
        "id": 1292
      },
      "response": "555-555-0199@example.com",
      "humanized_response": "555-555-0199@example.com"
    },
    {
      "question": {
        "title": "Session 1 — Third Choice",
        "description": "",
        "id": 1295
      },
      "response": "One",
      "humanized_response": "One"
    },
    {
      "question": {
        "title": "T-Shirt Size",
        "description": "",
        "id": 1009604
      },
      "response": "Women's S",
      "humanized_response": "Women's S"
    }
  ],
  "responses": {
    "phone-number": "12345",
    "session-1-second-choice": "One",
    "country": "AU",
    "session-1-first-choice": "555-555-0199@example.com",
    "session-1-third-choice": "One",
    "t-shirt-size": "Women's S"
  },
  "upgrade_ids": [

  ],
  "registration": {
    "url": "https://heroku.tito.io/registrations/pbidGD4FWx7r47py0dYdDeg",
    "admin_url": "https://heroku.tito.io/paulca/awesomeconf/admin/registrations/pbidGD4FWx7r47py0dYdDeg",
    "total": "3.00",
    "currency": "EUR",
    "payment_reference": "ch_4MkyHRycVDKfCp",
    "source": null,
    "name": "Paul Campbell",
    "email": "paul@rslw.com",
    "receipt": {
      "total": "3.00",
      "tax": "0.56",
      "payment_provider": "Stripe (live)",
      "paid": true,
      "receipt_lines": [
        {
          "total": "3.00",
          "quantity": 3,
          "tax": "0.56"
        }
      ]
    }
  }
}
```

## Verifying the payload

Each payload comes with a signed HMAC signature so that you can verify the origin of the webhook request.

In `Settings`   **>** `Webhook Endpoints`  , you’ll find a shared security token. You can use the to sign the payload.

The security token is used as a key to sign the payload data with an HMAC key.

The HMAC key is your security token, the HMAC digest is SHA2, and the data is the raw payload JSON that is sent. The key is sent Base64 encoded via the `Tito-Signature` HTTP header.

If you’re using Ruby, for example, you can verify the authenticity of your payload with the following code:

```
key = 'YOUR EVENT SECURITY TOKEN'
hash = OpenSSL::Digest.new('sha256')
data = 'THE WEBHOOK REQUEST'

Base64.encode64(OpenSSL::HMAC.digest(hash, key, data)).strip
```

---

Still need help? Search our [FAQs](https://help.tito.io/en/collections/2781-faqs-for-organisers) for instant answers. You can also leave a message for our support team by [email](mailto:support@tito.io) or in-app, and we'll get back to you by the next working day.

​