Browse documentation

Calendar & appointments

Current release · Updated October 2, 2026

DryKraft Calendar & appointments reference: methods, permissions, request fields, response shapes, examples and current limits. Read authentication and error handling first.

GET/api/calendar/members

List possible calendar hosts

Access: Workspace member · Success: 200

Up to500 current workspace user IDs and names; emails are excluded.

No request body is required.

Response

object[].

Request shape (illustrative)
curl --request GET \
  --url 'https://app.drykraft.com/api/calendar/members' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>'
GET/api/calendar/calendars

List calendars

Access: Workspace member · Success: 200

Up to100 retained personal, team or service calendars, including disabled definitions.

No request body is required.

Response

Calendar[].

Request shape (illustrative)
curl --request GET \
  --url 'https://app.drykraft.com/api/calendar/calendars' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>'
POST/api/calendar/calendars

Create calendar

Access: Owner or admin · Success: 201

Active billing required. Unique client UUID; duplicate IDs return409 rather than creating another definition. Public booking is opt-in. Working hours use the configured timezone.

JSON request

Use CalendarInput.

Response

Use Calendar.

Request shape (illustrative)
curl --request POST \
  --url 'https://app.drykraft.com/api/calendar/calendars' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
  "id": "00000000-0000-4000-8000-000000000001",
  "name": "<Calendar name>",
  "config": {
    "kind": "personal",
    "timezone": "<Valid IANA timezone>",
    "duration": 15,
    "buffer_before": 0,
    "buffer_after": 0,
    "notice_minutes": 0,
    "horizon_days": 1,
    "hosts": [
      "00000000-0000-4000-8000-000000000001"
    ],
    "assignment": "round_robin",
    "availability": [
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      }
    ],
    "exceptions": [],
    "location": "<Public booking location or link>",
    "description": "<Public booking description>",
    "reminder_minutes": []
  },
  "enabled": false,
  "public_enabled": false
}'
PUT/api/calendar/calendars/{id}

Update availability

Access: Owner or admin · Success: 200

Current version and matching body ID required. Changes affect new bookings/reschedules; existing appointment host/time/location snapshots stay fixed. Disable instead of deleting.

JSON request

FieldTypeRequiredDetails
iduuidYes
namestringYesCalendar name Max 120 characters.
configCalendarConfigYes
enabledbooleanYesAccept new appointments
public_enabledbooleanYesExplicitly publish availability and booking metadata
versionintegerYesPositive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes. Min 1.

Response

Use Calendar.

Request shape (illustrative)
curl --request PUT \
  --url 'https://app.drykraft.com/api/calendar/calendars/00000000-0000-4000-8000-000000000001' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
  "id": "00000000-0000-4000-8000-000000000001",
  "name": "<Calendar name>",
  "config": {
    "kind": "personal",
    "timezone": "<Valid IANA timezone>",
    "duration": 15,
    "buffer_before": 0,
    "buffer_after": 0,
    "notice_minutes": 0,
    "horizon_days": 1,
    "hosts": [
      "00000000-0000-4000-8000-000000000001"
    ],
    "assignment": "round_robin",
    "availability": [
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      },
      {
        "day": 0,
        "windows": []
      }
    ],
    "exceptions": [],
    "location": "<Public booking location or link>",
    "description": "<Public booking description>",
    "reminder_minutes": []
  },
  "enabled": false,
  "public_enabled": false,
  "version": 1
}'
GET/api/calendar/calendars/{id}/slots

Read available times

Access: Workspace member · Success: 200

15-minute grid, configured duration, notice, horizon, working windows/date overrides and buffers. Every host is checked across local calendars and fresh provider ranges. Stale provider cache blocks that host. Optional exclude must name an appointment in this calendar.

Query parameters

ParameterTypeRequiredDetails
datedateYesValid calendar date, YYYY-MM-DD.
timezonestringYesValid IANA timezone Max 100 characters.
excludeuuidNo

No request body is required.

Response

FieldTypeRequiredDetails
slotsobject[]Yes
unavailablebooleanYesSome connected host availability is stale
Request shape (illustrative)
curl --request GET \
  --url 'https://app.drykraft.com/api/calendar/calendars/00000000-0000-4000-8000-000000000001/slots?date=2026-10-02&timezone=%3CValid%20IANA%20timezone%3E' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>'
POST/api/calendar/local-times

Resolve local clock time

Access: Workspace member · Success: 200

Returns zero instants for a nonexistent daylight-saving time, one normally, two for a repeated time. Choose an explicit returned offset/instant before booking outside working hours.

JSON request

FieldTypeRequiredDetails
datedateYesValid calendar date, YYYY-MM-DD.
timestringYesHH:MM
timezonestringYesValid IANA timezone Max 100 characters.

Response

