Skip to main content

Event Booking Orders API

Event Booking Orders API Documentation

Author: Josh,Josh S. Sakweli, Backend Lead Backend Team
Last Updated: 2025-12-11
2026-05-23 Version: v1.0

Base URL: https://api.nexgate.com/api/v1

Short Description: The Event Booking Orders API provides comprehensive booking management functionality formanages confirmed event ticket purchases infor events on the Nexgate platform. ThisIt APIallows enables userscustomers to view their bookingbookings details includingwith JWT-signed QR codes for secure event entry,codes, track multi-day event check-ins, retrieve complete bookingin history, download ticket PDFs, and accessenables event snapshotsorganizers atto timemonitor ofall booking.orders Thefor system supports both single-day and multi-daytheir events with per-day check-in tracking, automated ticket series generation,filtering and comprehensiverevenue booking references.stats.

Hints:

  • Auto-Creation:Bookings Bookingsare created automatically after successful checkout payment — never created directly via this API
  • JWT Security: QR codes are RSA-signed JWTs containing full ticket and event datadata; they cannot be forged
  • Multi-Day Support: Full support for multi-day events with per-day check-in tracking
  • Ticket Series: Auto-generated unique series (e.g., "VIP-0001", "GENER-0042")
  • Event Snapshots: Event details captured(title, venue, organizer) are snapshotted at booking time (immutable)and never change on a booking record
  • BookingTicket Reference:series Shortare readable codesauto-generated (e.g., "EVT-2025-A3F4"VIP-0001, GENER-0042) using a per-ticket-type counter
  • Check-InMulti-day Tracking:events Completestore historya withfull location,checkIns staff,array andper ticket — one record per day informationattended
  • Access Control: Customers see their own bookings,bookings only; organizers see eventbookings bookings,for their events; admins see all
  • NotificationThe Integration:PDF Auto-emailsendpoint ticketsreturns toa buyerbinary andfile, optionallynot toa attendees
  • JSON
  • Virtual Events: Includes virtual meeting links for online/hybrid events
  • Attendee Management: Track tickets for buyer and other attendees separatelyresponse

Standard Response Format

All APIJSON responsesendpoints follow a consistent structure using ourthe Globe Response Builder pattern:

Success Response Structure

{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-12-11T10:2026-05-23T10:30:45",
  "data": {
    // Actual response data goes here
  }
}

Error Response Structure

{
  "success": false,
  "httpStatus": "BAD_REQUEST"NOT_FOUND",
  "message": "ErrorBooking description"not found",
  "action_time": "2025-12-11T10:2026-05-23T10:30:45",
  "data": "ErrorBooking description"not found"
}

Standard Response Fields

FieldTypeDescription
successbooleantrue for successful operations, false for errors
httpStatusstringHTTP status name (OK, NOT_FOUND, FORBIDDEN, etc.)
messagestringHuman-readable description of the result
action_timestringISO 8601 timestamp of when the response was generated
dataobject/stringResponse payload on success; error message string on failure

HTTP Method Badge Standards

  • GET - GET - Green (ReadSafe, read-only operations)
  • POST - POST - Blue (Create new resources)
  • PUT - PUT - Yellow (Update/replace entire resource)
  • PATCH - PATCH - Orange (Partial updates)
  • DELETE - DELETE - Red (Remove resources)

BookingOrderResponseEndpoints

Structure

1. Get Booking by ID

ThisPurpose: isRetrieve the comprehensive response structure returned bycomplete booking endpoints:details including all tickets, check-in history, and event snapshot for a specific booking.

Endpoint: GET {base_url}/e-events/booking-orders/{bookingId}

Access Level: 🔒 Protected (Booking Owner, Event Organizer, or Admin)

Authentication: Bearer Token

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token (format: Bearer <token>)

Path Parameters:

ParameterTypeRequiredDescriptionValidation
bookingIdstring (UUID)YesUnique booking order IDMust be valid UUID

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Booking retrieved successfully",
  "action_time": "2026-05-23T10:30:45",
  "data": {
    "bookingId": "550e8400-e29b-41d4-a716-446655440000",
    "bookingReference": "EVT-A3F4B21C",
    "status": "CONFIRMED",
    "event": {
      "eventId": "770e8400-e29b-41d4-a716-446655440002",
      "title": "East African Tech Summit 2025",
      "startDateTime": "2025-12-15T09:00:00",
      "endDateTime": "2025-12-17T18:00:00",
      "timezone": "Africa/Nairobi",
      "location": "KICC Nairobi, Harambee Avenue, Nairobi",
      "format": "HYBRID",
      "virtualDetails": {
        "platform": "ZOOM",
        "meetingUrl": "https://zoom.us/j/123456789",
        "meetingId": "123 456 789",
        "passcode": "summit2025",
        "additionalInstructions": "Join 5 minutes early for networking"
      }
    },
    "organizer": {
      "name": "TechEvents Kenya",
      "email": "organizer@techevents.ke",
      "phone": "+254712345678"
    },
    "customer": {
      "customerId": "660e8400-e29b-41d4-a716-446655440001",
      "name": "johndoe",
      "email": "john@example.com"
    },
    "tickets": [
      {
        "ticketInstanceId": "880e8400-e29b-41d4-a716-446655440010",
        "ticketTypeName": "VIP Pass",
        "ticketSeries": "VIP-0001",
        "ticketNumber": "VIP-0001",
        "price": 150.00,
        "qrCode": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
        "attendanceMode": "IN_PERSON",
        "attendee": {
          "name": "John Doe",
          "email": "john@example.com",
          "phone": "+255712345678"
        },
        "buyer": {
          "name": "John Doe",
          "email": "john@example.com",
          "buyerType": "SYSTEM_USER"
        },
        "checkIns": [
          {
            "checkInTime": "2025-12-15T09:15:00+03:00",
            "checkInLocation": "Main Gate",
            "checkedInBy": "Scanner Operator 1",
            "dayName": "Day 1 - Opening Day",
            "scannerId": "SCANNER-001",
            "checkInMethod": "QR_SCAN"
          },
          {
            "checkInTime": "2025-12-16T08:45:00+03:00",
            "checkInLocation": "VIP Entrance",
            "checkedInBy": "Scanner Operator 2",
            "dayName": "Day 2 - Conference Day",
            "scannerId": "SCANNER-003",
            "checkInMethod": "QR_SCAN"
          }
        ],
        "hasBeenCheckedIn": true,
        "lastCheckedInAt": "2025-12-16T08:45:00+03:00",
        "lastCheckedInBy": "Scanner Operator 2",
        "lastCheckInLocation": "VIP Entrance",
        "lastCheckInDayName": "Day 2 - Conference Day",
        "status": "USED",
        "validFrom": "2025-12-15T09:00:00+03:00",
        "validUntil": "2025-12-17T18:00:00+03:00"
      },
      {
        "ticketInstanceId": "880e8400-e29b-41d4-a716-446655440011",
        "ticketTypeName": "General Admission",
        "ticketSeries": "GENER-0042",
        "ticketNumber": "GENER-0042",
        "price": 50.00,
        "qrCode": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
        "attendanceMode": "IN_PERSON",
        "attendee": {
          "name": "Jane Smith",
          "email": "jane@example.com",
          "phone": "+255723456789"
        },
        "buyer": {
          "name": "John Doe",
          "email": "john@example.com",
          "buyerType": "SYSTEM_USER"
        },
        "checkIns": [],
        "hasBeenCheckedIn": false,
      "lastCheckedInAt": null,
      "lastCheckedInBy": null,
      "lastCheckInLocation": null,
      "lastCheckInDayName": null,
        "status": "ACTIVE",
        "validFrom": "2025-12-15T09:00:00+03:00",
        "validUntil": "2025-12-17T18:00:00+03:00"
      }
    ],
    "totalTickets": 2,
    "checkedInTicketsCount": 1,
    "subtotal": 200.00,
    "total": 200.00,
    "bookedAt": "2025-12-11T10:30:45",
    "cancelledAt": null
  }
}

