Scheduling

Scheduling links, their open slots, and bookings.

Guides: Scheduling links and bookings.

MethodPathOperationScope
GET/v1/scheduling-linksList scheduling linksread
POST/v1/scheduling-linksCreate a scheduling linkwrite
GET/v1/scheduling-links/{linkId}Get a scheduling linkread
PATCH/v1/scheduling-links/{linkId}Update a scheduling linkwrite
DELETE/v1/scheduling-links/{linkId}Delete a scheduling linkwrite
GET/v1/scheduling-links/{linkId}/slotsList bookable slotsread
POST/v1/scheduling-links/{linkId}/bookingsBook a slotwrite
DELETE/v1/bookings/{bookingId}Cancel a bookingwrite
GET
/v1/scheduling-links

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.

Query Parameters

limit?integer
Range1 <= value <= 1000
Default100
cursor?string
Length1 <= length <= 512

Response Body

OK

application/json
  1. response
items*array<>
nextCursor*|null
Example Request
curl -X GET 'https://api.workwae.com/v1/scheduling-links'
Example Response
{  "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"}
POST
/v1/scheduling-links

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.

Request Body

application/json
  1. body
name*string
Length1 <= length <= 100
accountIds*array<>
Items1 <= items <= 20
mode?AvailabilityMode
Default"all"
Value in"all""any"
durationMinutes?integer
Range5 <= value <= 1440
Default30
stepMinutes?integer
Range5 <= value <= 1440
Default30
windowDays?integer
Range1 <= value <= 365
Default14
timeZone*string
Length1 <= length <= 64
hours?
Default
{  "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?integer
Range0 <= value <= 1440
Default0
bufferAfterMinutes?integer
Range0 <= value <= 1440
Default0
minimumNoticeMinutes?integer
Range0 <= value <= 86400
Default0
maxPerDay?|
Defaultnull
title?string
Length1 <= length <= 255
Default"{{invitee}}"
description?string
Lengthlength <= 10000
location?string
Lengthlength <= 255
onlineMeeting?boolean
Defaultfalse
onlineMeetingService?MeetingService
Value in"zoom""webex"

Response Body

OK

application/json
  1. response
name*string
Length1 <= length <= 100
accountIds*array<>
Items1 <= items <= 20
mode?AvailabilityMode
Default"all"
Value in"all""any"
durationMinutes?integer
Range5 <= value <= 1440
Default30
stepMinutes?integer
Range5 <= value <= 1440
Default30
windowDays?integer
Range1 <= value <= 365
Default14
timeZone*string
Length1 <= length <= 64
hours?
Default
{  "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?integer
Range0 <= value <= 1440
Default0
bufferAfterMinutes?integer
Range0 <= value <= 1440
Default0
minimumNoticeMinutes?integer
Range0 <= value <= 86400
Default0
maxPerDay?|
Defaultnull
title?string
Length1 <= length <= 255
Default"{{invitee}}"
description?string
Lengthlength <= 10000
location?string
Lengthlength <= 255
onlineMeeting?boolean
Defaultfalse
onlineMeetingService?MeetingService
Value in"zoom""webex"
id*string
Formatuuid
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -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"}'
Example Response
{  "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"}
GET
/v1/scheduling-links/{linkId}

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.

Path Parameters

linkId*string
Formatuuid

Response Body

OK

application/json
  1. response
name*string
Length1 <= length <= 100
accountIds*array<>
Items1 <= items <= 20
mode?AvailabilityMode
Default"all"
Value in"all""any"
durationMinutes?integer
Range5 <= value <= 1440
Default30
stepMinutes?integer
Range5 <= value <= 1440
Default30
windowDays?integer
Range1 <= value <= 365
Default14
timeZone*string
Length1 <= length <= 64
hours?
Default
{  "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?integer
Range0 <= value <= 1440
Default0
bufferAfterMinutes?integer
Range0 <= value <= 1440
Default0
minimumNoticeMinutes?integer
Range0 <= value <= 86400
Default0
maxPerDay?|
Defaultnull
title?string
Length1 <= length <= 255
Default"{{invitee}}"
description?string
Lengthlength <= 10000
location?string
Lengthlength <= 255
onlineMeeting?boolean
Defaultfalse
onlineMeetingService?MeetingService
Value in"zoom""webex"
id*string
Formatuuid
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X GET 'https://api.workwae.com/v1/scheduling-links/a6670f08-11c3-4f9a-891f-1622bd1334a5'
Example Response
{  "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"}
PATCH
/v1/scheduling-links/{linkId}

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.

Path Parameters

linkId*string
Formatuuid

Request Body

application/json
  1. body
name?string
Length1 <= length <= 100
accountIds?array<>
Items1 <= items <= 20
mode?AvailabilityMode
Default"all"
Value in"all""any"
durationMinutes?integer
Range5 <= value <= 1440
Default30
stepMinutes?integer
Range5 <= value <= 1440
Default30
windowDays?integer
Range1 <= value <= 365
Default14
timeZone?string
Length1 <= length <= 64
hours?
Default
{  "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?integer
Range0 <= value <= 1440
Default0
bufferAfterMinutes?integer
Range0 <= value <= 1440
Default0
minimumNoticeMinutes?integer
Range0 <= value <= 86400
Default0
maxPerDay?|null
title?string
Length1 <= length <= 255
Default"{{invitee}}"
description?|null
location?|null
onlineMeeting?boolean
Defaultfalse
onlineMeetingService?|null

Response Body

OK

application/json
  1. response
name*string
Length1 <= length <= 100
accountIds*array<>
Items1 <= items <= 20
mode?AvailabilityMode
Default"all"
Value in"all""any"
durationMinutes?integer
Range5 <= value <= 1440
Default30
stepMinutes?integer
Range5 <= value <= 1440
Default30
windowDays?integer
Range1 <= value <= 365
Default14
timeZone*string
Length1 <= length <= 64
hours?
Default
{  "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?integer
Range0 <= value <= 1440
Default0
bufferAfterMinutes?integer
Range0 <= value <= 1440
Default0
minimumNoticeMinutes?integer
Range0 <= value <= 86400
Default0
maxPerDay?|
Defaultnull
title?string
Length1 <= length <= 255
Default"{{invitee}}"
description?string
Lengthlength <= 10000
location?string
Lengthlength <= 255
onlineMeeting?boolean
Defaultfalse
onlineMeetingService?MeetingService
Value in"zoom""webex"
id*string
Formatuuid
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X PATCH 'https://api.workwae.com/v1/scheduling-links/a6670f08-11c3-4f9a-891f-1622bd1334a5' \  -H 'Content-Type: application/json' \  -d '{}'
Example Response
{  "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"}
DELETE
/v1/scheduling-links/{linkId}

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.

Path Parameters

linkId*string
Formatuuid

Response Body

OK

application/json
  1. response
Example Request
curl -X DELETE 'https://api.workwae.com/v1/scheduling-links/a6670f08-11c3-4f9a-891f-1622bd1334a5'
Example Response
null

List bookable slots

GET
/v1/scheduling-links/{linkId}/slots

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.

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.

Path Parameters

linkId*string
Formatuuid

Query Parameters

from?string
Formatdate-time
to?string
Formatdate-time
limit?integer
Range1 <= value <= 1000
Default200

Response Body

OK

application/json
  1. response
items*array<>
Example Request
curl -X GET 'https://api.workwae.com/v1/scheduling-links/a6670f08-11c3-4f9a-891f-1622bd1334a5/slots'
Example Response
{  "items": [    {      "start": "2026-05-04T09:30:00.000Z",      "end": "2026-05-04T09:30:00.000Z",      "accountIds": [        "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b"      ]    }  ]}

Book a slot

POST
/v1/scheduling-links/{linkId}/bookings

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.

Path Parameters

linkId*string
Formatuuid

Request Body

application/json
  1. body
start*string
Formatdate-time
invitee*
notes?string
Lengthlength <= 2000

Response Body

OK

application/json
  1. response
id*string
Formatuuid
linkId*string
Formatuuid
accountId*string
Formatuuid
eventId*|null
start*string
Formatdate-time
end*string
Formatdate-time
invitee*
notes*string|null
status*BookingStatus
Value in"booked""cancelled"
createdAt*string
Formatdate-time
cancelledAt*|null
Example Request
curl -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"  }}'
Example Response
{  "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"}

Cancel a booking

DELETE
/v1/bookings/{bookingId}

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.

Path Parameters

bookingId*string
Formatuuid

Response Body

OK

application/json
  1. response
id*string
Formatuuid
linkId*string
Formatuuid
accountId*string
Formatuuid
eventId*|null
start*string
Formatdate-time
end*string
Formatdate-time
invitee*
notes*string|null
status*BookingStatus
Value in"booked""cancelled"
createdAt*string
Formatdate-time
cancelledAt*|null
Example Request
curl -X DELETE 'https://api.workwae.com/v1/bookings/e2cbbf01-50a4-43e6-a0eb-8f4b37e7ec0a'
Example Response
{  "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"}