Skip to content

# Ticketed Events

Create and manage events with paid, free, or donation-based tickets at `/app/events`.

## Creating an Event

Click Create Event to open the event drawer. Required fields are marked with an asterisk.

Field | Purpose
--- | ---
Title | Event name (also used to generate the public slug)
Description | Shown on the public event page
Date / Start Time / End Time | Required — used for timezone-aware display and calendar exports
Doors Open Time | Optional — shown to attendees separately from start time
Event Format | `In-Person`, `Online`, or `Hybrid`. Online/Hybrid prompts for a Jitsi Meet link
Venue Name / Address | In-Person or Hybrid events only
Visibility | `PUBLIC` (listed), `UNLISTED` (direct link only), `PRIVATE` (invite-code gated)
Max Attendees | Hard cap across all tiers — leave blank for unlimited
Organizer Name | Shown on the public page under "Organized by…"

Events start in `DRAFT` status and are not publicly visible until you publish them.

## Ticket Tiers

Every event needs at least one ticket tier before it can be published. Tiers support three types:

Type | Behavior
--- | ---
`PAID` | Fixed price, Stripe checkout required. Payments module must be enabled.
`FREE` | No payment, email-only registration
`DONATION` | Suggested price, but attendees can enter any amount ≥ $1

Each tier has a name (e.g. "General Admission", "Student", "VIP"), price in CAD (stored in cents at the API — the admin UI accepts dollars), max quantity, and max per order. Tiers are sorted by `sortOrder` on the public page.

The Tier Breakdown panel on the event detail page shows sold/remaining counts per tier in real time.

Paid tiers require Stripe

Paid tiers only work when the Payments module is enabled and Stripe API keys are configured in Admin → Payments → Settings. If Stripe isn't configured, the public checkout button won't work.

## Publishing

From the event detail page, click Publish to move the event from `DRAFT` to `PUBLISHED`:

- A public URL is generated at `/event/{slug}` (the slug is auto-derived from the title)
- The event appears on `/events` if visibility is `PUBLIC`
- Tickets become purchasable
- Attendees can start registering

Use the Copy Link button in the Actions row to grab the public URL for social media or email campaigns.

## Event Statuses and Actions

Status | Available Actions
--- | ---
`DRAFT` | Edit, Publish, Delete
`PENDING_APPROVAL` | Approve, Reject (admin only)
`PUBLISHED` | Edit (restricted), Cancel, Mark Completed, Check-in Scanner
`CANCELLED` | View only
`COMPLETED` | View stats, export

Cancelling a published event marks all existing tickets as cancelled and triggers refund processing for paid tickets (if Stripe is configured).

## Attendee Management

The event detail page includes two tabs:

- Tickets — all issued tickets with holder name, email, tier, status, and purchase timestamp. You can resend the ticket email or cancel an individual ticket from the Actions column.
- Check-ins — chronological record of check-in events recorded by the Check-in Scanner.

Admins and event owners can filter, search, and export ticket lists for at-the-door lookup or post-event reporting.

## Public Event Page

The public-facing page at `/event/:slug` shows the event details and lets attendees pick a tier and register:

- Paid tiers link to Stripe Checkout
- Free tiers use a simple email-only form
- Donation tiers prompt for a custom amount
- After purchase, attendees receive an email with their ticket code and QR

## Admin Routes

- `/app/events` — event list, search, filter by status
- `/app/events/:id` — event detail, tier management, ticket list, check-ins
- `/app/events/:id/checkin` — full-screen Check-in Scanner

## Related

- Check-in Scanner — QR and manual check-in at the door
- Payments Settings — Stripe configuration required for paid tiers
- Video Meet (Jitsi) — used for Online and Hybrid event formats