Skip to main content

Events Management API

Author: Josh S. Sakweli, Backend Lead Team Last Updated: 2025-02-20 Version: v1.1

Base URL: https://your-api-domain.com/api/v1/e-events

Short Description: The Event Core API provides full lifecycle management for events on the NextGate platform — from creating drafts and configuring schedules, to publishing, managing live events, and discovery. It is used by event organizers to build, publish, and manage events step-by-step, and by all authenticated users to browse, search, and filter published events.

Hints:

  • All write operations (create, update, publish) require a valid Bearer token. Read operations on published events are public.
  • Dates and times must always use ISO 8601 format with timezone offset (e.g., 2025-06-15T09:00:00+03:00). The API stores and returns ZonedDateTime.
  • Event creation follows a staged workflow: BASIC_INFO → SCHEDULE → LOCATION_DETAILS → REGISTRATION_SETUPS → TICKETS → REVIEW. All required stages must be completed before publishing.
  • Slugs are auto-generated from the event title with a UUID suffix to guarantee uniqueness — do not pass a slug manually.
  • Pagination uses 1-based page numbers (page=1 is the first page).
  • Category seeding and management live in the Event Categories API (base: /api/v1/e-events/categories), documented separately.

Event Creation User Journey

  [Organizer]
       │
       │  POST /draft
       ▼
  ┌─────────────┐
  │  BASIC INFO │  title, category, format, description, media
  └──────┬──────┘
         │  PATCH /drafts/{id}/basic-info  (optional update)
         │
         │  PATCH /draft/{id}/schedule
         ▼
  ┌──────────────┐
  │   SCHEDULE   │  days[ date, startTime, endTime ], timezone
  └──────┬───────┘
         │
         │  PATCH /draft/{id}/location
         ▼
  ┌──────────────────┐
  │ LOCATION DETAILS │  venue (IN_PERSON/HYBRID) or virtualDetails (ONLINE/HYBRID)
  └──────┬───────────┘         or skip entirely (TBA format)
         │
         │  PATCH /drafts/{id}/registration
         ▼
  ┌───────────────────────┐
  │  REGISTRATION SETUPS  │  registrationOpensAt, registrationClosesAt
  └──────┬────────────────┘
         │
         │  (Ticket creation via Tickets API — required before publish)
         ▼
  ┌──────────────┐
  │   TICKETS    │  at least one active ticket required
  └──────┬───────┘
         │
         │  (Optional enrichment)
         │  PATCH /drafts/{id}/highlights
         │  PATCH /drafts/{id}/faqs
         │  PATCH /drafts/{id}/lineup
         │  PATCH /drafts/{id}/agenda
         │  POST  /draft/{id}/products/{productId}
         │  POST  /draft/{id}/shops/{shopId}
         │
         │  PATCH /{eventId}/publish
         ▼
  ┌───────────────┐
  │   PUBLISHED   │  RSA keys generated, category count incremented,
  │               │  event visible in public feed
  └───────────────┘

Event Status Flow

  DRAFT ◄──────────────────────► PUBLISHED
    │           (unpublish           │
    │        if 0 tickets sold)      │  (unpublish — only if no tickets sold)
    │                                │
    │  (discardDraft)                │
    ▼                                ▼
  [deleted]                     CANCELLED ◄─── (cancel from any non-terminal status)
                                     │
                              [terminal state]

  PUBLISHED ──► (system / scheduled job) ──► HAPPENING ──► COMPLETED

Status Rules:

  • DRAFT ↔ PUBLISHED — Free movement. Unpublish is only allowed if zero tickets have been sold.
  • CANCELLED — Terminal. Can be triggered from any non-terminal status. Triggers bulk refund if tickets were sold.
  • HAPPENING / COMPLETED — System-managed via scheduled jobs.

Standard Response Format

All API responses follow a consistent structure using the Globe Response Builder pattern.

Success Response Structure

{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-09-23T10:30:45",
  "data": { }
}

Error Response Structure

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

Standard Response Fields

Field Type Description
success boolean true for successful operations, false for errors
httpStatus string HTTP status name (OK, CREATED, BAD_REQUEST, etc.)
message string Human-readable description of the result
action_time string ISO 8601 timestamp of when the response was generated
data object / string Response payload on success; error detail on failure

Shared Response Object Definitions

The following objects are returned by multiple endpoints. They are defined once here and referenced throughout.

A. EventResponse (Full Event Object)

Returned by all draft and event management endpoints.

Field Type Description
id UUID Unique event identifier
title string Event title
slug string URL-friendly identifier, auto-generated
description string Full event description
category.categoryId UUID Category identifier
category.categoryName string Category display name
category.categorySlug string Category slug
eventFormat string IN_PERSON, ONLINE, HYBRID, or TBA
eventVisibility string PUBLIC, PRIVATE, or UNLISTED
status string DRAFT, PUBLISHED, HAPPENING, CANCELLED, COMPLETED
schedule.startDateTime ZonedDateTime Event start (ISO 8601 with offset)
schedule.endDateTime ZonedDateTime Event end (ISO 8601 with offset)
schedule.timezone string IANA timezone string (e.g., Africa/Dar_es_Salaam)
schedule.days[] array Day-level schedule entries (see EventDayInfo below)
venue.name string Venue name (IN_PERSON / HYBRID only)
venue.address string Venue address
venue.coordinates.latitude string Latitude decimal string
venue.coordinates.longitude string Longitude decimal string
virtualDetails.meetingLink string Meeting URL (ONLINE / HYBRID only)
virtualDetails.meetingId string Platform meeting ID
virtualDetails.passcode string Meeting passcode
media.banner string Banner image URL
media.thumbnail string Thumbnail image URL
media.gallery[] array List of gallery image URLs
highlights[] array See HighlightEntry definition below
faqs[] array See FaqEntry definition below
lineup[] array See LineupEntry definition below
agenda[] array See AgendaDay definition below
linkedProducts[] array { productId, productName, productSlug }
linkedShops[] array { shopId, shopName, shopSlug }
tickets[] array See TicketSummaryInfo definition below
organizer.organizerId UUID Organizer account ID
organizer.organizerName string Organizer full name
organizer.organizerUsername string Organizer system username
currentStage string Current event creation stage
completedStages[] array List of completed stage names
completionPercentage integer 0–100 completion percentage
canPublish boolean Whether all required stages are completed
createdAt ZonedDateTime Creation timestamp
updatedAt ZonedDateTime Last update timestamp
createdBy string Username of creator
updatedBy string Username of last editor

