Scheduling
A subscribing workspace's own calendar: what is bookable, what is free, and booking it.
A subscribing workspace's own calendar - the same one their team sees under /calendar, and the same one a voice agent books into.
const { eventTypes } = await connect.scheduling.listEventTypes({ workspaceId });
const { slots, timezone } = await connect.scheduling.findSlots({
workspaceId,
eventTypeId: eventTypes[0].id,
from,
to,
});
const booking = await connect.scheduling.createBooking({
workspaceId,
eventTypeId: eventTypes[0].id,
startAt: slots[0].startAt,
attendee: { name: "Priya", phone: "+919000000001" },
});There is one calendar, not one per application. A booking your integration makes is visible on the workspace's own calendar screen immediately, and a slot their receptionist just took is gone from your next findSlots. That is the point of reading it through Connect rather than keeping your own copy - two calendars double-book, and nothing can reconcile them after the fact.
findSlots is advisory by construction. Between reading it and booking, another caller can take any of those times, so createBooking re-checks inside a transaction and answers 409 if it has gone. Handle that as an ordinary outcome and offer the next slot; it is not an error condition.
Times are instants. startAt goes back exactly as findSlots gave it, and timezone is the business's zone - what to render the wall time in, which is rarely the viewer's.
Endpoints
GET /api/v1/application/scheduling/schedules
List a workspace's availability schedules
Scope calendar:read · Rate limit 60 requests / min per key
The working-hours templates an appointment type points at. Read this before offering to create one, so a workspace that already has hours set does not get a second "Working hours" from your integration.
Implementation
curl "https://connect.cosmoops.com/api/v1/application/scheduling/schedules?workspaceId=WORKSPACE_ID" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT"Errors
forbidden (403), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
workspaceId | query | yes |
Responses
| Status | Meaning |
|---|---|
200 | Availability schedules |
403 | forbidden |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
schedules | array | yes |
POST /api/v1/application/scheduling/schedules
Create an availability schedule
Scope calendar:write · Rate limit 20 requests / min per key
A working-hours template, for a workspace that has none yet. Create at most one for a first-run setup flow - check GET /scheduling/schedules first.
Implementation
curl -X POST "https://connect.cosmoops.com/api/v1/application/scheduling/schedules" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","name":"Working hours","timezone":"Asia/Kolkata","weeklyHours":{"0":[],"1":[{"startMinute":540,"endMinute":1020}],"2":[{"startMinute":540,"endMinute":1020}],"3":[{"startMinute":540,"endMinute":1020}],"4":[{"startMinute":540,"endMinute":1020}],"5":[{"startMinute":540,"endMinute":1020}],"6":[]}}'This is deliberately narrower than what the workspace's own Calendar settings can do - no date overrides, and it is never owned by one person (ownerMemberId stays null). Anything beyond that is a Console edit, not a second write path for your integration to maintain.
Errors
validation_error (400 - an interval does not end after it starts, or overlaps another in the same day), forbidden (403), rate_limited (429).
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
name | string | yes | |
timezone | string | yes | |
weeklyHours | object | yes |
Responses
| Status | Meaning |
|---|---|
201 | The created schedule |
400 | validation_error |
403 | forbidden |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | |
name | string | yes | |
timezone | string | yes | |
weeklyHours | object | yes |
GET /api/v1/application/scheduling/event-types
List what a workspace offers as bookable
Scope calendar:read · Rate limit 60 requests / min per key
The workspace's own appointment types - the same ones their team configures under Calendar, and the same ones their voice agent books into. Start here: every other endpoint in this module takes an eventTypeId from this list.
Implementation
1. Prerequisites - an API key scoped to calendar:read, and a live subscription to your application in that workspace. The key proves which application is calling; the subscription is what makes you welcome in a given tenant. A workspace that has not installed your application answers 403, with the same message as an unknown workspace id.
2. Send the request:
curl "https://connect.cosmoops.com/api/v1/application/scheduling/event-types?workspaceId=WORKSPACE_ID" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT"3. Active only. An inactive appointment type is one the workspace has taken out of service; rendering it would offer something that cannot be booked.
locationKind is the kind and never the value - the address or the meeting link belongs to whoever booked, not to a catalogue.
Errors
forbidden (403 - key missing calendar:read, or your application is not installed in that workspace), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
workspaceId | query | yes |
Responses
| Status | Meaning |
|---|---|
200 | Bookable appointment types |
403 | forbidden |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
eventTypes | array | yes |
POST /api/v1/application/scheduling/event-types
Create an appointment type
Scope calendar:write · Rate limit 20 requests / min per key
The first thing a workspace can be booked for, for a workspace that has none yet. Needs a schedule - create or pick one with the /scheduling/schedules endpoints first.
Implementation
curl -X POST "https://connect.cosmoops.com/api/v1/application/scheduling/event-types" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","name":"Consultation","durationMinutes":30,"hostMemberId":"MEMBER_ID","scheduleId":"SCHEDULE_ID","location":{"kind":"phone","value":null}}'Host is a specific member, never a team. There is no groups read in this API, so hostMemberId must name one GET /workspaces/members row; a round-robin team host is a Console-only capability. The slug for a future public booking link is derived from name server-side - you cannot choose one.
Buffers default to 5 minutes either side; notice and booking-horizon rules default to the same 60/60 the Console form starts a new appointment type with, and are a Console edit from there.
Errors
validation_error (400), forbidden (403), not_found (404 - unknown scheduleId or hostMemberId), rate_limited (429).
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
name | string | yes | |
description | any | no | |
durationMinutes | integer | no | |
bufferBeforeMinutes | integer | no | |
bufferAfterMinutes | integer | no | |
hostMemberId | string | yes | |
scheduleId | string | yes | |
location | object | yes | |
publicBookingEnabled | boolean | no |
Responses
| Status | Meaning |
|---|---|
201 | The created appointment type |
400 | validation_error |
403 | forbidden |
404 | not_found |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | |
slug | string | yes | |
name | string | yes | |
description | any | yes | |
durationMinutes | integer | yes | |
locationKind | phone | address | link | yes |
GET /api/v1/application/scheduling/slots
Find free times for an appointment type
Scope calendar:read · Rate limit 60 requests / min per key
Free slots for one appointment type over one window, computed server-side from the workspace's working hours, its existing bookings and the appointment type's own buffers and notice rules.
Implementation
1. Send the request with an ISO-8601 from and to:
curl "https://connect.cosmoops.com/api/v1/application/scheduling/slots?workspaceId=WORKSPACE_ID&eventTypeId=EVENT_TYPE_ID&from=2026-09-08T00:00:00Z&to=2026-09-15T00:00:00Z" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT"2. The window is clamped, silently and on both ends - to now, and to the appointment type's own booking horizon. Asking for a year of a sixty-day appointment type returns sixty days, not an error.
3. timezone is the business's zone, not yours and not your user's. It is what to render the wall time in; a slot shown in the viewer's zone is an hour the business may not be open.
4. This answer is advisory. Between reading it and booking, anyone else on that calendar - a member, a voice agent mid-call, someone on the workspace's public booking link - can take any of these. POST /scheduling/bookings re-checks inside a transaction, so treat its 409 as an ordinary outcome and offer the next slot.
Errors
validation_error (400 - missing eventTypeId, or from not earlier than to), forbidden (403), not_found (404 - no such appointment type in that workspace), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
workspaceId | query | yes | |
eventTypeId | query | yes | |
from | query | yes | |
to | query | yes |
Responses
| Status | Meaning |
|---|---|
200 | Free slots |
400 | validation_error |
403 | forbidden |
404 | not_found |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
timezone | string | yes | |
durationMinutes | integer | yes | |
slots | array | yes |
GET /api/v1/application/scheduling/bookings
List what is already booked
Scope calendar:read · Rate limit 60 requests / min per key
The workspace's diary, with the same filters their own team has: one host, a period, a status.
Implementation
curl "https://connect.cosmoops.com/api/v1/application/scheduling/bookings?workspaceId=WORKSPACE_ID&from=2026-09-08T00:00:00Z&order=asc&limit=5" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT"order follows what you are asking for. asc with a from is an upcoming diary; the default desc is a history. An upcoming list read newest-first shows next year before tomorrow.
source is the field worth rendering. It says whether a booking came from your integration (api), from the workspace's own screen or public link (portal), or from a voice agent during a call (agent-call) - which is usually the first question anyone asks about an appointment they did not expect.
Page with cursor from nextCursor. A cursor belongs to one particular set of filters; changing a filter means starting again.
Errors
validation_error (400 - limit outside 1..100), forbidden (403), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
workspaceId | query | yes | |
status | query | no | |
hostMemberId | query | no | |
from | query | no | |
to | query | no | |
order | query | no | |
cursor | query | no | |
limit | query | no |
Responses
| Status | Meaning |
|---|---|
200 | One page of bookings |
400 | validation_error |
403 | forbidden |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
bookings | array | yes | |
nextCursor | any | yes | |
hasMore | boolean | yes | |
totalCount | integer | yes |
GET /api/v1/application/scheduling/bookings/{bookingId}
Read one booking you stored the id of
Scope calendar:read · Rate limit 60 requests / min per key
One appointment, by id. This is the read to make when you kept a booking id on a record of your own - a meeting on a deal, an appointment on a case.
Implementation
curl "https://connect.cosmoops.com/api/v1/application/scheduling/bookings/BOOKING_ID?workspaceId=WORKSPACE_ID" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT"GET /scheduling/bookings cannot answer this. That is a window over startAt, and the startAt you cached is precisely what is wrong once someone has moved the appointment on the workspace's own calendar - so the window you build from it comes back without the row, in the one case worth re-reading for.
A retired booking still resolves, deliberately. status: "rescheduled" answers with rescheduledToId, so an id you stored months ago leads to the appointment that exists today - follow the pointer. cancelled answers with cancelledReason. A 404 means this workspace never had that booking, which is a different fact from "it moved".
hostMemberIds - and the hostMemberId filter - are memberId values from GET /workspaces/members, not userId. So showing who an appointment belongs to, or narrowing the diary to one person, is a lookup against a roster you already hold; matching on userId finds nothing and fails silently, because a filter nobody matches reads as a free calendar rather than an error.
Errors
validation_error (400), forbidden (403), not_found (404 - no such booking in that workspace), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
bookingId | path | yes | |
workspaceId | query | yes |
Responses
| Status | Meaning |
|---|---|
200 | The booking |
400 | validation_error |
403 | forbidden |
404 | not_found |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | |
eventTypeId | string | yes | |
hostMemberIds | array | yes | |
status | hold | confirmed | cancelled | rescheduled | no_show | yes | |
startAt | string | yes | |
endAt | string | yes | |
timezone | string | yes | |
attendee | object | yes | |
notes | any | yes | |
source | agent-call | portal | api | yes | |
sourceCallId | any | yes | |
holdExpiresAt | any | yes | |
cancelledReason | any | yes | |
rescheduledToId | any | yes | |
createdAt | string | yes |
POST /api/v1/application/scheduling/bookings
Book a slot
Scope calendar:write · Rate limit 20 requests / min per key
Takes one of the times GET /scheduling/slots offered. Holds and confirms in a single call - you already have the attendee, so there is no half-finished state for your integration to remember.
Implementation
1. Prerequisite - an API key scoped to calendar:write. Split from calendar:read the same way drive:write is from drive:read: a key that renders "your next appointment" beside a contact has no business taking slots.
2. Pass startAt back exactly as /slots gave it. It is an instant, and re-deriving it from a local wall time is how an integration books an hour that was never offered.
curl -X POST "https://connect.cosmoops.com/api/v1/application/scheduling/bookings" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","eventTypeId":"EVENT_TYPE_ID","startAt":"2026-09-08T04:30:00.000Z","attendee":{"name":"Priya","phone":"+919000000001"}}'3. Handle 409 as a normal outcome. The slot is re-checked inside a transaction, so a time taken since you read it is refused rather than double-booked. Read the slots again and offer the next one; the message is written to be shown to whoever is booking.
The booking appears on the workspace's own calendar immediately, tagged source: "api" - or "agent-call" with your own sourceCallId, when an AI agent you run made it on a call. No contact is linked - naming one would mean naming a row in Connect's contact graph you cannot see.
Errors
validation_error (400), forbidden (403), not_found (404 - unknown appointment type), conflict (409 - the slot was taken, or is outside the appointment type's rules), rate_limited (429).
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
eventTypeId | string | yes | |
startAt | string | yes | |
attendee | object | yes | |
notes | any | no | |
source | api | agent-call | no | |
sourceCallId | any | no |
Responses
| Status | Meaning |
|---|---|
201 | The confirmed booking |
400 | validation_error |
403 | forbidden |
404 | not_found |
409 | conflict - the slot was taken |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | |
eventTypeId | string | yes | |
hostMemberIds | array | yes | |
status | hold | confirmed | cancelled | rescheduled | no_show | yes | |
startAt | string | yes | |
endAt | string | yes | |
timezone | string | yes | |
attendee | object | yes | |
notes | any | yes | |
source | agent-call | portal | api | yes | |
sourceCallId | any | yes | |
holdExpiresAt | any | yes | |
cancelledReason | any | yes | |
rescheduledToId | any | yes | |
createdAt | string | yes |
POST /api/v1/application/scheduling/holds
Hold a slot before you know who it is for
Scope calendar:write · Rate limit 20 requests / min per key
Phase one of the two-phase booking, for a caller that learns the attendee only after the time is picked - a voice agent reading three options aloud, then asking for a name. If you already have the attendee, use POST /scheduling/bookings instead.
Implementation
curl -X POST "https://connect.cosmoops.com/api/v1/application/scheduling/holds" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","eventTypeId":"EVENT_TYPE_ID","startAt":"2026-09-08T04:30:00.000Z","source":"agent-call","sourceCallId":"CALL_ID"}'The hold is a real hold booking on the workspace's calendar, written in the same transaction that re-checks the slot - so from this moment nobody else can take it, including the workspace's own public booking page. That is the race a one-shot booking cannot close while a caller is still spelling their name.
It lapses at holdExpiresAt (3 minutes by default, holdTtlMinutes up to 30) and frees the slot the instant it does. Confirm it with POST /scheduling/bookings/{bookingId}/confirm; only your application can.
source is agent-call by default here and sourceCallId is your own call id, returned on every read of the booking.
Errors
validation_error (400), forbidden (403), not_found (404 - unknown appointment type), conflict (409 - the slot was taken, or is not one /slots offers), rate_limited (429).
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
eventTypeId | string | yes | |
startAt | string | yes | |
holdTtlMinutes | integer | no | |
source | api | agent-call | no | |
sourceCallId | any | no |
Responses
| Status | Meaning |
|---|---|
201 | The hold - a booking with status hold |
400 | validation_error |
403 | forbidden |
404 | not_found |
409 | conflict - the slot was taken |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | |
eventTypeId | string | yes | |
hostMemberIds | array | yes | |
status | hold | confirmed | cancelled | rescheduled | no_show | yes | |
startAt | string | yes | |
endAt | string | yes | |
timezone | string | yes | |
attendee | object | yes | |
notes | any | yes | |
source | agent-call | portal | api | yes | |
sourceCallId | any | yes | |
holdExpiresAt | any | yes | |
cancelledReason | any | yes | |
rescheduledToId | any | yes | |
createdAt | string | yes |
POST /api/v1/application/scheduling/bookings/{bookingId}/confirm
Confirm a hold
Scope calendar:write · Rate limit 20 requests / min per key
Phase two: a hold from POST /scheduling/holds becomes a booking, and the attendee is told they are booked - the same confirmation, WhatsApp consent and booking.confirmed webhook as a booking made inside Connect.
Implementation
curl -X POST "https://connect.cosmoops.com/api/v1/application/scheduling/bookings/BOOKING_ID/confirm" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","attendee":{"name":"Priya","phone":"+919000000001"}}'Idempotent. Confirming a booking that is already confirmed answers it unchanged and notifies nobody, so a retry after a dropped response is safe. Do not tell the caller they are booked until this has returned.
Only a hold your application took resolves; any other id answers 404.
Errors
validation_error (400), forbidden (403), not_found (404 - no such hold for your application), conflict (409 - the hold lapsed or was cancelled; hold a slot again), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
bookingId | path | yes |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
attendee | object | yes | |
notes | any | no |
Responses
| Status | Meaning |
|---|---|
200 | The confirmed booking |
400 | validation_error |
403 | forbidden |
404 | not_found |
409 | conflict - the hold lapsed |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | |
eventTypeId | string | yes | |
hostMemberIds | array | yes | |
status | hold | confirmed | cancelled | rescheduled | no_show | yes | |
startAt | string | yes | |
endAt | string | yes | |
timezone | string | yes | |
attendee | object | yes | |
notes | any | yes | |
source | agent-call | portal | api | yes | |
sourceCallId | any | yes | |
holdExpiresAt | any | yes | |
cancelledReason | any | yes | |
rescheduledToId | any | yes | |
createdAt | string | yes |
POST /api/v1/application/scheduling/bookings/{bookingId}/reschedule
Move a booking to a different time
Scope calendar:write · Rate limit 20 requests / min per key
Moves an appointment, keeping the same appointment type and the same attendee.
The original row is not edited - it is retired. It stays on the workspace's diary as rescheduled, with rescheduledToId pointing at the booking that replaced it, and the response hands you both. So a booking id your integration cached still resolves, and still tells you where the appointment went; "we moved you twice" is a chain anyone can follow.
Implementation
curl -X POST "https://connect.cosmoops.com/api/v1/application/scheduling/bookings/BOOKING_ID/reschedule" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","startAt":"2026-09-09T05:00:00.000Z"}'Read the new times with excludeBookingId set to this booking. GET /scheduling/slots otherwise counts the appointment as blocking its own replacement, and the adjustment people actually make - same day, half an hour later - comes back with nothing available.
A refused move changes nothing. The new slot is claimed before the old one is retired, so a 409 leaves the customer holding the appointment they already had. Re-read the slots and offer another.
The attendee carries over unchanged; correcting a name is not what this endpoint is for. notes replaces the original note when given.
Errors
validation_error (400), forbidden (403), not_found (404 - no such booking in that workspace), conflict (409 - the new time was taken, or the booking is cancelled or already moved), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
bookingId | path | yes |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
startAt | string | yes | |
notes | any | no |
Responses
| Status | Meaning |
|---|---|
200 | The new booking, and the retired original |
400 | validation_error |
403 | forbidden |
404 | not_found |
409 | conflict - the new time was taken |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
booking | object | yes | |
previous | object | yes |
POST /api/v1/application/scheduling/bookings/{bookingId}/cancel
Cancel a booking
Scope calendar:write · Rate limit 20 requests / min per key
Frees the slot and records why.
A POST rather than a DELETE, because cancelling is not deleting: the booking stays on the workspace's diary as cancelled with your reason, which is what makes a late cancellation or a no-show something anyone can look up afterwards.
curl -X POST "https://connect.cosmoops.com/api/v1/application/scheduling/bookings/BOOKING_ID/cancel" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","reason":"Customer rescheduled by phone"}'The time becomes bookable again on the next /scheduling/slots read.
Errors
validation_error (400), forbidden (403), not_found (404 - no such booking in that workspace), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
bookingId | path | yes |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
reason | any | no |
Responses
| Status | Meaning |
|---|---|
200 | The cancelled booking |
400 | validation_error |
403 | forbidden |
404 | not_found |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | |
eventTypeId | string | yes | |
hostMemberIds | array | yes | |
status | hold | confirmed | cancelled | rescheduled | no_show | yes | |
startAt | string | yes | |
endAt | string | yes | |
timezone | string | yes | |
attendee | object | yes | |
notes | any | yes | |
source | agent-call | portal | api | yes | |
sourceCallId | any | yes | |
holdExpiresAt | any | yes | |
cancelledReason | any | yes | |
rescheduledToId | any | yes | |
createdAt | string | yes |
POST /api/v1/application/scheduling/bookings/{bookingId}/attendance
Record whether the attendee turned up
Scope calendar:write · Rate limit 20 requests / min per key
attended: false marks the booking no_show; true takes a no-show back to confirmed, for the one marked by mistake.
There is no "held" status to set: a confirmed booking whose time has passed already is a held one. The slot is not released either way - the time was reserved and consumed - and the attendee is not notified.
curl -X POST "https://connect.cosmoops.com/api/v1/application/scheduling/bookings/BOOKING_ID/attendance" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","attended":false}'Errors
validation_error (400), forbidden (403), not_found (404 - no such booking in that workspace), conflict (409 - the booking is not confirmed or no_show, or has not started yet), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
bookingId | path | yes |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
attended | boolean | yes |
Responses
| Status | Meaning |
|---|---|
200 | The booking, with its new status |
400 | validation_error |
403 | forbidden |
404 | not_found |
409 | conflict - not attendable, or not started |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | |
eventTypeId | string | yes | |
hostMemberIds | array | yes | |
status | hold | confirmed | cancelled | rescheduled | no_show | yes | |
startAt | string | yes | |
endAt | string | yes | |
timezone | string | yes | |
attendee | object | yes | |
notes | any | yes | |
source | agent-call | portal | api | yes | |
sourceCallId | any | yes | |
holdExpiresAt | any | yes | |
cancelledReason | any | yes | |
rescheduledToId | any | yes | |
createdAt | string | yes |