20 endpoints

API Reference

REST API for managing profiles, events, bookings, availability, and schedules.

Quick Start

https://skdul.ai/api/v1
curl -X GET https://skdul.ai/api/v1/profile \
  -H "Authorization: Bearer sk_live_<your_key>"

Authentication

All /api/v1/* endpoints require an API key passed via the Authorization header.

Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx
{ "error": "Missing or invalid API key" }

Profile

2 endpoints

GET/api/v1/profile

Get your full profile including name, username, timezone, and settings

Response

{
  "id": "uuid",
  "username": "janedoe",
  "full_name": "Jane Doe",
  "timezone": "America/New_York",
  "time_format": "12h",
  "brand_color": "#E8634A",
  "bio": "Product designer based in NYC",
  "week_start": "sunday",
  "avatar_url": "https://...",
  "plan": "free"
}

Example

curl -X GET https://skdul.ai/api/v1/profile \
  -H "Authorization: Bearer sk_live_<your_key>"

PATCH/api/v1/profile

Update your profile settings

Parameters

NameTypeRequiredDescription
fullNamestringNoYour display name
timezonestringNoIANA timezone (e.g. America/New_York)
timeFormat"12h" | "24h"NoTime display format
brandColorstringNoHex color code (e.g. #E8634A)
biostringNoShort bio for your booking page
weekStart"sunday" | "monday"NoFirst day of the week

Response

{
  "id": "uuid",
  "username": "janedoe",
  "full_name": "Jane Doe",
  "timezone": "America/New_York",
  "time_format": "12h",
  "brand_color": "#E8634A",
  "bio": "Updated bio",
  "week_start": "sunday"
}

Example

curl -X PATCH https://skdul.ai/api/v1/profile \
  -H "Authorization: Bearer sk_live_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{"fullName": "Jane Doe", "timezone": "America/New_York"}'

Events

4 endpoints

GET/api/v1/event-types

List all your events

Parameters

NameTypeRequiredDescription
includeInactivebooleanNoInclude disabled events (default false)

Response

[
  {
    "id": "uuid",
    "title": "30 Minute Meeting",
    "slug": "30min",
    "duration_minutes": 30,
    "description": "Quick chat",
    "location_type": "video",
    "buffer_before": 0,
    "buffer_after": 5,
    "minimum_notice": 60,
    "max_per_day": null,
    "color": "#E8634A",
    "is_active": true
  }
]

Example

curl -X GET "https://skdul.ai/api/v1/event-types?includeInactive=true" \
  -H "Authorization: Bearer sk_live_<your_key>"

POST/api/v1/event-types

Create a new event (meeting template)

Parameters

NameTypeRequiredDescription
titlestringYesEvent title (e.g. '30 Minute Meeting')
slugstringYesURL slug (e.g. '30min')
durationMinutesnumberYesDuration in minutes
descriptionstringNoDescription shown on booking page
locationType"video" | "phone" | "in_person" | "custom"NoMeeting location type
bufferBeforenumberNoBuffer minutes before the meeting
bufferAfternumberNoBuffer minutes after the meeting
minimumNoticenumberNoMinimum notice in minutes before booking
maxPerDaynumberNoMaximum bookings per day
colorstringNoDisplay color hex code

Response

{
  "id": "uuid",
  "title": "30 Minute Meeting",
  "slug": "30min",
  "duration_minutes": 30,
  "location_type": "video",
  "is_active": true
}

Example

curl -X POST https://skdul.ai/api/v1/event-types \
  -H "Authorization: Bearer sk_live_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "30 Minute Meeting",
    "slug": "30min",
    "durationMinutes": 30,
    "locationType": "video"
  }'

PATCH/api/v1/event-types/[id]

Update an existing event

Parameters

NameTypeRequiredDescription
titlestringNoEvent title
slugstringNoURL slug
durationMinutesnumberNoDuration in minutes
descriptionstringNoDescription
locationType"video" | "phone" | "in_person" | "custom"NoLocation type
bufferBeforenumberNoBuffer minutes before
bufferAfternumberNoBuffer minutes after
minimumNoticenumberNoMinimum notice in minutes
maxPerDaynumberNoMaximum bookings per day
colorstringNoDisplay color hex code
isActivebooleanNoWhether the event is active

Response

{
  "id": "uuid",
  "title": "Updated Meeting",
  "slug": "30min",
  "duration_minutes": 30,
  "is_active": true
}

Example

curl -X PATCH https://skdul.ai/api/v1/event-types/<event_type_id> \
  -H "Authorization: Bearer sk_live_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{"title": "Updated Meeting", "isActive": true}'

DELETE/api/v1/event-types/[id]

Delete an event

Response

{ "success": true }

Example

curl -X DELETE https://skdul.ai/api/v1/event-types/<event_type_id> \
  -H "Authorization: Bearer sk_live_<your_key>"

Availability

1 endpoint

GET/api/v1/availability/slots

Get available time slots for an event within a date range

Parameters

NameTypeRequiredDescription
eventTypeIdstringYesEvent ID to check availability for
startDatestringYesStart date (YYYY-MM-DD)
endDatestringYesEnd date (YYYY-MM-DD)
timezonestringNoIANA timezone (defaults to UTC)

Response

[
  { "start": "2026-02-21T09:00:00Z", "end": "2026-02-21T09:30:00Z" },
  { "start": "2026-02-21T09:30:00Z", "end": "2026-02-21T10:00:00Z" },
  { "start": "2026-02-21T10:00:00Z", "end": "2026-02-21T10:30:00Z" }
]

Example

curl -X GET "https://skdul.ai/api/v1/availability/slots?eventTypeId=<id>&startDate=2026-02-21&endDate=2026-02-28" \
  -H "Authorization: Bearer sk_live_<your_key>"

Bookings

5 endpoints

GET/api/v1/bookings

List your bookings with optional filters

Parameters

NameTypeRequiredDescription
statusstringNoFilter by status: confirmed, cancelled_by_host, cancelled_by_guest, rescheduled, completed, no_show
upcomingbooleanNoOnly show future bookings (default true)
guestEmailstringNoFilter by guest email
limitnumberNoMax number of bookings to return (default 20)

Response

[
  {
    "id": "uuid",
    "event_type_id": "uuid",
    "start_time": "2026-02-21T14:00:00Z",
    "end_time": "2026-02-21T14:30:00Z",
    "guest_name": "John Smith",
    "guest_email": "john@example.com",
    "guest_timezone": "America/Chicago",
    "status": "confirmed",
    "guest_notes": "Looking forward to it"
  }
]

Example

curl -X GET "https://skdul.ai/api/v1/bookings?status=confirmed&upcoming=true&limit=10" \
  -H "Authorization: Bearer sk_live_<your_key>"

POST/api/v1/bookings

Create a new booking for a guest on one of your events

Parameters

NameTypeRequiredDescription
eventTypeIdstringYesEvent ID to book
startTimestringYesStart time (ISO 8601)
endTimestringYesEnd time (ISO 8601)
guestNamestringYesGuest's full name
guestEmailstringYesGuest's email address
durationMinutesnumberYesDuration in minutes
guestTimezonestringNoGuest's IANA timezone
guestNotesstringNoNotes from the guest

Response

{
  "id": "uuid",
  "event_type_id": "uuid",
  "start_time": "2026-02-21T14:00:00Z",
  "end_time": "2026-02-21T14:30:00Z",
  "guest_name": "John Smith",
  "guest_email": "john@example.com",
  "status": "confirmed"
}

Example

curl -X POST https://skdul.ai/api/v1/bookings \
  -H "Authorization: Bearer sk_live_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "eventTypeId": "<event_type_id>",
    "startTime": "2026-02-21T14:00:00Z",
    "endTime": "2026-02-21T14:30:00Z",
    "guestName": "John Smith",
    "guestEmail": "john@example.com",
    "durationMinutes": 30
  }'

GET/api/v1/bookings/[id]

Get full details for a specific booking including event info

Response

{
  "id": "uuid",
  "event_type_id": "uuid",
  "start_time": "2026-02-21T14:00:00Z",
  "end_time": "2026-02-21T14:30:00Z",
  "guest_name": "John Smith",
  "guest_email": "john@example.com",
  "guest_timezone": "America/Chicago",
  "status": "confirmed",
  "guest_notes": "Looking forward to it",
  "event_types": {
    "title": "30 Minute Meeting",
    "duration_minutes": 30,
    "location_type": "video"
  }
}

Example

curl -X GET https://skdul.ai/api/v1/bookings/<booking_id> \
  -H "Authorization: Bearer sk_live_<your_key>"

POST/api/v1/bookings/[id]/cancel

Cancel a confirmed booking

Parameters

NameTypeRequiredDescription
reasonstringNoCancellation reason

Response

{
  "id": "uuid",
  "status": "cancelled_by_host",
  "guest_name": "John Smith",
  "guest_email": "john@example.com"
}

Example

curl -X POST https://skdul.ai/api/v1/bookings/<booking_id>/cancel \
  -H "Authorization: Bearer sk_live_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Schedule conflict"}'

POST/api/v1/bookings/[id]/reschedule

Reschedule a booking to a new time slot

Parameters

NameTypeRequiredDescription
newStartTimestringYesNew start time (ISO 8601)
newEndTimestringYesNew end time (ISO 8601)

Response

{
  "id": "uuid",
  "start_time": "2026-02-22T10:00:00Z",
  "end_time": "2026-02-22T10:30:00Z",
  "status": "confirmed",
  "guest_name": "John Smith"
}

Example

curl -X POST https://skdul.ai/api/v1/bookings/<booking_id>/reschedule \
  -H "Authorization: Bearer sk_live_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "newStartTime": "2026-02-22T10:00:00Z",
    "newEndTime": "2026-02-22T10:30:00Z"
  }'

Schedule

2 endpoints

GET/api/v1/schedule

Get your weekly working hours and availability rules

Response

{
  "schedule": {
    "id": "uuid",
    "name": "Default",
    "timezone": "America/New_York"
  },
  "rules": [
    { "day_of_week": 1, "start_time": "09:00", "end_time": "17:00", "is_enabled": true },
    { "day_of_week": 2, "start_time": "09:00", "end_time": "17:00", "is_enabled": true },
    { "day_of_week": 3, "start_time": "09:00", "end_time": "17:00", "is_enabled": true },
    { "day_of_week": 4, "start_time": "09:00", "end_time": "17:00", "is_enabled": true },
    { "day_of_week": 5, "start_time": "09:00", "end_time": "17:00", "is_enabled": true }
  ]
}

Example

curl -X GET https://skdul.ai/api/v1/schedule \
  -H "Authorization: Bearer sk_live_<your_key>"

PUT/api/v1/schedule

Set your weekly working hours for each day of the week

Parameters

NameTypeRequiredDescription
rulesarrayYesArray of availability rules
rules[].dayOfWeeknumber (0-6)YesDay of week (0=Sunday, 6=Saturday)
rules[].startTimestringYesStart time (HH:MM, 24h format)
rules[].endTimestringYesEnd time (HH:MM, 24h format)
rules[].isEnabledbooleanNoWhether this day is enabled (default true)

Response

{
  "schedule": { "id": "uuid", "name": "Default" },
  "rules": [
    { "day_of_week": 1, "start_time": "09:00", "end_time": "17:00", "is_enabled": true }
  ]
}

Example

curl -X PUT https://skdul.ai/api/v1/schedule \
  -H "Authorization: Bearer sk_live_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "rules": [
      { "dayOfWeek": 1, "startTime": "09:00", "endTime": "17:00", "isEnabled": true },
      { "dayOfWeek": 2, "startTime": "09:00", "endTime": "17:00", "isEnabled": true },
      { "dayOfWeek": 3, "startTime": "09:00", "endTime": "17:00", "isEnabled": true },
      { "dayOfWeek": 4, "startTime": "09:00", "endTime": "17:00", "isEnabled": true },
      { "dayOfWeek": 5, "startTime": "09:00", "endTime": "17:00", "isEnabled": true }
    ]
  }'

Public Endpoints

No auth required2 endpoints

GET/api/availability

Get available time slots (no authentication required)

Parameters

NameTypeRequiredDescription
eventTypeIdstringYesEvent ID to check
startDatestringYesStart date (YYYY-MM-DD)
endDatestringYesEnd date (YYYY-MM-DD)
timezonestringNoIANA timezone (defaults to UTC)

Response

{
  "slots": [
    { "start": "2026-02-21T09:00:00Z", "end": "2026-02-21T09:30:00Z" },
    { "start": "2026-02-21T09:30:00Z", "end": "2026-02-21T10:00:00Z" }
  ]
}

Example

curl -X GET "https://skdul.ai/api/availability?eventTypeId=<id>&startDate=2026-02-21&endDate=2026-02-28"

POST/api/bookings

Create a booking on behalf of a guest (requires hostId instead of API key auth)

Parameters

NameTypeRequiredDescription
hostIdstringYesHost's user ID (unlike v1 which infers from API key)
eventTypeIdstringYesEvent ID to book
startTimestringYesStart time (ISO 8601)
endTimestringYesEnd time (ISO 8601)
guestNamestringYesGuest's full name
guestEmailstringYesGuest's email address
durationMinutesnumberYesDuration in minutes
guestTimezonestringNoGuest's IANA timezone
guestNotesstringNoNotes from the guest

Response

{
  "id": "uuid",
  "event_type_id": "uuid",
  "start_time": "2026-02-21T14:00:00Z",
  "end_time": "2026-02-21T14:30:00Z",
  "guest_name": "John Smith",
  "guest_email": "john@example.com",
  "status": "confirmed"
}

Example

curl -X POST https://skdul.ai/api/bookings \
  -H "Content-Type: application/json" \
  -d '{
    "hostId": "<host_user_id>",
    "eventTypeId": "<event_type_id>",
    "startTime": "2026-02-21T14:00:00Z",
    "endTime": "2026-02-21T14:30:00Z",
    "guestName": "John Smith",
    "guestEmail": "john@example.com",
    "durationMinutes": 30
  }'

Error Handling

{ "error": "Description of what went wrong" }
CodeMeaningDescription
400Bad RequestMissing required fields or invalid data
401UnauthorizedMissing or invalid API key
404Not FoundResource does not exist or you don't own it
409ConflictTime slot no longer available (booking conflict)
500Internal Server ErrorSomething went wrong on our end

Frequently Asked Questions

How do I authenticate with the skdul API?
All /api/v1/* endpoints require an API key passed via the Authorization header as a Bearer token. Generate a key from your dashboard's MCP Server page. Format: Authorization: Bearer sk_live_<your_key>.
What is the base URL for the skdul API?
The production base URL is https://skdul.ai/api/v1. For local development, use http://localhost:3000/api/v1.
Does the skdul API have rate limits?
The API currently does not enforce hard rate limits, but we recommend keeping requests under 60 per minute per API key. Excessive usage may be throttled.
How do I get available time slots for booking?
Use GET /api/v1/availability/slots with eventTypeId, startDate, and endDate parameters. The response returns an array of available time slots with start and end times in ISO 8601 format.
Can I create a booking via the API?
Yes. Use POST /api/v1/bookings with eventTypeId, startTime, endTime, guestName, guestEmail, and durationMinutes. The API validates slot availability and returns the confirmed booking.
Are there public endpoints that don't require authentication?
Yes. GET /api/availability and POST /api/bookings are public endpoints that don't require an API key. The public booking endpoint requires a hostId parameter instead of inferring the host from an API key.
What error format does the API use?
All errors return a JSON object with an "error" field containing a human-readable description. Standard HTTP status codes are used: 400 (Bad Request), 401 (Unauthorized), 404 (Not Found), 409 (Conflict), and 500 (Internal Server Error).
Is there a webhook for new bookings?
Webhooks are on the roadmap but not yet available. Currently, you can poll GET /api/v1/bookings with the upcoming=true filter to check for new bookings.

Ready to try it yourself?

Set up your booking page in two minutes. No credit card required.

Start building with skdul
Free forever plan MCP server included
Ask AI about skdul