Read Appointo bookings, availability and subscriptions; create, reschedule and cancel bookings.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
WRITE: cancel a booking, or only some of its customers. The slot is freed and Appointo may notify the customers; whether a Shopify order is refunded is not controlled by this call. Cannot be undone through this server (create a new booking instead). The docs cap this at 100 requests per day. PUT /bookings/cancel.
Booking id (from appointo_list_bookings).
Only cancel these customer ids of the booking; omit to cancel the whole booking.
The server marks this tool as destructive. Running it may delete or overwrite data on the server or in any account you connected with your headers.
WRITE: cancel a booking, or only some of its customers. The slot is freed and Appointo may notify the customers; whether a Shopify order is refunded is not controlled by this call. Cannot be undone through this server (create a new booking instead). The docs cap this at 100 requests per day. PUT /bookings/cancel.
| Argument | Type | Description |
|---|---|---|
| booking_id* | integer | Booking id (from appointo_list_bookings). |
| customer_ids | array | Only cancel these customer ids of the booking; omit to cancel the whole booking. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"booking_id"
],
"properties": {
"booking_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Booking id (from appointo_list_bookings).",
"exclusiveMinimum": 0
},
"customer_ids": {
"type": "array",
"items": {
"type": "integer",
"maximum": 9007199254740991,
"exclusiveMinimum": 0
},
"maxItems": 100,
"minItems": 1,
"description": "Only cancel these customer ids of the booking; omit to cancel the whole booking."
}
}
}WRITE: create a booking for a customer on an appointment (bookable service) at a time slot. This is a real booking: Appointo may email the customer a confirmation and reserve the slot; the booking can later be cancelled with appointo_cancel_booking. Check appointo_get_availability first. Not idempotent: calling twice creates two bookings. The docs cap this at 100 requests per day. POST /bookings.
| Argument | Type | Description |
|---|---|---|
| name* | string | Customer name. |
| email* | string | Customer email. |
| phone | string | Customer phone number. |
| quantity | integer | Number of spots (default 1). |
| timestring* | string | Start of the time slot, ISO 8601, e.g. 2026-11-03T14:00:00-05:00 (use a date only, 2026-11-03, for a day booking). Check appointo_get_availability for real slots. |
| appointment_id* | integer | Appointo appointment id (from appointo_list_appointments). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"appointment_id",
"timestring",
"name",
"email"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Customer name."
},
"email": {
"type": "string",
"pattern": "^[^\\s@<>\",;]+@[^\\s@<>\",;]+\\.[^\\s@<>\",;]+$",
"maxLength": 254,
"minLength": 3,
"description": "Customer email."
},
"phone": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "Customer phone number."
},
"quantity": {
"type": "integer",
"maximum": 1000,
"description": "Number of spots (default 1).",
"exclusiveMinimum": 0
},
"timestring": {
"type": "string",
"description": "Start of the time slot, ISO 8601, e.g. 2026-11-03T14:00:00-05:00 (use a date only, 2026-11-03, for a day booking). Check appointo_get_availability for real slots."
},
"appointment_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Appointo appointment id (from appointo_list_appointments).",
"exclusiveMinimum": 0
}
}
}The free time slots of one appointment (bookable service) from start_date, optionally to end_date. Use it before creating or rescheduling a booking. GET /appointments/{appointment_id}/calendar_availability.
| Argument | Type | Description |
|---|---|---|
| end_date | string | Last day, yyyy-mm-dd. |
| start_date* | string | First day, yyyy-mm-dd. |
| appointment_id* | integer | Appointo appointment id (from appointo_list_appointments). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"appointment_id",
"start_date"
],
"properties": {
"end_date": {
"type": "string",
"pattern": "^(\\d{4})-(\\d{2})-(\\d{2})$",
"description": "Last day, yyyy-mm-dd."
},
"start_date": {
"type": "string",
"pattern": "^(\\d{4})-(\\d{2})-(\\d{2})$",
"description": "First day, yyyy-mm-dd."
},
"appointment_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Appointo appointment id (from appointo_list_appointments).",
"exclusiveMinimum": 0
}
}
}List appointments, i.e. the bookable services/variants, with name, price, currency and configuration. Filter by product or fetch one by id. These are the services customers book, not the bookings themselves (use appointo_list_bookings for those). GET /appointments.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Results per page, 1-100 (default 25). |
| offset | integer | Number of results to skip (default 0). Pass the previous reply's next_offset. |
| product_id | integer | Only appointments of this Appointo product id (the `id` from appointo_list_products). |
| search_term | string | |
| appointment_id | integer | Fetch a single appointment by id. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"description": "Results per page, 1-100 (default 25).",
"exclusiveMinimum": 0
},
"offset": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Number of results to skip (default 0). Pass the previous reply's next_offset."
},
"product_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only appointments of this Appointo product id (the `id` from appointo_list_products).",
"exclusiveMinimum": 0
},
"search_term": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"appointment_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Fetch a single appointment by id.",
"exclusiveMinimum": 0
}
}
}List bookings with time, product, duration, quantity, price and the customers (name, email, phone, address). Filter upcoming/past or search; pass booking_id for one booking. The customers' cancel/reschedule link ids are never returned. GET /bookings.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Results per page, 1-100 (default 25). |
| offset | integer | Number of results to skip (default 0). Pass the previous reply's next_offset. |
| status | string | Only upcoming or only past bookings. |
| booking_id | integer | Fetch a single booking by id. |
| search_term | string | Searches product name, customer name, email, phone and order name. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"description": "Results per page, 1-100 (default 25).",
"exclusiveMinimum": 0
},
"offset": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Number of results to skip (default 0). Pass the previous reply's next_offset."
},
"status": {
"enum": [
"upcoming",
"past"
],
"type": "string",
"description": "Only upcoming or only past bookings."
},
"booking_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Fetch a single booking by id.",
"exclusiveMinimum": 0
},
"search_term": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Searches product name, customer name, email, phone and order name."
}
}
}List cancelled bookings, same shape as appointo_list_bookings. GET /bookings/cancelled_bookings.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Results per page, 1-100 (default 25). |
| offset | integer | Number of results to skip (default 0). Pass the previous reply's next_offset. |
| status | string | Only upcoming or only past bookings. |
| search_term | string | Searches product name, customer name, email, phone and order name. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"description": "Results per page, 1-100 (default 25).",
"exclusiveMinimum": 0
},
"offset": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Number of results to skip (default 0). Pass the previous reply's next_offset."
},
"status": {
"enum": [
"upcoming",
"past"
],
"type": "string",
"description": "Only upcoming or only past bookings."
},
"search_term": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Searches product name, customer name, email, phone and order name."
}
}
}List the Shopify products that are set up as bookable in Appointo: name, appointment type, whether the widget is shown, and each product's appointments (the bookable variants/services with price, currency and id). Use an appointment id for availability and bookings. GET /products.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Results per page, 1-100 (default 25). |
| offset | integer | Number of results to skip (default 0). Pass the previous reply's next_offset. |
| search_term | string | Filter by product name. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"description": "Results per page, 1-100 (default 25).",
"exclusiveMinimum": 0
},
"offset": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Number of results to skip (default 0). Pass the previous reply's next_offset."
},
"search_term": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Filter by product name."
}
}
}List the recurring booking subscription contracts (customers who subscribed to repeat appointments). Search by product, variant, order number or customer name. The API documents no paging for this list. GET /appointment_subscriptions.
| Argument | Type | Description |
|---|---|---|
| search_term | string | Product name, variant name, order number or customer name. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"search_term": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Product name, variant name, order number or customer name."
}
}
}WRITE: move a booking (or only some of its customers) to a new time slot. Appointo may notify the customers of the change. override=true forces the booking into the slot even if it is unavailable or full, so leave it off unless the user explicitly asked for it. The docs cap this at 100 requests per day. PUT /bookings/reschedule.
| Argument | Type | Description |
|---|---|---|
| override | boolean | Force the slot even if unavailable (default false). |
| booking_id* | integer | Booking id (from appointo_list_bookings). |
| timestring* | string | Start of the time slot, ISO 8601, e.g. 2026-11-03T14:00:00-05:00 (use a date only, 2026-11-03, for a day booking). Check appointo_get_availability for real slots. |
| customer_ids | array | Only move these customer ids of the booking; omit to move the whole booking. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"booking_id",
"timestring"
],
"properties": {
"override": {
"type": "boolean",
"description": "Force the slot even if unavailable (default false)."
},
"booking_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Booking id (from appointo_list_bookings).",
"exclusiveMinimum": 0
},
"timestring": {
"type": "string",
"description": "Start of the time slot, ISO 8601, e.g. 2026-11-03T14:00:00-05:00 (use a date only, 2026-11-03, for a day booking). Check appointo_get_availability for real slots."
},
"customer_ids": {
"type": "array",
"items": {
"type": "integer",
"maximum": 9007199254740991,
"exclusiveMinimum": 0
},
"maxItems": 100,
"minItems": 1,
"description": "Only move these customer ids of the booking; omit to move the whole booking."
}
}
}WRITE: set the start and/or end buffer time (minutes blocked before/after) of one booking. At least one value is required. The docs cap this at 100 requests per day. PUT /bookings/{booking_id}.
| Argument | Type | Description |
|---|---|---|
| booking_id* | integer | Booking id (from appointo_list_bookings). |
| end_buffer_time | integer | Buffer after the booking, minutes (> 0). |
| start_buffer_time | integer | Buffer before the booking, minutes (> 0). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"booking_id"
],
"properties": {
"booking_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Booking id (from appointo_list_bookings).",
"exclusiveMinimum": 0
},
"end_buffer_time": {
"type": "integer",
"maximum": 100000,
"description": "Buffer after the booking, minutes (> 0).",
"exclusiveMinimum": 0
},
"start_buffer_time": {
"type": "integer",
"maximum": 100000,
"description": "Buffer before the booking, minutes (> 0).",
"exclusiveMinimum": 0
}
}
}