EventDayInfo

Field Type Description
id UUID Day entity ID
date string Date in YYYY-MM-DD format
startTime string Start time in HH:mm:ss
endTime string End time in HH:mm:ss
description string Optional day description
dayOrder integer Display order (1-based)

HighlightEntry

Field Type Description
type string AGE_RESTRICTION, CHECK_IN_TIME, PARKING, DRESS_CODE, FOOD_DRINKS, ACCESSIBILITY, REFUND_POLICY, WHAT_TO_BRING, PROHIBITED_ITEMS, WEATHER_INFO, CUSTOM
title string Display title for this highlight
value string Short value (e.g., "18+")
description string Longer explanation

FaqEntry

Field Type Description
question string The FAQ question
answer string The answer
order integer Display order

LineupEntry

Field Type Description
entryType string PLATFORM_USER or CUSTOM
userId UUID Platform user ID (only when entryType=PLATFORM_USER)
name string Display name (auto-enriched from user profile when PLATFORM_USER)
role string HEADLINER, PERFORMER, SPEAKER, DJ, HOST, PANELIST, MODERATOR, GUEST
title string Professional title (e.g., "Lead Vocalist")
bio string Short biography
image string Profile/headshot image URL
performanceDay integer Which day number of the event they perform
performanceTime string Time of performance
order integer Display order

AgendaDay

Field Type Description
dayNumber integer Day number (1-based)
date string Date in YYYY-MM-DD format
sessions[] array See AgendaSession definition below

AgendaSession

Field Type Description
startTime string Session start time (HH:mm)
endTime string Session end time (HH:mm)
title string Session title
description string Session description
type string GENERAL, PERFORMANCE, CEREMONY, PANEL, WORKSHOP, NETWORKING, MEAL, BREAK
location string Sub-location within the event venue
presenterType string PLATFORM_USER or CUSTOM
presenterId UUID Platform user ID (when presenterType=PLATFORM_USER)
presenterName string Presenter name (auto-enriched from user profile when PLATFORM_USER)
presenterTitle string Professional title
presenterBio string Short biography
presenterImage string Headshot image URL

TicketSummaryInfo

Field Type Description
id UUID Ticket type ID
name string Ticket type name (e.g., "VIP", "General Admission")
price BigDecimal Ticket price (0.00 for free)
totalTickets integer Total slots allocated
ticketsSold integer Number sold
ticketsAvailable integer Remaining slots
isSoldOut boolean True when available = 0
attendanceMode string Ticket attendance mode enum value
status string Ticket status enum value
isOnSale boolean Whether the ticket is currently on sale

B. EventSummaryResponse (Lightweight List Object)

Returned by all paginated list and search endpoints.

Field Type Description
id UUID Event ID
title string Event title
slug string URL slug
shortDescription string First 150 characters of description
categoryId UUID Category ID
categoryName string Category display name
eventFormat string IN_PERSON, ONLINE, HYBRID, TBA
eventVisibility string PUBLIC, PRIVATE, UNLISTED
status string Event status
startDateTime ZonedDateTime Start date/time with offset
endDateTime ZonedDateTime End date/time with offset
timezone string IANA timezone
locationSummary string Human-readable location (e.g., "Dar es Salaam, TZ", "Online Event", "Location To Be Announced")
thumbnail string Thumbnail URL
pricing.minPrice BigDecimal Lowest available ticket price
pricing.maxPrice BigDecimal Highest available ticket price
pricing.isFree boolean True when all tickets are free
pricing.hasPaidTickets boolean True when at least one paid ticket exists
organizerId UUID Organizer ID
organizerName string Organizer full name
organizerUsername string Organizer username
stats.totalTickets integer Sum of all ticket slots
stats.ticketsSold integer Total tickets sold
stats.ticketsAvailable integer Remaining tickets
stats.isSoldOut boolean True when no tickets remain
stats.attendeeCount integer Same as ticketsSold
createdAt ZonedDateTime Creation timestamp

C. Standard Paginated Response Wrapper

All list endpoints return data inside a Spring Page wrapper.

{
  "success": true,
  "httpStatus": "OK",
  "message": "Events retrieved successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "content": [ ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 10
    },
    "totalElements": 42,
    "totalPages": 5,
    "last": false,
    "first": true,
    "empty": false
  }
}

Note: All list endpoints accept page (1-based, default 1) and size (default 10) as query parameters. Spring internally converts to 0-based before querying.


HTTP Method Badge Standards

  • GET — Green (#28a745) — Safe, read-only operations
  • POST — Blue (#007bff) — Create new resources
  • PUT — Yellow (#ffc107, black text) — Replace entire resource
  • PATCH — Orange (#fd7e14) — Partial update
  • DELETE — Red (#dc3545) — Remove resource

Standard Error Types

Application-Level Exceptions (400–499)

Code Name When it occurs
400 BAD_REQUEST Invalid request data, already published event, duplicate product/shop, unpublish blocked due to ticket sales
401 UNAUTHORIZED Missing, expired, or malformed Bearer token
403 FORBIDDEN Authenticated but not the event organizer, or accessing a draft belonging to another user
404 NOT_FOUND Event, category, product, or shop ID not found
422 UNPROCESSABLE_ENTITY Bean validation failures with per-field detail

Server-Level Exceptions (500+)

Code Name When it occurs
500 INTERNAL_SERVER_ERROR RSA key generation failure, unexpected runtime error

Shared Error Response Examples

All endpoints may return these error shapes. Each endpoint section references them rather than repeating the full JSON.

401 — Unauthorized:

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-02-17T10:30:45",
  "data": "Token has expired"
}

403 — Forbidden:

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Access denied: Insufficient permissions",
  "action_time": "2025-02-17T10:30:45",
  "data": "Access denied: Insufficient permissions"
}

404 — Not Found:

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Event not found with ID: 3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "action_time": "2025-02-17T10:30:45",
  "data": "Event not found with ID: 3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

422 — Validation Error:

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Validation failed",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "title": "size must be between 3 and 200",
    "categoryId": "must not be null",
    "eventFormat": "must not be null"
  }
}

Endpoints


1. Create Event Draft

Purpose: Creates a new event in DRAFT status as the first step of the event creation workflow. Marks BASIC_INFO stage as completed automatically.

Endpoint: POST /api/v1/e-events/drafts

Access Level: 🔒 Protected (Any authenticated user — becomes event organizer)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Request JSON Sample:

{
  "title": "Dar es Salaam Jazz Festival 2025",
  "categoryId": "8e3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
  "eventFormat": "IN_PERSON",
  "eventVisibility": "PUBLIC",
  "description": "An annual celebration of jazz and live music at the heart of the city.",
  "media": {
    "banner": "https://cdn.example.com/banners/jazz-2025.jpg",
    "thumbnail": "https://cdn.example.com/thumbs/jazz-2025.jpg",
    "gallery": []
  }
}

Request Body Parameters:

Parameter Type Required Description Validation
title string Yes Event title Min: 3, Max: 200 characters
categoryId UUID Yes ID of an active event category Must exist and be active
eventFormat string Yes Event format Enum: IN_PERSON, ONLINE, HYBRID, TBA
eventVisibility string No Who can see the event Enum: PUBLIC, PRIVATE, UNLISTED. Defaults to PUBLIC
description string No Full event description Max: 5000 characters
media object No Media URLs for the event See MediaRequest below
media.banner string No Banner image URL Max: 500 characters
media.thumbnail string No Thumbnail image URL Max: 500 characters
media.gallery array No List of gallery image URLs

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Event draft created",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "title": "Dar es Salaam Jazz Festival 2025",
    "slug": "dar-es-salaam-jazz-festival-2025-a1b2c3d4",
    "description": "An annual celebration of jazz...",
    "category": {
      "categoryId": "8e3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      "categoryName": "Music & Concerts",
      "categorySlug": "music-concerts"
    },
    "eventFormat": "IN_PERSON",
    "eventVisibility": "PUBLIC",
    "status": "DRAFT",
    "currentStage": "BASIC_INFO",
    "completedStages": ["BASIC_INFO"],
    "completionPercentage": 20,
    "canPublish": false,
    "schedule": null,
    "venue": null,
    "virtualDetails": null,
    "media": {
      "banner": "https://cdn.example.com/banners/jazz-2025.jpg",
      "thumbnail": "https://cdn.example.com/thumbs/jazz-2025.jpg",
      "gallery": []
    },
    "highlights": null,
    "faqs": null,
    "lineup": null,
    "agenda": null,
    "linkedProducts": [],
    "linkedShops": [],
    "tickets": [],
    "organizer": {
      "organizerId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
      "organizerName": "Amina Hassan",
      "organizerUsername": "amina.hassan"
    },
    "createdAt": "2025-02-17T10:30:45+03:00",
    "updatedAt": null,
    "createdBy": "amina.hassan",
    "updatedBy": null
  }
}

Success Response Fields: See Shared Response Object A — EventResponse.

Possible Error Responses:

Status Scenario
401 No or expired token — see Shared Error: 401
404 Category ID not found
422 Missing required fields (title, categoryId, eventFormat) — see Shared Error: 422

2. Get My Drafts

Purpose: Returns a paginated list of all DRAFT events owned by the authenticated organizer.

Endpoint: GET /api/v1/e-events/drafts

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-based) Min: 1 1
size integer No Items per page Min: 1 10

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Drafts retrieved",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "content": [
      {
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "title": "Dar es Salaam Jazz Festival 2025",
        "slug": "dar-es-salaam-jazz-festival-2025-a1b2c3d4",
        "shortDescription": "An annual celebration of jazz and live music...",
        "categoryId": "8e3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
        "categoryName": "Music & Concerts",
        "eventFormat": "IN_PERSON",
        "eventVisibility": "PUBLIC",
        "status": "DRAFT",
        "startDateTime": null,
        "endDateTime": null,
        "timezone": null,
        "locationSummary": null,
        "thumbnail": "https://cdn.example.com/thumbs/jazz-2025.jpg",
        "pricing": { "isFree": true, "hasPaidTickets": false },
        "organizerName": "Amina Hassan",
        "organizerUsername": "amina.hassan",
        "stats": { "totalTickets": 0, "ticketsSold": 0, "ticketsAvailable": 0, "isSoldOut": false },
        "createdAt": "2025-02-17T10:30:45+03:00"
      }
    ],
    "totalElements": 3,
    "totalPages": 1,
    "first": true,
    "last": true,
    "empty": false
  }
}

Success Response Fields: data.content[] contains EventSummaryResponse objects. Pagination fields follow Standard Paginated Response Wrapper.

Possible Error Responses:

Status Scenario
401 No or expired token — see Shared Error: 401

3. Get Draft by ID

Purpose: Retrieves the full detail of a specific draft. Only the draft's organizer can access it.

Endpoint: GET /api/v1/e-events/drafts/{draftId}

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The ID of the draft event Must be a valid UUID

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Draft retrieved",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Authenticated but not the owner of this draft
404 Draft not found with given ID

4. Discard Draft

Purpose: Permanently deletes a draft event and all its associated day schedules, linked products, and linked shops. This action is irreversible.

Endpoint: DELETE /api/v1/e-events/drafts/{draftId}

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The ID of the draft to discard Must be a valid UUID

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Draft discarded",
  "action_time": "2025-02-17T10:30:45",
  "data": null
}

Possible Error Responses:

Status Scenario
401 No or expired token
403 Authenticated but not the owner of this draft
404 Draft not found with given ID

5. Update Draft — Basic Info

Purpose: Updates the basic information of a draft. All fields are optional — only provided fields are updated. Advances currentStage to SCHEDULE upon completion.

Endpoint: PATCH /api/v1/e-events/drafts/{draftId}/basic-info

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The draft to update Must be a valid UUID

Request JSON Sample:

{
  "title": "Dar es Salaam Jazz Festival 2025 — Updated",
  "description": "The biggest jazz event in East Africa returns for its 10th edition with over 30 artists.",
  "categoryId": "8e3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
  "eventVisibility": "PUBLIC",
  "eventFormat": "IN_PERSON",
  "media": {
    "banner": "https://cdn.example.com/banners/jazz-2025-v2.jpg",
    "thumbnail": "https://cdn.example.com/thumbs/jazz-2025-v2.jpg",
    "gallery": ["https://cdn.example.com/gallery/img1.jpg"]
  }
}

Request Body Parameters:

