Skip to main content

Overview

The Tickets API handles ticket booking for both free and paid events, including registration management, ticket transfers, and QR code generation for event check-in.

Book Event Ticket

Purchase tickets for a paid event.
import { bookEventTicket } from '@/app/actions/tickets';

const result = await bookEventTicket({
  eventId: 'evt_abc123',
  tickets: [
    {
      ticketId: 'tkt_early_bird',
      quantity: 2
    },
    {
      ticketId: 'tkt_vip',
      quantity: 1
    }
  ]
});

Parameters

eventId
string
required
ID of the event to book tickets for
tickets
array
required
Array of ticket selections. Each item contains:
  • ticketId (string): ID of the ticket type
  • quantity (number): Number of tickets to book (minimum 1)

Response

success
boolean
Whether the booking was successful
error
string
Error message if booking failed

Example Response

{
  "success": true
}

How Ticket Booking Works

1

Authentication Check

User must be authenticated to book tickets.
2

Ticket Validation

System validates:
  • Event exists and is active
  • All ticket IDs belong to the event
  • Sufficient tickets are available
  • Ticket quantities are valid (≥ 1)
3

Availability Check

For each ticket type, the system checks:
const totalPurchased = // Sum of all purchased tickets
const remaining = availabilityQuantity - totalPurchased;

if (quantity > remaining) {
  return { error: "Not enough tickets available" };
}
4

Batch Insert

Tickets are created using a single batch insert for performance:
// Create all tickets in one database operation
const purchasedTickets = await db
  .insert(tables.purchased_tickets)
  .values(purchasedTicketValues)
  .returning({ id: tables.purchased_tickets.id });
5

Confirmation Email

System sends a confirmation email with:
  • Event details
  • Ticket information
  • QR code for check-in
  • Calendar invite
6

Queue Counter Update

If event has queue management enabled, the counter is decremented.

Register for Free Event

Register for a free event without payment.
import { registerForFreeEvent } from '@/app/actions/tickets';

const result = await registerForFreeEvent({
  eventId: 'evt_abc123'
});

Parameters

eventId
string
required
ID of the free event to register for

Response

success
boolean
Whether registration was successful
alreadyRegistered
boolean
True if user was already registered for this event
error
string
Error message if registration failed

Validation

Free Events Only: This endpoint only works for events with pricing: FREE. For paid events, use bookEventTicket() instead.
if (event.pricing !== EventPricing.FREE) {
  return { error: "This event requires ticket purchase" };
}

Check Event Registration

Check if the current user is registered for an event.
import { checkEventRegistration } from '@/app/actions/tickets';

const result = await checkEventRegistration('evt_abc123');

if (result.isRegistered) {
  console.log('User is already registered');
}

Parameters

eventId
string
required
ID of the event to check

Response

isRegistered
boolean
True if user is registered, false otherwise

Transfer Ticket

Transfer a purchased ticket to another user.
import { transferTicket } from '@/app/actions/tickets';

const result = await transferTicket({
  purchasedTicketId: 'ptkt_abc123',
  recipientEmail: '[email protected]'
});

Parameters

purchasedTicketId
string
required
ID of the purchased ticket to transfer
recipientEmail
string
required
Email address of the recipient (must be a registered user)

Response

success
boolean
Whether transfer was successful
recipientId
string
User ID of the recipient
error
string
Error message if transfer failed

Transfer Validation Rules

Ticket transfers are subject to several validation rules:
Only the ticket owner can initiate a transfer:
if (purchasedTicket.userId !== user.id) {
  return { error: "You don't have permission to transfer this ticket" };
}
  • Recipient must have an EventPalour account
  • Cannot transfer to yourself
  • Recipient must not already be registered for the event
if (recipient.id === user.id) {
  return { error: "You cannot transfer a ticket to yourself" };
}
Tickets can only be transferred if they are:
  • Not already used (scanned at event)
  • Not cancelled
  • Not refunded
  • Not previously transferred
