Calendar Events

Manage calendar event groups and events. Supports bulk event creation, shared access, and integration with messages.

All endpoints require authentication via the X-API-Key header. See Authentication.

Shared access model

Calendar events and event groups use ownership-based visibility:

  • Records with shared: true are visible to all users in the organization.
  • Records with shared: false are only visible to the owner.

Deletes cascade by disassociation, not deletion — related records have their reference set to null.


Create an event group

POST /calendar/events/groups

Request body

FieldTypeRequiredNotes
namestringYesGroup name.
iconobjectYes{ type: "image" | "icon" | "emoji", value: string, color: string }.
sharedbooleanYesWhether the group is visible to all org users.

Example request

curl -X POST https://<host>/api/calendar/events/groups \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring Events",
    "icon": { "type": "emoji", "value": "🌸", "color": "#FF69B4" },
    "shared": true
  }'

Response

{
  "error": false,
  "success": true,
  "message": "Event group created successfully",
  "data": {
    "_id": "672a...",
    "orgId": "...",
    "ownerId": "...",
    "name": "Spring Events",
    "icon": { "type": "emoji", "value": "🌸", "color": "#FF69B4" },
    "shared": true,
    "createdAt": 1716000000000,
    "updatedAt": 1716000000000
  }
}

Errors

StatusMessageCause
400Validation errorMissing or invalid fields.

List event groups

GET /calendar/events/groups

Returns groups visible to the current user (shared or owned). Each group includes an eventsCount of associated calendar events.

Query parameters

ParameterTypeDefaultNotes
searchstring—Case-insensitive text search on group name.

Example request

curl "https://<host>/api/calendar/events/groups?search=spring" \
  -H "X-API-Key: your-api-key"

Response

{
  "error": false,
  "success": true,
  "message": "Event groups fetched successfully",
  "data": [
    {
      "_id": "672a...",
      "name": "Spring Events",
      "icon": { "type": "emoji", "value": "🌸", "color": "#FF69B4" },
      "shared": true,
      "ownerId": "...",
      "eventsCount": 5,
      "createdAt": 1716000000000
    }
  ]
}

Get an event group

GET /calendar/events/groups/:id

Path parameters

ParameterTypeDescription
idstringEvent group ID.

Example request

curl https://<host>/api/calendar/events/groups/672a... \
  -H "X-API-Key: your-api-key"

Response

Standard success envelope with the event group in data.

Errors

StatusMessageCause
400Invalid IDInvalid ObjectId format.
404Event group not foundNo group with that ID.

Update an event group

PATCH /calendar/events/groups/:id

All fields are optional. Note: icon.type only allows image or icon when updating (not emoji).

Path parameters

ParameterTypeDescription
idstringEvent group ID.

Request body

FieldTypeRequiredNotes
namestringNo
iconobjectNo{ type: "image" | "icon", value: string, color: string }. Note: emoji type not allowed in updates.
sharedbooleanNo

Example request

curl -X PATCH https://<host>/api/calendar/events/groups/672a... \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Spring 2026 Events" }'

Response

{
  "error": false,
  "success": true,
  "message": "Event group updated successfully",
  "data": null
}

Errors

StatusMessageCause
400Validation errorInvalid ObjectId or invalid fields.
404Event group not foundNo group with that ID.

Delete an event group

DELETE /calendar/events/groups/:id

Cascade: All calendar events in this group have their eventGroupId set to null. The events themselves are not deleted.

Path parameters

ParameterTypeDescription
idstringEvent group ID.

Example request

curl -X DELETE https://<host>/api/calendar/events/groups/672a... \
  -H "X-API-Key: your-api-key"

Response

{
  "error": false,
  "success": true,
  "message": "Event group deleted successfully",
  "data": null
}

Errors

StatusMessageCause
400Invalid IDInvalid ObjectId format.
404Event group not foundNo group with that ID.

Create a calendar event

POST /calendar/events

Request body

FieldTypeRequiredNotes
namestringYesEvent name.
datenumberYesUnix timestamp in milliseconds.
colorstringYesDisplay color.
typestringYesEvent type.
sharedbooleanYesWhether the event is visible to all org users.
descriptionstringNo
eventGroupIdstringNoEvent group to associate with.

Example request

curl -X POST https://<host>/api/calendar/events \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring Practice",
    "date": 1716000000000,
    "color": "#4CAF50",
    "type": "practice",
    "shared": true,
    "eventGroupId": "672a..."
  }'

Response

{
  "error": false,
  "success": true,
  "message": "Calendar event created successfully",
  "data": {
    "_id": "673a...",
    "orgId": "...",
    "ownerId": "...",
    "eventGroupId": "672a...",
    "name": "Spring Practice",
    "date": 1716000000000,
    "color": "#4CAF50",
    "type": "practice",
    "shared": true,
    "createdAt": 1716000000000,
    "updatedAt": 1716000000000
  }
}

Errors

StatusMessageCause
400Validation errorMissing or invalid fields.