Parameter Type Required Description Validation
title string No Updated event title Min: 3, Max: 200 characters
description string No Updated description Min: 15, Max: 5000 characters
categoryId UUID No New category Must exist and be active
eventVisibility string No Visibility change Enum: PUBLIC, PRIVATE, UNLISTED
eventFormat string No Format change Enum: IN_PERSON, ONLINE, HYBRID, TBA
media object No Updated media See media fields in endpoint 1

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Basic info updated",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. Note that completedStages will now include "BASIC_INFO" and currentStage will be "SCHEDULE".

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the draft owner
404 Draft or category not found
422 Validation failure on provided fields

6. Update Draft — Schedule

Purpose: Sets the event's day-by-day schedule. Supports multi-day events. Each day must have a unique date in chronological order. Advances currentStage to LOCATION_DETAILS. The overall startDateTime and endDateTime on the event are derived automatically from the first and last day.

Endpoint: PATCH /api/v1/e-events/drafts/{draftId}/schedule

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The draft to update Must be a valid UUID

Request JSON Sample:

{
  "timezone": "Africa/Dar_es_Salaam",
  "days": [
    {
      "date": "2025-07-18",
      "startTime": "18:00:00",
      "endTime": "23:00:00",
      "description": "Opening Night",
      "dayOrder": 1
    },
    {
      "date": "2025-07-19",
      "startTime": "16:00:00",
      "endTime": "23:59:00",
      "description": "Main Concert Day",
      "dayOrder": 2
    }
  ]
}

Request Body Parameters:

Parameter Type Required Description Validation
timezone string No IANA timezone identifier Must be a valid IANA zone ID (e.g., Africa/Dar_es_Salaam). Defaults to UTC
days array Yes List of event days Min 1 day required
days[].date string Yes Date of the day YYYY-MM-DD format; must not be in the past
days[].startTime string Yes Day start time HH:mm:ss format
days[].endTime string Yes Day end time HH:mm:ss; must be after startTime
days[].description string No Optional day description
days[].dayOrder integer No Display order Defaults to position in array if omitted

Notes:

  • All existing days are replaced on each call. To update the schedule, resend the full days array.
  • Dates must be unique — duplicate dates in the same request are rejected with 422.
  • Days must be provided in chronological order (sorted ascending by date).

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Schedule updated",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. schedule.days will be populated, and schedule.startDateTime / schedule.endDateTime will be set from the first and last day.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the draft owner
404 Draft not found
422 Days out of order, duplicate dates, date in the past, missing time fields

7. Update Draft — Location

Purpose: Sets the physical venue and/or virtual meeting details for the event. Required fields depend on eventFormat. For TBA format, this endpoint can be called but no fields are required — the stage is automatically marked complete.

Endpoint: PATCH /api/v1/e-events/drafts/{draftId}/location

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The draft to update Must be a valid UUID

Request JSON Sample (IN_PERSON):

{
  "venue": {
    "name": "Mlimani City Arena",
    "address": "Sam Nujoma Road, Dar es Salaam",
    "coordinates": {
      "latitude": -6.7724,
      "longitude": 39.2083
    }
  }
}

Request JSON Sample (ONLINE):

{
  "virtualDetails": {
    "meetingLink": "https://zoom.us/j/123456789",
    "meetingId": "123 456 789",
    "passcode": "jazz2025"
  }
}

Request Body Parameters:

Parameter Type Required Description Validation
venue object Conditional Required when format is IN_PERSON or HYBRID
venue.name string Yes (if venue) Venue name Max: 200 characters
venue.address string No Full address Max: 500 characters
venue.coordinates.latitude BigDecimal No GPS latitude
venue.coordinates.longitude BigDecimal No GPS longitude
virtualDetails object Conditional Required when format is ONLINE or HYBRID
virtualDetails.meetingLink string Yes (if virtualDetails) Meeting URL Max: 500 characters
virtualDetails.meetingId string No Platform meeting ID Max: 100 characters
virtualDetails.passcode string No Meeting passcode Max: 100 characters

Format-based rules:

  • IN_PERSONvenue.name is required; virtualDetails is ignored
  • ONLINEvirtualDetails.meetingLink is required; venue is ignored
  • HYBRID → both venue.name and virtualDetails.meetingLink are required
  • TBA → no fields required; stage is immediately marked complete

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Location updated",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. completedStages will include "LOCATION_DETAILS" when requirements are met.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the draft owner
404 Draft not found
422 Missing required venue/virtual fields for the event format

8. Update Draft — Registration Config

Purpose: Sets the registration window (open and close dates) for the event. The window must be valid relative to itself and cannot close after the event ends. Advances currentStage to TICKETS.

Endpoint: PATCH /api/v1/e-events/drafts/{draftId}/registration

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The draft to update Must be a valid UUID

Request JSON Sample:

{
  "registrationOpensAt": "2025-05-01T08:00:00+03:00",
  "registrationClosesAt": "2025-07-17T23:59:00+03:00",
  "ctaLabel":"Get ticket"
}

Request Body Parameters:

Parameter Type Required Description Validation
registrationOpensAt ZonedDateTime Yes When registration opens ISO 8601 with timezone offset; must be before registrationClosesAt
registrationClosesAt ZonedDateTime Yes When registration closes ISO 8601 with timezone offset; must not be after the event's endDateTime

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Registration config updated",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. completedStages will include "REGISTRATION_SETUPS" and currentStage will advance to "TICKETS".

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the draft owner
404 Draft not found
422 registrationOpensAt is after registrationClosesAt, or registrationClosesAt is after event end

9. Update Draft — Highlights

Purpose: Replaces the full list of event highlights (key attendee-facing info such as age restriction, dress code, parking, etc.). Sending an empty array clears all highlights.

Endpoint: PATCH /api/v1/e-events/drafts/{draftId}/highlights

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The draft to update Must be a valid UUID

Request JSON Sample:

{
  "highlights": [
    {
      "type": "AGE_RESTRICTION",
      "title": "Age Limit",
      "value": "18+",
      "description": "This event is strictly for adults aged 18 and above."
    },
    {
      "type": "DRESS_CODE",
      "title": "Dress Code",
      "value": "Smart Casual",
      "description": "No sportswear or flip flops allowed."
    }
  ]
}

Request Body Parameters:

Parameter Type Required Description Validation
highlights array Yes Full list of highlights Empty array is valid (clears existing)
highlights[].type string Yes Highlight category Enum: AGE_RESTRICTION, CHECK_IN_TIME, PARKING, DRESS_CODE, FOOD_DRINKS, ACCESSIBILITY, REFUND_POLICY, WHAT_TO_BRING, PROHIBITED_ITEMS, WEATHER_INFO, CUSTOM
highlights[].title string Yes Display title
highlights[].value string No Short value summary
highlights[].description string No Longer explanation

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Highlights updated",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. data.highlights will reflect the new list.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the draft owner
404 Draft not found

10. Update Draft — FAQs

Purpose: Replaces the full list of frequently asked questions for the event. Sending an empty array clears all FAQs.

Endpoint: PATCH /api/v1/e-events/drafts/{draftId}/faqs

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The draft to update Must be a valid UUID

Request JSON Sample:

{
  "faqs": [
    {
      "question": "Is this event suitable for children?",
      "answer": "No. This event is strictly 18+ only.",
      "order": 1
    },
    {
      "question": "Is parking available?",
      "answer": "Yes, free parking is available on site.",
      "order": 2
    }
  ]
}

Request Body Parameters:

Parameter Type Required Description Validation
faqs array Yes Full list of FAQs Empty array is valid (clears existing)
faqs[].question string Yes FAQ question text
faqs[].answer string Yes FAQ answer text
faqs[].order integer No Display order

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "FAQs updated",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. data.faqs will reflect the new list.

Possible Error Responses: Same as Endpoint 9 (401, 403, 404).


11. Update Draft — Lineup

Purpose: Replaces the full event lineup. Supports both platform users (whose profile data is auto-enriched) and custom entries for external performers or speakers. Sending an empty array clears the lineup.

Endpoint: PATCH /api/v1/e-events/drafts/{draftId}/lineup

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The draft to update Must be a valid UUID

Request JSON Sample:

{
  "lineup": [
    {
      "entryType": "PLATFORM_USER",
      "userId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
      "role": "HEADLINER",
      "performanceDay": 1,
      "performanceTime": "21:00",
      "order": 1
    },
    {
      "entryType": "CUSTOM",
      "name": "DJ Afrobeat",
      "role": "DJ",
      "title": "International Guest DJ",
      "bio": "Award-winning DJ from Lagos with 10 years of experience.",
      "image": "https://cdn.example.com/artists/dj-afrobeat.jpg",
      "performanceDay": 2,
      "performanceTime": "22:00",
      "order": 2
    }
  ]
}

Request Body Parameters:

Parameter Type Required Description Validation
lineup array Yes Full lineup list Empty array is valid
lineup[].entryType string Yes Entry source Enum: PLATFORM_USER, CUSTOM
lineup[].userId UUID Conditional Platform user ID Required when entryType=PLATFORM_USER; must exist in the system
lineup[].name string Conditional Display name Required when entryType=CUSTOM; auto-set from user profile when PLATFORM_USER
lineup[].role string No Lineup role Enum: HEADLINER, PERFORMER, SPEAKER, DJ, HOST, PANELIST, MODERATOR, GUEST
lineup[].title string No Professional title
lineup[].bio string No Biography text Auto-set from user profile when PLATFORM_USER
lineup[].image string No Headshot URL Auto-set from user profile when PLATFORM_USER
lineup[].performanceDay integer No Day number of performance
lineup[].performanceTime string No Performance start time (HH:mm)
lineup[].order integer No Display order

Auto-enrichment: When entryType=PLATFORM_USER, the system automatically fetches and populates name, bio, and image from the user's profile. These are also refreshed on every GET of the event.

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Lineup updated",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. data.lineup will contain enriched entries.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the draft owner
404 Draft not found, or a userId in lineup does not exist

12. Update Draft — Agenda

Purpose: Replaces the full event agenda organized by day and session. Supports both platform users and custom entries as session presenters. Sending an empty array clears the agenda.

Endpoint: PATCH /api/v1/e-events/drafts/{draftId}/agenda

Access Level: 🔒 Protected (Organizer — own drafts only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
draftId UUID Yes The draft to update Must be a valid UUID

Request JSON Sample:

{
  "agenda": [
    {
      "dayNumber": 1,
      "date": "2025-07-18",
      "sessions": [
        {
          "startTime": "18:00",
          "endTime": "19:00",
          "title": "Welcome & Opening Ceremony",
          "type": "CEREMONY",
          "location": "Main Stage",
          "presenterType": "PLATFORM_USER",
          "presenterId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
        },
        {
          "startTime": "20:00",
          "endTime": "22:00",
          "title": "Headliner Performance",
          "type": "PERFORMANCE",
          "presenterType": "CUSTOM",
          "presenterName": "The Sauti Sol Band",
          "presenterTitle": "Headline Act",
          "presenterBio": "East Africa's most celebrated group."
        }
      ]
    }
  ]
}

Request Body Parameters:

Parameter Type Required Description Validation
agenda array Yes Full agenda list (by day) Empty array is valid
agenda[].dayNumber integer Yes Day number (1-based)
agenda[].date string No Date string (YYYY-MM-DD)
agenda[].sessions array Yes Sessions for this day
sessions[].startTime string Yes Session start (HH:mm)
sessions[].endTime string Yes Session end (HH:mm)
sessions[].title string Yes Session name
sessions[].description string No Session description
sessions[].type string No Session type Enum: GENERAL, PERFORMANCE, CEREMONY, PANEL, WORKSHOP, NETWORKING, MEAL, BREAK
sessions[].location string No Sub-location within venue
sessions[].presenterType string No Presenter source Enum: PLATFORM_USER, CUSTOM
sessions[].presenterId UUID Conditional Platform user ID Required when presenterType=PLATFORM_USER
sessions[].presenterName string Conditional Presenter name Required when presenterType=CUSTOM; auto-set when PLATFORM_USER
sessions[].presenterTitle string No Professional title Auto-enriched for platform users
sessions[].presenterBio string No Biography Auto-enriched for platform users
sessions[].presenterImage string No Image URL Auto-enriched for platform users

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Agenda updated",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. data.agenda will contain enriched sessions.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the draft owner
404 Draft not found, or a presenterId does not exist

13. Attach Product to Event

Endpoint: POST /api/v1/e-events/draft/{eventId}/products/{productId}

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The event (DRAFT or PUBLISHED) Must be a valid UUID
productId UUID Yes The product to attach Must exist and have status ACTIVE

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Product attached",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. data.linkedProducts will include the newly attached product.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event or product not found
400 Product is not active, already attached, or event is not in DRAFT/PUBLISHED status

14. Remove Product from Event

Purpose: Detaches a previously linked product from the event. Allowed on both DRAFT and PUBLISHED events.

Endpoint: DELETE /api/v1/e-events/draft/{eventId}/products/{productId}

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The event (DRAFT or PUBLISHED) Must be a valid UUID
productId UUID Yes The product to remove Must be a valid UUID

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Product removed",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found, or product not currently attached

15. Attach Shop to Event

Endpoint: POST /api/v1/e-events/draft/{eventId}/shops/{shopId}

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The event (DRAFT or PUBLISHED) Must be a valid UUID
shopId UUID Yes The shop to attach Must exist and have status ACTIVE

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Shop attached",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. data.linkedShops will include the newly attached shop.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event or shop not found
400 Shop is not active, already attached, or event is not in DRAFT/PUBLISHED status

16. Remove Shop from Event

Purpose: Detaches a previously linked shop from the event. Allowed on both DRAFT and PUBLISHED events.

Endpoint: DELETE /api/v1/e-events/draft/{eventId}/shops/{shopId}

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The event (DRAFT or PUBLISHED) Must be a valid UUID
shopId UUID Yes The shop to remove Must be a valid UUID

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Shop removed",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse.

Possible Error Responses: Same as Endpoint 14 (401, 403, 404).


17. Publish Event

Purpose: Transitions a draft event to PUBLISHED status. This is the final step of the creation workflow. The system validates all required stages are complete, performs a duplicate event check against existing published events, and generates an RSA key pair used for secure ticket QR code signing.

Endpoint: PATCH /api/v1/e-events/{eventId}/publish

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The event to publish Must be a valid UUID

Pre-publish checklist (all must pass or the request is rejected with 422):

  • BASIC_INFO stage completed ✓
  • SCHEDULE stage completed (at least one day, not in the past) ✓
  • LOCATION_DETAILS stage completed ✓
  • REGISTRATION_SETUPS stage completed ✓
  • At least one active ticket exists for the event ✓
  • registrationOpensAt is before registrationClosesAt
  • registrationClosesAt is not after event end ✓
  • Event start date is not in the past ✓
  • No duplicate event detected with ≥85% similarity score to another organizer's public event ✓

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Event published successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. data.status will be "PUBLISHED".

Error Response Sample (duplicate detected):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "This event appears to be a duplicate of 'Dar es Salaam Jazz Night' by user123. Please make the title, date, or location more distinct.",
  "action_time": "2025-02-17T10:30:45",
  "data": "This event appears to be a duplicate..."
}

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found
400 Event is already published, or duplicate event detected
422 One or more required stages are incomplete, or date/registration validation fails
500 RSA key generation failed