FieldTypeRequiredDetails
choicesdate-time[]No
Request shape (illustrative)
curl --request POST \
  --url 'https://app.drykraft.com/api/calendar/local-times' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
  "date": "2026-10-02",
  "time": "<HH:MM>",
  "timezone": "<Valid IANA timezone>"
}'
GET/api/calendar/appointments

List appointments

Access: Workspace member · Success: 200

Requested range must be positive and at most62days. Up to1000 rows plus more=true; narrow by calendar if truncated. Includes lifecycle, linked record metadata and calendar name.

Query parameters

ParameterTypeRequiredDetails
fromdate-timeYesISO instant with explicit UTC offset.
todate-timeYesISO instant with explicit UTC offset.
calendar_iduuidNo

No request body is required.

Response

FieldTypeRequiredDetails
itemsAppointment[]No
morebooleanNoAdditional rows exist
Request shape (illustrative)
curl --request GET \
  --url 'https://app.drykraft.com/api/calendar/appointments?from=%3CISO%20instant%20with%20explicit%20UTC%20offset%3E&to=%3CISO%20instant%20with%20explicit%20UTC%20offset%3E' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>'
GET/api/calendar/appointments/{id}

Read appointment and history

Access: Workspace member · Success: 200

Tenant-scoped appointment plus latest50 append-only version snapshots. Snapshots exclude management keys and request hashes.

No request body is required.

Response

FieldTypeRequiredDetails
iduuidYes
calendar_iduuidYes
titlestringYesTitle Max 160 characters.
guest_namestringNoGuest name Max 120 characters.
guest_emailemailNo Max 200 characters.
record_idstring or nullNo
starts_atdate-timeYesISO instant with explicit UTC offset.
timezonestringYesValid IANA timezone Max 100 characters.
notesstringNoInternal only Max 4000 characters.
outside_hoursbooleanNoWorkspace only: bypass working hours/notice/horizon, never host conflicts or stale provider availability. Defaults false.
ends_atdate-timeYesISO instant with explicit UTC offset.
host_idsuuid[]No
statebooked | completed | no_show | cancelledYesLifecycle
sourceworkspace | public | workflowNoCreation source
manage_keyuuidNo
locationstringNoSaved location
versionintegerYesPositive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes. Min 1.
created_atdate-timeNoISO instant with explicit UTC offset.
updated_atdate-timeNoISO instant with explicit UTC offset.
historyobject[]No
Request shape (illustrative)
curl --request GET \
  --url 'https://app.drykraft.com/api/calendar/appointments/00000000-0000-4000-8000-000000000001' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>'
POST/api/calendar/appointments

Book appointment

Access: Owner, admin or member · Success: 201

Workspace scheduling lock prevents cross-calendar double booking and serializes round robin. Same UUID and original normalized request returns the committed appointment. Different content returns409. Linked CRM records resolve contact merges. Future times must be within one year.

JSON request

Use AppointmentInput.

Response

Use Appointment.

Request shape (illustrative)
curl --request POST \
  --url 'https://app.drykraft.com/api/calendar/appointments' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
  "id": "00000000-0000-4000-8000-000000000001",
  "calendar_id": "00000000-0000-4000-8000-000000000001",
  "title": "<Title>",
  "guest_name": "<Guest name>",
  "guest_email": "person@example.com",
  "record_id": "00000000-0000-4000-8000-000000000001",
  "starts_at": "<ISO instant with explicit UTC offset>",
  "timezone": "<Valid IANA timezone>",
  "notes": "<Internal only>"
}'
PUT/api/calendar/appointments/{id}

Change appointment

Access: Owner, admin or member · Success: 200

Current version required. Rescheduling checks availability excluding this appointment and uses current calendar duration/buffers/location rules. Attendance is allowed only after start. Cancellation remains available after billing expiry. Notes-only edits do not repeat emitted reminders.

JSON request

FieldTypeRequiredDetails
versionintegerYesPositive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes. Min 1.
statebooked | cancelled | completed | no_showYesClosed appointments cannot reopen
starts_atdate-timeNoISO instant with explicit UTC offset.
timezonestringNoValid IANA timezone Max 100 characters.
notesstringNoInternal notes Max 4000 characters.
outside_hoursbooleanNoWorkspace only

Response

Use Appointment.

Request shape (illustrative)
curl --request PUT \
  --url 'https://app.drykraft.com/api/calendar/appointments/00000000-0000-4000-8000-000000000001' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
  "version": 1,
  "state": "booked"
}'
GET/api/calendar/appointments/{id}/ics

Download calendar event

Access: Workspace member · Success: 200

UTC event times, stable UID, lifecycle status and version. Excludes guest emails and internal notes; no invitation delivery.

No request body is required.

Response

string. RFC5545 event text, downloadable .ics

Request shape (illustrative)
curl --request GET \
  --url 'https://app.drykraft.com/api/calendar/appointments/00000000-0000-4000-8000-000000000001/ics' \
  --cookie 'drykraft_session=<YOUR_SESSION_TOKEN>'