Calendar meetings and refresh
Both endpoints need the write:calendar scope. Reading the calendar is GET /api/v1/calendar with read:calendar.
Put a meeting on the calendar
POST /api/v1/calendar/meetings HTTP/1.1
Content-Type: application/json
{
"title": "Quarterly review",
"date": "2026-10-05",
"startTime": "14:00",
"durationMinutes": 45,
"contactId": "cmq2cont0alk34567891",
"assigneeUserId": "cmq1user0alk34567890"
}| Field | Required | Notes |
|---|---|---|
title | Yes | Up to 200 characters |
date | Yes | YYYY-MM-DD. With repeat, the day the repeat starts |
startTime | No | HH:MM in the workspace's timezone. Omit for an all-day entry |
durationMinutes | No | 1 to 1,440. Needs startTime |
description | No | Agenda, dial-in |
contactId, leadId, dealId | No | Must be in this workspace |
assigneeUserId | No | An active user. Omit to leave it unassigned |
repeat | No | { freq: DAILY | WEEKLY | MONTHLY, interval?, weekdays?, monthDay?, nthWeek?, nthWeekday?, until?, count? }. Name neither until nor count for an open-ended repeat |
Times are never read as UTC: 14:00 means 14:00 in the workspace's timezone, returned as timeZone.
{
"timeZone": "America/New_York",
"seriesId": null,
"tasks": [
{ "id": "cmq7task0alk34567890", "title": "Quarterly review", "type": "MEETING", "dueDate": "2026-10-05T18:00:00.000Z", "endAt": "2026-10-05T18:45:00.000Z", "allDay": false }
]
}A repeat returns its seriesId and every occurrence created so far. This endpoint sends no invitation and ignores booking-link availability. To book someone into a host's open time, use POST /api/v1/bookings.
Calling it twice creates two meetings.
Refresh a user's connected calendars
POST /api/v1/calendar/refresh HTTP/1.1
Content-Type: application/json
{ "hostUserId": "cmq1user0alk34567890", "from": "2026-10-01", "to": "2026-10-31" }Re-reads that user's connected Google, Outlook or Exchange calendars for the window, so their busy time and open booking slots are current. from defaults to now, to to 30 days later, and the window can be at most 90 days. Calendars also refresh on their own every 15 minutes.
{ "hostUserId": "cmq1user0alk34567890", "from": "2026-10-01T00:00:00.000Z", "to": "2026-10-31T00:00:00.000Z", "refreshed": 1, "failed": [] }failed lists the address of each mailbox that could not be read; its cached events are kept. The events themselves are never returned by the API, since they are private to that user.