18. Unpublish Event

Purpose: Reverts a PUBLISHED event back to DRAFT status. Only allowed if zero tickets have been sold across all ticket types. If tickets have been sold, the organizer must cancel the event instead.

Endpoint: PATCH /api/v1/e-events/{eventId}/unpublish

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The event to unpublish Must be a valid UUID

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Event unpublished successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. data.status will be "DRAFT".

Error Response Sample (tickets sold):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot unpublish: tickets have already been sold. Please cancel the event instead.",
  "action_time": "2025-02-17T10:30:45",
  "data": "Cannot unpublish: tickets have already been sold. Please cancel the event instead."
}

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found
400 Event is not currently PUBLISHED, or tickets have been sold

19. Cancel Event

Purpose: Cancels an event. Can be triggered from any non-terminal status (DRAFT, PUBLISHED, HAPPENING). This action is irreversible. If the event was published and tickets were sold, a bulk refund process is triggered.

Endpoint: PATCH /api/v1/e-events/{eventId}/cancel

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The event to cancel Must be a valid UUID

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Event cancelled successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse. data.status will be "CANCELLED".

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found
400 Event is already CANCELLED or COMPLETED

20. Update Published Event — Basic Info

Purpose: Updates the description and/or media of a published event. Title, category, and format changes are blocked on published events as the slug has already been shared publicly.

Endpoint: PATCH /api/v1/e-events/{eventId}/published/basic-info

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The published event to update Must be a valid UUID

Request JSON Sample:

{
  "description": "Updated: The biggest jazz event in East Africa. Now featuring 35 artists across 3 stages.",
  "media": {
    "banner": "https://cdn.example.com/banners/jazz-2025-v3.jpg",
    "thumbnail": "https://cdn.example.com/thumbs/jazz-2025-v3.jpg",
    "gallery": ["https://cdn.example.com/gallery/img1.jpg", "https://cdn.example.com/gallery/img2.jpg"]
  }
}

Request Body Parameters:

Parameter Type Required Description Validation
description string No Updated event description Min: 15, Max: 5000 characters
media object No Updated media URLs See media fields in Endpoint 1
media.banner string No Banner image URL Max: 500 characters
media.thumbnail string No Thumbnail image URL Max: 500 characters
media.gallery array No Gallery image URLs

Blocked fields: title, categoryId, eventFormat, and eventVisibility cannot be changed on a published event. Providing them will have no effect.

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Published event updated successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse.

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found
400 Event is not in PUBLISHED status
422 Validation failure on provided fields

21. Update Published Event — Registration Window

Purpose: Extends the registration close date for a published event. The new registrationClosesAt must be later than the current value — shortening the registration window is not allowed.

Endpoint: PATCH /api/v1/e-events/{eventId}/published/registration

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The published event to update Must be a valid UUID

Request JSON Sample:

{
  "registrationClosesAt": "2025-07-20T23:59:00+03:00"
}

Request Body Parameters:

Parameter Type Required Description Validation
registrationClosesAt ZonedDateTime Yes New registration close date Must be after the current registrationClosesAt; must not be after event end

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Registration window extended successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found
400 Event is not PUBLISHED
422 New close date is not after current close date, or is after event end

22. Update Published Event — Highlights

Purpose: Replaces the full list of highlights for a published event. Behavior is identical to the draft equivalent — sending an empty array clears all highlights.

Endpoint: PATCH /api/v1/e-events/{eventId}/published/highlights

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The published event to update Must be a valid UUID

Request Body: Same format as Endpoint 9 — Update Draft Highlights.

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Highlights updated successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found
400 Event is not PUBLISHED

23. Update Published Event — FAQs

Purpose: Replaces the full list of FAQs for a published event. Sending an empty array clears all FAQs.

Endpoint: PATCH /api/v1/e-events/{eventId}/published/faqs

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The published event to update Must be a valid UUID

