Install
openclaw skills install acuity-schedulingAcuity Scheduling API integration with managed OAuth. Manage appointments, calendars, clients, and availability. Use this skill when users want to schedule, reschedule, or cancel appointments, check availability, or manage clients and calendars. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
openclaw skills install acuity-schedulingAccess the Acuity Scheduling API with managed OAuth authentication. Manage appointments, calendars, clients, availability, and more.
# List appointments
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/appointments?max=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/acuity-scheduling/{native-api-path}
Maton proxies requests to acuityscheduling.com and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your Acuity Scheduling OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=acuity-scheduling&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'acuity-scheduling'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "acuity-scheduling",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple Acuity Scheduling connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/appointments')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
GET /acuity-scheduling/api/v1/me
Returns account information including timezone, scheduling page URL, and plan details.
Response:
{
"id": 12345,
"email": "user@example.com",
"timezone": "America/Los_Angeles",
"name": "My Business",
"schedulingPage": "https://app.acuityscheduling.com/schedule.php?owner=12345",
"plan": "Professional",
"currency": "USD"
}
GET /acuity-scheduling/api/v1/appointments
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
max | integer | Maximum results (default: 100) |
minDate | date | Appointments on or after this date |
maxDate | date | Appointments on or before this date |
calendarID | integer | Filter by calendar |
appointmentTypeID | integer | Filter by appointment type |
canceled | boolean | Include canceled appointments (default: false) |
firstName | string | Filter by client first name |
lastName | string | Filter by client last name |
email | string | Filter by client email |
excludeForms | boolean | Omit intake forms for faster response |
direction | string | Sort order: ASC or DESC (default: DESC) |
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/appointments?max=10&minDate=2026-02-01')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
[
{
"id": 1630290133,
"firstName": "Jane",
"lastName": "McTest",
"phone": "1235550101",
"email": "jane.mctest@example.com",
"date": "February 4, 2026",
"time": "9:30am",
"endTime": "10:20am",
"datetime": "2026-02-04T09:30:00-0800",
"type": "Consultation",
"appointmentTypeID": 88791369,
"duration": "50",
"calendar": "Chris",
"calendarID": 13499175,
"canceled": false,
"confirmationPage": "https://app.acuityscheduling.com/schedule.php?..."
}
]
GET /acuity-scheduling/api/v1/appointments/{id}
POST /acuity-scheduling/api/v1/appointments
Content-Type: application/json
{
"datetime": "2026-02-15T09:00",
"appointmentTypeID": 123,
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "555-123-4567",
"timezone": "America/New_York"
}
Required Fields:
datetime - Date and time (parseable by PHP's strtotime)appointmentTypeID - Appointment type IDfirstName - Client's first namelastName - Client's last nameemail - Client's emailOptional Fields:
phone - Client phone numbercalendarID - Specific calendar (auto-selected if omitted)timezone - Client's timezonecertificate - Package or coupon codenotes - Admin notesaddonIDs - Array of addon IDsfields - Array of form field valuesExample:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
'datetime': '2026-02-15T09:00',
'appointmentTypeID': 123,
'firstName': 'John',
'lastName': 'Doe',
'email': 'john.doe@example.com'
}).encode()
req = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/appointments', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
PUT /acuity-scheduling/api/v1/appointments/{id}
Content-Type: application/json
{
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com"
}
PUT /acuity-scheduling/api/v1/appointments/{id}/cancel
Returns the canceled appointment with canceled: true.
PUT /acuity-scheduling/api/v1/appointments/{id}/reschedule
Content-Type: application/json
{
"datetime": "2026-02-20T10:00"
}
Note: The new datetime must be an available time slot.
GET /acuity-scheduling/api/v1/calendars
Response:
[
{
"id": 13499175,
"name": "Chris",
"email": "",
"replyTo": "chris@example.com",
"description": "",
"location": "",
"timezone": "America/Los_Angeles"
}
]
GET /acuity-scheduling/api/v1/appointment-types
Query Parameters:
includeDeleted (boolean) - Include deleted typesResponse:
[
{
"id": 88791369,
"name": "Consultation",
"active": true,
"description": "",
"duration": 50,
"price": "45.00",
"category": "",
"color": "#ED7087",
"private": false,
"type": "service",
"calendarIDs": [13499175],
"schedulingUrl": "https://app.acuityscheduling.com/schedule.php?..."
}
]
GET /acuity-scheduling/api/v1/availability/dates?month=2026-02&appointmentTypeID=123
Required Parameters:
month - Month to check (e.g., "2026-02")appointmentTypeID - Appointment type IDOptional Parameters:
calendarID - Specific calendartimezone - Timezone for results (e.g., "America/New_York")Response:
[
{"date": "2026-02-09"},
{"date": "2026-02-10"},
{"date": "2026-02-11"}
]
GET /acuity-scheduling/api/v1/availability/times?date=2026-02-10&appointmentTypeID=123
Required Parameters:
date - Date to checkappointmentTypeID - Appointment type IDOptional Parameters:
calendarID - Specific calendartimezone - Timezone for resultsResponse:
[
{"time": "2026-02-10T09:00:00-0800", "slotsAvailable": 1},
{"time": "2026-02-10T09:50:00-0800", "slotsAvailable": 1},
{"time": "2026-02-10T10:40:00-0800", "slotsAvailable": 1}
]
GET /acuity-scheduling/api/v1/clients
Query Parameters:
search - Filter by first name, last name, or phoneExample:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/clients?search=John')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
[
{
"firstName": "Jane",
"lastName": "McTest",
"email": "jane.mctest@example.com",
"phone": "(123) 555-0101",
"notes": ""
}
]
POST /acuity-scheduling/api/v1/clients
Content-Type: application/json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"phone": "555-123-4567"
}
PUT /acuity-scheduling/api/v1/clients
Content-Type: application/json
{
"firstName": "John",
"lastName": "Doe",
"email": "john.updated@example.com"
}
Note: Client update/delete only works for clients with existing appointments.
DELETE /acuity-scheduling/api/v1/clients
Content-Type: application/json
{
"firstName": "John",
"lastName": "Doe"
}
GET /acuity-scheduling/api/v1/blocks
Query Parameters:
max - Maximum results (default: 100)minDate - Blocks on or after this datemaxDate - Blocks on or before this datecalendarID - Filter by calendarGET /acuity-scheduling/api/v1/blocks/{id}
POST /acuity-scheduling/api/v1/blocks
Content-Type: application/json
{
"start": "2026-02-15T12:00",
"end": "2026-02-15T13:00",
"calendarID": 1234,
"notes": "Lunch break"
}
Response:
{
"id": 9589304654,
"calendarID": 13499175,
"start": "2026-02-15T12:00:00-0800",
"end": "2026-02-15T13:00:00-0800",
"notes": "Lunch break",
"description": "Sunday, February 15, 2026 12:00pm - 1:00pm"
}
DELETE /acuity-scheduling/api/v1/blocks/{id}
Returns 204 No Content on success.
GET /acuity-scheduling/api/v1/forms
Response:
[
{
"id": 123,
"name": "Client Intake Form",
"appointmentTypeIDs": [456, 789],
"fields": [
{
"id": 1,
"name": "How did you hear about us?",
"type": "dropdown",
"options": ["Google", "Friend", "Social Media"],
"required": true
}
]
}
]
GET /acuity-scheduling/api/v1/labels
Response:
[
{"id": 23116714, "name": "Checked In", "color": "green"},
{"id": 23116715, "name": "Completed", "color": "pink"},
{"id": 23116713, "name": "Confirmed", "color": "yellow"}
]
Acuity Scheduling uses the max parameter to limit results. Use minDate and maxDate to paginate through date ranges:
# First page
GET /acuity-scheduling/api/v1/appointments?max=100&minDate=2026-01-01&maxDate=2026-01-31
# Next page
GET /acuity-scheduling/api/v1/appointments?max=100&minDate=2026-02-01&maxDate=2026-02-28
const response = await fetch(
'https://api.maton.ai/acuity-scheduling/api/v1/appointments?max=10',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const appointments = await response.json();
import os
import requests
response = requests.get(
'https://api.maton.ai/acuity-scheduling/api/v1/appointments',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
params={'max': 10}
)
appointments = response.json()
strtotime() functionexcludeForms=true for faster appointment list responsescurl -g when URLs contain brackets to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.| Status | Meaning |
|---|---|
| 400 | Invalid request (e.g., time not available, client not found) |
| 401 | Invalid or missing Maton API key |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Acuity API |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
acuity-scheduling. For example:https://api.maton.ai/acuity-scheduling/api/v1/appointmentshttps://api.maton.ai/api/v1/appointments