TidyCal API (0.1)

Download OpenAPI specification:Download

Introduction

TidyCal's REST API provides a handful of endpoints which can be used to get information about your account and bookings. It uses conventional OAuth 2.0 protocol for authentication.

Authentication

Personal Access Token

Create a personal access token from Integrations -> Advanced -> "Manage API keys" -> "Personal tokens" tab at https://tidycal.com/integrations/advanced (API access requires a paid plan). Once created, it can be used to authenticate requests by passing it in the Authorization header.

Authorization: Bearer {TOKEN}

OAuth 2.0 Client

If you're building a custom integration to TidyCal which requires users to authenticate in order to get access tokens to make API requests on their behalf, you'll need to create an OAuth 2.0 client. This is easy to do from Integrations -> Advanced -> "Manage API keys" -> "OAuth clients" tab found here https://tidycal.com/integrations/advanced

Using the authorization_code grant type to authenticate users using OAuth 2.0 to retrieve an access token is fairly conventional, more information on that process can be found here: https://www.oauth.com/oauth2-servers/server-side-apps/authorization-code/

AI Assistants (MCP)

TidyCal ships an MCP server that lets AI assistants such as Claude read your TidyCal scheduling data through natural language — ask things like "what bookings do I have next week?" and the assistant answers using your live account data. It is read-only: the assistant can look things up, but it cannot create, change, or cancel anything.

Requirements

  • A TidyCal Pro subscription (the MCP server is gated to Pro accounts).
  • A supported AI client. Today that's Claude.ai via its custom connector flow.

Connecting Claude

  1. In Claude.ai, open Settings -> Connectors and choose Add custom connector.
  2. Paste the TidyCal MCP server URL: https://tidycal.com/mcp
  3. Claude redirects you to TidyCal to sign in (OAuth 2.1). Log in and approve access — TidyCal requests the single mcp:scheduling:read scope (read-only scheduling data).
  4. Once connected, ask Claude about your schedule in plain language.

The connection uses OAuth 2.1 with Dynamic Client Registration; you never paste an API key or token into Claude.

Available tools

The server exposes these 10 read-only tools to the AI client:

Tool What it does
get_current_user Your profile: name, email, timezone, language, currency, and Pro status.
list_teams The teams you own or belong to.
get_team Details for a single team you own or belong to.
list_booking_types Your booking types — the scheduling pages you offer (title, slug, duration, price, description).
get_booking_type Full detail for one booking type: availability windows, questions, reminders, pricing.
list_booking_type_available_times The bookable time slots for a booking type in a date range (honors your schedule, existing bookings, calendar conflicts, and buffers).
list_bookings Your scheduled bookings, with optional date-range and cancelled filters.
get_booking Full detail for one booking: booking type, contact, questions, payment, and hosts.
list_busy_times External Google Calendar events that block your availability in a date range.
list_locations The configured locations for a booking type (address, phone, video provider).

Scope and limitations

  • Read-only. No tool can create, edit, or cancel bookings, booking types, or any other data.
  • Exposed data: your profile, booking types, bookings, availability, busy times, teams, and locations.
  • list_busy_times currently reflects connected Google calendars only — Microsoft and Apple calendar events are not included yet.
  • Dates/times use ISO 8601 (e.g. 2026-06-01T14:30:00Z); returned times are UTC unless a resource notes otherwise.

Example prompts

  • "What bookings do I have next week?"
  • "When am I free for a 30-minute consult over the next few days?"
  • "Show my cancelled bookings from last month."
  • "Which booking types do I offer, and how long is each?"

Account

Account information

Get account details.

Responses

Response samples

Content type
application/json
{}

Bookings

List bookings

Get a list of bookings.

path Parameters
starts_at
date

Get bookings starting from a specific date.

ends_at
date

Get bookings ending before a specific date.

cancelled
boolean

Get only cancelled bookings.

page
number

Page number.

include_teams
boolean

Include team bookings.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Get booking

Get a booking by ID.

path Parameters
booking
required
integer

The ID of the booking.

Responses

Response samples

Content type
application/json
{
  • "id": 1,
  • "contact_id": 1,
  • "booking_type_id": 1,
  • "starts_at": "2022-01-01T00:00:00Z",
  • "ends_at": "2022-02-01T00:00:00Z",
  • "cancelled_at": "2022-02-01T00:00:00Z",
  • "created_at": "2022-02-01T00:00:00Z",
  • "updated_at": "2022-02-01T00:00:00Z",
  • "timezone": "America/Los_Angeles",
  • "meeting_id": "fw44lkj48fks",
  • "questions": [
    ],
  • "contact": {
    },
  • "payment": {
    }
}