Bulk create calendar events

POST /calendar/events/create/bulk

Create multiple calendar events at once. The response does not include the created event IDs.

Request body

FieldTypeRequiredNotes
eventsarrayYesArray of event objects. Each has the same structure as single create: name, date, color, type, shared (all required), optional description and eventGroupId.

Example request

curl -X POST https://<host>/api/calendar/events/create/bulk \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      { "name": "Game 1", "date": 1716000000000, "color": "#F44336", "type": "game", "shared": true },
      { "name": "Game 2", "date": 1716100000000, "color": "#F44336", "type": "game", "shared": true }
    ]
  }'

Response

{
  "error": false,
  "success": true,
  "message": "Calendar event created successfully",
  "data": null
}

Note: data is null — created event IDs are not returned.

Errors

StatusMessageCause
400Validation errorevents is not an array, or any event fails validation. All-or-nothing — if one event fails, none are created.

List calendar events

GET /calendar/events

Returns events visible to the current user (shared or owned), sorted by date ascending. Each event includes populated messages and eventGroup.

Query parameters

ParameterTypeDefaultNotes
eventGroupIdstring—Filter by event group.
startDatenumber—Unix timestamp (ms). Inclusive lower bound on date.
endDatenumber—Unix timestamp (ms). Inclusive upper bound on date.
searchstring—Case-insensitive text search on event name.

Example request

curl "https://<host>/api/calendar/events?startDate=1716000000000&endDate=1717000000000" \
  -H "X-API-Key: your-api-key"

Response

{
  "error": false,
  "success": true,
  "message": "Calendar events fetched successfully",
  "data": [
    {
      "_id": "673a...",
      "name": "Spring Practice",
      "date": 1716000000000,
      "color": "#4CAF50",
      "type": "practice",
      "shared": true,
      "ownerId": "...",
      "eventGroup": {
        "_id": "672a...",
        "name": "Spring Events",
        "icon": { "type": "emoji", "value": "🌸", "color": "#FF69B4" }
      },
      "messages": []
    }
  ]
}

Get a calendar event

GET /calendar/events/:id

Path parameters

ParameterTypeDescription
idstringCalendar event ID.

Example request

curl https://<host>/api/calendar/events/673a... \
  -H "X-API-Key: your-api-key"

Response

Standard success envelope with the calendar event in data.

Errors

StatusMessageCause
400Invalid IDInvalid ObjectId format.
404Calendar event not foundNo event with that ID.

Update a calendar event

PATCH /calendar/events/:id

All fields are optional. Set eventGroupId to null to disassociate from a group.

Path parameters

ParameterTypeDescription
idstringCalendar event ID.

Request body

FieldTypeRequiredNotes
namestringNo
datenumberNoUnix timestamp in milliseconds.
colorstringNo
typestringNo
sharedbooleanNo
descriptionstringNo
eventGroupIdstring | nullNoSet to null to disassociate.

Example request

curl -X PATCH https://<host>/api/calendar/events/673a... \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Updated Spring Practice", "date": 1716050000000 }'

Response

{
  "error": false,
  "success": true,
  "message": "Calendar event updated successfully",
  "data": null
}

Errors

StatusMessageCause
400Validation errorInvalid ObjectId or invalid fields.
404Calendar event not foundNo event with that ID.

Delete a calendar event

DELETE /calendar/events/:id

Cascade: All messages linked to this event have their calendarEventId set to null. The messages themselves are not deleted.

Path parameters

ParameterTypeDescription
idstringCalendar event ID.

Example request

curl -X DELETE https://<host>/api/calendar/events/673a... \
  -H "X-API-Key: your-api-key"

Response

{
  "error": false,
  "success": true,
  "message": "Calendar event deleted successfully",
  "data": null
}

Errors

StatusMessageCause
400Invalid IDInvalid ObjectId format.
404Calendar event not foundNo event with that ID.

Response envelope

All endpoints use the standard envelope:

{
  "error": false,
  "success": true,
  "message": "...",
  "code": 200,
  "data": "..."
}

Error responses:

{
  "error": true,
  "success": false,
  "message": "...",
  "code": 400,
  "data": null
}

data is null for a general failure, such as a database error or an upstream timeout. When the request is rejected because of a specific field, data carries the field(s) at fault instead:

{
  "error": true,
  "success": false,
  "message": "phone: Phone parse failed: The string supplied did not seem to be a phone number (input: <masked>)",
  "code": 400,
  "data": {
    "issues": [
      {
        "path": "phone",
        "message": "Phone parse failed: The string supplied did not seem to be a phone number (input: <masked>)"
      }
    ]
  }
}

Each issue carries a path (the dotted path into the request body) and a message. A label is added when the path is not self-describing, which today means custom fields only, for example "path": "fields.68b0a1f39c2e4d0012ab77e5", "label": "Class Year". issues is an array, but treat it as holding at most one entry: validation stops at the first failure.

On this page