Attendance Analytics API
Attendance Management API Documentation
Base URL: https://api.nexgate.com/api/v1
Short Description: The Attendance Management API provides comprehensive attendee tracking and analytics for event organizers. Organizers can view overall attendance statistics with per-day and per-ticket-type breakdowns, browse a unified attendance list (present, absent, and partially attended in one view) with rich filtering, and drill into the full check-in history for any individual ticket. The system supports both single-day and multi-day events. All status filtering, day filtering, buyer-type filtering, and search are handled through query parameters on a single list endpoint.
Hints:
- Organizer Only: All endpoints restricted to the event organizer
- Unified List: Present and absent tickets are in one list —
filter withuse?status=PRESENT|ABSENT|PARTIALLY_ATTENDEDto filter - Ticket-Based Rows: Each row in the list is one ticket, not one person — one buyer can appear multiple times
- Attendee Number:
EachUnique human-readable tickethas a uniqueID =attendeeNumberbookingReference + "-" + ticketSeries(e.g.EVT-A3F4B21C-VIP-0042) - Buyer vs Attendee:
buyer= who paid,attendee= who holds the ticket — can be different people - Buyer Types:
SYSTEM_USER=boughtonlineonline,purchase with account,AT_DOOR= walk-in namecaptured at dooronly (no account) Multi-DaySupportFiltering:Per-day filtering via?is optional —dayNumber=1dayNumberoptional,omit for overallviewview, provide for per-day status- Partial Attendance:
PARTIALLY_ATTENDED=onlycheckedappliesinwhensomenodaysdayNumberbutfilternotisallset(on multi-day eventsonly) - Pagination: Default 20 per page
Standard Response StructuresFormat
All API responses follow a consistent structure using our Globe Response Builder pattern:
AttendanceSummaryResponseSuccess Response Structure
Returned
{
by"success": true,
"httpStatus": "OK",
"message": "Operation completed successfully",
"action_time": "2026-05-23T10:30:45",
"data": {
}
}
Error Response Structure
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Error description",
"action_time": "2026-05-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, NOT_FOUND, FORBIDDEN, etc.) |
message |
string | Human-readable message describing the result |
action_time |
string | ISO 8601 timestamp of when the response was generated |
data |
object | Response payload for success, error string for failures |
HTTP Method Badge Standards
- GET
/summary.- GET - Green (Safe, read-only operations) - POST - POST - Blue (Create new resources)
- PUT - PUT - Yellow (Update/replace entire resource)
- PATCH - PATCH - Orange (Partial updates)
- DELETE - DELETE - Red (Remove resources)
Endpoints
1. Get Attendance Summary
Purpose: Returns overall attendance statistics for an event including per-day and per-ticket-type breakdowns. Always covers the full event — no filtering.filtering applied.
Endpoint: GET /e-events/attendance/{eventId}/summary
Access Level: 🔒 Protected — Event Organizer 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 | Event identifier | Must be a valid UUID of an existing event owned by the authenticated organizer |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Attendance summary retrieved",
"action_time": "2026-05-23T10:30:45",
"data": {
"eventId": "uuid"3fa85f64-5717-4562-b3fc-2c963f66afa6",
"eventTitle": "East African Tech Summit 2026",
"totalDays": 3,
"eventSchedule": [
{ "dayNumber": 1, "dayName": "Day 1 - Opening", "date": "2026-12-15" },
{ "dayNumber": 2, "dayName": "Day 2 - Conference", "date": "2026-12-16" },
{ "dayNumber": 3, "dayName": "Day 3 - Closing", "date": "2026-12-17" }
],
"overallStats": {
"totalTickets": 500,
"present": 310,
"partiallyAttended": 45,
"absent": 145,
"attendanceRate": 71.0,
"byDay": [
{
"dayNumber": 1,
"dayName": "Day 1 - Opening",
"date": "2026-12-15",
"totalTickets": 500,
"checkedIn": 400,
"absent": 100,
"attendanceRate": 80.0,
"status": "COMPLETED"
},
{
"dayNumber": 2,
"dayName": "Day 2 - Conference",
"date": "2026-12-16",
"totalTickets": 500,
"checkedIn": 355,
"absent": 145,
"attendanceRate": 71.0,
"status": "ONGOING"
},
{
"dayNumber": 3,
"dayName": "Day 3 - Closing",
"date": "2026-12-17",
"totalTickets": 500,
"checkedIn": 0,
"absent": 500,
"attendanceRate": 0.0,
"status": "UPCOMING"
}
]
},
"byTicketType": [
{
"ticketTypeId": "uuid"3fa85f64-5717-4562-b3fc-2c963f66afa7",
"ticketTypeName": "VIP Pass",
"totalSold": 100,
"present": 75,
"partiallyAttended": 10,
"absent": 15,
"attendanceRate": 85.0,
"byDay": [
{
"dayNumber": 1,
"dayName": "Day 1 - Opening",
"checkedIn": 90,
"absent": 10,
"attendanceRate": 90.0
}
]
}
]
}
}
Success
Response AttendanceListResponseReturnedFields
| Field | Description |
|---|---|
|
Event UUID |
data.eventTitle |
Event |
|
Number |
|
List dayNumber, dayName, date |
data.overallStats.totalTickets |
Total tickets sold |
data.overallStats.present |
Tickets checked in for all days |
data.overallStats.partiallyAttended |
Tickets checked in for some days (multi-day |
data.overallStats.absent |
Tickets never checked in |
data.overallStats.attendanceRate |
((present + partiallyAttended) / total) × 100, 2 dp |
data.overallStats.byDay[].status |
COMPLETED, ONGOING, or UPCOMING |
data.byTicketType |
Same stats broken down per ticket type |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Event not found",
"action_time": "2026-05-23T10:30:45",
"data": "Event not found"
}
Standard Error Types:
2. Get Attendance List
Purpose: Returns a paginated, filterable list of all tickets for an event. Each row is one ticket. Present and absent tickets are unified in one list — use the status filter to narrow down.
Endpoint: GET /e-events/attendance/{eventId}/list
Access Level: 🔒 Protected — Event Organizer 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 | Event identifier | Must be a valid UUID of an existing event owned by the authenticated organizer |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
status |
enum | No | Filter by attendance status | PRESENT, ABSENT, PARTIALLY_ATTENDED |
All |
dayNumber |
integer | No | Filter for a specific event day | Must be between 1 and totalDays |
None (overall) |
ticketTypeId |
UUID | No | Filter by ticket type | Must belong to this event | All types |
buyerType |
enum | No | Filter by how the ticket was purchased | SYSTEM_USER, AT_DOOR |
All |
search |
string | No | Search by attendee name, email, or phone | Partial match, case-insensitive | None |
page |
integer | No | Page number (0-indexed) | Min: 0 |
0 |
size |
integer | No | Items per page | Min: 1 |
20 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Attendance list retrieved",
"action_time": "2026-05-23T10:30:45",
"data": {
"eventId": "uuid"3fa85f64-5717-4562-b3fc-2c963f66afa6",
"eventTitle": "East African Tech Summit 2026",
"appliedFilters": {
"ticketTypeId": "uuid"3fa85f64-5717-4562-b3fc-2c963f66afa7",
"ticketTypeName": "VIP Pass",
"status": "ALL",
"dayNumber": 1,
"dayName": "Day 1 - Opening",
"buyerType": "ALL",
"search": null
},
"summary": {
"totalTickets": 100,
"present": 90,
"absent": 10,
"partiallyAttended": null,
"attendanceRate": 90.0
},
"attendees": [
{
"ticketInstanceId": "uuid"3fa85f64-5717-4562-b3fc-2c963f66afa8",
"attendeeNumber": "EVT-A3F4B21C-VIP-0042",
"ticketTypeId": "uuid"3fa85f64-5717-4562-b3fc-2c963f66afa7",
"ticketType": "VIP Pass",
"ticketSeries": "VIP-0042",
"attendeeName": "John Doe",
"attendeeEmail": "john@example.com",
"attendeePhone": "+255712345678",
"buyer": {
"buyerName": "Jane Doe",
"buyerEmail": "jane@example.com",
"buyerId": "uuid"3fa85f64-5717-4562-b3fc-2c963f66afa9",
"buyerType": "SYSTEM_USER"
},
"bookingReference": "EVT-A3F4B21C",
"pricePaid": 150.00,
"attendanceStatus": "PRESENT",
"checkInTime": "2026-12-15T09:15:00+03:00",
"checkInLocation": "Main Gate",
"checkedInBy": "Scanner Operator 1",
"scannerId": "uuid-string"3fa85f64-5717-4562-b3fc-2c963f66afb0"
},
{
"ticketInstanceId": "uuid-2"3fa85f64-5717-4562-b3fc-2c963f66afb1",
"attendeeNumber": "EVT-B5D2E12F-GENE-0101",
"ticketType": "General Admission",
"ticketSeries": "GENE-0101",
"attendeeName": "Ali Hassan",
"attendeeEmail": null,
"attendeePhone": null,
"buyer": {
"buyerName": "Ali Hassan",
"buyerEmail": null,
"buyerId": null,
"buyerType": "AT_DOOR"
},
"bookingReference": "EVT-B5D2E12F",
"pricePaid": 50.00,
"attendanceStatus": "ABSENT",
"checkInTime": null,
"checkInLocation": null,
"checkedInBy": null,
"scannerId": null
}
],
"pagination": {
"currentPage": 0,
"pageSize": 20,
"totalPages": 5,
"totalElements": 100,
"hasNext": true,
"hasPrevious": false
}
}
}
Success
Response AttendeeDetailResponseReturnedFields
| Field | Description |
|---|---|
data.appliedFilters |
Echo of all active filters so the client knows what was applied |
data.summary.totalTickets |
Total tickets matching the ticket type filter (unaffected by status/search) |
|
Tickets with PRESENT status under current filters |
data.summary.absent |
Tickets with ABSENT status under current filters |
data.summary.partiallyAttended |
null when dayNumber is active; count when viewing overall multi-day |
data.summary.attendanceRate |
((present + partiallyAttended) /, 2 dp |
data.attendees[].attendeeNumber |
Unique readable ID = bookingReference + "-" + ticketSeries |
data.attendees[].attendanceStatus |
PRESENT, ABSENT, or PARTIALLY_ATTENDED |
data.attendees[].buyer.buyerType |
SYSTEM_USER (online) or AT_DOOR (walk-in) |
data.attendees[].buyer.buyerId |
Populated for SYSTEM_USER, null for AT_DOOR |
data.attendees[].checkInTime |
null when attendanceStatus is ABSENT |
data.pagination |
Standard pagination envelope |
Notes:
- When
dayNumberis provided:attendanceStatusisPRESENTorABSENTfor that specific day only - When
dayNumberis omitted:attendanceStatusreflects the overall across all days (PARTIALLY_ATTENDEDpossible) summaryreflects the current filter scope, not the whole eventpartiallyAttendedinsummaryisnullwhen adayNumberfilter is active
Error Response JSON Sample:
{ticketInstanceId}"success": false, "httpStatus": "NOT_FOUND", "message": "Invalid day 5. Valid: 1-3", "action_time": "2026-05-23T10:30:45", "data": "Invalid day 5. Valid: 1-3" }.
Standard per-Error Types:
3. Get Attendee Detail
Purpose: Returns the full check-in history for onea ticket.single ticket across all event days. Shows per-day status including upcoming days.
Endpoint: GET /e-events/attendance/{eventId}/attendees/{ticketInstanceId}
Access Level: 🔒 Protected — Event Organizer 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 | Event identifier | Must be owned by the authenticated organizer |
ticketInstanceId |
UUID | Yes | Individual ticket instance identifier | Must belong to a booking under this event |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Attendee detail retrieved",
"action_time": "2026-05-23T10:30:45",
"data": {
"ticketInstanceId": "uuid"3fa85f64-5717-4562-b3fc-2c963f66afa8",
"attendeeNumber": "EVT-A3F4B21C-VIP-0042",
"attendeeName": "John Doe",
"attendeeEmail": "john@example.com",
"attendeePhone": "+255712345678",
"ticketType": "VIP Pass",
"ticketSeries": "VIP-0042",
"bookingReference": "EVT-A3F4B21C",
"pricePaid": 150.00,
"overallStatus": "PARTIALLY_ATTENDED",
"daysAttended": 2,
"daysTotal": 3,
"checkInsByDay": [
{
"dayNumber": 1,
"dayName": "Day 1 - Opening",
"dayDate": "2026-12-15",
"status": "CHECKED_IN",
"checkInTime": "2026-12-15T09:15:00+03:00",
"checkInLocation": "Main Gate",
"checkedInBy": "Scanner Operator 1",
"scannerId": "uuid-string"3fa85f64-5717-4562-b3fc-2c963f66afb0"
},
{
"dayNumber": 2,
"dayName": "Day 2 - Conference",
"dayDate": "2026-12-16",
"status": "NOT_CHECKED_IN",
"checkInTime": null,
"checkInLocation": null,
"checkedInBy": null,
"scannerId": null
},
{
"dayNumber": 3,
"dayName": "Day 3 - Closing",
"dayDate": "2026-12-17",
"status": "UPCOMING",
"checkInTime": null,
"checkInLocation": null,
"checkedInBy": null,
"scannerId": null
}
]
}
}
Endpoints
1. Get Attendance Summary
Endpoint:Success GETResponse /attendance/{eventId}/summary
Access: 🔒 Event Organizer Only
Path ParametersFields:
| Description | |||
|---|---|---|---|
data.attendeeNumber |
Success Response: Returns AttendanceSummaryResponse
Success Response Message: "Attendance summary retrieved"
Behavior:
Validates organizer owns the eventReturns overall attendance metrics across all ticketsBreaks down by day (all events, including single-day)Breaks down by ticket type with per-day statspresent= checked in for all days,partiallyAttended= some days,absent= noneattendanceRateincludes bothpresentandpartiallyAttendedtickets
Errors:
403 FORBIDDEN: Not event organizer404 NOT_FOUND: Event not found
2. Get Attendance List
Endpoint: GET /attendance/{eventId}/list
Access: 🔒 Event Organizer Only
Path Parameters:
Query Parameters:
| |||
| |||
| |||
|
Success Response: Returns AttendanceListResponse with pagination
Success Response Message: "Attendance list retrieved"
Behavior:
Returns one row per ticket (not per person)One buyer can appear multiple times if they purchased multiple ticketsID =attendeeNumberbookingReference + "-" + ticketSeries(uniqueperticket)data.overallStatusWhendayNumberis set:attendanceStatusisPRESENTor(all days),PARTIALLY_ATTENDED(some),ABSENTfor(none)thatspecificdaydata.daysAttendedWhenCount dayNumberis omitted:attendanceStatusreflects overall across allof days(thisPARTIALLY_ATTENDEDpossible)ticketwassummaryblock always reflects the current filter scope (not the full event)checked inpartiallyAttendedsummaryisdata.daysTotalTotal number of event days data.checkInsByDay[].statusCHECKED_IN,NOT_CHECKED_IN, orUPCOMINGdata.checkInsByDay[].checkInTimenullwhenanotcheckeddayNumberfilterin or day isactiveupcomingdata.checkInsByDay[].checkedInByName of the scanner operator who processed the check-in ValidationError Response JSON Sample:{ "success": false, "httpStatus": "NOT_FOUND", "message": "Ticket not found", "action_time": "2026-05-23T10:30:45", "data": "Ticket not found" }Standard Error Types:
Errors:403 FORBIDDEN:NotAuthenticated user is not the event organizer404 NOT_FOUND: Event not found/ invalid day number /or tickettypeinstance does notfoundbelong to this event
3.QuickGetReferenceAttendee DetailGuideEndpoint:GET/attendance/{eventId}/attendees/{ticketInstanceId}Access: 🔒 Event Organizer OnlyPath Parameters:ParameterTypeRequiredDescriptioneventIdstring (UUID)YesEvent identifierticketInstanceIdstring (UUID)YesIndividual ticket instance identifierSuccess Response: ReturnsAttendeeDetailResponseSuccess Response Message:"Attendee detail retrieved"Behavior:Returns the full check-in history for one specific ticket across all event daysoverallStatuscomputed from all dayscheckInsByDaylists every event day with its status and check-in detailsDay status reflects whether the day has passed, is today, or is upcoming
Errors:403 FORBIDDEN: Not event organizer404 NOT_FOUND: Event or ticket not found
Key ConceptsAttendee NumberEvery ticket has a uniqueattendeeNumberformatted as:{bookingReference}-{ticketSeries}Example:EVT-A3F4B21C-VIP-0042Use this as the primary human-readable identifier for a ticket on the attendance list — safer thanticketInstanceId(UUID) for display and manual lookup.Buyer vs AttendeeThese are two different people on the same ticket:FieldWhoattendeeName/attendeeEmailThe person who will attend (holds the ticket)buyer.buyerName/buyer.buyerEmailThe person who paidExample: Jane buys 3 VIP tickets. She is the buyer on all 3. The attendees are John, Ali, and herself.One buyer can appear multiple times in the list — once per ticket they purchased.Buyer TypesValueMeaningSYSTEM_USERBought online — has a platform account,buyerIdis populatedAT_DOORWalk-in sale — only name captured at door,buyerEmailandbuyerIdarenull
Attendance Status Values
Value Meaning WhenAvailable whenPRESENTChecked in (all days if no day filter) WithdayNumber: checked in that day. Without: checked in all daysAlwaysABSENTNotNever checked inWithdayNumber: not that day. Without: never checked inAlwaysPARTIALLY_ATTENDEDChecked in some days but not all Only possible withoutNodayNumberfilter,onmulti-day events onlyDay Status
(in detail view)ValuesValue Meaning CHECKED_INScannedTicket was scanned on that dayNOT_CHECKED_INDay haspassed,wasticket not scannedUPCOMINGDay has not happenedstarted yetBuyer
AttendanceTypeRate CalculationattendanceRate = ((present + partiallyAttended) / totalTickets) × 100Rounded to 2 decimal places.Per-day rate(in summarybyDay):rate = (checkedIn for that day / totalTickets) × 100Multi-Day Event LogicDay Filter BehaviourValuesValue dayNumberbuyerEmailStatusbuyerIdscopeMeaning Provided (e.g.?dayNumber=2SYSTEM_USER)StatusPopulated=Populated didBought thisonline,tickethascheckplatformin on Day 2? (PRESENTorABSENTonly)accountOmittedAT_DOORStatusnull=nulloverallWalk-in acrosssale,allnamedaysonly(PRESENT,capturedABSENT,atorPARTIALLY_ATTENDED)doorDayCommon
number validation:Event has 3 days → dayNumber must be 1, 2, or 3 Request dayNumber=5 → 404: "Invalid day 5. Valid: 1-3"Single-day events:dayNumberis always optional. Omitting it gives the same result as?dayNumber=1.Use CasesDashboard OverviewGET /attendance/{eventId}/summary Use: top-of-page stats card Shows: overall rate, per-day breakdown, per-ticket-type breakdownFull Attendance TableGET /attendance/{eventId}/list Use: default organizer table view — all tickets, all statusesWho Attended Today (Day 2)GET /attendance/{eventId}/list?dayNumber=2&status=PRESENT Shows: tickets checked in on Day 2Who Missed TodayGET /attendance/{eventId}/list?dayNumber=2&status=ABSENT Shows: tickets that didn't check in on Day 2 (regardless of other days)At-Door Walk-Ins OnlyGET /attendance/{eventId}/list?buyerType=AT_DOOR Shows: all tickets sold at the doorPartially Attended (Multi-Day)GET /attendance/{eventId}/list?status=PARTIALLY_ATTENDED Shows: tickets that attended some days but not all Requires: no dayNumber filterSearch by NameGET /attendance/{eventId}/list?search=john Matches: attendee name, email, or phone containing "john"Individual Ticket HistoryGET /attendance/{eventId}/attendees/{ticketInstanceId} Shows: full per-day check-in record for one ticketQuick ReferenceHTTP Status Codes
200 OK:SuccessSuccessful request401 UNAUTHORIZED:NotAuthenticationauthenticatedrequired or token invalid403 FORBIDDEN: Not the event organizer404 NOT_FOUND:EventEvent,/ticket,ticket /or day number not found
Attendance Status Values:PRESENT500 INTERNAL_SERVER_ERROR—Unexpectedattendedserver(all days if no day filter)ABSENT— did not attendPARTIALLY_ATTENDED— attended some days (multi-day, no day filter)error
Day Status ValuesCOMPLETED— day has passedONGOING— day is todayUPCOMING— day has not started
Buyer Type ValuesSYSTEM_USER— online purchase, has platform accountAT_DOOR— walk-in, name only, no account
Default Paginationpage:0(first page)size:20items per page