Skip to main content

Ticket Management API

Author: Josh, Lead Backend Team
Last Updated: 2025-12-11
Version: v1.0

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

Short Description: The Ticket Management API provides comprehensive functionality for creating and managing ticket types for events in the Nexgate platform. This API enables event organizers to define multiple ticket tiers (VIP, Early Bird, Student, etc.) with flexible pricing, capacity management, sales periods, purchase limits, and attendance modes for hybrid events. Tickets can only be created for DRAFT events, with automatic validation to ensure events meet ticketing requirements before publishing.

Hints:

  • DRAFT Events Only: Tickets can only be created/added to events in DRAFT status
  • Minimum Ticket Requirement: Events need at least 1 ACTIVE ticket to be published
  • Hybrid Event Requirement: HYBRID events need at least 1 IN_PERSON and 1 ONLINE ticket
  • Unique Constraint: Ticket name + attendance mode must be unique per event
  • Capacity Protection: Cannot reduce capacity below tickets already sold
  • Delete Protection: Can only delete tickets with zero sales (otherwise must CLOSE)
  • Automatic TICKETS Stage: Creating first ticket marks TICKETS stage as complete
  • Status Transitions: CLOSED is permanent, SOLD_OUT is automatic, DELETED requires endpoint
  • Sales Period: Tickets must be sold before event starts
  • Purchase Limits: Min/max per order, max per user
  • Ticket Validity: Define when tickets expire (before event, at event end, or custom)

Standard Response Format

All API responses follow a consistent structure using our Globe Response Builder pattern:

Success Response Structure

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

Error Response Structure

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Error description",
  "action_time": "2025-12-11T10:30:45",
  "data": "Error description"
}

HTTP Method Badge Standards

  • GET - GET - Green (Read operations)
  • POST - POST - Blue (Create operations)
  • PATCH - PATCH - Orange (Partial update operations)
  • DELETE - DELETE - Red (Delete operations)

TicketResponse Structure

This is the comprehensive response structure returned by ticket endpoints:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "eventId": "660e8400-e29b-41d4-a716-446655440001",
  "name": "Early Bird VIP",
  "description": "VIP access with early bird discount - includes backstage pass, premium seating, and meet & greet",
  "price": 150.00,
  "totalTickets": 100,
  "ticketsSold": 75,
  "ticketsRemaining": 25,
  "ticketsAvailable": 25,
  "isSoldOut": false,
  "salesStartDateTime": "2025-11-01T00:00:00+03:00",
  "salesEndDateTime": "2025-12-14T23:59:59+03:00",
  "isOnSale": true,
  "minQuantityPerOrder": 1,
  "maxQuantityPerOrder": 5,
  "maxQuantityPerUser": 10,
  "checkInValidUntil": "EVENT_END",
  "customCheckInDate": null,
  "attendanceMode": "IN_PERSON",
  "inclusiveItems": [
    "Backstage pass",
    "Premium seating",
    "Meet & greet with artists",
    "Event merchandise pack",
    "Complimentary refreshments"
  ],
  "isHidden": false,
  "status": "ACTIVE",
  "createdAt": "2025-11-01T10:30:45+03:00",
  "updatedAt": "2025-12-01T14:20:30+03:00",
  "createdBy": "johndoe",
  "updatedBy": "johndoe"
}

Response Field Descriptions

