Overview
The Attendees API allows you to manage attendees for your events, including creating, updating, and deleting attendee records. Each attendee is assigned a unique 8-character ID for check-in purposes.
The Attendee Object
Unique UUID identifier for the attendee
UUID of the event this attendee belongs to
Attendee’s full name (max 200 characters)
Unique 8-character alphanumeric ID for check-in (e.g., “A3F7K9M2”)
Whether the attendee has checked in
Timestamp when the attendee checked in (ISO 8601 format)
Method used for check-in: manual, qr_scan, or self_service
Whether the attendee portal is active for this attendee
Whether a confirmation email has been sent
Object containing custom field values (e.g., {"Department": "Engineering", "Seat": "A12"})
Timestamp when the attendee was created
Timestamp when the attendee was last updated
List Attendees
Retrieve all attendees for an event:
const { data : attendees , error } = await supabase
. from ( 'attendees' )
. select ( '*' )
. eq ( 'event_id' , eventId )
. order ( 'created_at' , { ascending: false })
if ( error ) {
console . error ( 'Error fetching attendees:' , error )
} else {
console . log ( 'Attendees:' , attendees )
}
Response
[
{
"id" : "456e7890-e89b-12d3-a456-426614174001" ,
"event_id" : "123e4567-e89b-12d3-a456-426614174000" ,
"name" : "Jane Smith" ,
"email" : "[email protected] " ,
"unique_id" : "K7M9P2Q5" ,
"checked_in" : false ,
"checked_in_at" : null ,
"checkin_method" : null ,
"portal_active" : true ,
"confirmation_email_sent" : true ,
"custom_fields" : {
"Department" : "Engineering" ,
"Seat" : "A12"
},
"created_at" : "2026-03-01T10:30:00Z" ,
"updated_at" : "2026-03-01T10:30:00Z"
}
]
Get Attendee
Retrieve a single attendee by ID:
const { data : attendee , error } = await supabase
. from ( 'attendees' )
. select ( '*' )
. eq ( 'id' , attendeeId )
. single ()
if ( error ) {
console . error ( 'Error fetching attendee:' , error )
} else {
console . log ( 'Attendee:' , attendee )
}
Create Attendee
Add a new attendee to an event (requires 1 attendee token):
Single Attendee
Bulk Import
// Generate unique ID
function generateUniqueId () {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
let result = ''
for ( let i = 0 ; i < 8 ; i ++ ) {
result += chars [ Math . floor ( Math . random () * chars . length )]
}
return result
}
// Deduct token
const { data : deducted , error : tokenError } = await supabase . rpc (
'deduct_attendee_tokens' ,
{
_organization_id: organizationId ,
_count: 1
}
)
if ( tokenError || ! deducted ) {
console . error ( 'Insufficient attendee tokens' )
return
}
// Create attendee
const { data : attendee , error } = await supabase
. from ( 'attendees' )
. insert ({
event_id: eventId ,
name: 'John Doe' ,
email: '[email protected] ' ,
unique_id: generateUniqueId (),
custom_fields: {
Department: 'Sales' ,
Seat: 'B5'
}
})
. select ()
. single ()
if ( error ) {
console . error ( 'Error creating attendee:' , error )
} else {
console . log ( 'Attendee created:' , attendee )
}
Parameters
Update Attendee
Update attendee information:
const { data : attendee , error } = await supabase
. from ( 'attendees' )
. update ({
name: 'Jane Smith-Doe' ,
email: '[email protected] ' ,
custom_fields: {
Department: 'Engineering' ,
Seat: 'A15'
}
})
. eq ( 'id' , attendeeId )
. select ()
. single ()
if ( error ) {
console . error ( 'Error updating attendee:' , error )
} else {
console . log ( 'Attendee updated:' , attendee )
}
Delete Attendee
Delete an attendee:
const { error } = await supabase
. from ( 'attendees' )
. delete ()
. eq ( 'id' , attendeeId )
if ( error ) {
console . error ( 'Error deleting attendee:' , error )
} else {
console . log ( 'Attendee deleted successfully' )
}
Deleting an attendee does NOT automatically return attendee tokens. Tokens are only returned when the entire event is deleted.
Toggle Portal Access
Enable or disable portal access for an attendee:
const { error } = await supabase
. from ( 'attendees' )
. update ({ portal_active: true })
. eq ( 'id' , attendeeId )
if ( error ) {
console . error ( 'Error toggling portal:' , error )
} else {
console . log ( 'Portal access updated' )
}
Search Attendees
Search attendees by name, email, or unique ID:
const searchTerm = 'john'
const { data : results } = await supabase
. from ( 'attendees' )
. select ( '*' )
. eq ( 'event_id' , eventId )
. or ( `unique_id.ilike.% ${ searchTerm } %,email.ilike.% ${ searchTerm } %,name.ilike.% ${ searchTerm } %` )
. limit ( 20 )
if ( results ) {
console . log ( 'Search results:' , results )
}
Get Attendee Portal Data
Retrieve attendee data for the public portal (no authentication required):
const { data : portalData } = await supabase . rpc (
'get_attendee_portal_data' ,
{
_event_id: eventId ,
_unique_id: 'K7M9P2Q5'
}
)
if ( portalData && portalData . length > 0 ) {
const attendee = portalData [ 0 ]
console . log ( 'Portal data:' , attendee )
}
Response
Filter Attendees
By Check-in Status
// Get checked-in attendees
const { data : checkedIn } = await supabase
. from ( 'attendees' )
. select ( '*' )
. eq ( 'event_id' , eventId )
. eq ( 'checked_in' , true )
// Get pending attendees
const { data : pending } = await supabase
. from ( 'attendees' )
. select ( '*' )
. eq ( 'event_id' , eventId )
. eq ( 'checked_in' , false )
By Email Status
const { data : emailSent } = await supabase
. from ( 'attendees' )
. select ( '*' )
. eq ( 'event_id' , eventId )
. eq ( 'confirmation_email_sent' , true )
By Portal Access
const { data : activePortals } = await supabase
. from ( 'attendees' )
. select ( '*' )
. eq ( 'event_id' , eventId )
. eq ( 'portal_active' , true )
Export Attendees
Export attendee data for reporting:
// Get all attendees with check-in data
const { data : attendees } = await supabase
. from ( 'attendees' )
. select ( 'name, email, unique_id, checked_in, checked_in_at, checkin_method, portal_active, custom_fields' )
. eq ( 'event_id' , eventId )
. order ( 'created_at' , { ascending: false })
// Format for export
const exportData = attendees ?. map ( a => ({
Name: a . name ,
Email: a . email ,
'Unique ID' : a . unique_id ,
'Checked In' : a . checked_in ? 'Yes' : 'No' ,
'Check-In Time' : a . checked_in_at || '' ,
'Check-In Method' : a . checkin_method || '' ,
'Portal Active' : a . portal_active ? 'Yes' : 'No' ,
... a . custom_fields
}))
console . log ( 'Export data:' , exportData )
Validation
Always validate attendee data before insertion:
Name: 1-200 characters, no HTML tags
Email: Valid email format, max 255 characters
Unique ID: 8 alphanumeric characters, unique per event
Custom fields: Max 50 characters per field name, max 500 characters per value
function validateAttendee ( data : any ) : string [] {
const errors : string [] = []
if ( ! data . name || data . name . length > 200 ) {
errors . push ( 'Invalid name' )
}
const emailRegex = / ^ [ ^ \s@ ] + @ [ ^ \s@ ] + \. [ ^ \s@ ] + $ /
if ( ! data . email || ! emailRegex . test ( data . email )) {
errors . push ( 'Invalid email' )
}
if ( ! data . unique_id || data . unique_id . length !== 8 ) {
errors . push ( 'Invalid unique ID' )
}
return errors
}
Next Steps
Check-ins API Check in attendees at your event
Email API Send confirmation emails to attendees