Success Response Field Descriptions

Root Level Fields

:

IN_PERSON,VirtualZOOM, ticketsin
FieldType Description
bookingIdstring (UUID) Unique booking identifierUUID
bookingReferencestring Short readable code (e.g., "EVT-A3F4B21C"A3F4B21C)
statusenum Booking status: CONFIRMED,CONFIRMED, CANCELLED
eventobjectevent.eventId Event snapshotUUID
event.titleEvent title at time of booking (immutable snapshot)
event.startDateTimeEvent start — LocalDateTime (no timezone)
event.endDateTimeEvent end — LocalDateTime (no timezone)
event.timezoneIANA timezone string (e.g., Africa/Nairobi)
event.locationFull venue address snapshotted at booking
organizerevent.format object OrganizerONLINE, detailsor snapshotHYBRID
customerevent.virtualDetails object Customermeeting (buyer)info information— only present for ONLINE/HYBRID events
ticketsevent.virtualDetails.platform array ListGOOGLE_MEET, ofMS_TEAMS, allor booked tickets with check-in historyCUSTOM
totalTicketsevent.virtualDetails.meetingUrl integerFull meeting URL
event.virtualDetails.meetingId TotalMeeting numberID of(optional)
event.virtualDetails.passcodeMeeting passcode (optional)
organizer.nameOrganizer name snapshotted at booking
checkedInTicketsCountorganizer.email integerOrganizer email
organizer.phoneOrganizer phone
customer.customerIdCustomer account UUID
customer.nameCustomer username
customer.emailCustomer email
ticketsArray of all booked ticket instances
tickets[].ticketInstanceIdUnique ticket instance UUID
tickets[].ticketTypeNameTicket type name (e.g., VIP Pass)
tickets[].ticketSeriesAuto-generated series (e.g., VIP-0001)
tickets[].ticketNumberSame as ticketSeries — used for PDF labeling
tickets[].pricePrice paid for this ticket
tickets[].qrCodeRSA-signed JWT — used for gate check-in scanning
tickets[].attendanceModeIN_PERSON or ONLINE (relevant for hybrid events)
tickets[].attendeePerson this ticket is for
tickets[].attendee.nameAttendee full name
tickets[].attendee.emailAttendee email
tickets[].attendee.phoneAttendee phone
tickets[].buyerPerson who purchased this ticket
tickets[].buyer.nameBuyer name
tickets[].buyer.emailBuyer email (null for AT_DOOR purchases)
tickets[].buyer.buyerTypeSYSTEM_USER (online) or AT_DOOR (sold at gate)
tickets[].checkInsFull check-in history — one record per day attended
tickets[].checkIns[].checkInTimeZonedDateTime of check-in
tickets[].checkIns[].checkInLocationWhere checked in (e.g., Main Gate, VIP Entrance)
tickets[].checkIns[].checkedInByStaff/scanner operator name
tickets[].checkIns[].dayNameEvent day label (e.g., Day 1 - Opening Day)
tickets[].checkIns[].scannerIdScanner device ID
tickets[].checkIns[].checkInMethodQR_SCAN (default), MANUAL, or NFC
tickets[].hasBeenCheckedIntrue if ticket has at least one check-in
tickets[].lastCheckedInAtMost recent check-in time (ZonedDateTime, null if none)
tickets[].lastCheckedInByWho performed the most recent check-in (null if none)
tickets[].lastCheckInLocationLocation of most recent check-in (null if none)
tickets[].lastCheckInDayNameDay label of most recent check-in (null if none)
tickets[].statusACTIVE, USED, or CANCELLED
tickets[].validFromTicket validity start — ZonedDateTime
tickets[].validUntilTicket validity end — ZonedDateTime
totalTicketsTotal ticket count in this booking
checkedInTicketsCount Count of tickets with at least one check-in
subtotaldecimal Subtotal amountbefore any deductions
totaldecimal Total amount paid
bookedAtstring (LocalDateTime) When the booking was created — LocalDateTime
cancelledAtstring (LocalDateTime) When bookingcancelled was cancelledLocalDateTime (null if still active)

Event Snapshot Object

FieldTypeDescription
eventIdstring (UUID)Event identifier
titlestringEvent title at time of booking
startDateTimestring (LocalDateTime)Event start date/time
endDateTimestring (LocalDateTime)Event end date/time
timezonestringIANA timezone (e.g., "Africa/Nairobi")
locationstringFull venue location (name + address)
formatstringEvent format: IN_PERSON, ONLINE, HYBRID
virtualDetailsobjectVirtual meeting details (for ONLINE/HYBRID)

Virtual Details Object

FieldTypeDescription
platformstringPlatform: ZOOM, GOOGLE_MEET, MS_TEAMS, CUSTOM
meetingUrlstringFull meeting URL
meetingIdstringMeeting ID (optional)
passcodestringMeeting passcode (optional)
additionalInstructionsstringExtra instructions (optional)

Organizer Snapshot Object

FieldTypeDescription
namestringOrganizer name at time of booking
emailstringOrganizer email
phonestringOrganizer phone

Customer Info Object

FieldTypeDescription
customerIdstring (UUID)Customer account ID
namestringCustomer username
emailstringCustomer email

Booked Ticket Response Object

