Proposed Slots
Time options for a meeting that participants vote on, used for collaborative scheduling.
Proposed slots are time options for a board meeting that participants vote on. They enable collaborative scheduling — members propose times, vote on availability, and the organizer confirms the winning slot as the meeting time.
Relationship to Meetings
Every proposed slot belongs to exactly one meeting. All endpoints are nested under a meeting.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v1/boards/:boardId/meetings/:meetingId/slots | List proposed slots |
POST | /api/v1/boards/:boardId/meetings/:meetingId/slots | Create a proposed slot |
PUT | /api/v1/boards/:boardId/meetings/:meetingId/slots/:slotId/vote | Vote on a slot |
DELETE | /api/v1/boards/:boardId/meetings/:meetingId/slots/:slotId | Delete a slot |
POST | /api/v1/boards/:boardId/meetings/:meetingId/slots/:slotId/confirm | Confirm slot as meeting time |
Proposed Slot Object
{
"object": "proposed_slot",
"id": "60d5ec49f1a2c8b1f8e4e1c1",
"meetingId": "60d5ec49f1a2c8b1f8e4e1b1",
"createdByUserId": "507f1f77bcf86cd799439011",
"startTime": "2025-07-15T14:00:00.000Z",
"timezone": "America/New_York",
"durationInMinutes": 120,
"feedbacks": [
{
"userId": "507f1f77bcf86cd799439011",
"vote": "ok",
"comment": null,
"email": null,
"isGuest": false
},
{
"userId": null,
"vote": "challenging",
"comment": "Tight but can make it",
"email": "[email protected]",
"isGuest": true
}
],
"createdAt": "2025-06-01T10:00:00.000Z",
"updatedAt": "2025-06-10T09:30:00.000Z"
}Fields
| Field | Type | Description |
|---|---|---|
object | "proposed_slot" | Always "proposed_slot" |
id | string | Opaque slot ID |
meetingId | string | The meeting this slot belongs to |
createdByUserId | string | null | User who proposed this time |
startTime | string | Proposed start time (ISO-8601 UTC) |
timezone | string | IANA timezone for display (e.g. America/New_York) |
durationInMinutes | number | Duration in minutes (default 120) |
feedbacks | array | Votes from board members and invited guests (see below) |
createdAt | string | ISO-8601 timestamp |
updatedAt | string | ISO-8601 timestamp |
Feedback Object
| Field | Type | Description |
|---|---|---|
userId | string | null | The voting member's user ID, null for a guest vote |
vote | string | One of: ok, challenging, cant, didNotVote |
comment | string | null | Optional comment (max 500 characters) |
email | string | null | Email address the vote was submitted under, for guest votes |
isGuest | boolean | true when the vote came from a meeting guest rather than a board member |
Vote Values
| Value | Meaning |
|---|---|
ok | Can attend |
challenging | Maybe / difficult |
cant | Cannot attend |
didNotVote | Has not voted yet (system-assigned; not settable via the vote endpoint) |
List Proposed Slots
GET /api/v1/boards/:boardId/meetings/:meetingId/slotsReturns all proposed time slots for a meeting. Feedbacks are filtered to include only current board members plus any guest votes.
Response
{
"data": [
/* array of proposed slot objects */
],
"meta": { "nextCursor": null, "hasMore": false }
}Errors
| Code | Status | When |
|---|---|---|
UNAUTHENTICATED | 401 | Missing or invalid token |
FORBIDDEN | 403 | User does not have access to this board |
RESOURCE_NOT_FOUND | 404 | Board or meeting does not exist |
Create a Proposed Slot
POST /api/v1/boards/:boardId/meetings/:meetingId/slotsProposes a new time slot. The creator is automatically marked as ok. All other board members start as didNotVote. Requires at least collaborator access.
Request Body
Only startTime, timezone, and durationInMinutes are accepted — unknown fields are rejected.
| Field | Type | Required | Description |
|---|---|---|---|
startTime | string | Yes | Proposed start time (ISO-8601), must not be in the past |
timezone | string | Yes | IANA timezone (e.g. America/New_York) |
durationInMinutes | integer | No | Duration 15–180 (default 120) |
Response
Returns 201 with the created proposed slot object wrapped in { "data": ... }.
Errors
| Code | Status | When |
|---|---|---|
INVALID_REQUEST_BODY | 400 | Missing/invalid fields, or startTime is in the past |
UNAUTHENTICATED | 401 | Missing or invalid token |
FORBIDDEN | 403 | Caller is not at least a collaborator |
BILLING_RESTRICTED | 403 | Billing not active |
RESOURCE_NOT_FOUND | 404 | Board or meeting does not exist |
CONFLICT | 409 | A slot already exists at the same start time — details.slotId names the existing slot; treat this as "already proposed," not a transient error |
Vote on a Slot
PUT /api/v1/boards/:boardId/meetings/:meetingId/slots/:slotId/voteCasts or updates the authenticated user's vote on a proposed slot. Only vote and comment are accepted.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
vote | string | Yes | One of ok, challenging, cant (didNotVote cannot be set directly) |
comment | string | No | Optional comment (max 500 characters) |
Response
Returns the updated proposed slot object wrapped in { "data": ... }.
Errors
| Code | Status | When |
|---|---|---|
INVALID_REQUEST_BODY | 400 | Invalid vote value or unknown fields |
UNAUTHENTICATED | 401 | Missing or invalid token |
FORBIDDEN | 403 | Caller is not at least a collaborator |
BILLING_RESTRICTED | 403 | Billing not active |
RESOURCE_NOT_FOUND | 404 | Board, meeting, or slot does not exist |
CONFLICT | 409 | details.reason: "SLOT_VOTES_CLOSED" — the meeting is no longer collecting slot votes; not retryable |
Delete a Slot
DELETE /api/v1/boards/:boardId/meetings/:meetingId/slots/:slotIdRemoves a proposed time slot.
Response
{ "data": { "deleted": true } }Errors
| Code | Status | When |
|---|---|---|
UNAUTHENTICATED | 401 | Missing or invalid token |
FORBIDDEN | 403 | Caller is not at least a collaborator |
BILLING_RESTRICTED | 403 | Billing not active |
RESOURCE_NOT_FOUND | 404 | Board or slot does not exist |
CONFLICT | 409 | details.reason: "SLOT_IS_PROMOTED" — this slot backs the meeting's currently booked time; not retryable |
Confirm Slot as Meeting Time
POST /api/v1/boards/:boardId/meetings/:meetingId/slots/:slotId/confirmConfirms a proposed slot as the meeting's scheduled time. Copies the slot's start time, duration, and timezone to the meeting.
Response
Returns the updated meeting object (see Meetings).
Errors
| Code | Status | When |
|---|---|---|
UNAUTHENTICATED | 401 | Missing or invalid token |
FORBIDDEN | 403 | Caller is not at least a collaborator |
BILLING_RESTRICTED | 403 | Billing not active |
RESOURCE_NOT_FOUND | 404 | Board, meeting, or slot does not exist |
CONFLICT | 409 | details.reason is one of: SLOT_START_IN_PAST (slot's start time already passed), MEETING_FINALIZED (the meeting is no longer editable) — neither is retryable |