Field Type Description
id string (UUID) Unique ticket identifier
eventId string (UUID) Event this ticket belongs to
name string Ticket type name (2-100 chars)
description string Ticket description (max 500 chars)
price decimal Ticket price (can be 0.00 for free tickets)
totalTickets integer Total capacity/quantity available
ticketsSold integer Number of tickets sold
ticketsRemaining integer Calculated: totalTickets - ticketsSold
ticketsAvailable integer Currently available for purchase (same as ticketsRemaining)
isSoldOut boolean Whether all tickets are sold (ticketsSold >= totalTickets)
salesStartDateTime string When ticket sales begin (ISO 8601, optional)
salesEndDateTime string When ticket sales end (ISO 8601, optional)
isOnSale boolean Calculated: currently available for purchase based on status, dates, sold out
minQuantityPerOrder integer Minimum tickets per purchase (default: 1)
maxQuantityPerOrder integer Maximum tickets per purchase (optional, null = no limit)
maxQuantityPerUser integer Maximum tickets per user total (optional, null = no limit)
checkInValidUntil enum When ticket expires: BEFORE_EVENT_START, EVENT_END, CUSTOM
customCheckInDate string Custom expiry date (required if checkInValidUntil=CUSTOM)
attendanceMode enum IN_PERSON or ONLINE (required for HYBRID events)
inclusiveItems array List of items/perks included with ticket (max 50 items)
isHidden boolean Whether ticket is hidden (invite-only)
status enum Ticket status: ACTIVE, INACTIVE, CLOSED, SOLD_OUT, DELETED
createdAt string ISO 8601 timestamp
updatedAt string ISO 8601 timestamp
createdBy string Username of ticket creator
updatedBy string Username of last updater

TicketSummaryResponse Structure

Lightweight response for list views:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Early Bird VIP",
  "price": 150.00,
  "totalTickets": 100,
  "ticketsSold": 75,
  "ticketsAvailable": 25,
  "isSoldOut": false,
  "attendanceMode": "IN_PERSON",
  "status": "ACTIVE",
  "isOnSale": true
}

Endpoints

1. Create Ticket

Purpose: Create a new ticket type for an event (only for DRAFT events)

Endpoint: POST {base_url}/e-events/tickets/{eventId}

Access Level: 🔒 Protected (Requires Bearer Token + Event Organizer)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description
eventId string (UUID) Yes UUID of event to create ticket for

Request JSON Sample (Hybrid Event - In-Person Ticket):

{
  "name": "Early Bird VIP",
  "description": "VIP access with early bird discount - includes backstage pass, premium seating, and meet & greet",
  "price": 150.00,
  "totalQuantity": 100,
  "salesStartDateTime": "2025-11-01T00:00:00+03:00",
  "salesEndDateTime": "2025-12-14T23:59:59+03:00",
  "minQuantityPerOrder": 1,
  "maxQuantityPerOrder": 5,
  "maxQuantityPerUser": 10,
  "checkInValidUntil": "EVENT_END",
  "attendanceMode": "IN_PERSON",
  "inclusiveItems": [
    "Backstage pass",
    "Premium seating",
    "Meet & greet with artists",
    "Event merchandise pack",
    "Complimentary refreshments"
  ],
  "isHidden": false
}

Request Body Parameters:

Basic Information

Parameter Type Required Description Validation
name string Yes Ticket type name Min: 2, Max: 100 characters
description string No Ticket description Max: 500 characters
price decimal Yes Ticket price (TZS) Min: 0.00, Max 8 digits + 2 decimals

Capacity Management

Parameter Type Required Description Validation
totalQuantity integer Yes Total tickets available Min: 1, Max: 1,000,000

Sales Period (Optional)

Parameter Type Required Description Validation
salesStartDateTime string No When sales begin ISO 8601, cannot be after event start
salesEndDateTime string No When sales end ISO 8601, must be before event start, after salesStartDateTime

Purchase Limits

Parameter Type Required Description Validation
minQuantityPerOrder integer No Min per purchase Min: 1, Default: 1
maxQuantityPerOrder integer No Max per purchase Min: 1, Max: 100, must be >= minQuantityPerOrder
maxQuantityPerUser integer No Max per user total Min: 1, Max: 1000, must be >= maxQuantityPerOrder

Ticket Validity

Parameter Type Required Description Validation
checkInValidUntil enum No When ticket expires BEFORE_EVENT_START, EVENT_END (default), CUSTOM
customCheckInDate string Conditional Custom expiry date Required if checkInValidUntil=CUSTOM, ISO 8601

For Hybrid Events

Parameter Type Required Description Validation
attendanceMode enum Conditional Attendance type IN_PERSON or ONLINE (required for HYBRID events)

Additional Features

Parameter Type Required Description Validation
inclusiveItems array No Included perks/items Max 50 items, each max 200 chars
isHidden boolean No Invite-only ticket Default: false

Success Response: Returns complete TicketResponse structure

Success Response Message: "Ticket created successfully"

HTTP Status Code: 201 CREATED

Behavior:

  • Event must be in DRAFT status
  • Ticket name + attendanceMode must be unique per event
  • First ticket creation marks TICKETS stage as complete
  • Sets currentStage to REVIEW if TICKETS was current stage
  • HYBRID events require attendanceMode (IN_PERSON or ONLINE)
  • Sales period must be before event starts
  • Initial status set to ACTIVE
  • Initial quantitySold set to 0

Standard Error Types:

  • 400 BAD_REQUEST: Event not in DRAFT status, duplicate ticket name, validation errors
  • 401 UNAUTHORIZED: Authentication issues
  • 403 FORBIDDEN: Not event organizer
  • 404 NOT_FOUND: Event not found
  • 422 UNPROCESSABLE_ENTITY: Validation errors
  • 500 INTERNAL_SERVER_ERROR: Server errors

Error Response Examples:

Event Not Draft (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Tickets can only be created for events in DRAFT status. Current status: PUBLISHED",
  "action_time": "2025-12-11T10:30:45",
  "data": "Tickets can only be created for events in DRAFT status. Current status: PUBLISHED"
}

Duplicate Ticket Name (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "A ticket with name 'VIP Pass' and attendance mode 'IN_PERSON' already exists for this event",
  "action_time": "2025-12-11T10:30:45",
  "data": "A ticket with name 'VIP Pass' and attendance mode 'IN_PERSON' already exists for this event"
}

Missing Attendance Mode for Hybrid (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Attendance mode (IN_PERSON or ONLINE) is required for HYBRID events",
  "action_time": "2025-12-11T10:30:45",
  "data": "Attendance mode (IN_PERSON or ONLINE) is required for HYBRID events"
}

Sales End After Event Start (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Sales end date cannot be after event start date. Tickets must be sold before the event begins.",
  "action_time": "2025-12-11T10:30:45",
  "data": "Sales end date cannot be after event start date. Tickets must be sold before the event begins."
}

Invalid Purchase Limits (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Maximum quantity per order (3) must be greater than or equal to minimum (5)",
  "action_time": "2025-12-11T10:30:45",
  "data": "Maximum quantity per order (3) must be greater than or equal to minimum (5)"
}

2. Get All Tickets by Event

Purpose: Retrieve all ticket types for an event

Endpoint: GET {base_url}/e-events/tickets/{eventId}

Access Level: 🔓 Public (Anyone can view tickets for public events)

Authentication: Bearer Token (optional for public events)

Path Parameters:

Parameter Type Required Description
eventId string (UUID) Yes UUID of event

Success Response: Returns array of TicketSummaryResponse objects

Success Response Message: "Tickets retrieved successfully"

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Tickets retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Early Bird VIP",
      "price": 150.00,
      "totalTickets": 100,
      "ticketsSold": 75,
      "ticketsAvailable": 25,
      "isSoldOut": false,
      "attendanceMode": "IN_PERSON",
      "status": "ACTIVE",
      "isOnSale": true
    },
    {
      "id": "660e8400-e29b-41d4-a716-446655440001",
      "name": "Regular",
      "price": 50.00,
      "totalTickets": 500,
      "ticketsSold": 320,
      "ticketsAvailable": 180,
      "isSoldOut": false,
      "attendanceMode": "IN_PERSON",
      "status": "ACTIVE",
      "isOnSale": true
    },
    {
      "id": "770e8400-e29b-41d4-a716-446655440002",
      "name": "Virtual Pass",
      "price": 25.00,
      "totalTickets": 1000,
      "ticketsSold": 850,
      "ticketsAvailable": 150,
      "isSoldOut": false,
      "attendanceMode": "ONLINE",
      "status": "ACTIVE",
      "isOnSale": true
    }
  ]
}

Behavior:

  • Returns only non-deleted tickets
  • Sorted by creation date (oldest first)
  • Includes tickets in all statuses (ACTIVE, INACTIVE, CLOSED, SOLD_OUT)
  • Hidden tickets (isHidden=true) are included

Standard Error Types:

  • 404 NOT_FOUND: Event not found

3. Get Ticket by ID

Purpose: Retrieve detailed information for a single ticket

Endpoint: GET {base_url}/e-events/tickets/{eventId}/{ticketId}

Access Level: 🔓 Public

Authentication: Bearer Token (optional)

Path Parameters:

Parameter Type Required Description
eventId string (UUID) Yes UUID of event (for URL consistency)
ticketId string (UUID) Yes UUID of ticket to retrieve

Success Response: Returns complete TicketResponse structure with all details

Success Response Message: "Ticket retrieved successfully"

Standard Error Types:

  • 404 NOT_FOUND: Ticket not found

4. Update Ticket Capacity

Purpose: Update the total ticket quantity/capacity

Endpoint: PATCH {base_url}/e-events/tickets/{eventId}/{ticketId}/capacity

Access Level: 🔒 Protected (Event Organizer Only)

Authentication: Bearer Token

Path Parameters:

Parameter Type Required Description
eventId string (UUID) Yes UUID of event
ticketId string (UUID) Yes UUID of ticket to update

Request JSON Sample:

{
  "newTotalQuantity": 150
}

Request Body Parameters:

Parameter Type Required Description Validation
newTotalQuantity integer Yes New capacity Min: 1, Max: 1,000,000, must be >= ticketsSold

Success Response: Returns updated TicketResponse

Success Response Message: "Ticket capacity updated successfully"

Behavior:

  • Can update capacity for both DRAFT and PUBLISHED events
  • New capacity must be >= tickets already sold
  • If ticket was SOLD_OUT and new capacity > ticketsSold, status changes to ACTIVE
  • Works for all event statuses (DRAFT, PUBLISHED, HAPPENING, etc.)

Use Cases:

  • Increase Capacity: Venue size increased, add more tickets
  • Decrease Capacity: Venue size reduced (if not below sold count)
  • Reopen Sold Out Tickets: Increase capacity to resume sales

Standard Error Types:

  • 400 BAD_REQUEST: New capacity below tickets sold
  • 403 FORBIDDEN: Not event organizer
  • 404 NOT_FOUND: Ticket not found

Error Response Examples:

Capacity Below Sold Count (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot reduce capacity to 50 because 75 tickets have already been sold",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot reduce capacity to 50 because 75 tickets have already been sold"
}

5. Update Ticket Status

Purpose: Change ticket status (ACTIVE, INACTIVE, CLOSED)

Endpoint: PATCH {base_url}/e-events/tickets/{eventId}/{ticketId}/status

Access Level: 🔒 Protected (Event Organizer Only)

Authentication: Bearer Token

Path Parameters:

Parameter Type Required Description
eventId string (UUID) Yes UUID of event
ticketId string (UUID) Yes UUID of ticket to update

Request JSON Sample:

{
  "status": "INACTIVE"
}

Request Body Parameters:

Parameter Type Required Description Valid Values
status enum Yes New ticket status ACTIVE, INACTIVE, CLOSED

Success Response: Returns updated TicketResponse

Success Response Message: "Ticket status updated successfully"

Status Transition Rules:

From Status To Status Allowed? Notes
ACTIVE INACTIVE ✅ Yes Temporarily stop sales
ACTIVE CLOSED ✅ Yes Permanently stop sales
INACTIVE ACTIVE ✅ Yes Resume sales
INACTIVE CLOSED ✅ Yes Permanently stop sales
CLOSED ANY ❌ No CLOSED is permanent
SOLD_OUT ACTIVE ✅ Yes Only if capacity increased
SOLD_OUT CLOSED ✅ Yes Permanently close
SOLD_OUT INACTIVE ❌ No Invalid transition
DELETED ANY ❌ No Cannot change deleted tickets
ANY SOLD_OUT ❌ No Automatic status only
ANY DELETED ❌ No Use delete endpoint

Use Cases:

  • ACTIVE → INACTIVE: Temporarily pause sales (during review, pricing adjustment)
  • INACTIVE → ACTIVE: Resume sales after pause
  • ACTIVE/INACTIVE → CLOSED: Permanently stop sales (event capacity changed, tier removed)
  • SOLD_OUT → ACTIVE: Resume sales after capacity increase (requires capacity update first)

Standard Error Types:

  • 400 BAD_REQUEST: Invalid status transition
  • 403 FORBIDDEN: Not event organizer
  • 404 NOT_FOUND: Ticket not found

Error Response Examples:

Invalid Transition - CLOSED is Permanent (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot change status of closed ticket. Closed status is permanent.",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot change status of closed ticket. Closed status is permanent."
}

Cannot Manually Set SOLD_OUT (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot manually set status to SOLD_OUT. This status is automatically set when tickets are sold out.",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot manually set status to SOLD_OUT. This status is automatically set when tickets are sold out."
}

6. Delete Ticket

Purpose: Soft delete a ticket type (only if no tickets sold)

Endpoint: DELETE {base_url}/e-events/tickets/{eventId}/{ticketId}

Access Level: 🔒 Protected (Event Organizer Only)

Authentication: Bearer Token

Path Parameters:

Parameter Type Required Description
eventId string (UUID) Yes UUID of event
ticketId string (UUID) Yes UUID of ticket to delete

Success Response Message: "Ticket deleted successfully"

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Ticket deleted successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Behavior:

  • Soft delete (sets isDeleted=true, status=DELETED)
  • Can only delete if quantitySold = 0
  • If tickets have been sold, must use status update to CLOSE instead
  • Sets deletedAt timestamp and deletedBy user
  • Deleted tickets excluded from GET lists

Standard Error Types:

  • 400 BAD_REQUEST: Cannot delete ticket with sales
  • 403 FORBIDDEN: Not event organizer
  • 404 NOT_FOUND: Ticket not found

Error Response Example:

Cannot Delete Ticket with Sales (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot delete ticket 'Early Bird VIP' because 75 tickets have been sold. You can close the ticket instead to stop sales.",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot delete ticket 'Early Bird VIP' because 75 tickets have been sold. You can close the ticket instead to stop sales."
}

Ticket Status Lifecycle

Status Flow Diagram

ACTIVE ⇄ INACTIVE → CLOSED (permanent)
   ↓
SOLD_OUT → ACTIVE (if capacity increased)
   ↓
DELETED (if no sales)

Status Descriptions

Status Description Can Edit? Can Delete? Available for Purchase?
ACTIVE Normal selling status Yes Yes (if no sales) Yes (if within sales period)
INACTIVE Temporarily paused Yes Yes (if no sales) No
CLOSED Permanently stopped No No No
SOLD_OUT All tickets sold Capacity only No No
DELETED Soft deleted No N/A No

Automatic Status Changes

  • SOLD_OUT: Automatically set when ticketsSold >= totalTickets
  • ACTIVE: Automatically set when capacity increased on SOLD_OUT ticket

Ticket Types & Use Cases

Common Ticket Types

1. Early Bird