Request Body: Same format as Endpoint 10 — Update Draft FAQs.

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "FAQs updated successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Possible Error Responses: Same as Endpoint 22 (401, 403, 404, 400).


24. Update Published Event — Lineup

Purpose: Replaces the full event lineup on a published event. Supports the same platform user enrichment as the draft equivalent.

Endpoint: PATCH /api/v1/e-events/{eventId}/published/lineup

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The published event to update Must be a valid UUID

Request Body: Same format as Endpoint 11 — Update Draft Lineup.

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Lineup updated successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found, or a userId in lineup does not exist
400 Event is not PUBLISHED

25. Update Published Event — Agenda

Purpose: Replaces the full event agenda on a published event. Supports the same platform user enrichment as the draft equivalent.

Endpoint: PATCH /api/v1/e-events/{eventId}/published/agenda

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The published event to update Must be a valid UUID

Request Body: Same format as Endpoint 12 — Update Draft Agenda.

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Agenda updated successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found, or a presenterId does not exist
400 Event is not PUBLISHED

26. Reveal Location (TBA → Actual)

Purpose: Reveals the actual location for an event that was originally published with eventFormat=TBA. The new format cannot be TBA. Required fields depend on the new format chosen.

Endpoint: PATCH /api/v1/e-events/{eventId}/published/reveal-location

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The published TBA event Must be a valid UUID

Request JSON Sample (revealing as IN_PERSON):

{
  "eventFormat": "IN_PERSON",
  "venue": {
    "name": "Mlimani City Arena",
    "address": "Sam Nujoma Road, Dar es Salaam",
    "coordinates": {
      "latitude": -6.7724,
      "longitude": 39.2083
    }
  }
}

Request JSON Sample (revealing as ONLINE):

{
  "eventFormat": "ONLINE",
  "virtualDetails": {
    "meetingLink": "https://zoom.us/j/123456789",
    "meetingId": "123 456 789",
    "passcode": "jazz2025"
  }
}

Request Body Parameters:

Parameter Type Required Description Validation
eventFormat string Yes The actual event format Enum: IN_PERSON, ONLINE, HYBRIDcannot be TBA
venue object Conditional Physical venue details Required when new format is IN_PERSON or HYBRID
venue.name string Yes (if venue) Venue name Max: 200 characters
venue.address string No Full address Max: 500 characters
venue.coordinates.latitude BigDecimal No GPS latitude
venue.coordinates.longitude BigDecimal No GPS longitude
virtualDetails object Conditional Virtual meeting details Required when new format is ONLINE or HYBRID
virtualDetails.meetingLink string Yes (if virtualDetails) Meeting URL Max: 500 characters
virtualDetails.meetingId string No Platform meeting ID Max: 100 characters
virtualDetails.passcode string No Meeting passcode Max: 100 characters

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Location revealed successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Possible Error Responses:

Status Scenario
401 No or expired token
403 Not the event organizer
404 Event not found
400 Event is not PUBLISHED, current format is not TBA, or new format is TBA
422 Missing required venue/virtual fields for the chosen format

27. Get Event by ID

Purpose: Retrieves full event details. Published events are publicly accessible without authentication. Draft events can only be viewed by their organizer.

Endpoint: GET /api/v1/e-events/{eventId}

Access Level: 🌐 Public (for PUBLISHED events) | 🔒 Protected (for DRAFT events — organizer only)

Authentication: Bearer Token (required only for DRAFT access)

Request Headers:

Header Type Required Description
Authorization string Conditional Required when accessing a DRAFT event

Path Parameters:

Parameter Type Required Description Validation
eventId UUID Yes The event to retrieve Must be a valid UUID

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Event retrieved successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": { "...": "Full EventResponse object" }
}

Success Response Fields: data is a full EventResponse.

Possible Error Responses:

Status Scenario
403 Attempting to access a DRAFT event without being its organizer
404 Event not found or is soft-deleted

28. Get My Events

Purpose: Returns a paginated list of all events (any status) created by the authenticated organizer.

Endpoint: GET /api/v1/e-events/my-events

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-based) Min: 1 1
size integer No Items per page Min: 1 10

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Events retrieved successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "content": [ "[ EventSummaryResponse objects ]" ],
    "totalElements": 12,
    "totalPages": 2
  }
}

Success Response Fields: data.content[] contains EventSummaryResponse objects. Pagination follows Standard Paginated Response Wrapper.

Possible Error Responses: 401 — see Shared Error: 401.


29. Get My Events by Status

Purpose: Returns a paginated list of the authenticated organizer's events filtered by a specific status.

Endpoint: GET /api/v1/e-events/my-events/status/{status}

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Path Parameters:

Parameter Type Required Description Validation
status string Yes Event status filter Enum: DRAFT, PUBLISHED, HAPPENING, CANCELLED, COMPLETED

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-based) Min: 1 1
size integer No Items per page Min: 1 10

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Events retrieved successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "content": [ "[ EventSummaryResponse objects ]" ],
    "totalElements": 5,
    "totalPages": 1
  }
}

Success Response Fields: Same as Endpoint 28.

Possible Error Responses:

Status Scenario
401 No or expired token
400 Invalid status enum value

30. Get Events Feed

Purpose: Returns a paginated list of all published events for the public discovery feed. Results are ordered by creation date descending. This endpoint will eventually incorporate a recommendation algorithm.

Endpoint: GET /api/v1/e-events/events-feed

Access Level: 🌐 Public

Authentication: None required

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-based) Min: 1 1
size integer No Items per page Min: 1 10

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Events feed retrieved successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "content": [ "[ EventSummaryResponse objects — PUBLISHED only ]" ],
    "totalElements": 87,
    "totalPages": 9
  }
}

Success Response Fields: data.content[] contains EventSummaryResponse objects (PUBLISHED status only).

Possible Error Responses: None expected (no authentication required).


31. Search Events

Purpose: Full-text search across published event titles. Results are ordered by start date ascending.

Endpoint: GET /api/v1/e-events/search

Access Level: 🌐 Public

Authentication: None required

Query Parameters:

Parameter Type Required Description Validation Default
query string Yes Search keyword(s) Non-empty string
page integer No Page number (1-based) Min: 1 1
size integer No Items per page Min: 1 10

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Search results retrieved successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "content": [ "[ EventSummaryResponse objects ]" ],
    "totalElements": 4,
    "totalPages": 1
  }
}

