The customer events API at /client/events/* is what an event-attendee app calls — browse events, buy tickets, transfer them, check in, and access session content. It's separate from the CRM events module, which handles internal appointment scheduling and service-queue flows. This module is for customer-facing ticketed events.
Browse events
/client/eventsJWT/client/events/:eventIdJWT/client/events/:eventId/ticket-typesJWT/client/events/:eventId/sessionsJWT/client/events/:eventId/scheduleJWTStandard browse. ticket-types returns available tiers (general, VIP, early bird) with pricing and availability. sessions and schedule cover multi-session events (conferences) — sessions are individual talks/workshops within an event.
Ticket purchase
/client/events/tickets/purchaseJWT/client/events/tickets/confirm-orderJWTTwo-step flow. purchase creates a pending ticket order and a payment intent. confirm-order finalises after payment succeeds.
// Step 1: create order
const { orderId, paymentIntentSecret } = await fetch(
'/api/client/events/tickets/purchase',
{
method: 'POST',
headers: { orgid: ORG_ID, Authorization: `Bearer ${customerJwt}` },
body: JSON.stringify({
eventId: 'evt-spring-2026',
tickets: [
{ ticketTypeId: 'tt-vip', quantity: 2 },
],
}),
},
).then(r => r.json());
// Step 2: confirm payment with Stripe Elements
// Step 3: confirm order
await fetch('/api/client/events/tickets/confirm-order', {
method: 'POST',
headers: { orgid: ORG_ID, Authorization: `Bearer ${customerJwt}` },
body: JSON.stringify({ orderId }),
});
Stripe / checkout
/client/events/stripe/configJWT/client/events/stripe/intentJWT/client/events/stripe/checkout-sessionJWTThe events module uses Stripe directly for ticket payments rather than going through the storefront. stripe/config returns the publishable key for client-side init. stripe/intent is the embedded-Elements path; stripe/checkout-session is the hosted-checkout path.
My tickets
/client/events/tickets/mineJWT/client/events/tickets/:ticketIdJWT/client/events/tickets/:ticketId/qrJWT/client/events/tickets/:ticketId/perksJWTtickets/mine returns every ticket the customer owns across all events. qr returns the QR code for entry — what the customer shows at the door. perks returns ticket-tier-specific benefits (VIP lounge access, free drink voucher).
Transfer a ticket
/client/events/tickets/:ticketId/transferJWTTransfer the ticket to another email. The recipient receives a claim email; once claimed, the ticket moves to their account. Transfers don't refund — money stays with the original buyer.
Registration
/client/events/tickets/registerJWTFor free events or RSVPs without payment. Creates a ticket in confirmed state without going through the payment flow.
Bookings
/client/events/bookingJWTReturns the customer's reservations across all events — used for an "upcoming events" dashboard widget.
Sessions and participation
/client/events/:eventId/participantsJWT/client/events/participation/mineJWT/client/events/participation/:participantId/respondJWTFor multi-session events, customers select which sessions they'll attend. participation/mine returns the customer's session selections; respond accepts/declines an organiser-issued participation invite.
Media
/client/events/:eventId/mediaJWT/client/events/:eventId/media/guest/:guestIdJWT/client/events/:eventId/media/uploadJWT/client/events/:eventId/media/upload/:guestIdJWTEvent galleries — attendees upload photos, view others'. The guest/:guestId variant lets non-account holders upload via an invite token (used for wedding photos and similar).
Check-in
Check-in happens through the staff side — POST /events/check-in/:ticketId (see standalone events module). Customers check in by showing the QR code; the staff scanner calls the staff endpoint. Customers don't have a self-service check-in endpoint to prevent ticket fraud.
Tickets are first-class records in the data layer. After purchase, they live in the ticket collection with the customer's sk as the owner. Custom logic (post-event surveys, badge issuance) wires through the Automation module listening for ticket events.