{
  "name": "Early Bird",
  "price": 50.00,
  "totalQuantity": 100,
  "salesEndDateTime": "2025-11-30T23:59:59+03:00",
  "maxQuantityPerOrder": 5
}
  • Limited quantity
  • Sales end date before regular tickets
  • Discounted price

2. VIP/Premium

{
  "name": "VIP Pass",
  "price": 200.00,
  "totalQuantity": 50,
  "inclusiveItems": [
    "Backstage access",
    "Premium seating",
    "Meet & greet",
    "Gift bag"
  ],
  "checkInValidUntil": "CUSTOM",
  "customCheckInDate": "2025-12-18T00:00:00+03:00"
}
  • Higher price
  • Limited quantity
  • Multiple perks
  • Extended validity (after-party access)

3. Student/Discount

{
  "name": "Student Discount",
  "price": 25.00,
  "totalQuantity": 200,
  "maxQuantityPerUser": 2,
  "isHidden": true
}
  • Discounted price
  • Per-user limit
  • Hidden (requires special link/code)

4. Group Tickets

{
  "name": "Group Pass (5 people)",
  "price": 200.00,
  "totalQuantity": 50,
  "minQuantityPerOrder": 5,
  "maxQuantityPerOrder": 5
}
  • Fixed quantity per purchase
  • Bulk pricing

5. Hybrid Event - In-Person

{
  "name": "In-Person Pass",
  "price": 100.00,
  "totalQuantity": 300,
  "attendanceMode": "IN_PERSON",
  "inclusiveItems": [
    "Physical venue access",
    "Networking lunch",
    "Event materials"
  ]
}
  • Physical venue access
  • Higher price than online

6. Hybrid Event - Online

{
  "name": "Virtual Pass",
  "price": 50.00,
  "totalQuantity": 1000,
  "attendanceMode": "ONLINE",
  "inclusiveItems": [
    "Live stream access",
    "Recording access (30 days)",
    "Digital materials"
  ]
}
  • Virtual access
  • Higher capacity
  • Lower price

Ticket Validity Types

BEFORE_EVENT_START

Ticket expires just before event begins.

Use Cases:

  • Early bird tickets that expire at event time
  • Tickets that don't grant event entry (pre-event workshops)

Behavior:

  • Cannot check in once event starts
  • Useful for time-limited promotional tickets

EVENT_END (Default)

Ticket valid until event ends.

Use Cases:

  • Standard event tickets
  • Multi-day pass valid for all days

Behavior:

  • Can check in anytime during event
  • For multi-day events, valid until last day ends
  • Most common validity type

CUSTOM

Ticket valid until specific custom date/time.

Use Cases:

  • VIP after-party access extending beyond event
  • Early access tickets (valid before event starts)
  • Extended access (recordings, venue access)

Behavior:

  • Requires customCheckInDate field
  • Flexible validity period
  • Can extend before or after event dates

Example (VIP with After-Party):

{
  "checkInValidUntil": "CUSTOM",
  "customCheckInDate": "2025-12-18T02:00:00+03:00"
}

Event ends Dec 17 at 23:00, but VIP ticket valid until Dec 18 at 02:00 (after-party).


Purchase Limits Explained

minQuantityPerOrder

Minimum tickets required per purchase.

Default: 1

Use Cases:

  • minQuantityPerOrder: 2 - Couples/pairs only
  • minQuantityPerOrder: 5 - Group bookings only
  • minQuantityPerOrder: 1 - Standard (anyone can buy)

maxQuantityPerOrder

Maximum tickets per single purchase.

Default: null (no limit)

Use Cases:

  • maxQuantityPerOrder: 5 - Prevent bulk buying
  • maxQuantityPerOrder: 10 - Reasonable group size
  • maxQuantityPerOrder: 2 - Limit resellers

maxQuantityPerUser

Maximum tickets per user across all purchases.

Default: null (no limit)

Use Cases:

  • maxQuantityPerUser: 2 - Limit high-demand events
  • maxQuantityPerUser: 10 - Fair distribution
  • maxQuantityPerUser: 1 - One per person (exclusive events)

