API ReferenceEvents

Events

Event listing and management, club ownership, and registration contracts.

Status: complete · Source: content/docs/api-reference/events.mdx

Paths follow the reference conventions. Read Clubs, Events & Registrations for domain behavior. The router has eight operations; it does not expose a public GET /events/:id or an unregister operation.

An event record below means the returned model scalars: id, title, description, nullable imageUrl, date, clubId, and createdAt. When selected, club contains name and nullable imageUrl. Request fields call the date data, while response/database fields call it date.

List public events

GET/eventsPublic

List events with registration counts and pagination metadata.

QueryParsing and default
pageOptional string; parseInt(value) || 1.
limitOptional string; parseInt(value) || 12.
sortOptional asc or desc; default desc, ordering by date.

Zod checks string types and the sort enum, not positive numeric bounds. Zero/unparseable page or limit values fall back; partially numeric strings use their integer prefix. Negative values are not rejected by the schema. Skip is (page - 1) * limit; unsupported database arguments reach the 500 branch. No upcoming-only or club filter is implemented.

HTTP 200 example:

{
  "events": [{
    "id": "illustrative-event-id",
    "title": "Example workshop",
    "description": "An introductory programming workshop.",
    "imageUrl": "https://example.com/workshop.png",
    "date": "2026-11-12T10:00:00.000Z",
    "clubId": "illustrative-club-id",
    "createdAt": "2026-10-01T10:00:00.000Z",
    "club": {"name": "Example Coding Club", "imageUrl": null},
    "registrationCount": 0
  }],
  "pagination": {"page": 1, "pages": 1, "total": 1, "limit": 12}
}

_count is transformed into registrationCount rather than returned. The controller sets Cache-Control: public, s-maxage=60, stale-while-revalidate=120. Errors: 400 Zod validation; 500 Error fetching events.

List the requesting user's club events

GET/events/mineAuthenticated · Role restricted

Return events for the authenticated user's currently associated club.

Authorization: CLUB_HEAD or ADMIN. No body/query schema. The controller loads the user's current club; admins receive their associated club's events, not all events.

HTTP 200: { "events": [...] }, ordered by date descending. Each item is an event record with club and registrations: [{ "id": "illustrative-registration-id" }]. It returns registration IDs, not registrationCount or attendee profiles.

Errors: middleware 401/403; 400 You are not associated with any club; 500 Error fetching club events.

Create an event

POST/eventsAuthenticated · Role restricted

Create an event for the requesting club head's current club.

Authorization: CLUB_HEAD only; an ADMIN token is rejected by this role list. The controller also requires current club membership. It ignores a supplied clubId when creating the record.

Body fieldEffective contract
titleRequired string, minimum three characters.
descriptionRequired string, minimum ten characters.
dataRequired nonempty string. Zod accepts an ISO datetime or any nonempty string; the controller uses new Date(data). Send a parseable datetime.
imageUrlEffectively required URL string; see the mismatch below.
POST /events
Authorization: Bearer <club-head-jwt>
Content-Type: application/json

{"title":"Example workshop","description":"An introductory programming workshop.","data":"2026-11-12T10:00:00.000Z","imageUrl":"https://example.com/workshop.png"}

HTTP 201: { "event": ... } with an event record and selected club. No registration count/array is included. Errors: middleware 401/403; 400 validation or All fields are required; 400 You must be a club head to create an event when the user has no club; 500 Error creating event, including a date string accepted by validation but unusable by Prisma.

Update an event

PUT/events/:idAuthenticated · Role restricted

Change selected event fields after checking access to the existing event.

Authorization: ADMIN or CLUB_HEAD; a club head's current club must match the event's current clubId. Path id is a nonempty string.

All body fields are optional: title (minimum three characters), description (minimum ten), data (nonempty string converted to a date), imageUrl (URL string), and clubId (string). Only truthy values are included in the update. Empty clubId is accepted by the schema and ignored; nullable fields cannot be cleared with null through this schema.

The existing-event ownership check does not constrain the replacement clubId to the requester's club. The target must exist because of the foreign key. An empty object is permitted by validation.

HTTP 200: { "event": ... , "message": "Event updated successfully" }, with an event record and club. Errors: middleware 401/403; 400 validation or Event ID is required; 404 Event not found; 403 Not allowed to modify this event; 500 Error updating event for caught failures.

Delete an event

DELETE/events/:idAuthenticated · Role restricted

Remove registrations, then delete an accessible event.

Authorization: ADMIN or owning CLUB_HEAD. Zod requires a nonempty id; no body is used. The controller deletes registrations first because the event foreign key restricts deletion. These two writes are not transactional.

HTTP 200: { "message": "Event deleted successfully" }. Errors: middleware 401/403; 400 validation or Event ID is required; 404 Event not found; 403 Not allowed to delete this event; 500 Error deleting event. A failure after registration removal can leave the event without those registrations.

Sourcebackend/src/validators/events.ts

Register for an event

POST/events/:eventId/registerAuthenticated

Create the current user's registration for the URL's event.

No role restriction, body fields, or route-specific Zod validator. eventId identifies the event; the user comes from the token. The controller checks the compound (userId, eventId) key for a prior registration.

HTTP 201:

{
  "registration": {
    "id": "illustrative-registration-id",
    "userId": "illustrative-user-id",
    "eventId": "illustrative-event-id",
    "registeredAt": "2026-10-07T10:00:00.000Z",
    "event": {"title": "Example workshop"},
    "user": {"firstName": "Alex", "lastName": "Morgan"}
  }
}

Errors: middleware 401; 400 You have already registered for this event; 500 Error registering for event. Unknown events/users and uniqueness races reach caught database failures, not a dedicated 404/409 branch. Database uniqueness prevents two registrations for the same pair.

List the current user's registrations

GET/events/registeredAuthenticated

Return registrations belonging to the token's user identifier.

No role restriction or validated query/body. HTTP 200: { "registrations": [...] }. Each item contains id, userId, eventId, registeredAt, and an event record with selected club. Records are ordered by the related event's date descending, not registration time. Errors: middleware 401; 500 Error fetching registered events.

List attendees for an event

GET/events/:id/registrationsAuthenticated · Role restricted

Return a summary of the event and its registrations with attendee contact details.

Authorization: ADMIN or owning CLUB_HEAD. Path id identifies the event; no Zod validator is attached. HTTP 200:

{
  "event": {"id": "illustrative-event-id", "title": "Example workshop", "date": "2026-11-12T10:00:00.000Z"},
  "registrations": [{
    "id": "illustrative-registration-id",
    "userId": "illustrative-user-id",
    "name": "Alex Morgan",
    "email": "alex@example.com",
    "registeredAt": "2026-10-07T10:00:00.000Z"
  }]
}

The controller combines and trims first/last names and orders by registeredAt descending. Errors: middleware 401/403; 400 Event ID is required; 404 Event not found; 403 Not allowed to view registrations for this event; 500 Error fetching event registrations.

Sourcebackend/src/routes/events.ts

Sourcebackend/src/controllers/eventController.ts

Sourcebackend/prisma/schema.prisma

Last updated · Edit this page on GitHub

On this page