Cancel booking

Cancel a booking by ID.

path Parameters
booking
required
integer

The ID of the booking to cancel.

Request Body schema: application/json
reason
string

Optional reason for cancellation

Responses

Request samples

Content type
application/json
{
  • "reason": "Client requested cancellation"
}

Response samples

Content type
application/json
{
  • "id": 1,
  • "contact_id": 1,
  • "booking_type_id": 1,
  • "starts_at": "2022-01-01T00:00:00Z",
  • "ends_at": "2022-02-01T00:00:00Z",
  • "cancelled_at": "2022-02-01T00:00:00Z",
  • "created_at": "2022-02-01T00:00:00Z",
  • "updated_at": "2022-02-01T00:00:00Z",
  • "timezone": "America/Los_Angeles",
  • "meeting_id": "fw44lkj48fks",
  • "questions": [
    ],
  • "contact": {
    },
  • "payment": {
    }
}

Booking Types

List booking types

Get a list of booking types.

path Parameters
page
number

Page number.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Create booking type

Create a new booking type.

Request Body schema: application/json
title
required
string <= 191 characters
description
required
string <html>
duration_minutes
required
integer >= 1
url_slug
required
string <= 191 characters
padding_minutes
integer >= 0
Default: 0
latest_availability_days
integer [ 0 .. 36500 ]
Default: 60
private
boolean
Default: false
max_bookings
integer >= 1
Default: 1
max_guest_invites_per_booker
integer [ 0 .. 10 ]
Default: 0
display_seats_remaining
boolean
Default: false
booking_availability_interval_minutes
integer [ 15 .. 1440 ]
Default: 15
redirect_url
string or null <= 60000 characters
approval_required
boolean or null
booking_type_category_id
integer or null
price
number <float> >= 0
Default: 0

Price for the booking type. Set to 0 for free booking types.

payment_platform
string
Enum: "stripe" "paypal" "tidycal"

Payment platform to use. The platform must be connected in your account Integrations settings. Required when price > 0.

currency_code
string

ISO 4217 currency code (e.g. USD, EUR, GBP). Defaults to your account currency.

booking_threshold
integer [ 0 .. 15000 ]

Minimum notice required before a booking, in minutes. Omit for the default of 120 (2 hours); set to 0 for no minimum notice.

Responses

Request samples

