Meetings
Scheduling links your patients book against, and the bookings that result.
Each meeting link defines an offering — duration, buffers, location kind. Bookings created against a link show up here and on the corresponding contact's timeline. locationKind is one of IN_PERSON, PHONE, VIDEO, CUSTOM.
Create a meeting link
Create a bookable meeting offering. Requires a user actor (service accounts can read but not create).
Required scopes:
contacts.writeRequest body
| Name | Type | Description |
|---|---|---|
titlerequired | string | Link display name. |
slug | string | URL slug. ≤ 80 chars. |
description | string | Public description shown to bookers. |
durationMinutes | integer | Visit length. 5–480. |
bufferBeforeMin | integer | Buffer before. 0–240. |
bufferAfterMin | integer | Buffer after. 0–240. |
minNoticeHours | integer | Minimum hours of advance notice. 0–720. |
availabilityRules | Rule[] | Weekly availability windows. { weekday: 0..6, start: HH:MM, end: HH:MM }. |
timezone | string | IANA timezone. |
locationKind | string | IN_PERSON | PHONE | VIDEO | CUSTOM. |
locationDetail | string | Free-form location detail. |
isActive | boolean | Whether the link is published. |
Request body
{ "title": "Intake call", "durationMinutes": 30, "locationKind": "VIDEO" }Responses
201 CreatedCreated.example { "id": "ml_5h8w2d…", "slug": "intake-call", "title": "Intake call", "durationMinutes": 30, "bufferBeforeMin": 5, "bufferAfterMin": 5, "minNoticeHours": 4, "timezone": "America/New_York", "locationKind": "VIDEO", "isActive": true, "ownerId": "usr_8h2c3p…" }
Code samples
curl -X POST https://app.contactfollowup.com/api/meetings \
-H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "title": "Intake call", "durationMinutes": 30, "locationKind": "VIDEO" }'List meeting links
Meeting links owned by the caller.
Required scopes:
contacts.readResponses
200 OKMeeting links.example { "meetings": [{ "id": "ml_5h8w2d…", "slug": "intake-call", "title": "Intake call", "durationMinutes": 30, "bufferBeforeMin": 5, "bufferAfterMin": 5, "minNoticeHours": 4, "timezone": "America/New_York", "locationKind": "VIDEO", "isActive": true, "ownerId": "usr_8h2c3p…" }] }
Code samples
curl -X GET https://app.contactfollowup.com/api/meetings \
-H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
-H "Content-Type: application/json"List bookings
Filtered bookings across all meeting links the caller can see.
Required scopes:
contacts.readQuery parameters
| Name | Type | Description |
|---|---|---|
ownerId | string | Owner filter. |
from | string | Earliest scheduled time (ISO 8601). |
to | string | Latest scheduled time (ISO 8601). |
Responses
200 OKBookings.example { "bookings": [{ "id": "mb_qkr8d…", "meetingLinkId": "ml_5h8w2d…", "contactId": "cln1f8s7p…", "scheduledAt": "2026-05-22T19:00:00Z", "status": "BOOKED", "createdAt": "2026-05-18T14:00:00Z" }] }
Code samples
curl -X GET https://app.contactfollowup.com/api/meetings/bookings \
-H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
-H "Content-Type: application/json"