FieldTypeDescription
ticketInstanceIdstring (UUID)Unique ticket instance ID
ticketTypeNamestringTicket type name (e.g., "VIP Pass")
ticketSeriesstringAuto-generated series (e.g., "VIP-0001")
pricedecimalTicket price
qrCodestringJWT-signed QR code (very long string)
attendanceModestringIN_PERSON or ONLINE (for hybrid events)
attendeeobjectAttendee information
buyerobjectBuyer information (who paid)
checkInsarrayComplete check-in history (all days)
hasBeenCheckedInbooleanTrue if checked in at least once
lastCheckedInAtstring (ZonedDateTime)Most recent check-in time
lastCheckedInBystringWho performed last check-in
lastCheckInLocationstringLocation of last check-in
lastCheckInDayNamestringDay name of last check-in
statusenumACTIVE, USED, CANCELLED
validFromstring (ZonedDateTime)Ticket valid from
validUntilstring (ZonedDateTime)Ticket valid until

Attendee/Buyer Info Object

FieldTypeDescription
namestringPerson's name
emailstringPerson's email
phonestringPerson's phone (attendee only)

Check-In Record Object

FieldTypeDescription
checkInTimestring (ZonedDateTime)When check-in occurred
checkInLocationstringWhere (e.g., "Main Gate", "VIP Entrance")
checkedInBystringStaff/scanner operator name
dayNamestringEvent day (e.g., "Day 1", "Day 2 - Saturday")
scannerIdstringScanner device ID
checkInMethodstringMethod: QR_SCAN (default), MANUAL, NFC

BookingOrderSummaryResponse Structure

Lightweight response for listing bookings:

{
  "bookingId": "550e8400-e29b-41d4-a716-446655440000",
  "bookingReference": "EVT-A3F4B21C",
  "status": "CONFIRMED",
  "eventTitle": "East African Tech Summit 2025",
  "eventStartDateTime": "2025-12-15T09:00:00",
  "eventLocation": "KICC Nairobi, Harambee Avenue, Nairobi",
  "totalTickets": 2,
  "checkedInTickets": 1,
  "total": 200.00,
  "bookedAt": "2025-12-11T10:30:45"
}

Endpoints

1. Get Booking by ID

Purpose: Retrieve complete booking details including all tickets and check-in history

Endpoint: GET {base_url}/e-events/booking-orders/{bookingId}

Access Level: 🔒 Protected (Booking Owner, Event Organizer, or Admin)

Authentication: Bearer Token

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token (format: Bearer <token>)

Path Parameters:

ParameterTypeRequiredDescription
bookingIdstring (UUID)YesBooking order ID

Success Response: Returns complete BookingOrderResponse structure

Success Response Message: "Booking retrieved successfully"

HTTP Status Code: 200 OK

Access Rules:

  • Customers: Can view their own bookings
  • Organizers: Can view bookings for their events
  • Admins (SUPER_ADMIN, STAFF_ADMIN): Can view any booking

Behavior:

  • Returns complete booking details with all tickets
  • Includes event snapshot (as it was at booking time)
  • Shows full check-in history for multi-day events
  • Includes JWT-signed QR codes for all tickets
  • Virtual details included for ONLINE/HYBRID events

Use Cases:

  • Customer viewing booking confirmation
  • Customer retrieving QR codes for event entry
  • Organizer checking booking details
  • Admin reviewing booking for support

Standard Error Types:

  • 401 UNAUTHORIZED: Authentication issues
  • 403 FORBIDDEN: User doesn't have permission to view this booking
  • 404 NOT_FOUND: Booking not found

Error Response ExamplesJSON Sample:

Booking Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Booking not found: 550e8400-e29b-41d4-a716-446655440000",
  "action_time": "2025-12-11T10:2026-05-23T10:30:45",
  "data": "Booking not found: 550e8400-e29b-41d4-a716-446655440000"
}

AccessStandard DeniedError (403)Types:

  • {401 "success"UNAUTHORIZED: false,Missing "httpStatus"or expired Bearer token
  • 403 FORBIDDEN: "FORBIDDEN",Authenticated "message"user is not the booking owner, event organizer, or admin
  • 404 NOT_FOUND: "YouBooking don'twith havegiven permissionID todoes viewnot thisexist
  • booking", "action_time": "2025-12-11T10:30:45", "data": "You don't have permission to view this booking" }

2. Get My Bookings

Purpose: Retrieve a summary list of all bookings for the authenticated useruser, sorted newest first.

Endpoint: GET {base_url}/e-events/booking-orders/my-bookings

Access Level: 🔒 Protected (Authenticated Users)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token (format: Bearer <token>)

Success Response: Returns array of BookingOrderSummaryResponse

Success Response Message: "Bookings retrieved successfully"

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Bookings retrieved successfully",
  "action_time": "2025-12-11T10:2026-05-23T10:30:45",
  "data": [
    {
      "bookingId": "550e8400-e29b-41d4-a716-446655440000",
      "bookingReference": "EVT-A3F4B21C",
      "status": "CONFIRMED",
      "eventTitle": "East African Tech Summit 2025",
      "eventStartDateTime": "2025-12-15T09:00:00",
      "eventLocation": "KICC Nairobi, Harambee Avenue, Nairobi",
      "totalTickets": 2,
      "checkedInTickets": 1,
      "total": 200.00,
      "bookedAt": "2025-12-11T10:30:45"
    },
    {
      "bookingId": "550e8400-e29b-41d4-a716-446655440001",
      "bookingReference": "EVT-B5D2E12F",
      "status": "CONFIRMED",
      "eventTitle": "Dar es Salaam Food Festival",
      "eventStartDateTime": "2025-12-20T11:00:00",
      "eventLocation": "Mlimani City, Sam Nujoma Road, Dar es Salaam",
      "totalTickets": 4,
      "checkedInTickets": 0,
      "total": 150.00,
      "bookedAt": "2025-12-10T14:20:30"
    }
  ]
}

HTTPSuccess StatusResponse Code: 200 OK

Sorting: Bookings sorted by bookedAt descending (newest first)