const invalidStatuses = [
  TicketStatus.CANCELLED,
  TicketStatus.REFUNDED,
  TicketStatus.TRANSFERRED
];

if (ticket.used || invalidStatuses.includes(ticket.status)) {
  return { error: "This ticket cannot be transferred" };
}
Each ticket can only be transferred once:
const existingTransfer = await db.query.ticket_transfers.findFirst({
  where: eq(tables.ticket_transfers.purchased_ticket_id, ticketId)
});

if (existingTransfer) {
  return { error: "This ticket has already been transferred" };
}

Transfer Process

When a ticket is transferred:
1

Transfer Record Created

A record is created in the ticket_transfers table tracking:
  • Original owner ID
  • New owner ID
  • Transfer timestamp
2

Ownership Updated

The purchased ticket record is updated:
await db.update(tables.purchased_tickets).set({
  user_id: recipient.id,
  status: TicketStatus.TRANSFERRED,
  updated_at: new Date()
});
3

Notification Sent

The recipient receives an email with:
  • Transfer details
  • Event information
  • New QR code for check-in
  • Sender information

Ticket Statuses

Tickets progress through various statuses:
enum TicketStatus {
  AVAILABLE = "available",   // Available for purchase
  RESERVED = "reserved",     // Temporarily held during checkout
  SOLD = "sold",             // Successfully purchased
  CANCELLED = "cancelled",   // Booking cancelled
  REFUNDED = "refunded",     // Payment refunded
  TRANSFERRED = "transferred", // Transferred to another user
  USED = "used",             // Scanned/redeemed at event
  EXPIRED = "expired",       // Validity period expired
  ON_HOLD = "on_hold"        // Admin hold
}

QR Code Check-In

Each purchased ticket includes a unique QR code for event check-in:
QR codes encode the purchased ticket ID:
const qrCodeData = {
  purchasedTicketId: 'ptkt_abc123',
  eventShortId: 'xyz789',
  userId: 'usr_def456'
};
Organizers scan the QR code to verify and mark tickets as used.

Error Handling

Common ticket booking errors:
ErrorCauseSolution
"Authentication required"User not signed inSign in before booking
"Event not found"Invalid event IDVerify event exists
"Invalid ticket"Ticket doesn’t belong to eventCheck ticket ID
"Not enough tickets available"Sold outChoose different ticket type or quantity
"This event requires ticket purchase"Called registerForFreeEvent on paid eventUse bookEventTicket instead
"Recipient not found"Transfer to non-existent userRecipient must create account first
"This ticket has already been transferred"Double transfer attemptTicket can only be transferred once

Complete Booking Example

Booking multiple ticket types with error handling:
import { bookEventTicket } from '@/app/actions/tickets';
import { EventPricing } from '@/lib/db/schema/enums';

async function bookTickets(eventId: string, event: Event) {
  // Check if event is free or paid
  if (event.pricing === EventPricing.FREE) {
    const result = await registerForFreeEvent({ eventId });
    
    if (result.alreadyRegistered) {
      console.log('Already registered for this event');
      return;
    }
    
    if (!result.success) {
      console.error('Registration failed:', result.error);
      return;
    }
    
    console.log('Successfully registered!');
    return;
  }
  
  // For paid events
  const result = await bookEventTicket({
    eventId,
    tickets: [
      { ticketId: 'tkt_early_bird', quantity: 2 },
      { ticketId: 'tkt_vip', quantity: 1 }
    ]
  });
  
  if (!result.success) {
    console.error('Booking failed:', result.error);
    
    // Handle specific error cases
    if (result.error?.includes('not enough')) {
      console.log('Tickets sold out, try different type');
    }
    return;
  }
  
  console.log('Tickets booked successfully!');
  console.log('Check your email for confirmation and QR codes');
}

Next Steps

Payments API

Process ticket payments

Events API

Manage event details

Ticketing Features

Learn about ticket management

Attendee Management

Check in attendees at events

Build docs developers (and LLMs) love