Ticket Management API
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 errors401 UNAUTHORIZED: Authentication issues403 FORBIDDEN: Not event organizer404 NOT_FOUND: Event not found422 UNPROCESSABLE_ENTITY: Validation errors500 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 sold403 FORBIDDEN: Not event organizer404 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 transition403 FORBIDDEN: Not event organizer404 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 sales403 FORBIDDEN: Not event organizer404 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
customCheckInDatefield - 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 onlyminQuantityPerOrder: 5- Group bookings onlyminQuantityPerOrder: 1- Standard (anyone can buy)
maxQuantityPerOrder
Maximum tickets per single purchase.
Default: null (no limit)
Use Cases:
maxQuantityPerOrder: 5- Prevent bulk buyingmaxQuantityPerOrder: 10- Reasonable group sizemaxQuantityPerOrder: 2- Limit resellers
maxQuantityPerUser
Maximum tickets per user across all purchases.
Default: null (no limit)
Use Cases:
maxQuantityPerUser: 2- Limit high-demand eventsmaxQuantityPerUser: 10- Fair distributionmaxQuantityPerUser: 1- One per person (exclusive events)
Validation Rules
maxQuantityPerOrdermust be >=minQuantityPerOrdermaxQuantityPerUsermust be >=maxQuantityPerOrder- If only
maxQuantityPerUserset, 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 timesalesEndDateTime: 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:
status = ACTIVEisDeleted = false!isSoldOut(tickets available)- Current time >=
salesStartDateTime(or null) - 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:
- Ticket Existence: At least minimum required tickets exist
- Ticket Status: Tickets are in ACTIVE status
- Not Deleted: Tickets are not soft deleted
- 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 request201 CREATED: Ticket created successfully400 Bad Request: Validation errors, business rule violations401 Unauthorized: Authentication required/failed403 Forbidden: Not event organizer404 Not Found: Ticket/event not found422 Unprocessable Entity: Validation errors500 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
- ✅ Event is in DRAFT status
- ✅ Choose unique name (+ attendance mode for HYBRID)
- ✅ Set price and quantity
- ✅ Define sales period (optional)
- ✅ Configure purchase limits
- ✅ Set ticket validity type
- ✅ Add inclusive items (optional)
- ✅ 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:
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
No comments to display
No comments to display