BehaviorFields:

  • Returns
  • lightweightsummaryforalluser'sbookings
  • Sorted
  • newestfirst progress(checkedInTickets/totalTickets)andpastevents
    Field Description
    bookingId Unique
  • Includesbooking UUID
  • bookingReferenceShort readable code (e.g., EVT-A3F4B21C)
    statusCONFIRMED or CANCELLED
    eventTitleEvent title snapshotted at booking time
    eventStartDateTimeEvent start date/time — LocalDateTime (no timezone)
    eventLocationVenue address snapshotted at booking time
    totalTicketsTotal number of tickets in this booking
    checkedInTicketsNumber of tickets with at least one check-in
    total Total
  • Showsamount upcomingpaid
  • bookedAt When booking was created — LocalDateTime

    UseError CasesResponse JSON Sample:

      {
        
    • "success": false, "httpStatus": "NOT_FOUND", "message": "User viewingnot bookingfound", history
    • "action_time":
    • Dashboard"2026-05-23T10:30:45", showing"data": all"User purchases
    • not
    • Findingfound" booking} for upcoming event
    • Checking past event attendance

    Standard Error Types:

    • 401 UNAUTHORIZED: AuthenticationMissing issuesor expired Bearer token
    • 404 NOT_FOUND: UserAuthenticated user account not found/authenticatedfound

    3. Download Ticket PDF

    Purpose: Download or preview the PDF ticket PDF for a specific ticket instance belonging to the authenticated useruser.

    Endpoint: GET {base_url}/e-events/booking-orders/tickets/{ticketId}ticketInstanceId}/pdf

    Access Level: 🔒 Protected (AuthenticatedTicket Users)Owner)

    Authentication: Bearer Token


    Request Headers:

    Header Type Required Description
    Authorization string Yes Bearer token (format: Bearer <token>)

    Path Parameters:

    Parameter Type Required Description Validation
    ticketIdticketInstanceId UUIDstring (UUID) Yes The uniqueUnique ID of the ticket to downloadMust be valid UUID

    Query Parameters:

    Parameter Type Required DefaultDescription DescriptionDefault
    mode string No download Controls how the PDF is served. download forcesprompts a file save dialog.dialog; inline opens the PDF directly in the browser.browser tabdownload

    Mode Values:

    ValueContent-DispositionBehaviour
    downloadattachment; filename="ticket-{series}.pdf"Browser prompts user to save the file
    inlineinline; filename="ticket-{series}.pdf"PDF opens directly in the browser tab

    Success Response: Returns a binaryBinary PDF file (not JSON)

    Success Response Headers:

    Header Value
    Content-Type application/pdf
    Content-Disposition attachment; filename="ticket-{series}.pdf" (or inlineinline; ... dependingby on mode)mode

    HTTPPDF StatusContent Code: 200 OK


    BehaviorIncludes:

    • VerifiesEvent thename, ticketdate, belongsand to the authenticated user before generating the PDFvenue
    • GeneratesAttendee the ticket PDF on-the-fly using the event's SVG templatename
    • TheTicket PDF contains event details, attendee name, seat/series, QR code for check-in,series and ticket numbertype
    • QR code encodes a (RSA-signed JWTJWT) token used byfor gate staff to verify the ticket at entryscanning
    • FileTicket namevalidity in the Content-Disposition header uses the ticket's series (e.g. ticket-VIP-0033.pdf)period

    UseError CasesResponse JSON Sample:

      {
        
    • User"success": downloadingfalse, their"httpStatus": ticket"FORBIDDEN", after"message": booking
    • "You
    • Re-downloadingdon't ahave lost or deleted ticket
    • Saving ticketpermission to deviceaccess forthis offlineticket", "action_time": "2026-05-23T10:30:45", "data": "You don't have permission to access atthis theticket" event
    • }

    Standard Error Types:

    • 401 UNAUTHORIZED: Missing or expired Bearer token
    • 403 FORBIDDEN: Ticket does not belong to the authenticated user
    • 404 NOT_FOUND: Ticket with given ID does not exist
    • 500 INTERNAL_SERVER_ERROR: PDF generation failed

    4. Get Event Orders (Organizer)

    Purpose: Retrieve a paginated list of all booking orders for a specific event with filtering by status, buyer type, and ticket type, plus aggregated revenue and order stats.

    Endpoint: GET {base_url}/e-events/booking-orders/event/{eventId}

    Access Level: 🔒 Protected (Event Organizer or Admin)

    Authentication: Bearer Token

    Request Headers:

    orinvalid (format:Bearer
    CodeHeader TypeRequired Description
    401UNAUTHORIZEDAuthorization Missingstring Yes Bearer token
    403FORBIDDEN<token>Ticket does not belong to the authenticated user
    404NOT_FOUNDTicket with the given ID not found
    500INTERNAL_SERVER_ERRORPDF generation failed)

    Path

    Booking Status Lifecycle

    Status Descriptions

    Parameters
    :

    eventvalid
    StatusParameterTypeRequired Description Can Cancel?Tickets Valid?Validation
    CONFIRMEDeventId Booking active and tickets validFuturestring (not implemented)UUID) Yes
    Target
    CANCELLEDUUID BookingMust cancelledbe (placeholder) N/ANoUUID

    CurrentQuery ImplementationParameters:

    • All bookings created as CONFIRMED
    • Cancellation not yet implemented (status exists for future)
    • Tickets remain ACTIVE after booking until checked in

    Ticket Instance Status

    Status Lifecycle

    Check In? (for
    StatusParameterTypeRequired Description CanValidation Default
    ACTIVEstatus Ticketstring ready for use(enum) YesNoFilter by booking statusCONFIRMED, CANCELLED
    USEDbuyerType Ticketstring checked in(enum) YesNo Filter multi-day)by how the ticket was purchasedSYSTEM_USER, AT_DOOR
    CANCELLEDticketTypeId Ticketstring cancelled(UUID) NoFilter orders that include a specific ticket typeMust be valid UUID
    searchstringNoSearch by buyer name, email, or booking reference
    pageintegerNoZero-based page indexMin: 00
    sizeintegerNoNumber of orders per pageMin: 120

    Multi-DaySuccess EventsResponse JSON Sample:

    {
      "success": true,
      "httpStatus": "OK",
      "message": "Event orders retrieved",
      "action_time": "2026-05-23T10:30:45",
      "data": {
        "eventId": "770e8400-e29b-41d4-a716-446655440002",
        "eventTitle": "East African Tech Summit 2025",
        "appliedFilters": {
          "status": "CONFIRMED",
          "buyerType": null,
          "ticketTypeId": null,
          "ticketTypeName": null,
          "search": null
        },
        "stats": {
          "totalOrders": 142,
          "totalTicketsSold": 318,
          "totalRevenue": 47500.00,
          "confirmedOrders": 139,
          "cancelledOrders": 3,
          "refundedOrders": 0,
          "onlineOrders": 128,
          "atDoorOrders": 14
        },
        "orders": [
          {
            "bookingId": "550e8400-e29b-41d4-a716-446655440000",
            "bookingReference": "EVT-A3F4B21C",
            "status": "CONFIRMED",
            "bookedAt": "2025-12-11T10:30:45",
            "buyer": {
              "buyerName": "John Doe",
              "buyerEmail": "john@example.com",
              "buyerType": "SYSTEM_USER"
            },
            "totalTickets": 2,
            "checkedInCount": 1,
            "total": 200.00,
            "ticketTypes": [
              {
                "ticketTypeName": "VIP Pass",
                "quantity": 1
              },
              {
                "ticketTypeName": "General Admission",
                "quantity": 1
              }
            ]
          },
          {
            "bookingId": "550e8400-e29b-41d4-a716-446655440099",
            "bookingReference": "EVT-C7E1F34A",
            "status": "CONFIRMED",
            "bookedAt": "2025-12-10T18:15:00",
            "buyer": {
              "buyerName": "Grace Njeri",
              "buyerEmail": null,
              "buyerType": "AT_DOOR"
            },
            "totalTickets": 1,
            "checkedInCount": 1,
            "total": 50.00,
            "ticketTypes": [
              {
                "ticketTypeName": "General Admission",
                "quantity": 1
              }
            ]
          }
        ],
        "pagination": {
          "currentPage": 0,
          "pageSize": 20,
          "totalPages": 8,
          "totalElements": 142,
          "hasNext": true,
          "hasPrevious": false
        }
      }
    }
    

    Success Response Fields:

    FieldDescription
    eventIdUUID of the queried event
    eventTitleEvent title
    appliedFiltersEcho of the active filter values (null = not filtered)
    appliedFilters.statusActive booking status filter
    appliedFilters.buyerTypeActive buyer type filter
    appliedFilters.ticketTypeIdActive ticket type UUID filter
    appliedFilters.ticketTypeNameResolved name of the filtered ticket type
    appliedFilters.searchActive search string
    statsAggregated stats across ALL orders for the event (not just current page)
    stats.totalOrdersTotal booking count
    stats.totalTicketsSoldTotal individual tickets across all bookings
    stats.totalRevenueSum of all order totals
    stats.confirmedOrdersOrders with status CONFIRMED
    stats.cancelledOrdersOrders with status CANCELLED
    stats.refundedOrdersOrders with status REFUNDED
    stats.onlineOrdersOrders placed online (SYSTEM_USER buyer type)
    stats.atDoorOrdersOrders sold at the gate (AT_DOOR buyer type)
    ordersPaginated list of order rows
    orders[].bookingIdBooking UUID
    orders[].bookingReferenceShort readable code (e.g., EVT-A3F4B21C)
    orders[].statusBooking status string
    orders[].bookedAtWhen booking was created — LocalDateTime
    orders[].buyer.buyerNameBuyer's name
    orders[].buyer.buyerEmailBuyer's email (null for AT_DOOR)
    orders[].buyer.buyerTypeSYSTEM_USER or AT_DOOR
    orders[].totalTicketsNumber of tickets in this order
    orders[].checkedInCountNumber of tickets checked in at least once
    orders[].totalOrder total amount
    orders[].ticketTypesBreakdown of ticket types in this order
    orders[].ticketTypes[].ticketTypeNameName of the ticket type
    orders[].ticketTypes[].quantityHow many of this type are in the order
    pagination.currentPageZero-based current page index
    pagination.pageSizeNumber of items per page
    pagination.totalPagesTotal number of pages
    pagination.totalElementsTotal matching orders
    pagination.hasNexttrue if a next page exists
    pagination.hasPrevioustrue if a previous page exists

    Error Response JSON Sample:

    {
      "success": false,
      "httpStatus": "FORBIDDEN",
      "message": "Access denied: you are not the organizer of this event",
      "action_time": "2026-05-23T10:30:45",
      "data": "Access denied: you are not the organizer of this event"
    }
    

    Standard Error Types:

    • Ticket401 statusUNAUTHORIZED: remainsMissing ACTIVEor evenexpired afterBearer first check-intoken
    • Can403 checkFORBIDDEN: inAuthenticated multipleuser timesis (oncenot perthe day)event organizer or an admin
    • Status404 changesNOT_FOUND: toEvent USEDwith aftergiven allID expecteddoes check-ins
    • not
    • Each check-in tracked separately in checkIns arrayexist

    Ticket Series Generation

    How Ticket Series Work

    Format: {TICKET_CODE}-{COUNTER}

    The ticket code is the first 5 characters of the ticket type name (uppercased, spaces removed). The counter is a zero-padded incrementing integer per ticket type, managed with pessimistic locking to prevent duplicates.

    Examples:

    • VIP PassVIP-0001, VIP-0002, VIP-0003
    • General AdmissionGENER-0001, GENER-00020042
    • Early BirdEARLY-0001, EARLY-0002

    Ticket Code Extraction:

    1. Take first 5 characters of ticket type name
    2. Remove spaces
    3. Convert to uppercase
    4. Fallback to "TICK" if name empty

    Counter System:

    • SeparateThe counter per ticket type (stored in DB)
    • Pessimistic locking prevents duplicates
    • Counter never resets (unique forever)
    • Increments with each ticket created
    • series
    are

    Exampleglobally Flow:unique per type forever.

    Ticket Type: "VIP Pass"
    Counter: 0
    
    First Booking (3 tickets):
    - VIP-0001 (counter now 1)
    - VIP-0002 (counter now 2)
    - VIP-0003 (counter now 3)
    
    Second Booking (2 tickets):
    - VIP-0004 (counter now 4)
    - VIP-0005 (counter now 5)
    

    Why Series Numbers?

    • Easy reference for staff
    • Quick ticket identification
    • Helps track capacity sold
    • Professional appearance on PDF tickets

    JWT-Signed QR Codes

    Security

    Each Architecture

    ticket's

    WhatqrCode field is a full RSA-signed JWT (2048-bit key pair generated when the QRevent Code?is published). The JWT payload contains:

    • NotticketInstanceId, aticketTypeId, randomticketTypeName, stringticketSeries
    • FulleventId, JWTeventName, (JSON Web Token)eventStartDateTime
    • SignedattendeeName, withattendeeEmail, event'sattendeePhone, RSA private keyattendanceMode
    • Contains complete ticket and event databookingReference
    • CannoteventSchedules be forged or tampered with

    JWT Structure:

    Header.Payload.Signature
    
    eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.
    eyJ0aWNrZXRJbnN0YW5jZUlkIjoiODgw...
    [RSA signature]
    

    JWT Payload Contains:

    • ticketInstanceId (UUID)
    • ticketTypeId (UUID)
    • ticketTypeName (string)
    • ticketSeries (string)
    • eventId (UUID)
    • eventName (string)
    • eventStartDateTime (timestamp)
    • attendeeName (string)
    • attendeeEmail (string)
    • attendeePhone (string)
    • attendanceMode (IN_PERSON/ONLINE)
    • bookingReference (string)
    • eventSchedules (array of daysday objects for multi-day events)
    • validFrom (timestamp)
    • validUntil (timestamp)events:

    Multi-Day Event Schedules:

    "eventSchedules": [
      {
        "dayName": "Day 1 - Opening Day",
        "startDateTime": "2025-12-15T09:00:00+03:00",
        "endDateTime": "2025-12-15T18:00:00+03:00",
        "description": "Conference Opening & Keynotes"
      },
      {
        "dayName": "Day 2 - Conference Day",
        "startDateTime": "2025-12-16T09:00:00+03:00",
        "endDateTime": "2025-12-16T18:00:00+03:00",
        "description": "Technical Sessions & Workshops"
      },
      {
        "dayName": "Day 3 - Closing Day",
        "startDateTime": "2025-12-17T09:00:00+03:00",
        "endDateTime": "2025-12-17T18:00:00+03:00",
        "description": "Finals & Networking"
      }
    ]
    

    RSA Key Pair:

    • GeneratedvalidFrom, when event is published (2048-bit)
    • Private key: Stored securely in database (for signing)
    • Public key: Available to scanners (for verification)
    • Cannot derive private key from public keyvalidUntil

    VerificationWhy ProcessJWT? (Scanner App):

    1. Scanner reads QR code
    2. Extracts JWT token
    3. Fetches event's public key
    4. Verifies JWT signature
    5. Checks expiry and validity
    6. Checks if already checked in for this day
    7. Records check-in if valid

    Why JWT over Simple Codes?

    • Cannot be forged: Requires private key
    • Contains all data: No database lookup needed
    • Offline capable: ScannerScanners can verify the ticket offline using the public key without internet
    • a
    • Tamper-proof:database lookup. Any modificationtampering breaks signature
    • the
    • Time-limited:signature. validFrom/validUntilThe builtembedded in
    • eventSchedules
    • Daylets tracking:scanners Multi-enforce per-day schedulescheck-in embedded
    • rules
    without an internet connection.


    Multi-Day Event Check-Ins

    How

    For Multi-Daymulti-day Check-Insevents, Work

    each

    Single-Dayticket Event:

    can
      be
    • Onechecked check-in expected
    • After check-in, status changes to USED
    • Simple entry tracking

    Multi-Day Event (e.g., 3-day festival):

    • Multiple check-ins allowed (oneonce per day)
    • day.
    • Each day tracked separately
    • Ticket remains ACTIVE after first day
    • Full history stored inThe checkIns array
    stores

    Check-Inthe Recordfull Fields:

    history.
      The
    • checkInTime: When check-in happened
    • checkInLocation: Where (e.g.hasBeenCheckedIn, "Main Gate"lastCheckedInAt, "VIP Entrance")
    • checkedInBy: Staff/scanner operator name
    • dayName: Which day (must match eventSchedules)
    • scannerId: Scanner device ID
    • checkInMethod: QR_SCAN, MANUAL, NFC (default: QR_SCAN)

    Example: 3-Day Festival

    Day 1 (Friday):

    {
      "checkInTime": "2025-12-15T18:30:00+03:00"lastCheckedInBy, "checkInLocation": "Main Gate"lastCheckInLocation, "checkedInBy":and "StafflastCheckInDayName Memberconvenience 1",fields "dayName":reflect "Daythe 1most -recent Friday Night",
      "scannerId": "SCANNER-001",
      "checkInMethod": "QR_SCAN"
    }
    

    Day 2 (Saturday):

    {
      "checkInTime": "2025-12-16T14:15:00+03:00",
      "checkInLocation": "VIP Entrance",
      "checkedInBy": "Staff Member 2",
      "dayName": "Day 2 - Saturday",
      "scannerId": "SCANNER-003",
      "checkInMethod": "QR_SCAN"
    }
    

    Day 3 (Sunday):

    {
      "checkInTime": "2025-12-17T12:00:00+03:00",
      "checkInLocation": "Main Gate",
      "checkedInBy": "Staff Member 1",
      "dayName": "Day 3 - Sunday",
      "scannerId": "SCANNER-001",
      "checkInMethod": "QR_SCAN"
    }
    

    Validation Rules:entry.

    • dayName in a check-in record must match one fromof JWT'sthe eventSchedules day names embedded in the JWT
    • CannotA checkticket cannot be checked in twice on the same day
    • CanTicket checkstatus instays onACTIVE differentacross days
    • Check-inand time must be within day's start/end

    Benefits:

    • Accurate attendance tracking per day
    • Prevents duplicate same-day entries
    • Allows organizerstransitions to seeUSED daily attendance
    • Supports flexible entry (don't needafter all days)expected check-ins

    Event Snapshots

    Why Snapshots?

    Problem: Event details can(title, changevenue, aftertimes, organizer contacts) are captured into the booking record at the moment of purchase and never change. This means:

    • Event renamed
    • Time changed
    • Venue moved
    • Organizer updated contact

    Solution: Capture event state at booking time

    Snapshot Fields (Immutable after booking):

    • eventTitle
    • eventStartDateTime
    • eventEndDateTime
    • eventTimezone
    • eventLocation (full venue details)
    • eventFormat
    • virtualDetails (for online/hybrid)
    • organizerName
    • organizerEmail
    • organizerPhone

    Benefits:

    • PDF Tickets:tickets Generatealways correctshow ticketwhat with original details
    • Legal Record: Whatthe customer actually purchasedbought
    • EmailBookings Confirmations: Showremain accurate bookingeven detailsif the organizer later renames or reschedules the event
    • RefundThe Logic:event Referenceand originalorganizer eventblocks details
    • in
    • AuditBookingOrderResponse Trail:always Trackreflect whatbooking-time changed vs. what was bookedstate

    Example Scenario:

    1. User books ticket for "Tech Summit" at KICC
    2. Snapshot created: "Tech Summit", "KICC Nairobi"
    3. Organizer renames event to "African Tech Summit"
    4. Organizer moves venue to "Safari Park Hotel"
    5. User's booking still shows original: "Tech Summit at KICC"
    6. This is what they paid for (legal protection)

    Booking Creation Flow

    Automatic

    Bookings Creationare Aftercreated Payment

    automatically

    Trigger:by EventPaymentCompletedListener fires after a successful payment

    Steps:— never through a direct API call. The flow:

    1. Fetch Entities:

      checkout
        session,
      • Getevent, EventCheckoutSessionand ticket type from the database
      • Get Event details
      • Get TicketType details
    2. Generate Bookinga Reference:

      unique
        booking
      • Format:reference (EVT-{8-char-UUID})
      • Example:Create EVT-A3F4B21Cticket instances (one per quantity unit, tagged with attendee and buyer info)
      • UniqueSign and readable
    3. Create Ticket Instances:

      • For buyer's tickets (ticketsForMe count)
      • For each other attendee (their quantity)
      • Each ticket gets unique series number
      • Each ticket assigned to correct attendee
    4. Generatea JWT QR Codes:

      code
        for
      • Create JWT payload witheach ticket data
      • using
      • Include event schedules for multi-day
      • Sign withthe event's RSA private key
      • Set as ticket's qrCode field
    5. Snapshot Event Details:

      • Capture current event title, times, location
      • Captureand organizer details
      • Storeinto inthe booking (immutable)
    6. Save Booking:

      • Create EventBookingOrderEntityrecord
      • Save tothe databasebooking withand allmark tickets
      • Link tothe checkout session
      as COMPLETED
    7. Update Checkout Session:

      • Set createdBookingOrderId
      • Mark as COMPLETED
    8. Publish Event:

      a
        BookingCreatedEvent
      • Fireto BookingCreatedEvent
      • Triggers notifications
    9. Send Notifications:

      • Email buyer confirmation with tickets
      • Optionallytrigger email othernotifications attendeesto theirbuyer, tickets
      • attendees,
      • Notify eventand organizer of new booking

    TransactionThe Safety:

    • Entireentire flow runs in a single transaction
    • If any step fails, everything rolls back
    • Nono partial bookings created
    • are

    Timing:created.

    • Happens immediately after payment success
    • Usually completes in < 2 seconds
    • User gets instant confirmation

    Notification System Integration

    Who Gets Notified?

    1. Buyer (ALWAYS):

    • Receives booking confirmation
    • Gets ALL tickets (if sendTicketsToAttendees = false)
    • Gets only THEIR tickets (if sendTicketsToAttendees = true)
    • Channels: EMAIL, SMS, PUSH, IN_APP
    • Priority: HIGH

    2. Other Attendees (CONDITIONAL):

    • Only if sendTicketsToAttendees = true
    • Each attendee gets ONLY their tickets
    • Channels: EMAIL, SMS
    • Priority: HIGH
    • Grouped by email (all tickets for same person)

    3. Event Organizer (ALWAYS):

    • Notified of new booking
    • Gets booking summary (not tickets)
    • Channels: EMAIL, IN_APP
    • Priority: NORMAL

    Notification Content

    Buyer Confirmation:

    • Booking reference
    • Event title and date
    • Number of tickets
    • QR codes attached
    • Event location/virtual link
    • Instructions for entry

    Attendee Ticket Email:

    • "You've received tickets from [Buyer Name]"
    • Event details
    • Their specific QR codes
    • Entry instructions

    Organizer Alert:

    • New booking notification
    • Buyer name and email
    • Number of tickets sold
    • Total amount
    • Booking reference for lookup

    QR Code Delivery

    sendTicketsToAttendees = false:

    Buyer receives:
    - Ticket 1 QR (for self)
    - Ticket 2 QR (for self)
    - Ticket 3 QR (for Jane)
    - Ticket 4 QR (for Jane)
    - Ticket 5 QR (for Bob)
    
    Buyer must forward to Jane and Bob manually
    

    sendTicketsToAttendees = true:

    Buyer receives:
    - Ticket 1 QR (for self)
    - Ticket 2 QR (for self)
    
    Jane receives:
    - Ticket 3 QR (for Jane)
    - Ticket 4 QR (for Jane)
    
    Bob receives:
    - Ticket 5 QR (for Bob)
    
    Everyone gets their own tickets directly
    

    Access Control Rules

    WhoCanViewBookings?

    1.

    • Can view all their own bookings
    • GET /booking-orders/my-bookings (all)
    Actor Endpoint Allowed?
    Booking Ownerowner (Customer):

    customer)
    GET /booking-orders/{bookingId}id}Yes
    Event organizerGET /booking-orders/{id}Yes
    Admin (specific)SUPER_ADMIN/STAFF_ADMIN) GET /booking-orders/{id}Yes
    Other authenticated userGET /booking-orders/{id}No — 403
    Any authenticated userGET /my-bookingsYes (own bookings only)
    Ticket ownerGET /tickets/{id}/pdfYes
    Other authenticated userGET /tickets/{id}/pdfNo — 403
    Event organizerGET /booking-orders/event/{id}Yes
    AdminGET /booking-orders/event/{id}Yes
    Non-organizer userGET /booking-orders/event/{id}No — 403

    Booking and Ticket Status

    2.Booking Event OrganizerStatus:

    • Can
    • viewbookingsfortheirevents
    • Useful
    • forcheckingattendance
      Status Description
      CONFIRMED Active
    • Verifyingbooking, purchases
    • tickets
    • Customerare support
    • valid
      CANCELLEDBooking cancelled (placeholder — cancellation logic not yet implemented)

      3.Ticket PlatformInstance AdminsStatus:

      • Roles:
      • SUPER_ADMIN,STAFF_ADMIN
      • Can
      • viewanybooking
      • For
      • supportand

        Example

        "platform":
      • ONLINE
      • tickets:Virtual access
      • Both in same booking possible
      • Status Description
        ACTIVE Ticket dispute resolution

        4. Others:

        • Cannot view bookings they don't own
        • Cannot view other users' bookings
        • 403 Forbidden error

        Virtual Event Support

        Virtual Details Structure

        Included for:

        • ONLINE events (only virtual)
        • HYBRID events (both physical + virtual)

        Fields:

        • platform: ZOOM, GOOGLE_MEET, MS_TEAMS, CUSTOM
        • meetingUrl: Full meeting URL (required)
        • meetingId: Meeting ID if applicable
        • passcode: Meeting passcode if required
        • additionalInstructions: Extra guidance

        Example (Zoom):

        {
          "platform": "ZOOM",
          "meetingUrl": "https://zoom.us/j/123456789?pwd=abc123",
          "meetingId": "123 456 789",
          "passcode": "summit2025",
          "additionalInstructions": "Please join 5 minutes earlyready for ause; smoothcan start"be }scanned
        USED Ticket (Custom):

        has
        been checked in; still scannable for additional days
        {CANCELLED Ticket "CUSTOM",cancelled; "meetingUrl":cannot "https://customplatform.com/event/12345",be "meetingId":used null, "passcode": null, "additionalInstructions": "Use your booking email to log in" }

        Delivery:

        • Included in booking response
        • Sent in confirmation email
        • Sent in ticket emails
        • Available before event starts

        Hybrid Events:

        • Virtual details + physical venue
        • Attendees choose format via ticket type
        • IN_PERSON tickets: Physicalfor entry

        Date/Time Formats

        DateTimeStandards

        (No timezone):

        • Format:
      • Example:
      • Used
      • (With timezone):

        • Format:
      • Example:
      • Used
      • validUntil,checkInTime
        TypeFormatExampleUsed For
        LocalDateTime YYYY-MM-DDTHH:mm:ss 2025-12-15T09:00:00 bookedAt, for: bookedAt, cancelledAt,cancelledAt, event snapshots
        ZonedDateTime YYYY-MM-DDTHH:mm:ss±HH:mm 2025-12-15T09:00:00+03:00 validFrom, for:validUntil, validFrom,checkInTime

        WhyZonedDateTime Differentfields Formats?

        carry

        LocalDateTime:

        the
          event's
        • Server-local time
        • Audit timestamps
        • No conversion needed
        • Simple comparison

        ZonedDateTime:

        • User-aware time
        • Ticket validity
        • Check-in times
        • Handles timezone offset and display correctly
        regardless

        Example:of the viewer's locale.

        Event in Nairobi (UTC+3):
        startDateTime: 2025-12-15T09:00:00+03:00
        
        Ticket validFrom: 2025-12-15T09:00:00+03:00
        User in London sees: 2025-12-15T06:00:00+00:00 ✓
        User in New York sees: 2025-12-15T01:00:00-05:00 ✓
        

        Validation Rules Summary

        Booking Retrieval Validation

        Access Validation:

        • ✅ User must be authenticated
        • ✅ Booking must exist
        • ✅ User must be: owner OR organizer OR admin
        • ❌ Other users cannot access

        Data Validation:

        • ✅ bookingId must be valid UUID
        • ✅ Booking must not be deleted (soft delete support)

        Quick Reference Guide

        HTTP Method Badge Code Templates

        GET Badge:

        <span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">GET</span>
        

        POST Badge:

        <span style="background-color: #007bff; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">POST</span>
        

        PUT Badge:

        <span style="background-color: #ffc107; color: black; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">PUT</span>
        

        PATCH Badge:

        <span style="background-color: #fd7e14; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">PATCH</span>
        

        DELETE Badge:

        <span style="background-color: #dc3545; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">DELETE</span>
        

        Endpoint Summary

        #EndpointAccess
        1GET /e-events/booking-orders/{bookingId}Owner / Organizer / Admin
        2GET /e-events/booking-orders/my-bookingsAny authenticated user
        3GET /e-events/booking-orders/tickets/{ticketInstanceId}/pdfTicket owner
        4GET /e-events/booking-orders/event/{eventId}Event organizer / Admin

        Common HTTP Status Codes

        • 200 OK: Successful request
        • 401 Unauthorized: AuthenticationMissing required/failedor invalid token
        • 403 Forbidden: UserAccess doesn't have permissiondenied
        • 404 Not Found: BookingResource not found
        • 500 Internal Server Error: Server-side failure (e.g., PDF generation)

        BookingKey ReferenceData FormatFormats

        • Pattern:Booking reference: EVT-{8-char-UUID}
        • Examples:— e.g., EVT-A3F4B21C, EVT-F2D5E891
        • Unique and readable
        • Easy for customer service

        Ticket Series Format

        • Pattern:series: {CODE}-{COUNTER}
        • Examples:— e.g., VIP-0001, GENER-0042, EARLY-0123
        • Code: First 5 chars of ticket name
        • Counter: Unique incrementing number

        QR Code Format

        • Type:code: RSA-signed JWT
        • Length: (~1000-1000–2000 characters
        • Contains: Complete ticket + event data
        • Cannot be: Forged, tampered, reused (tracked)

        Data Format Standards

        • Dates: LocalDateTime for timestamps, ZonedDateTime for validitycharacters)
        • IDs: UUID format
        • MoneyAmounts: Decimal with 2 decimalsplaces (e.g., 150.00)00)
        • CurrencyTimestamps: TZS (Tanzanian Shilling)
        • Timezone: IANA format (Africa/Nairobi)

        Booking Flow Checklist

        1. ✅ User completes checkout payment
        2. ✅ Payment listener triggers
        3. ✅ System generates booking reference
        4. ✅ System creates ticket instances
        5. ✅ System generates JWT QR codes
        6. ✅ System snapshots event details
        7. ✅ System saves booking order
        8. ✅ System publishes booking event
        9. ✅ System sends email notifications
        10. ✅ User receives confirmation + QR codes

        Best Practices

        For Users:

        • Save QR codes to phone immediately
        • Screenshot confirmation email
        • Arrive earlyLocalDateTime for check-in
        • audit
        • Onefields; QR per person at gate

        For Developers:

        • Always show booking reference prominently
        • Display QR codes large enough to scan
        • Cache booking details locally
        • Handle offline QR display
        • Show check-in history clearly
        • Support PDF ticket generation

        For Organizers:

        • Provide clear entry instructions
        • Test scanner apps before event
        • Have backup manual verification
        • Track attendance by day
        • Monitor check-in progress live

        Error Handling Tips

        • 403 Forbidden: Show "This booking belongs to another user"
        • 404 Not Found: Suggest "Check your emailZonedDateTime for correct reference"
        • Network Error: Show cached booking if available
        • QR Load Failure: Provide booking reference as backup

        Common Mistakes to Avoid

        ❌ Showing other users' bookings
        ❌ Not displaying virtual details for ONLINE events
        ❌ Forgetting to show multi-day check-in history
        ❌ Not caching QR codes for offline use
        ❌ Displaying mutable event data instead of snapshot
        ❌ Not grouping attendees' tickets properly
        ❌ Ignoring timezone in validity checks


        Additional Notes

        Future Enhancements (Not Yet Implemented)

        Booking Cancellation:

        • Status: CANCELLED exists but not functional
        • Future: Refund logic + ticket release
        • Future: Cancellation deadline rules
        • Future: Partial cancellations

        Ticket Transfers:

        • Currently: Tickets assigned at booking
        • Future: Transfer ticket to another person
        • Future: Resale marketplace
        • Future: Name change requests

        Check-In API:

        • Currently: Manual check-ins not via API
        • Future: Scanner app endpoints
        • Future: QR verification endpoint
        • Future: Manual check-in endpoint

        Booking Modifications:

        • Currently: Cannot modify after creation
        • Future: Add more tickets
        • Future: Change attendee names
        • Future: Upgrade ticket types

        Integration Points

        Payment System:

        • Booking created after payment success
        • Linked via checkoutSessionId
        • Payment status determines creation

        Notification System:

        • BookingCreatedEvent triggers emails
        • Async processing via listeners
        • Multiple notification channels

        Escrow System:

        • Payments held until event completion
        • Booking tracks payment via checkout session
        • Organizer paid after event

        Scanner Apps:

        • Will consume booking data
        • Verify JWT QR codes
        • Recordand check-ins
        • Update ticket status

        Conclusion

        The Event Booking Orders API provides comprehensive booking management with:

        Security: JWT-signed QR codes prevent fraud
        Flexibility: Multi-day events with per-day tracking
        Reliability: Event snapshots preserve booking details
        Scalability: Unique ticket series with DB counters
        User Experience: Clear references and notifications
        Multi-Attendee: Support for group bookings
        Virtual Events: Full online/hybrid event support
        Access Control: Proper permissions for all parties