Validation Rules

  • maxQuantityPerOrder must be >= minQuantityPerOrder
  • maxQuantityPerUser must be >= maxQuantityPerOrder
  • If only maxQuantityPerUser set, must be >= minQuantityPerOrder

Example Configurations:

Standard Ticket:

{
  "minQuantityPerOrder": 1,
  "maxQuantityPerOrder": 10,
  "maxQuantityPerUser": 20
}

Group Only:

{
  "minQuantityPerOrder": 5,
  "maxQuantityPerOrder": 5,
  "maxQuantityPerUser": 10
}

Limited Per Person:

{
  "minQuantityPerOrder": 1,
  "maxQuantityPerOrder": 2,
  "maxQuantityPerUser": 2
}

Sales Period Management

Sales Period Rules

  • salesStartDateTime: Optional, defaults to ticket creation time
  • salesEndDateTime: Optional, defaults to event start time
  • Both must be before event starts
  • End must be after start

Use Cases

1. Phased Sales

// Early Bird Phase
{
  "name": "Early Bird",
  "salesEndDateTime": "2025-11-30T23:59:59+03:00"
}

// Regular Phase
{
  "name": "Regular",
  "salesStartDateTime": "2025-12-01T00:00:00+03:00"
}

2. Time-Limited Flash Sale

{
  "name": "Flash Sale",
  "salesStartDateTime": "2025-12-01T12:00:00+03:00",
  "salesEndDateTime": "2025-12-01T18:00:00+03:00"
}

3. Last Minute Tickets

{
  "name": "Last Minute",
  "salesStartDateTime": "2025-12-14T00:00:00+03:00",
  "salesEndDateTime": "2025-12-14T23:59:59+03:00"
}

isOnSale Calculation

Ticket isOnSale = true when ALL conditions met:

  1. status = ACTIVE
  2. isDeleted = false
  3. !isSoldOut (tickets available)
  4. Current time >= salesStartDateTime (or null)
  5. Current time <= salesEndDateTime (or null)

Hybrid Events - Attendance Modes

Requirements for HYBRID Events

  • Must have at least 1 ACTIVE ticket with attendanceMode: IN_PERSON
  • Must have at least 1 ACTIVE ticket with attendanceMode: ONLINE
  • Cannot publish HYBRID event without both modes

Attendance Mode Rules

  • Required: For HYBRID events only
  • Optional: For IN_PERSON and ONLINE events (ignored if provided)
  • Values: IN_PERSON or ONLINE
  • Uniqueness: Name + AttendanceMode must be unique per event

Example: HYBRID Event Tickets

[
  {
    "name": "VIP Pass",
    "price": 200.00,
    "attendanceMode": "IN_PERSON",
    "totalQuantity": 50
  },
  {
    "name": "VIP Pass",
    "price": 100.00,
    "attendanceMode": "ONLINE",
    "totalQuantity": 200
  },
  {
    "name": "Regular",
    "price": 100.00,
    "attendanceMode": "IN_PERSON",
    "totalQuantity": 300
  },
  {
    "name": "Regular",
    "price": 50.00,
    "attendanceMode": "ONLINE",
    "totalQuantity": 1000
  }
]

Note: Same name "VIP Pass" allowed because attendance modes differ.


Inclusive Items

Purpose

List of perks, benefits, or items included with ticket purchase.

Rules

  • Maximum 50 items per ticket
  • Each item max 200 characters
  • Cannot be null or empty strings
  • Displayed to attendees during purchase

Use Cases

VIP Ticket:

{
  "inclusiveItems": [
    "Backstage pass",
    "Premium seating (front 3 rows)",
    "Meet & greet with performers",
    "Exclusive merchandise pack",
    "Complimentary beverages",
    "Access to VIP lounge",
    "Reserved parking"
  ]
}

Conference Ticket:

