Skip to main content
Coming Soon - Webhook functionality is currently in development. This page documents the planned implementation.

Overview

The ticket.purchased event is triggered when someone purchases a ticket for your event through Givebutter. This event includes details about the ticket, attendee, and the associated transaction.

When This Event Fires

  • Ticket is purchased through event page
  • Multiple tickets are purchased in a single transaction
  • Ticket is purchased with a donation add-on
  • Complimentary ticket is issued
  • Ticket is purchased via the API
If multiple tickets are purchased in one transaction, a separate ticket.purchased event fires for each individual ticket.

Webhook Payload

{
  "id": "evt_qrs345tuv678",
  "type": "ticket.purchased",
  "created_at": "2024-01-15T14:20:00Z",
  "data": {
    "id": "tkt_456789",
    "ticket_type_id": "ttype_abc123",
    "ticket_type_name": "General Admission",
    "price": 5000,
    "quantity": 1,
    "order_id": "order_xyz789",
    "transaction_id": "txn_123456789",
    "campaign": {
      "id": "camp_abc123",
      "title": "Annual Gala 2024",
      "url": "https://givebutter.com/annual-gala-2024",
      "event_date": "2024-03-15T19:00:00Z",
      "event_location": "Grand Ballroom, 123 Main St, San Francisco, CA"
    },
    "attendee": {
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "[email protected]",
      "phone": "+1234567890"
    },
    "purchaser": {
      "id": "cont_987654321",
      "first_name": "John",
      "last_name": "Doe",
      "email": "[email protected]"
    },
    "checked_in": false,
    "checked_in_at": null,
    "custom_fields": {
      "dietary_restrictions": "Vegetarian",
      "t_shirt_size": "Medium"
    },
    "created_at": "2024-01-15T14:20:00Z",
    "updated_at": "2024-01-15T14:20:00Z"
  },
  "account_id": "acct_xyz789"
}

Event Data Fields

id
string
required
Unique identifier for the ticket (prefixed with tkt_)
ticket_type_id
string
required
ID of the ticket type purchased (prefixed with ttype_)
ticket_type_name
string
required
Name of the ticket type (e.g., “General Admission”, “VIP”, “Early Bird”)
price
integer
required
Ticket price in cents (e.g., 5000 = $50.00)
quantity
integer
required
Number of tickets purchased (usually 1 per event, but fires for each ticket)
order_id
string
required
ID of the order this ticket belongs to (prefixed with order_)
transaction_id
string
required
Associated transaction ID (prefixed with txn_)
campaign
object
required
Event campaign information
attendee
object
required
Information about the person attending the event
purchaser
object
required
Information about the person who purchased the ticket (may differ from attendee)
checked_in
boolean
required
Whether the attendee has checked in to the event
checked_in_at
string
ISO 8601 timestamp when attendee checked in (null if not checked in)
custom_fields
object
Custom field responses collected during ticket purchase
created_at
string
required
ISO 8601 timestamp when the ticket was purchased
updated_at
string
required
ISO 8601 timestamp when the ticket was last updated

Common Use Cases

Email tickets and event details to attendees:
async function handleTicketPurchased(event) {
  const { attendee, ticket_type_name, campaign, order_id } = event.data;

  await sendEmail({
    to: attendee.email,
    subject: `Your ticket for ${campaign.title}`,
    template: 'ticket-confirmation',
    data: {
      attendee_name: `${attendee.first_name} ${attendee.last_name}`,
      event_name: campaign.title,
      event_date: campaign.event_date,
      event_location: campaign.event_location,
      ticket_type: ticket_type_name,
      order_id: order_id,
      qr_code_url: await generateQRCode(event.data.id)
    }
  });
}
Sync ticket purchases to your event management platform:
async function handleTicketPurchased(event) {
  const { id, attendee, ticket_type_name, campaign, custom_fields } = event.data;

  await eventPlatform.addAttendee({
    ticket_id: id,
    event_id: campaign.id,
    first_name: attendee.first_name,
    last_name: attendee.last_name,
    email: attendee.email,
    phone: attendee.phone,
    ticket_type: ticket_type_name,
    dietary_restrictions: custom_fields.dietary_restrictions,
    t_shirt_size: custom_fields.t_shirt_size
  });
}
Track ticket sales and notify when capacity thresholds are reached:
async function handleTicketPurchased(event) {
  const { campaign, ticket_type_id } = event.data;

  const ticketsSold = await getTicketsSold(campaign.id, ticket_type_id);
  const capacity = await getTicketCapacity(ticket_type_id);
  const percentSold = (ticketsSold / capacity) * 100;

  // Alert at milestones
  if (percentSold >= 90) {
    await sendAlert({
      channel: '#events',
      message: `⚠️ ${campaign.title} is ${percentSold.toFixed(0)}% sold out!`,
      remaining: capacity - ticketsSold
    });
  }
}
Schedule pre-event reminders for attendees:
async function handleTicketPurchased(event) {
  const { id, attendee, campaign } = event.data;
  const eventDate = new Date(campaign.event_date);

  // Schedule reminders
  await scheduler.scheduleEmails([
    {
      to: attendee.email,
      template: 'event-reminder-1-week',
      send_at: new Date(eventDate.getTime() - 7 * 24 * 60 * 60 * 1000),
      data: { event_name: campaign.title, days_until: 7 }
    },
    {
      to: attendee.email,
      template: 'event-reminder-1-day',
      send_at: new Date(eventDate.getTime() - 24 * 60 * 60 * 1000),
      data: { event_name: campaign.title, event_location: campaign.event_location }
    }
  ]);
}
Create printable badges or QR codes for event check-in:
async function handleTicketPurchased(event) {
  const { id, attendee, ticket_type_name, campaign } = event.data;

  // Generate badge
  const badge = await badgeGenerator.create({
    attendee_name: `${attendee.first_name} ${attendee.last_name}`,
    event_name: campaign.title,
    ticket_type: ticket_type_name,
    qr_code: id,
    custom_fields: event.data.custom_fields
  });

  // Store for check-in app
  await storage.saveBadge(id, badge);
}

Ticket Types

Common ticket type names you might encounter:
  • General Admission
  • VIP / Premium
  • Early Bird
  • Student
  • Group / Table
  • Complimentary
  • Sponsor