Scheduling
Scheduling links, their open slots, and bookings.
Guides: Scheduling links and bookings.
| Method | Path | Operation | Scope |
|---|---|---|---|
GET | /v1/scheduling-links | List scheduling links | read |
POST | /v1/scheduling-links | Create a scheduling link | write |
GET | /v1/scheduling-links/{linkId} | Get a scheduling link | read |
PATCH | /v1/scheduling-links/{linkId} | Update a scheduling link | write |
DELETE | /v1/scheduling-links/{linkId} | Delete a scheduling link | write |
GET | /v1/scheduling-links/{linkId}/slots | List bookable slots | read |
POST | /v1/scheduling-links/{linkId}/bookings | Book a slot | write |
DELETE | /v1/bookings/{bookingId} | Cancel a booking | write |
Runs in your browser against api.workwae.com with the key you enter. Use a read-only key, limited to a test account if you can.
Newest first.
Required scope: read.
limit?integer1 <= value <= 1000100cursor?string1 <= length <= 512OK
application/json- response
items*array<>nextCursor*|nullcurl -X GET 'https://api.workwae.com/v1/scheduling-links'{ "items": [ { "name": "string", "accountIds": [ "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b" ], "mode": "all", "durationMinutes": 30, "stepMinutes": 30, "windowDays": 14, "timeZone": "Europe/Berlin", "hours": { "mon": [ { "start": "09:00", "end": "17:00" } ], "tue": [ { "start": "09:00", "end": "17:00" } ], "wed": [ { "start": "09:00", "end": "17:00" } ], "thu": [ { "start": "09:00", "end": "17:00" } ], "fri": [ { "start": "09:00", "end": "17:00" } ] }, "bufferBeforeMinutes": 0, "bufferAfterMinutes": 0, "minimumNoticeMinutes": 0, "maxPerDay": null, "title": "{{invitee}}", "description": "Production", "location": "string", "onlineMeeting": false, "onlineMeetingService": "zoom", "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b", "createdAt": "2026-05-04T09:30:00.000Z", "updatedAt": "2026-05-04T09:30:00.000Z" } ], "nextCursor": "eyJ0eG5pZCI6IjQyIiwiaWQiOjEwMDF9"}Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.
accountIds are accounts of the tenant whose calendars the link offers. mode all books every account into one event; mode any books one of them, the one with the fewest bookings of this link in the last 30 days (any status), the earliest in accountIds when tied.
Required scope: write.
application/json- body
name*string1 <= length <= 100accountIds*array<>1 <= items <= 20mode?AvailabilityMode"all""all""any"durationMinutes?integer5 <= value <= 144030stepMinutes?integer5 <= value <= 144030windowDays?integer1 <= value <= 36514timeZone*string1 <= length <= 64hours?{ "mon": [ { "start": "09:00", "end": "17:00" } ], "tue": [ { "start": "09:00", "end": "17:00" } ], "wed": [ { "start": "09:00", "end": "17:00" } ], "thu": [ { "start": "09:00", "end": "17:00" } ], "fri": [ { "start": "09:00", "end": "17:00" } ]}bufferBeforeMinutes?integer0 <= value <= 14400bufferAfterMinutes?integer0 <= value <= 14400minimumNoticeMinutes?integer0 <= value <= 864000maxPerDay?|nulltitle?string1 <= length <= 255"{{invitee}}"description?stringlength <= 10000location?stringlength <= 255onlineMeeting?booleanfalseonlineMeetingService?MeetingService"zoom""webex"OK
application/json- response
name*string1 <= length <= 100accountIds*array<>1 <= items <= 20mode?AvailabilityMode"all""all""any"durationMinutes?integer5 <= value <= 144030stepMinutes?integer5 <= value <= 144030windowDays?integer1 <= value <= 36514timeZone*string1 <= length <= 64hours?{ "mon": [ { "start": "09:00", "end": "17:00" } ], "tue": [ { "start": "09:00", "end": "17:00" } ], "wed": [ { "start": "09:00", "end": "17:00" } ], "thu": [ { "start": "09:00", "end": "17:00" } ], "fri": [ { "start": "09:00", "end": "17:00" } ]}bufferBeforeMinutes?integer0 <= value <= 14400bufferAfterMinutes?integer0 <= value <= 14400minimumNoticeMinutes?integer0 <= value <= 864000maxPerDay?|nulltitle?string1 <= length <= 255"{{invitee}}"description?stringlength <= 10000location?stringlength <= 255onlineMeeting?booleanfalseonlineMeetingService?MeetingService"zoom""webex"id*stringuuidcreatedAt*stringdate-timeupdatedAt*stringdate-timecurl -X POST 'https://api.workwae.com/v1/scheduling-links' \ -H 'Content-Type: application/json' \ -d '{ "name": "string", "accountIds": [ "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b" ], "timeZone": "Europe/Berlin"}'{ "name": "string", "accountIds": [ "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b" ], "mode": "all", "durationMinutes": 30, "stepMinutes": 30, "windowDays": 14, "timeZone": "Europe/Berlin", "hours": { "mon": [ { "start": "09:00", "end": "17:00" } ], "tue": [ { "start": "09:00", "end": "17:00" } ], "wed": [ { "start": "09:00", "end": "17:00" } ], "thu": [ { "start": "09:00", "end": "17:00" } ], "fri": [ { "start": "09:00", "end": "17:00" } ] }, "bufferBeforeMinutes": 0, "bufferAfterMinutes": 0, "minimumNoticeMinutes": 0, "maxPerDay": null, "title": "{{invitee}}", "description": "Production", "location": "string", "onlineMeeting": false, "onlineMeetingService": "zoom", "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b", "createdAt": "2026-05-04T09:30:00.000Z", "updatedAt": "2026-05-04T09:30:00.000Z"}Runs in your browser against api.workwae.com with the key you enter. Use a read-only key, limited to a test account if you can.
Required scope: read.
linkId*stringuuidOK
application/json- response
name*string1 <= length <= 100accountIds*array<>1 <= items <= 20mode?AvailabilityMode"all""all""any"durationMinutes?integer5 <= value <= 144030stepMinutes?integer5 <= value <= 144030windowDays?integer1 <= value <= 36514timeZone*string1 <= length <= 64hours?{ "mon": [ { "start": "09:00", "end": "17:00" } ], "tue": [ { "start": "09:00", "end": "17:00" } ], "wed": [ { "start": "09:00", "end": "17:00" } ], "thu": [ { "start": "09:00", "end": "17:00" } ], "fri": [ { "start": "09:00", "end": "17:00" } ]}bufferBeforeMinutes?integer0 <= value <= 14400bufferAfterMinutes?integer0 <= value <= 14400minimumNoticeMinutes?integer0 <= value <= 864000maxPerDay?|nulltitle?string1 <= length <= 255"{{invitee}}"description?stringlength <= 10000location?stringlength <= 255onlineMeeting?booleanfalseonlineMeetingService?MeetingService"zoom""webex"id*stringuuidcreatedAt*stringdate-timeupdatedAt*stringdate-timecurl -X GET 'https://api.workwae.com/v1/scheduling-links/a6670f08-11c3-4f9a-891f-1622bd1334a5'{ "name": "string", "accountIds": [ "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b" ], "mode": "all", "durationMinutes": 30, "stepMinutes": 30, "windowDays": 14, "timeZone": "Europe/Berlin", "hours": { "mon": [ { "start": "09:00", "end": "17:00" } ], "tue": [ { "start": "09:00", "end": "17:00" } ], "wed": [ { "start": "09:00", "end": "17:00" } ], "thu": [ { "start": "09:00", "end": "17:00" } ], "fri": [ { "start": "09:00", "end": "17:00" } ] }, "bufferBeforeMinutes": 0, "bufferAfterMinutes": 0, "minimumNoticeMinutes": 0, "maxPerDay": null, "title": "{{invitee}}", "description": "Production", "location": "string", "onlineMeeting": false, "onlineMeetingService": "zoom", "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b", "createdAt": "2026-05-04T09:30:00.000Z", "updatedAt": "2026-05-04T09:30:00.000Z"}Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.
Only the fields given change. Existing bookings keep their events.
Required scope: write.
linkId*stringuuidapplication/json- body
name?string1 <= length <= 100accountIds?array<>1 <= items <= 20mode?AvailabilityMode"all""all""any"durationMinutes?integer5 <= value <= 144030stepMinutes?integer5 <= value <= 144030windowDays?integer1 <= value <= 36514timeZone?string1 <= length <= 64hours?{ "mon": [ { "start": "09:00", "end": "17:00" } ], "tue": [ { "start": "09:00", "end": "17:00" } ], "wed": [ { "start": "09:00", "end": "17:00" } ], "thu": [ { "start": "09:00", "end": "17:00" } ], "fri": [ { "start": "09:00", "end": "17:00" } ]}bufferBeforeMinutes?integer0 <= value <= 14400bufferAfterMinutes?integer0 <= value <= 14400minimumNoticeMinutes?integer0 <= value <= 864000maxPerDay?|nulltitle?string1 <= length <= 255"{{invitee}}"description?|nulllocation?|nullonlineMeeting?booleanfalseonlineMeetingService?|nullOK
application/json- response
name*string1 <= length <= 100accountIds*array<>1 <= items <= 20mode?AvailabilityMode"all""all""any"durationMinutes?integer5 <= value <= 144030stepMinutes?integer5 <= value <= 144030windowDays?integer1 <= value <= 36514timeZone*string1 <= length <= 64hours?{ "mon": [ { "start": "09:00", "end": "17:00" } ], "tue": [ { "start": "09:00", "end": "17:00" } ], "wed": [ { "start": "09:00", "end": "17:00" } ], "thu": [ { "start": "09:00", "end": "17:00" } ], "fri": [ { "start": "09:00", "end": "17:00" } ]}bufferBeforeMinutes?integer0 <= value <= 14400bufferAfterMinutes?integer0 <= value <= 14400minimumNoticeMinutes?integer0 <= value <= 864000maxPerDay?|nulltitle?string1 <= length <= 255"{{invitee}}"description?stringlength <= 10000location?stringlength <= 255onlineMeeting?booleanfalseonlineMeetingService?MeetingService"zoom""webex"id*stringuuidcreatedAt*stringdate-timeupdatedAt*stringdate-timecurl -X PATCH 'https://api.workwae.com/v1/scheduling-links/a6670f08-11c3-4f9a-891f-1622bd1334a5' \ -H 'Content-Type: application/json' \ -d '{}'{ "name": "string", "accountIds": [ "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b" ], "mode": "all", "durationMinutes": 30, "stepMinutes": 30, "windowDays": 14, "timeZone": "Europe/Berlin", "hours": { "mon": [ { "start": "09:00", "end": "17:00" } ], "tue": [ { "start": "09:00", "end": "17:00" } ], "wed": [ { "start": "09:00", "end": "17:00" } ], "thu": [ { "start": "09:00", "end": "17:00" } ], "fri": [ { "start": "09:00", "end": "17:00" } ] }, "bufferBeforeMinutes": 0, "bufferAfterMinutes": 0, "minimumNoticeMinutes": 0, "maxPerDay": null, "title": "{{invitee}}", "description": "Production", "location": "string", "onlineMeeting": false, "onlineMeetingService": "zoom", "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b", "createdAt": "2026-05-04T09:30:00.000Z", "updatedAt": "2026-05-04T09:30:00.000Z"}Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.
Bookings of the link are deleted with it. Their events are left as they are.
Required scope: write.
linkId*stringuuidOK
application/json- response
curl -X DELETE 'https://api.workwae.com/v1/scheduling-links/a6670f08-11c3-4f9a-891f-1622bd1334a5'nullRuns in your browser against api.workwae.com with the key you enter. Use a read-only key, limited to a test account if you can.
Slots inside the link's window (windowDays ahead of now, in its time zone), not before its minimum notice, inside its hours, clear of each account's own calendar once widened by the buffers, and under maxPerDay. from and to narrow that range. accountIds on a slot are the accounts free for it.
Required scope: read.
linkId*stringuuidfrom?stringdate-timeto?stringdate-timelimit?integer1 <= value <= 1000200OK
application/json- response
items*array<>curl -X GET 'https://api.workwae.com/v1/scheduling-links/a6670f08-11c3-4f9a-891f-1622bd1334a5/slots'{ "items": [ { "start": "2026-05-04T09:30:00.000Z", "end": "2026-05-04T09:30:00.000Z", "accountIds": [ "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b" ] } ]}Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.
Books start only when it is one of the link's slots at that moment. mode any hosts it on the account with the fewest bookings of this link in the last 30 days among those free then (the earliest in accountIds when tied); mode all creates the event on the first account and invites the others. The invitee is an attendee. The slot is claimed in the database before the event is created, so two bookings of the same account and start cannot both succeed (slot_taken). Sends booking.created.
Required scope: write.
linkId*stringuuidapplication/json- body
start*stringdate-timeinvitee*notes?stringlength <= 2000OK
application/json- response
id*stringuuidlinkId*stringuuidaccountId*stringuuideventId*|nullstart*stringdate-timeend*stringdate-timeinvitee*notes*string|nullstatus*BookingStatus"booked""cancelled"createdAt*stringdate-timecancelledAt*|nullcurl -X POST 'https://api.workwae.com/v1/scheduling-links/a6670f08-11c3-4f9a-891f-1622bd1334a5/bookings' \ -H 'Content-Type: application/json' \ -d '{ "start": "2026-05-04T09:30:00.000Z", "invitee": { "address": "ada@example.com" }}'{ "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b", "linkId": "a6670f08-11c3-4f9a-891f-1622bd1334a5", "accountId": "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b", "eventId": "b6d8444a-dc76-4be5-849f-414f1b681c88", "start": "2026-05-04T09:30:00.000Z", "end": "2026-05-04T09:30:00.000Z", "invitee": { "name": "Ada Lovelace", "address": "ada@example.com" }, "notes": "string", "status": "booked", "createdAt": "2026-05-04T09:30:00.000Z", "cancelledAt": "2026-05-04T09:30:00.000Z"}Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.
Deletes the event (telling its attendees) and marks the booking cancelled. Sends booking.cancelled. An event already gone is still a successful cancel.
Required scope: write.
bookingId*stringuuidOK
application/json- response
id*stringuuidlinkId*stringuuidaccountId*stringuuideventId*|nullstart*stringdate-timeend*stringdate-timeinvitee*notes*string|nullstatus*BookingStatus"booked""cancelled"createdAt*stringdate-timecancelledAt*|nullcurl -X DELETE 'https://api.workwae.com/v1/bookings/e2cbbf01-50a4-43e6-a0eb-8f4b37e7ec0a'{ "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b", "linkId": "a6670f08-11c3-4f9a-891f-1622bd1334a5", "accountId": "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b", "eventId": "b6d8444a-dc76-4be5-849f-414f1b681c88", "start": "2026-05-04T09:30:00.000Z", "end": "2026-05-04T09:30:00.000Z", "invitee": { "name": "Ada Lovelace", "address": "ada@example.com" }, "notes": "string", "status": "booked", "createdAt": "2026-05-04T09:30:00.000Z", "cancelledAt": "2026-05-04T09:30:00.000Z"}