{
  "inclusiveItems": [
    "Access to all sessions",
    "Networking lunch (Day 1 & 2)",
    "Conference materials & notebook",
    "Certificate of attendance",
    "6 months digital content access"
  ]
}

Workshop Ticket:

{
  "inclusiveItems": [
    "4-hour hands-on workshop",
    "Toolkit & materials",
    "Digital resources library",
    "Follow-up Q&A session"
  ]
}

Event Publishing Requirements

Minimum Ticket Requirements

For IN_PERSON and ONLINE Events

  • Minimum: 1 ACTIVE ticket
  • Can have multiple ticket tiers (Early Bird, Regular, VIP)

For HYBRID Events

  • Minimum: 1 ACTIVE IN_PERSON ticket
  • Minimum: 1 ACTIVE ONLINE ticket
  • Total minimum: 2 ACTIVE tickets (one of each mode)

Pre-Publish Validation

When attempting to publish an event, the system validates:

  1. Ticket Existence: At least minimum required tickets exist
  2. Ticket Status: Tickets are in ACTIVE status
  3. Not Deleted: Tickets are not soft deleted
  4. Attendance Modes: HYBRID events have both IN_PERSON and ONLINE

Example Error (HYBRID event missing ONLINE ticket):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "HYBRID events must have at least 1 active ONLINE ticket before publishing",
  "action_time": "2025-12-11T10:30:45",
  "data": "HYBRID events must have at least 1 active ONLINE ticket before publishing"
}

Quick Reference Guide

Common HTTP Status Codes

  • 200 OK: Successful request
  • 201 CREATED: Ticket created successfully
  • 400 Bad Request: Validation errors, business rule violations
  • 401 Unauthorized: Authentication required/failed
  • 403 Forbidden: Not event organizer
  • 404 Not Found: Ticket/event not found
  • 422 Unprocessable Entity: Validation errors
  • 500 Internal Server Error: Server error

Data Format Standards

  • Dates: ISO 8601 with timezone (2025-12-15T18:00:00+03:00)
  • IDs: UUID format
  • Price: Decimal with 2 decimal places (150.00)
  • Currency: TZS (Tanzanian Shilling)
  • Quantity: Integer (positive numbers)

Ticket Creation Checklist

  1. ✅ Event is in DRAFT status
  2. ✅ Choose unique name (+ attendance mode for HYBRID)
  3. ✅ Set price and quantity
  4. ✅ Define sales period (optional)
  5. ✅ Configure purchase limits
  6. ✅ Set ticket validity type
  7. ✅ Add inclusive items (optional)
  8. ✅ Set attendance mode (required for HYBRID)

Best Practices

Pricing Strategy:

  • Early bird: 20-30% discount
  • Regular: Standard price
  • VIP: 2-3x regular price
  • Student: 40-50% discount

Capacity Planning:

  • VIP/Premium: 10-15% of total
  • Early Bird: 20-30% of total
  • Regular: Remaining capacity
  • Online (hybrid): 2-3x physical capacity

Sales Periods:

  • Early Bird: 1-2 months before event
  • Regular: Until 1 day before event
  • Last Minute: Final 24-48 hours

Purchase Limits:

  • Standard events: max 10 per order
  • High-demand events: max 2 per user
  • Group tickets: min 5, max 5 per order

Error Handling Tips

  • 422 Errors: Check validation rules for each field
  • 400 Draft Status: Only create tickets for DRAFT events
  • 400 Duplicate Name: Use different name or attendance mode
  • 400 Cannot Delete: Use CLOSE status instead
  • 400 Capacity Error: Cannot reduce below sold count

Common Mistakes to Avoid

❌ Creating tickets for PUBLISHED events ❌ Missing attendance mode for HYBRID events ❌ Sales period after event start ❌ maxPerOrder < minPerOrder ❌ Trying to delete tickets with sales ❌ Manually setting SOLD_OUT status ❌ Changing CLOSED ticket status