Success Response Fields: data.content[] contains EventSummaryResponse objects.

Possible Error Responses: None expected for normal queries (empty results return an empty content array, not a 404).


32. Filter Events by Date Range

Purpose: Returns published events whose schedule overlaps with the provided date range. An event is included if it starts before endDate AND ends after startDate (overlap logic, not exact range match).

Endpoint: GET /api/v1/e-events/filter/date

Access Level: 🌐 Public

Authentication: None required

Query Parameters:

Parameter Type Required Description Validation Default
startDate ZonedDateTime Yes Range start ISO 8601 with offset (e.g., 2025-07-01T00:00:00+03:00)
endDate ZonedDateTime Yes Range end ISO 8601 with offset; must be after startDate
page integer No Page number (1-based) Min: 1 1
size integer No Items per page Min: 1 10

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Filtered events retrieved successfully",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "content": [ "[ EventSummaryResponse objects ]" ],
    "totalElements": 7,
    "totalPages": 1
  }
}

Possible Error Responses:

Status Scenario
400 startDate is after endDate

33. Search and Filter Events (Combined)

Purpose: Combines keyword search with optional date range filtering in a single call. All parameters are optional — calling with no parameters is equivalent to getting the full published feed.

Endpoint: GET /api/v1/e-events/filter

Access Level: 🌐 Public

Authentication: None required

Query Parameters:

Parameter Type Required Description Validation Default
query string No Title keyword search
startDate ZonedDateTime No Date range start ISO 8601 with offset
endDate ZonedDateTime No Date range end ISO 8601 with offset; must be after startDate if both provided
page integer No Page number (1-based) Min: 1 1
size integer No Items per page Min: 1 10

Possible Error Responses:

Status Scenario
400 startDate is after endDate (when both are provided)

34. Search My Events (Organizer)

Purpose: Allows an organizer to search and filter within their own events across all statuses. Supports keyword, status filter, and date range simultaneously.

Endpoint: GET /api/v1/e-events/my-events/search

Access Level: 🔒 Protected (Organizer — own events only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>

Query Parameters:

Parameter Type Required Description Validation Default
query string No Keyword search on title
status string No Filter by status Enum: DRAFT, PUBLISHED, HAPPENING, CANCELLED, COMPLETED
startDate ZonedDateTime No Date range start ISO 8601 with offset
endDate ZonedDateTime No Date range end ISO 8601 with offset; must be after startDate if both provided
page integer No Page number (1-based) Min: 1 1
size integer No Items per page Min: 1 10

Possible Error Responses:

Status Scenario
401 No or expired token
400 startDate is after endDate

Quick Reference — Endpoint Summary

# Method Path Auth Description
1 POST /e-events/drafts 🔒 Create event draft
2 GET /e-events/drafts 🔒 List my drafts (paginated)
3 GET /e-events/drafts/{draftId} 🔒 Get draft by ID
4 DELETE /e-events/drafts/{draftId} 🔒 Discard a draft
5 PATCH /e-events/drafts/{draftId}/basic-info 🔒 Update basic info
6 PATCH /e-events/drafts/{draftId}/schedule 🔒 Update schedule / days
7 PATCH /e-events/drafts/{draftId}/location 🔒 Update venue / virtual details
8 PATCH /e-events/drafts/{draftId}/registration 🔒 Update registration window
9 PATCH /e-events/drafts/{draftId}/highlights 🔒 Update highlights
10 PATCH /e-events/drafts/{draftId}/faqs 🔒 Update FAQs
11 PATCH /e-events/drafts/{draftId}/lineup 🔒 Update lineup
12 PATCH /e-events/drafts/{draftId}/agenda 🔒 Update agenda
13 POST /e-events/draft/{eventId}/products/{productId} 🔒 Attach product (DRAFT or PUBLISHED)
14 DELETE /e-events/draft/{eventId}/products/{productId} 🔒 Remove product (DRAFT or PUBLISHED)
15 POST /e-events/draft/{eventId}/shops/{shopId} 🔒 Attach shop (DRAFT or PUBLISHED)
16 DELETE /e-events/draft/{eventId}/shops/{shopId} 🔒 Remove shop (DRAFT or PUBLISHED)
17 PATCH /e-events/{eventId}/publish 🔒 Publish event
18 PATCH /e-events/{eventId}/unpublish 🔒 Unpublish event (0 sales only)
19 PATCH /e-events/{eventId}/cancel 🔒 Cancel event (terminal)
20 PATCH /e-events/{eventId}/published/basic-info 🔒 Update description/media on published event
21 PATCH /e-events/{eventId}/published/registration 🔒 Extend registration close date
22 PATCH /e-events/{eventId}/published/highlights 🔒 Update highlights on published event
23 PATCH /e-events/{eventId}/published/faqs 🔒 Update FAQs on published event
24 PATCH /e-events/{eventId}/published/lineup 🔒 Update lineup on published event
25 PATCH /e-events/{eventId}/published/agenda 🔒 Update agenda on published event
26 PATCH /e-events/{eventId}/published/reveal-location 🔒 Reveal TBA location
27 GET /e-events/{eventId} 🌐/🔒 Get event by ID
28 GET /e-events/my-events 🔒 List my events
29 GET /e-events/my-events/status/{status} 🔒 My events by status
30 GET /e-events/events-feed 🌐 Public events feed
31 GET /e-events/search 🌐 Search events by keyword
32 GET /e-events/filter/date 🌐 Filter by date range
33 GET /e-events/filter 🌐 Combined search + filter
34 GET /e-events/my-events/search 🔒 Search within my events

Note on path inconsistency: Endpoints 5–12 use the path prefix /drafts/{id}/... (plural), while endpoints 6, 7, 13–16 use /draft/{id}/... (singular). This reflects the actual controller routing in the current codebase — use the exact paths shown in the table above.


Data Format Standards

Concern Standard
Timestamps ISO 8601 with timezone offset: 2025-07-18T18:00:00+03:00
Dates YYYY-MM-DD format: 2025-07-18
Times HH:mm:ss (24-hour): 18:00:00
IDs UUID v4: 3fa85f64-5717-4562-b3fc-2c963f66afa6
Pagination 1-based page query parameter, Spring Page wrapper in response
Prices BigDecimal with 2 decimal places; 0.00 for free
Enums Uppercase strings as defined (e.g., IN_PERSON, PUBLISHED)