Content type
application/json
{
  • "title": "30 Minute Meeting",
  • "description": "Book a 30 minute meeting with me",
  • "duration_minutes": 30,
  • "url_slug": "30-minute-meeting",
  • "padding_minutes": 15,
  • "latest_availability_days": 90,
  • "private": false,
  • "max_bookings": 1,
  • "max_guest_invites_per_booker": 0,
  • "display_seats_remaining": false,
  • "booking_availability_interval_minutes": 30,
  • "approval_required": false,
  • "booking_type_category_id": 1,
  • "price": 25,
  • "payment_platform": "stripe",
  • "currency_code": "USD",
  • "booking_threshold": 120
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List available timeslots

Get a list of available timeslots for a specific booking type.

path Parameters
bookingType
required
integer

The ID of the booking type.

query Parameters
starts_at
required
string <date-time>

Start date to get timeslots from (UTC).

ends_at
required
string <date-time>

End date to get timeslots until (UTC).

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Create booking

Create a new booking for a specific booking type.

Single vs Package Bookings:

  • For single bookings, use starts_at to specify the booking time
  • For package/multi-session bookings, use the bookings array to specify multiple time slots

Response Format:

  • Single booking: Returns {"data": {Booking}}
  • Multiple bookings (package): Returns {"data": [{Booking}, ...]}
path Parameters
bookingType
required
integer

The ID of the booking type.

Request Body schema: application/json
starts_at
string <date-time>

The start time of the booking in UTC. Required for single bookings. Ignored if bookings array is provided.

Array of objects

Array of booking times for package/multi-session bookings. If provided, starts_at is ignored.

name
required
string <= 191 characters

Name of the person making the booking

email
required
string <email> <= 191 characters

Email of the person making the booking

timezone
required
string <= 191 characters

The timezone of the booking

Array of objects

Answers to booking type questions

Responses

Request samples

Content type
application/json
{
  • "starts_at": "2024-03-20T10:00:00Z",
  • "bookings": [
    ],
  • "name": "John Doe",
  • "email": "[email protected]",
  • "timezone": "America/Los_Angeles",
  • "booking_questions": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Contacts

List contacts

Get a list of contacts.

path Parameters
page
number

Page number.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Create contact

Create a new contact.

Request Body schema: application/json
name
required
string
email
required
string <email>
timezone
string

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Teams

List teams

Get a list of teams the authenticated user has access to.

path Parameters
page
number

Page number.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Get team

Get details of a specific team.

path Parameters
team
required
integer

The ID of the team.

Responses

Response samples

Content type
application/json
{
  • "id": 1,
  • "name": "Sales Team",
  • "created_at": "2024-01-01T00:00:00Z",
  • "updated_at": "2024-01-01T00:00:00Z"
}

List team bookings

Get a list of bookings for a specific team.

path Parameters
team
required
integer

The ID of the team.

query Parameters
page
number

Page number.

start_date
string <date>

Get bookings starting from a specific date.

end_date
string <date>

Get bookings ending before a specific date.

email
string <email>

Get bookings for a specific email address.

host_id
integer

Get bookings for a specific user ID.

cancelled
boolean

Filter by cancellation status. Use true for cancelled bookings, false for non-cancelled bookings, or omit for all bookings.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

List team users

Get a list of users in a specific team.

path Parameters
team
required
integer

The ID of the team.

page
number

Page number.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Add user to team

Add a user to a team by sending an invitation email.

path Parameters
team
required
integer

The ID of the team.

Request Body schema: application/json
email
required
string <email>

Email address of the user to invite

role_name
string
Enum: "admin" "user"

Role name for the user in the team

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "message": "Invitation sent successfully",
  • "team_user_id": 123
}

Remove user from team

Remove a user from a team.

path Parameters
team
required
integer

The ID of the team.

teamUser
required
integer

The ID of the team user to remove.

Responses

Response samples

Content type
application/json
{
  • "message": "User removed from team"
}

List team booking types

Get a list of booking types for a specific team.

path Parameters
team
required
integer

The ID of the team.

query Parameters
page
number

Page number.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Create team booking type

Create a new booking type for a specific team.

path Parameters
team
required
integer

The ID of the team.

Request Body schema: application/json
title
required
string <= 191 characters
description
required
string <html>
duration_minutes
required
integer >= 1
url_slug
required
string <= 191 characters
padding_minutes
integer >= 0
Default: 0
latest_availability_days
integer [ 0 .. 36500 ]
Default: 60
private
boolean
Default: false
max_bookings
integer >= 1
Default: 1
max_guest_invites_per_booker
integer [ 0 .. 10 ]
Default: 0
display_seats_remaining
boolean
Default: false
booking_availability_interval_minutes
integer [ 15 .. 1440 ]
Default: 15
redirect_url
string or null <= 60000 characters
approval_required
boolean or null
booking_type_category_id
integer or null
price
number <float> >= 0
Default: 0

Price for the booking type. Set to 0 for free booking types.

payment_platform
string
Enum: "stripe" "paypal" "tidycal"

Payment platform to use. The platform must be connected in your account Integrations settings. Required when price > 0.

currency_code
string

ISO 4217 currency code (e.g. USD, EUR, GBP). Defaults to your account currency.

booking_threshold
integer [ 0 .. 15000 ]

Minimum notice required before a booking, in minutes. Omit for the default of 120 (2 hours); set to 0 for no minimum notice.

Responses

Request samples

Content type
application/json
{
  • "title": "30 Minute Meeting",
  • "description": "Book a 30 minute meeting with me",
  • "duration_minutes": 30,
  • "url_slug": "30-minute-meeting",
  • "padding_minutes": 15,
  • "latest_availability_days": 90,
  • "private": false,
  • "max_bookings": 1,
  • "max_guest_invites_per_booker": 0,
  • "display_seats_remaining": false,
  • "booking_availability_interval_minutes": 30,
  • "approval_required": false,
  • "booking_type_category_id": 1,
  • "price": 25,
  • "payment_platform": "stripe",
  • "currency_code": "USD",
  • "booking_threshold": 120
}

Response samples

Content type
application/json
{
  • "data": {
    }
}