Scheduling links and bookings

Offer bookable slots across one or more accounts' calendars, book them for invitees and cancel bookings.

A scheduling link is a stored booking configuration: which accounts can be booked, for how long and when. List its open slots, show them to an invitee, and book the one they pick; Workwae creates the calendar event.

Links belong to the tenant, not to one account. They need the calendar module in the plan (403 plan_module_unavailable).

How it relates to finding a time

Find a time answers a one-off question: when are these people free in this range? A scheduling link stores that question (accounts, hours, buffers, notice, cap) so slots can be listed again at any time, and adds booking: re-checking the slot, creating the event and recording the booking.

Create a link

curl -X POST "https://api.workwae.com/v1/scheduling-links" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "name": "Sales intro",
  "accountIds": ["'"$ALICE_ACCOUNT_ID"'", "'"$BOB_ACCOUNT_ID"'"],
  "mode": "any",
  "durationMinutes": 30,
  "timeZone": "America/New_York",
  "hours": {
    "mon": [{ "start": "09:00", "end": "12:00" }, { "start": "13:00", "end": "17:00" }],
    "wed": [{ "start": "09:00", "end": "17:00" }]
  },
  "bufferAfterMinutes": 10,
  "minimumNoticeMinutes": 240,
  "maxPerDay": 6,
  "title": "Intro call with {{invitee}}",
  "onlineMeeting": true
}'

Who is booked

accountIds lists 1 to 20 of the tenant's accounts, each once. An unknown account answers 422 unknown_account, listing it in data.

modeSlot is offered whenThe booking
all (default)Every account is free.One event on the first account, inviting the others.
any (round-robin)At least one account is free.Hosted by the free account with the fewest bookings of this link in the last 30 days (any status); ties go to the earliest in accountIds.

When slots are offered

FieldDefaultMeaning
timeZonerequiredIANA zone that hours, step and daily cap are read in (invalid_time_zone).
durationMinutes30Slot length, 5 to 1440.
stepMinutes30Slots start on multiples of this many minutes after local midnight.
windowDays14Days ahead slots are offered, up to 365.
hoursMon–Fri 09:00–17:00Up to 8 windows per weekday; a day left out has none. Each window's end must be after start (invalid_working_hours).
bufferBeforeMinutes, bufferAfterMinutes0Free time an account needs around the slot, up to 1440.
minimumNoticeMinutes0How far ahead a slot must start, up to 86400 (60 days).
maxPerDaynullMost bookings per local day, 1 to 1000; null is no limit.

The event a booking creates

FieldDefaultMeaning
title{{invitee}}Event subject, up to 255 characters.
descriptionnonePlain-text description, up to 10,000 characters.
locationnoneEvent location.
onlineMeetingfalseTeams (Microsoft 365) or Meet (Google) link.
onlineMeetingServicenonezoom or webex, created by Workwae; needs the meetings module. See Meetings.

{{invitee}} and {{inviteeEmail}} in title and description are replaced at booking time. Setting both onlineMeeting and onlineMeetingService answers multiple_meeting_options.

Manage links

  • GET /v1/scheduling-links lists links newest first; GET /v1/scheduling-links/{linkId} reads one.
  • PATCH /v1/scheduling-links/{linkId} changes only the fields given; null clears description, location, onlineMeetingService and maxPerDay. Existing bookings keep their events.
  • DELETE /v1/scheduling-links/{linkId} deletes the link and its bookings. Their events are left as they are.

A missing link answers 404 scheduling_link_not_found.

List slots

curl "https://api.workwae.com/v1/scheduling-links/$LINK_ID/slots?from=2026-11-02T00:00:00Z&to=2026-11-09T00:00:00Z" \
  -H "Authorization: Bearer $WORKWAE_API_KEY"
Response
{
  "items": [
    {
      "start": "2026-11-02T14:00:00.000Z",
      "end": "2026-11-02T14:30:00.000Z",
      "accountIds": ["…alice", "…bob"]
    }
  ]
}

A slot is listed when it is:

  • inside the link's window (windowDays ahead of now, in its time zone) and not before the minimum notice;
  • inside the link's hours;
  • clear of each account's own calendar once widened by the buffers;
  • under maxPerDay.

from and to narrow that range; to not after from, or a range longer than the link looks ahead, answers 400 invalid_range. limit caps the answer (default 200, up to 1000). A slot's accountIds are the accounts free for it, in the link's order.

Book a slot

Pass a slot's start and the invitee. Workwae re-checks the slot, picks the account, creates the event with the invitee as an attendee, and sends booking.created. notes (up to 2000 characters) is added to the event's description.

curl -X POST "https://api.workwae.com/v1/scheduling-links/$LINK_ID/bookings" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "start": "2026-11-02T14:00:00Z",
  "invitee": { "name": "Ada Lovelace", "address": "ada@example.com" },
  "notes": "Interested in the team plan"
}'

The event goes on the account's primary calendar, or the first calendar it can write. The slot is claimed in the database before the event is created, so two bookings of the same account and start cannot both succeed.

StatusReasonMeaning
409slot_takenThe slot was booked meanwhile. List slots again and let the invitee pick another.
409slot_unavailablestart is not a slot the link offers now, or no account is free for it.
409calendar_disabledThe chosen account has calendar sync off.
404calendar_not_foundThe account has no calendar an event can be created in.
403plan_module_unavailableNo calendar module, or the link creates a Zoom or Webex meeting without the meetings module.

Meeting errors such as meeting_service_not_connected are in Meetings.

Cancel a booking

DELETE /v1/bookings/{bookingId} deletes the event, telling its attendees, marks the booking cancelled with cancelledAt, and sends booking.cancelled. An event already gone still cancels successfully, and eventId becomes null once the event is gone.

curl -X DELETE "https://api.workwae.com/v1/bookings/$BOOKING_ID" \
  -H "Authorization: Bearer $WORKWAE_API_KEY"

A missing booking answers 404 booking_not_found, one already cancelled 409 booking_cancelled, and an account with calendar sync off calendar_disabled.

Booking events

booking.created and booking.cancelled report bookings made and cancelled through links. Payloads are in Calendar and contacts events.

On this page