events
17 endpoints.
/api/events/mine Bearer tokenList the caller's own events
Every unarchived event the caller is on — as a participant, a trainer, or both — in calendar order (unscheduled events last), each with their own attendance where they are a participant. Needs no permission grant: being on the event is the authorization. Cancelled events are included, flagged by cancelled_at.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| from | query | string (date-time) | no | Only events ending at or after this instant; unscheduled events are always included. |
| to | query | string (date-time) | no | Only events starting before this instant (unscheduled events included). |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The caller's events. | MyTrainingEventList |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 500 | The database could not be read. | ErrorResponse |
/api/events/batch Bearer tokenCreate a series of training events
Creates one event per window given, all owned by the same organization (or owning department within it), with the same title, venue, credit and subject tags — a recurring session scheduled for a term in one request. The trainers and participants named are put on every event of the series; each must be a member of the organization. Everything is written in one transaction, so a series is never half-created. Requires events:write over the owner. Answers the created events in calendar order.
| Field | Type | Required | Description |
|---|---|---|---|
| org | string | yes | Organization UUID id or slug the event belongs to. at least 1 character |
| department | string | no | UUID id or slug of the owning department within the organization; omit for an event owned by the organization directly. at least 1 character |
| title | string | yes | 1–200 characters |
| description_markdown | string | no | Omit or send empty for no description. at most 50000 characters |
| meeting_url | string (uri) | no | Video meeting link, for remote or hybrid sessions. at most 2000 characters |
| location | string | no | Free-text venue, for in-person sessions. 1–500 characters |
| credit_hours | number | no | Hours an attendance credits toward subject-hours rules. Omit to credit the event's wall-clock duration instead. maximum 10000 |
| subject_matter_ids | array of string (uuid) | no | Subjects the event (and every attendance record it produces) is filed under. Subjects of the event's own organization only. at most 50 items |
| windows | array of TrainingEventWindow | yes | One event is created per window, all sharing the fields above. A client scheduling weekly slots expands them into windows before sending. 1–200 items |
| trainer_user_ids | array of string (uuid) | no | `users.id` of members of the organization to schedule as trainers of every event in the series. at most 50 items |
| participant_user_ids | array of string (uuid) | no | `users.id` of members of the organization to put on every event's roster as `registered`. at most 200 items |
Responses
| Status | Description | Body |
|---|---|---|
| 201 | The created events, earliest first. | TrainingEventList |
| 400 | The request body failed validation, or a named trainer or participant is not a member of the organization. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:write over the intended owner. | ErrorResponse |
| 404 | No visible organization has that id or slug, or the department or a subject matter is not the organization's own. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/conflicts Bearer tokenCheck for scheduling conflicts
Says who among the given people is already on another live training event — as a participant or a trainer — during any of the given windows, so a double booking is seen before it is made. Cancelled, archived and unscheduled events never clash. Writes nothing: it is a POST only because the people and windows do not fit a query string. Requires events:write somewhere, since it serves the scheduling forms; the clash itself is reported wherever the other event lives, but that event's id and title are given only when the caller's events:read scope covers it.
| Field | Type | Required | Description |
|---|---|---|---|
| user_ids | array of string (uuid) | yes | `users.id` of the people about to be scheduled. 1–250 items |
| windows | array of TrainingEventWindow | yes | The windows they would be scheduled in — one for a single event, one per event for a series. Conflicts name the window by its index in this array. 1–200 items |
| exclude_event_id | string (uuid) | no | An event to leave out of the check: the one being edited, whose own roster would otherwise conflict with itself. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The clashes found, by window then by the other event's start; empty when none. | SchedulingConflictList |
| 400 | The request body failed validation. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller holds events:write nowhere. | ErrorResponse |
| 500 | The database could not be read. | ErrorResponse |
/api/events Bearer tokenList training events
Lists the training events the caller's events:read scope covers, in calendar order (unscheduled events last), optionally filtered to one organization or one owning department within it, and to a time window. Archived events are left out unless asked for; cancelled ones are listed with their cancelled_at set. The events one is on as a participant or trainer are listed by GET /events/mine instead.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| org | query | string | no | Organization UUID id or slug to filter by (and to resolve slug refs in). |
| department | query | string | no | Department UUID id or slug, resolved within org (which is then required). |
| include_archived | query | string | no | Include archived rows. Defaults to false. |
| from | query | string (date-time) | no | Only events ending at or after this instant. Unscheduled events (no time yet) are always included. |
| to | query | string (date-time) | no | Only events starting before this instant (unscheduled events included). |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The visible events. | TrainingEventList |
| 400 | The department filter was given without an org filter. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 404 | No visible organization has that id or slug, or the department is not one of the organization's own. | ErrorResponse |
| 500 | The database could not be read. | ErrorResponse |
/api/events Bearer tokenCreate a training event
Creates an event owned by the organization, or by the owning department named within it, tagged with the given subjects. Requires events:write over that owner. Give starts_at and ends_at to schedule it, or neither for an event whose time is not yet known: it is listed as unscheduled, and attendance cannot be marked until it is given a window. Trainers and participants are added afterwards through the event's own routes.
| Field | Type | Required | Description |
|---|---|---|---|
| org | string | yes | Organization UUID id or slug the event belongs to. at least 1 character |
| department | string | no | UUID id or slug of the owning department within the organization; omit for an event owned by the organization directly. at least 1 character |
| title | string | yes | 1–200 characters |
| description_markdown | string | no | Omit or send empty for no description. at most 50000 characters |
| meeting_url | string (uri) | no | Video meeting link, for remote or hybrid sessions. at most 2000 characters |
| location | string | no | Free-text venue, for in-person sessions. 1–500 characters |
| credit_hours | number | no | Hours an attendance credits toward subject-hours rules. Omit to credit the event's wall-clock duration instead. maximum 10000 |
| subject_matter_ids | array of string (uuid) | no | Subjects the event (and every attendance record it produces) is filed under. Subjects of the event's own organization only. at most 50 items |
| starts_at | string (date-time) | no | When the event starts. Omit both starts_at and ends_at for an event whose time is not yet known; it is listed as unscheduled until PATCHed with a window. |
| ends_at | string (date-time) | no | When the event ends; required exactly when starts_at is given. |
Responses
| Status | Description | Body |
|---|---|---|
| 201 | The created event. | TrainingEvent |
| 400 | The request body failed validation. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:write over the intended owner. | ErrorResponse |
| 404 | No visible organization has that id or slug, or the department or a subject matter is not the organization's own. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/{event_id}/permanent-deletion Bearer tokenPreview permanently deleting an event
Counts everything DELETE on this path would remove: the learning records attendance marks wrote (and the hours they credited), the roster and the trainers. Nothing is changed. Requires events:delete over the event's owner — a grant separate from events:write, which only archives.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | What the deletion would take with it. | DeletionImpact |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:delete over the event's owner. | ErrorResponse |
| 404 | No visible event has that id. | ErrorResponse |
| 500 | The database could not be read. | ErrorResponse |
/api/events/{event_id}/permanent-deletion Bearer tokenPermanently delete an event
Hard-deletes the event — unlike archiving (hides it) or cancelling (archives its records). The roster, trainers and subject tags go, and so do the learning records attendance marks produced, with their evidence: the hours they credited toward certification requirements disappear. Irreversible. Preview the cost with GET first. Requires events:delete over the event's owner — a grant separate from events:write, which only archives.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
Responses
| Status | Description | Body |
|---|---|---|
| 204 | The event, its roster and its attendance records are gone. | — |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:delete over the event's owner. | ErrorResponse |
| 404 | No visible event has that id. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/{event_id}/duplicate Bearer tokenDuplicate a training event
Creates a copy of an event — the next session of a recurring one — with the same owner, description, venue, meeting link, credit hours, subject tags and trainers. Participants, attendance and the learning records attendance wrote stay with the original, and the copy is neither cancelled nor archived. Give starts_at and ends_at to schedule the copy, or neither for an unscheduled one; the title is the original's unless given. Requires events:write over the event's owner.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | no | The copy's title; omit to keep the original's. 1–200 characters |
| starts_at | string (date-time) | no | When the copy starts. Omit both starts_at and ends_at for an unscheduled copy, whose time is set later by PATCH /events/{event_id}. |
| ends_at | string (date-time) | no | When the copy ends; required exactly when starts_at is given. |
Responses
| Status | Description | Body |
|---|---|---|
| 201 | The copy. | TrainingEvent |
| 400 | The request body failed validation, or the window is half set or out of order. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller can see the event but does not hold events:write over its owner. | ErrorResponse |
| 404 | No visible event has that id. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/{event_id} Bearer tokenRead one training event
Reads one event with its subject tags, trainers and participant roster (with attendance). Requires events:read over the event's owner — or being on the event as a participant or trainer.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The event. | TrainingEventDetail |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 404 | No visible event has that id. | ErrorResponse |
| 500 | The database could not be read. | ErrorResponse |
/api/events/{event_id} Bearer tokenEdit, cancel or archive an event
Changes an event's title, description, times (set both to schedule an unscheduled event, null both to unschedule it), meeting link, location or credit hours; cancels it (final — attendance can no longer be marked, and the learning records earlier attendance marks produced are archived); or archives/restores it. Edits never touch records already written for attendance. Requires events:write over the event's owner.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | no | 1–200 characters |
| description_markdown | string | null | no | Send null (or empty) to clear the description. at most 50000 characters |
| starts_at | string (date-time) | null | no | Send both halves to (re)schedule the event, or null on both to make it unscheduled again. An omitted half keeps its stored value; the result must still be both or neither. |
| ends_at | string (date-time) | null | no | Send null on both halves to clear the window. |
| meeting_url | string (uri) | null | no | Send null to clear. at most 2000 characters |
| location | string | null | no | Send null to clear. 1–500 characters |
| credit_hours | number | null | no | Send null to credit the wall-clock duration again. maximum 10000 |
| cancelled | boolean | no | Cancels the event. Final: attendance can no longer be marked, and the learning records earlier attendance marks produced are archived. one of true |
| archived | boolean | no | True hides the event from listings; false restores it. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The updated event. | TrainingEvent |
| 400 | The request body failed validation, or the new window is out of order or half set. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:write over the event's owner. | ErrorResponse |
| 404 | No visible event has that id. | ErrorResponse |
| 409 | The event is already cancelled. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/{event_id}/subjects Bearer tokenReplace an event's subject tags
Sets the complete set of subjects the event — and every attendance record it produces from now on — is filed under. Records already written keep their tags. Subjects of the event's own organization only. Requires events:write over the owner.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
| Field | Type | Required | Description |
|---|---|---|---|
| subject_matter_ids | array of string (uuid) | yes | The complete set of subject tags; an empty array clears them. at most 50 items |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The event's subjects after the change. | array of TrainingEventSubject |
| 400 | The request body failed validation. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:write over the event's owner. | ErrorResponse |
| 404 | No visible event has that id, or a subject is not the organization's own. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/{event_id}/participants Bearer tokenList an event's participants
The roster with each participant's attendance and, for attendees, the learning record their attendance wrote. Same visibility as reading the event.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The roster. | TrainingEventParticipantList |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 404 | No visible event has that id. | ErrorResponse |
| 500 | The database could not be read. | ErrorResponse |
/api/events/{event_id}/participants Bearer tokenAdd a participant
Puts a member of the event's organization on the roster as `registered`. Requires events:write over the event's owner.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
| Field | Type | Required | Description |
|---|---|---|---|
| user_id | string (uuid) | yes | `users.id` of a member of the event's organization. |
Responses
| Status | Description | Body |
|---|---|---|
| 201 | The new roster row. | TrainingEventParticipant |
| 400 | The request body failed validation, or the user is not an organization member. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:write over the event's owner. | ErrorResponse |
| 404 | No visible event has that id. | ErrorResponse |
| 409 | That user is already on the roster. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/{event_id}/participants/{user_id} Bearer tokenRemove a participant
Takes a person off the roster. If their attendance had been marked, the learning record it wrote is archived — off the roster means off the count. Requires events:write over the event's owner.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
| user_id | path | string (uuid) | yes | `users.id` of the person on the event. |
Responses
| Status | Description | Body |
|---|---|---|
| 204 | Removed. | — |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:write over the event's owner. | ErrorResponse |
| 404 | No visible event has that id, or the user is not on its roster. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/{event_id}/participants/{user_id}/attendance Bearer tokenMark a participant's attendance
Sets one participant's attendance once the event has started. `attended` writes a completed learning record for them — titled and owned like the event, filed under its subjects, with one evidence row worth its credit hours (or its duration) — which the subject-hours rules count immediately. Any other mark archives the record an earlier `attended` wrote. A cancelled or archived event, or one that has not started, takes no marks. Requires events:write over the event's owner.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
| user_id | path | string (uuid) | yes | `users.id` of the person on the event. |
| Field | Type | Required | Description |
|---|---|---|---|
| attendance | string | yes | registered: on the roster. attended: was there — a completed learning record was written for them. absent: was not there. one of "registered" | "attended" | "absent" |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The roster row after the mark. | TrainingEventParticipant |
| 400 | The request body failed validation. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:write over the event's owner. | ErrorResponse |
| 404 | No visible event has that id, or the user is not on its roster. | ErrorResponse |
| 409 | The event has not started, or is cancelled or archived. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/{event_id}/trainers Bearer tokenSchedule a trainer
Names a member of the event's organization as one of its trainers. Informational: being scheduled grants no permission over the event, though trainers can always read it. Requires events:write over the event's owner.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
| Field | Type | Required | Description |
|---|---|---|---|
| user_id | string (uuid) | yes | `users.id` of a member of the event's organization. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The event's trainers after the change. | array of TrainingEventTrainer |
| 400 | The request body failed validation, or the user is not an organization member. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:write over the event's owner. | ErrorResponse |
| 404 | No visible event has that id. | ErrorResponse |
| 409 | That user is already a trainer of the event. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/events/{event_id}/trainers/{user_id} Bearer tokenUnschedule a trainer
Removes a trainer from the event. Requires events:write over the event's owner.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| event_id | path | string (uuid) | yes | UUID id of the training event. |
| user_id | path | string (uuid) | yes | `users.id` of the person on the event. |
Responses
| Status | Description | Body |
|---|---|---|
| 204 | Removed. | — |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 403 | The caller does not hold events:write over the event's owner. | ErrorResponse |
| 404 | No visible event has that id, or the user is not one of its trainers. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |