Attendance Analytics API
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.
Hints:
- Organizer Only: All endpoints restricted to the event organizer
- Unified List: Present and absent tickets are in one list — use
?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: Unique human-readable ticket ID =
bookingReference + "-" + 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= online purchase with account,AT_DOOR= walk-in name only (no account) - Day Filtering:
?dayNumberis optional — omit for overall view, provide for per-day status - Partial Attendance:
PARTIALLY_ATTENDEDonly applies when nodayNumberfilter is set on multi-day events - Pagination: Default 20 per page
- Form Response:
formResponseIdon each attendee/ticket row links to the buyer's applicant form submission —nullif the event had no form or the form was not yet submitted
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": "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 - 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 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": "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": "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 Fields:
| Field | Description |
|---|---|
data.eventId |
Event UUID |
data.eventTitle |
Event name |
data.totalDays |
Number of event days |
data.eventSchedule |
List of days with 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 only) |
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": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"eventTitle": "East African Tech Summit 2026",
"appliedFilters": {
"ticketTypeId": "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": "3fa85f64-5717-4562-b3fc-2c963f66afa8",
"formResponseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"attendeeNumber": "EVT-A3F4B21C-VIP-0042",
"ticketTypeId": "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": "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": "3fa85f64-5717-4562-b3fc-2c963f66afb0"
},
{
"ticketInstanceId": "3fa85f64-5717-4562-b3fc-2c963f66afb1",
"formResponseId": null,
"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 Fields:
| 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) |
data.summary.present |
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) / total) × 100, 2 dp |
data.attendees[].ticketInstanceId |
Unique ticket instance UUID |
data.attendees[].formResponseId |
UUID of the buyer's applicant form response — null if the event had no form |
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:
{
"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 Error Types:
3. Get Attendee Detail
Purpose: Returns the full check-in history for a 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": "3fa85f64-5717-4562-b3fc-2c963f66afa8",
"formResponseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"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": "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
}
]
}
}
Success Response Fields:
| Field | Description |
|---|---|
data.ticketInstanceId |
Unique ticket instance UUID |
data.formResponseId |
UUID of the buyer's applicant form response — null if the event had no form |
data.attendeeNumber |
Unique readable ID = bookingReference + "-" + ticketSeries |
data.overallStatus |
PRESENT (all days), PARTIALLY_ATTENDED (some), ABSENT (none) |
data.daysAttended |
Count of days this ticket was checked in |
data.daysTotal |
Total number of event days |
data.checkInsByDay[].status |
CHECKED_IN, NOT_CHECKED_IN, or UPCOMING |
data.checkInsByDay[].checkInTime |
null when not checked in or day is upcoming |
data.checkInsByDay[].checkedInBy |
Name of the scanner operator who processed the check-in |
Error 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:
Quick Reference Guide
Attendance Status Values
| Value | Meaning | Available when |
|---|---|---|
PRESENT |
Checked in (all days if no day filter) | Always |
ABSENT |
Never checked in | Always |
PARTIALLY_ATTENDED |
Checked in some days but not all | No dayNumber filter, multi-day events only |
Day Status Values
| Value | Meaning |
|---|---|
CHECKED_IN |
Ticket was scanned on that day |
NOT_CHECKED_IN |
Day passed, ticket not scanned |
UPCOMING |
Day has not started yet |
Buyer Type Values
| Value | buyerEmail |
buyerId |
Meaning |
|---|---|---|---|
SYSTEM_USER |
Populated | Populated | Bought online, has platform account |
AT_DOOR |
null |
null |
Walk-in sale, name only captured at door |
Common HTTP Status Codes
200 OK: Successful request401 UNAUTHORIZED: Authentication required or token invalid403 FORBIDDEN: Not the event organizer404 NOT_FOUND: Event, ticket, or day number not found500 INTERNAL_SERVER_ERROR: Unexpected server error
No comments to display
No comments to display