Documentation

Sessions and scheduling

Multi-track agendas, day-grouped schedule, session CRUD.

A session is a scheduled item on an event's agenda — a keynote, a workshop, a panel, a break. Sessions live in their own collection (event_session) so multi-day, multi-track events can carry a full conference programme. The Events module gives you per-event session CRUD plus a shaped schedule endpoint that groups sessions by day for direct rendering in a programme view.

Endpoints

POST/events/:eventId/sessionsJWT
GET/events/:eventId/sessionsJWT
GET/events/:eventId/scheduleJWT
PUT/events/sessions/:sessionIdJWT
DELETE/events/sessions/:sessionIdJWT
GET/client/events/:eventId/sessionsNo auth
GET/client/events/:eventId/scheduleNo auth

Session shape

type Session = {
  pk: string;
  sk: string;
  datatype: 'event_session';
  data: {
    event: string;            // eventId
    title: string;
    description?: string;
    type: 'talk' | 'workshop' | 'panel' | 'break' | 'networking' | string;
    track?: string;           // e.g. 'design', 'engineering'
    room?: string;            // physical room name
    day?: string;             // 'YYYY-MM-DD'; auto-derived from startTime if omitted
    startTime: string;        // ISO 8601
    endTime: string;
    capacity?: number;
    speakers?: Array<{ email: string; name: string; bio?: string; image?: string }>;
    requiresTicket?: boolean;
    requiredTicketTypes?: string[];
    status: 'scheduled' | 'live' | 'ended' | 'cancelled';
    streamUrl?: string;       // virtual/hybrid
    recordingUrl?: string;
  };
};

Creating a session

await fetch(`/events/${eventId}/sessions`, {
  method: 'POST',
  headers: {
    orgid: 'my-org',
    Authorization: `Bearer ${jwt}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    title: 'The state of variable fonts',
    type: 'talk',
    track: 'typography',
    room: 'Hall A',
    startTime: '2026-09-12T10:00:00Z',
    endTime: '2026-09-12T11:00:00Z',
    speakers: [
      { email: '[email protected]', name: 'Alice Lee' },
    ],
    requiresTicket: true,
    requiredTicketTypes: ['general', 'vip'],
  }),
});

The service derives day from startTime (in the event's timezone) so the schedule grouping is consistent.

Listing sessions

GET /events/:eventId/sessions accepts day (YYYY-MM-DD), track, type, and status. Use this when you want a flat list with custom filtering.

const sessions = await fetch(
  `/client/events/${eventId}/sessions?day=2026-09-12&track=typography`,
  { headers: { orgid: 'my-org' } }
).then(r => r.json());

Schedule endpoint

GET /events/:eventId/schedule returns sessions pre-grouped by day, sorted by start time, with the room/track structure flattened for direct rendering:

{
  "days": [
    {
      "day": "2026-09-12",
      "sessions": [
        { "id": "...", "title": "...", "startTime": "...", "endTime": "...", "track": "...", "room": "..." }
      ]
    },
    { "day": "2026-09-13", "sessions": [...] }
  ]
}

Use this on a public event page to render a tabbed day-by-day programme without doing the grouping yourself.

Updating and deleting

// Update — partial body merged into data
await fetch(`/events/sessions/${sessionId}`, {
  method: 'PUT',
  headers: { orgid: 'my-org', Authorization: `Bearer ${jwt}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ room: 'Hall B', status: 'scheduled' }),
});

// Delete
await fetch(`/events/sessions/${sessionId}`, {
  method: 'DELETE',
  headers: { orgid: 'my-org', Authorization: `Bearer ${jwt}` },
});

Cancelling (status: 'cancelled') is the soft path — keeps the record so attendees who saved the session see "cancelled" instead of a 404. Hard delete is for genuine removal during planning.

Linking sessions to check-in

A session can be referenced from a check-in scan by passing sessionId to POST /events/checkin. This records per-session attendance and lets you compute "who actually came to the keynote" rather than just who walked through the front door. See Check-in.

Sessions don't sell tickets on their own. If a session is gated, set requiresTicket: true and list the qualifying requiredTicketTypes — the check-in service rejects scans for non-qualifying ticket types at session scan points.