Events
Registrations Service
The registrations service handles event registration CRUD, capacity management, email notifications, and the leaderboard. All handlers live in services/registrations/handler.js.
Endpoints
| Method | Path | Auth | Handler | Description |
|---|---|---|---|---|
POST | /registrations/ | Public | post | Register for an event |
PUT | /registrations/{email}/{fname} | Public | put | Update a registration (check-in, status change) |
GET | /registrations/ | Public | get | Query registrations by email or event |
DELETE | /registrations/{email} | Cognito | del | Delete one registration |
DELETE | /registrations | Cognito (admin) | delMany | Delete multiple registrations |
GET | /registrations/leaderboard/ | Public | leaderboard | Get leaderboard sorted by points |
PUT | /registrations/massUpdate | Public | massUpdate | Bulk update registrations |
Registration Data Model
Table: biztechRegistrations — Primary key: id (email) + sort key: eventID;year (string compound)
{
"id": "jane@student.ubc.ca",
"eventID;year": "blueprint;2026",
"registrationStatus": "registered",
"isPartner": false,
"points": 0,
"basicInformation": { "fname": "Jane", "lname": "Doe" },
"dynamicResponses": { "uuid-1": "I love tech!" },
"checkoutLink": "https://checkout.stripe.com/...",
"createdAt": 1735689600000,
"updatedAt": 1735689600000
}
GSI: event-query — indexes eventID;year so you can query all registrations for a given event.
Registration Statuses
| Status | Meaning |
|---|---|
incomplete | Started registration, hasn't paid (has checkoutLink) |
registered | Confirmed registration |
waitlist | Event at capacity |
checkedIn | Checked in at the event |
cancelled | Cancelled |
accepted | Application accepted (application events) |
acceptedPending | Accepted + free event |
acceptedComplete | Accepted + paid (application events) |
rejected | Application rejected |
POST /registrations/ Create Registration
Steps:
- Validates required fields (
eventID,year,email, etc.) - Checks if a registration already exists for this email + event
- If an
incompleteregistration exists, returns{ url: existingReg.checkoutLink }— the frontend uses this to redirect to the existing Stripe session instead of creating a new one - Hardcodes initial
balancefor kickstart events:kickstart;2025→50000kickstart-showcase;2025→100000
- Calls
createRegistration()which usesdb.putDB()with a conditional expression to prevent duplicates
Re-Registration Shortcut
When a user who started but didn't complete payment tries to register again, the backend returns their existing Stripe checkout link instead of creating a new registration. The frontend detects the url field in the response and redirects directly.
PUT /registrations/{email}/{fname} Update Registration
The primary endpoint for status changes (check-in, waitlist promotion, acceptance, etc.).
- Reads
{ eventID, year, registrationStatus, ...otherFields }from the body - Gets email from the path parameter
- For
acceptedstatus on free events: auto-sets status toacceptedPending - Delegates to
updateHelper()with the update payload
The updateHelper() Function
This is the core registration pipeline — called by create, update, and mass-update operations.
Steps
Fetch event from
biztechEventsto getcapac(capacity) and event detailsCount registrations by querying the
event-queryGSI onbiztechRegistrationsCapacity check: if
registeredCount >= capacand the new status would beregistered, auto-downgrade towaitlistEmail decision: determines whether to send emails based on status:
Status Email sent? registeredYes — QR code + calendar invite waitlistYes — QR code only (no calendar invite) acceptedCompleteYes — QR code only (no calendar invite) incompleteNo rejectedNo acceptedNo checkedInNo Partner registrations ( isPartner: true)No Send QR email via
SESEmailService.sendDynamicQR()— generates an inline QR code imageSend calendar invite via
SESEmailService.sendCalendarInvite()—.icsattachment (only forregisteredstatus)Publish SNS notification to Slack (registration alerts channel)
Write to DynamoDB —
db.updateDB()ordb.putDB()tobiztechRegistrations
GET /registrations/ Query Registrations
Supports two query patterns:
By email
GET /registrations/?email=jane@student.ubc.ca
Returns all registrations for that email (all events the user has registered for).
By event
GET /registrations/?eventID=blueprint&year=2026
Queries the event-query GSI to return all registrations for that event.
DELETE /registrations/{email} Delete One
Requires Cognito auth. Takes { eventID, year } in the request body (not query parameters) to identify which registration to delete.
DELETE /registrations Batch Delete
Admin-only (checks @ubcbiztech.com email in handler). Takes a body with:
{
"ids": ["email1@example.com", "email2@example.com"],
"eventID": "blueprint",
"year": 2026
}
The ids array contains email addresses. All specified registrations for the given event are deleted.
GET /registrations/leaderboard/ Leaderboard
Returns all registrations for a given event, sorted by points in descending order. Used by the companion app to show the event leaderboard.
Query parameters: eventID, year
PUT /registrations/massUpdate Bulk Update
Takes an array of registration updates and calls updateHelper() for each in parallel using Promise.all(). Each update independently runs the full pipeline (capacity check, email, SNS, DynamoDB write).
Email Sending Details
SESEmailService Class
File: services/registrations/EmailService/SESEmailService.js
Two methods:
sendDynamicQR(registrationData)
- Generates a QR code encoding the attendee's email and event ID
- Embeds the QR code as an inline image in the email
- Includes event name, date, and location
sendCalendarInvite(registrationData)
- Builds an
.icscalendar file with the event's start/end times - Attaches it to the email as a MIME attachment
- Uses
ses:SendRawEmailfor the attachment
DynamoDB Tables
| Table | Key | GSIs | Usage |
|---|---|---|---|
biztechRegistrations | id (email) + eventID;year | event-query (eventID;year → HASH) | Registration records |
biztechEvents | id + year | — | Event lookup for capacity, details |
biztechUsers | id (email) | — | User lookup in some flows |
Side Effects
| Side effect | When |
|---|---|
| SES email (QR code) | On registered, waitlist, acceptedComplete status |
| SES email (calendar invite) | On registered status only |
| SNS → Slack | On every registration/update via updateHelper() |
Key Files
| File | Purpose |
|---|---|
services/registrations/handler.js | All registration endpoint handlers + updateHelper() |
services/registrations/EmailService/SESEmailService.js | QR code and calendar invite email sending |
services/registrations/serverless.yml | Endpoint definitions, IAM permissions |
services/registrations/test/ | Unit tests |
services/registrations/test_integration/ | Integration tests |
Related Pages
- Registration System — the registration state machine and frontend integration
- Event Check-In — check-in via QR scan
- Payment Flow — how paid registrations complete
- Email Service — email infrastructure overview