Event Check-in & Anonymous Identifiers
This document describes the event check-in system, anonymous registration flows, and how anonymous identifiers are used across the platform.Check-in System Overview
The check-in system supports three primary flows:Logged-in self check-in
Users with accounts check in from the event page or via token link
Token-based check-in
Anyone with a valid check-in token (QR code or link) can access check-in
Anonymous pick-your-registration
Unauthenticated users with a token search and select their registration to check in
Check-in Settings
Events can configure check-in behavior viacheckInSettings:
| Setting | Description |
|---|---|
allowEarlyCheckIn | Allow check-in before event start time |
allowAnonymousCheckIn | Enable anonymous (FormResponse) registrations in check-in list |
allowOnPageCheckIn | Allow check-in from the event page (vs. token link only) |
requireRegistration | Require registration before check-in (logged-in users) |
autoCheckIn | Automatically check in when conditions are met |
Check-in Token
Each event with check-in enabled has acheckInToken — a secret hex string used to gate check-in access. The token is:
- Included in QR codes and check-in links (e.g.
/check-in/:eventId/:token) - Required for anonymous flows — self-registrations and anonymous check-in endpoints validate the token
- Not exposed to unauthenticated users except via the check-in URL (e.g. from QR scan)
Check-in Flows
1. Logged-in Self Check-in (no token)
Route: Event page → Check In buttonEndpoint:
POST /events/:eventId/check-in/selfAuth: Required (
verifyToken)
- User must be logged in
- No token needed
- Uses
req.user.userIdto find/create attendee - Validates event time and
requireRegistrationif set
2. Logged-in Token Check-in
Route:/check-in/:eventId/:tokenEndpoint:
POST /events/:eventId/check-inBody:
{ token }Auth: Optional (
verifyTokenOptional)
- User is logged in and has the token in the URL
- Token validates access
- Same logic as self check-in but with token validation
3. Anonymous Pick-Your-Registration
Route:/check-in/:eventId/:token (user not logged in)Endpoints:
GET /events/:eventId/check-in/self-registrations?token=xxx— list registrationsGET /events/:eventId/check-in/registration/:formResponseId?token=xxx— form detailsPOST /events/:eventId/check-in/anonymous— check in byuserIdorformResponseId
Auth: None (token validates)
- User opens check-in link (from QR or event page) with token
- Frontend fetches registrations via
self-registrations - User searches by name/email and selects their registration
- User can “View details” to see their full registration form (anonymous only)
- User clicks “Check In” →
POST /events/:eventId/check-in/anonymouswith{ token, formResponseId }or{ token, userId }
Anonymous check-in is not locked to the browser. Users can register on one device and check in on another — they only need the token and to find their name in the list.
4. Manual Check-in (Organizer)
Endpoints:POST /events/:eventId/check-in/:userId— check in logged-in attendeePOST /events/:eventId/check-in/by-form-response/:responseId— check in anonymous attendee
verifyToken) + event management permission
Organizers use the Event Dashboard Check-in tab to search and manually check in attendees.
Anonymous Registration
FormResponse Model
Anonymous registrations are stored asFormResponse documents with submittedBy: null:
Browser localStorage (anonymousRegistrationStorage)
The frontend usesmeridian-anonymous-registrations in localStorage to track when the current browser has registered for an event without an account.
Purpose:
- Show “You are registered” on the event page
- Verify with server that registration still exists (
GET /events/:eventId/check-anonymous-registration?guestEmail=...) - Support “Add another registration” — allow multiple anonymous registrations per event from the same browser
hasAnonymousRegistration(eventId)— whether this browser has a stored registrationgetAnonymousRegistration(eventId)— get stored detailssaveAnonymousRegistration(eventId, { guestName, guestEmail })— save after successful registrationremoveAnonymousRegistration(eventId)— clear when server says registration no longer existsgetAllAnonymousRegistrations()— for claim API
Claim Anonymous Registrations
When a user signs up or logs in, the frontend callsPOST /claim-anonymous-registrations with { registrations: [ { eventId, guestEmail } ] }. For each matching anonymous FormResponse (same event, submittedBy: null, email match), the backend:
- Sets
submittedByto the user’s ID - Updates
guestName/guestEmailfrom the user account if the form collects them - Adds the user to
event.attendeesif not already present
Anonymous Identifiers (Analytics)
Separate from event registration, the analytics platform uses ananonymous_id for tracking events before and after login:
| Concept | Purpose | Storage |
|---|---|---|
Analytics anonymous_id | Device-scoped persistent ID for analytics events (no PII) | Client (e.g. AsyncStorage, localStorage) |
| Anonymous FormResponse | Event registration without account (submittedBy: null) | Server (MongoDB) |
| localStorage registration | ”This browser registered for this event” | Client (localStorage) |
anonymous_id usage.
API Reference
Public Check-in (token required, no auth)
| Method | Endpoint | Description |
|---|---|---|
| GET | /events/:eventId/check-in/self-registrations?token=xxx | List registrations (logged-in + anonymous) for pick-your-registration |
| GET | /events/:eventId/check-in/registration/:formResponseId?token=xxx | Get form snapshot + answers for an anonymous registration |
| POST | /events/:eventId/check-in/anonymous | Check in by { token, formResponseId } or { token, userId } |
Authenticated Check-in
| Method | Endpoint | Description |
|---|---|---|
| POST | /events/:eventId/check-in/self | Self check-in (logged-in, no token) |
| POST | /events/:eventId/check-in | Token check-in (body: { token }) |
| POST | /events/:eventId/check-out | Remove own check-in |
Organizer / Management
| Method | Endpoint | Description |
|---|---|---|
| POST | /events/:eventId/check-in/enable | Enable check-in |
| POST | /events/:eventId/check-in/disable | Disable check-in |
| PUT | /events/:eventId/check-in/settings | Update check-in settings |
| GET | /events/:eventId/check-in/qr | Get QR code for check-in |
| GET | /events/:eventId/check-in/link | Get check-in URL |
| GET | /events/:eventId/check-in/attendees | List checked-in attendees |
| POST | /events/:eventId/check-in/:userId | Manual check-in (logged-in) |
| POST | /events/:eventId/check-in/by-form-response/:responseId | Manual check-in (anonymous) |
Anonymous Registration Verification
| Method | Endpoint | Description |
|---|---|---|
| GET | /events/:eventId/check-anonymous-registration?guestEmail=xxx | Check if anonymous registration exists (for localStorage sync) |
| POST | /claim-anonymous-registrations | Claim anonymous registrations after sign-up (body: { registrations: [ { eventId, guestEmail } ] }) |
Frontend Components
| Component | Location | Purpose |
|---|---|---|
EventCheckInButton | Meridian/frontend/src/components/EventCheckInButton | Check-in button on event page; navigates with token for anonymous |
CheckInConfirmation | Meridian/frontend/src/pages/CheckIn | Check-in page; handles token validation, anonymous pick UI, form details modal |
ManualCheckInModal | Meridian/frontend/.../EventCheckInTab | Organizer manual check-in (search + select) |
RSVPButton / RSVPSection | Meridian/frontend/src/components | Registration; uses anonymousRegistrationStorage for “registered” state and “Add another” |
Related pages
Event dashboard
Event management, readiness, and organizer tooling around the same events.
Event management API
REST paths for RSVPs, agendas, and org-event operations used by check-in flows.
Beacon events
Event lifecycle, approvals, and RSVP from the Beacon product lens.
Platform analytics
Event pipeline, envelope schema, and
anonymous_id–friendly tracking.Analytics collected events
Named events and properties emitted by web and mobile clients.
Atlas messaging
Announcements and anonymous recipients tied to event outreach.