{"skill":{"slug":"acuity-scheduling","displayName":"Acuity Scheduling","summary":"Acuity Scheduling API integration with managed OAuth. Manage appointments, calendars, clients, and availability. Use this skill when users want to schedule,...","description":"---\nname: acuity-scheduling\ndescription: |\n  Acuity 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).\ncompatibility: Requires network access and valid Maton API key\nmetadata:\n  author: maton\n  version: \"1.0\"\n  clawdbot:\n    emoji: 🧠\n    requires:\n      env:\n        - MATON_API_KEY\n---\n\n# Acuity Scheduling\n\nAccess the Acuity Scheduling API with managed OAuth authentication. Manage appointments, calendars, clients, availability, and more.\n\n## Quick Start\n\n```bash\n# List appointments\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/appointments?max=10')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n## Base URL\n\n```\nhttps://api.maton.ai/acuity-scheduling/{native-api-path}\n```\n\nMaton proxies requests to `acuityscheduling.com` and automatically injects your OAuth token.\n\n## Authentication\n\nAll requests require the Maton API key in the Authorization header:\n\n```\nAuthorization: Bearer $MATON_API_KEY\n```\n\n**Environment Variable:** Set your API key as `MATON_API_KEY`:\n\n```bash\nexport MATON_API_KEY=\"YOUR_API_KEY\"\n```\n\n### Getting Your API Key\n\n1. Sign in or create an account at [maton.ai](https://maton.ai)\n2. Go to [maton.ai/settings](https://maton.ai/settings)\n3. Copy your API key\n\n## Connection Management\n\nManage your Acuity Scheduling OAuth connections at `https://api.maton.ai`.\n\n### List Connections\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/connections?app=acuity-scheduling&status=ACTIVE')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n### Create Connection\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\ndata = json.dumps({'app': 'acuity-scheduling'}).encode()\nreq = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nreq.add_header('Content-Type', 'application/json')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n### Get Connection\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n**Response:**\n```json\n{\n  \"connection\": {\n    \"connection_id\": \"{connection_id}\",\n    \"status\": \"ACTIVE\",\n    \"creation_time\": \"2025-12-08T07:20:53.488460Z\",\n    \"last_updated_time\": \"2026-01-31T20:03:32.593153Z\",\n    \"url\": \"https://connect.maton.ai/?session_token=...\",\n    \"app\": \"acuity-scheduling\",\n    \"metadata\": {}\n  }\n}\n```\n\nOpen the returned `url` in a browser to complete OAuth authorization.\n\n### Delete Connection\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n### Specifying Connection\n\nIf you have multiple Acuity Scheduling connections, specify which one to use with the `Maton-Connection` header:\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/appointments')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nreq.add_header('Maton-Connection', '{connection_id}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\nIf you have multiple connections, always include this header to ensure requests go to the intended account.\n\n## Security & Permissions\n\n- Access is scoped to appointments, calendars, clients, and availability within the connected Acuity Scheduling account.\n- **All write operations require explicit user approval.** Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.\n\n## API Reference\n\n### Account Information\n\n#### Get Account Info\n\n```bash\nGET /acuity-scheduling/api/v1/me\n```\n\nReturns account information including timezone, scheduling page URL, and plan details.\n\n**Response:**\n```json\n{\n  \"id\": 12345,\n  \"email\": \"user@example.com\",\n  \"timezone\": \"America/Los_Angeles\",\n  \"name\": \"My Business\",\n  \"schedulingPage\": \"https://app.acuityscheduling.com/schedule.php?owner=12345\",\n  \"plan\": \"Professional\",\n  \"currency\": \"USD\"\n}\n```\n\n### Appointments\n\n#### List Appointments\n\n```bash\nGET /acuity-scheduling/api/v1/appointments\n```\n\n**Query Parameters:**\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `max` | integer | Maximum results (default: 100) |\n| `minDate` | date | Appointments on or after this date |\n| `maxDate` | date | Appointments on or before this date |\n| `calendarID` | integer | Filter by calendar |\n| `appointmentTypeID` | integer | Filter by appointment type |\n| `canceled` | boolean | Include canceled appointments (default: false) |\n| `firstName` | string | Filter by client first name |\n| `lastName` | string | Filter by client last name |\n| `email` | string | Filter by client email |\n| `excludeForms` | boolean | Omit intake forms for faster response |\n| `direction` | string | Sort order: ASC or DESC (default: DESC) |\n\n**Example:**\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/appointments?max=10&minDate=2026-02-01')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n**Response:**\n```json\n[\n  {\n    \"id\": 1630290133,\n    \"firstName\": \"Jane\",\n    \"lastName\": \"McTest\",\n    \"phone\": \"1235550101\",\n    \"email\": \"jane.mctest@example.com\",\n    \"date\": \"February 4, 2026\",\n    \"time\": \"9:30am\",\n    \"endTime\": \"10:20am\",\n    \"datetime\": \"2026-02-04T09:30:00-0800\",\n    \"type\": \"Consultation\",\n    \"appointmentTypeID\": 88791369,\n    \"duration\": \"50\",\n    \"calendar\": \"Chris\",\n    \"calendarID\": 13499175,\n    \"canceled\": false,\n    \"confirmationPage\": \"https://app.acuityscheduling.com/schedule.php?...\"\n  }\n]\n```\n\n#### Get Appointment\n\n```bash\nGET /acuity-scheduling/api/v1/appointments/{id}\n```\n\n#### Create Appointment\n\n```bash\nPOST /acuity-scheduling/api/v1/appointments\nContent-Type: application/json\n\n{\n  \"datetime\": \"2026-02-15T09:00\",\n  \"appointmentTypeID\": 123,\n  \"firstName\": \"John\",\n  \"lastName\": \"Doe\",\n  \"email\": \"john.doe@example.com\",\n  \"phone\": \"555-123-4567\",\n  \"timezone\": \"America/New_York\"\n}\n```\n\n**Required Fields:**\n- `datetime` - Date and time (parseable by PHP's strtotime)\n- `appointmentTypeID` - Appointment type ID\n- `firstName` - Client's first name\n- `lastName` - Client's last name\n- `email` - Client's email\n\n**Optional Fields:**\n- `phone` - Client phone number\n- `calendarID` - Specific calendar (auto-selected if omitted)\n- `timezone` - Client's timezone\n- `certificate` - Package or coupon code\n- `notes` - Admin notes\n- `addonIDs` - Array of addon IDs\n- `fields` - Array of form field values\n\n**Example:**\n```bash\npython <<'EOF'\nimport urllib.request, os, json\ndata = json.dumps({\n    'datetime': '2026-02-15T09:00',\n    'appointmentTypeID': 123,\n    'firstName': 'John',\n    'lastName': 'Doe',\n    'email': 'john.doe@example.com'\n}).encode()\nreq = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/appointments', data=data, method='POST')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nreq.add_header('Content-Type', 'application/json')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n#### Update Appointment\n\n```bash\nPUT /acuity-scheduling/api/v1/appointments/{id}\nContent-Type: application/json\n\n{\n  \"firstName\": \"Jane\",\n  \"lastName\": \"Smith\",\n  \"email\": \"jane.smith@example.com\"\n}\n```\n\n#### Cancel Appointment\n\n```bash\nPUT /acuity-scheduling/api/v1/appointments/{id}/cancel\n```\n\nReturns the canceled appointment with `canceled: true`.\n\n#### Reschedule Appointment\n\n```bash\nPUT /acuity-scheduling/api/v1/appointments/{id}/reschedule\nContent-Type: application/json\n\n{\n  \"datetime\": \"2026-02-20T10:00\"\n}\n```\n\n**Note:** The new datetime must be an available time slot.\n\n### Calendars\n\n#### List Calendars\n\n```bash\nGET /acuity-scheduling/api/v1/calendars\n```\n\n**Response:**\n```json\n[\n  {\n    \"id\": 13499175,\n    \"name\": \"Chris\",\n    \"email\": \"\",\n    \"replyTo\": \"chris@example.com\",\n    \"description\": \"\",\n    \"location\": \"\",\n    \"timezone\": \"America/Los_Angeles\"\n  }\n]\n```\n\n### Appointment Types\n\n#### List Appointment Types\n\n```bash\nGET /acuity-scheduling/api/v1/appointment-types\n```\n\n**Query Parameters:**\n- `includeDeleted` (boolean) - Include deleted types\n\n**Response:**\n```json\n[\n  {\n    \"id\": 88791369,\n    \"name\": \"Consultation\",\n    \"active\": true,\n    \"description\": \"\",\n    \"duration\": 50,\n    \"price\": \"45.00\",\n    \"category\": \"\",\n    \"color\": \"#ED7087\",\n    \"private\": false,\n    \"type\": \"service\",\n    \"calendarIDs\": [13499175],\n    \"schedulingUrl\": \"https://app.acuityscheduling.com/schedule.php?...\"\n  }\n]\n```\n\n### Availability\n\n#### Get Available Dates\n\n```bash\nGET /acuity-scheduling/api/v1/availability/dates?month=2026-02&appointmentTypeID=123\n```\n\n**Required Parameters:**\n- `month` - Month to check (e.g., \"2026-02\")\n- `appointmentTypeID` - Appointment type ID\n\n**Optional Parameters:**\n- `calendarID` - Specific calendar\n- `timezone` - Timezone for results (e.g., \"America/New_York\")\n\n**Response:**\n```json\n[\n  {\"date\": \"2026-02-09\"},\n  {\"date\": \"2026-02-10\"},\n  {\"date\": \"2026-02-11\"}\n]\n```\n\n#### Get Available Times\n\n```bash\nGET /acuity-scheduling/api/v1/availability/times?date=2026-02-10&appointmentTypeID=123\n```\n\n**Required Parameters:**\n- `date` - Date to check\n- `appointmentTypeID` - Appointment type ID\n\n**Optional Parameters:**\n- `calendarID` - Specific calendar\n- `timezone` - Timezone for results\n\n**Response:**\n```json\n[\n  {\"time\": \"2026-02-10T09:00:00-0800\", \"slotsAvailable\": 1},\n  {\"time\": \"2026-02-10T09:50:00-0800\", \"slotsAvailable\": 1},\n  {\"time\": \"2026-02-10T10:40:00-0800\", \"slotsAvailable\": 1}\n]\n```\n\n### Clients\n\n#### List Clients\n\n```bash\nGET /acuity-scheduling/api/v1/clients\n```\n\n**Query Parameters:**\n- `search` - Filter by first name, last name, or phone\n\n**Example:**\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/acuity-scheduling/api/v1/clients?search=John')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n**Response:**\n```json\n[\n  {\n    \"firstName\": \"Jane\",\n    \"lastName\": \"McTest\",\n    \"email\": \"jane.mctest@example.com\",\n    \"phone\": \"(123) 555-0101\",\n    \"notes\": \"\"\n  }\n]\n```\n\n#### Create Client\n\n```bash\nPOST /acuity-scheduling/api/v1/clients\nContent-Type: application/json\n\n{\n  \"firstName\": \"John\",\n  \"lastName\": \"Doe\",\n  \"email\": \"john@example.com\",\n  \"phone\": \"555-123-4567\"\n}\n```\n\n#### Update Client\n\n```bash\nPUT /acuity-scheduling/api/v1/clients\nContent-Type: application/json\n\n{\n  \"firstName\": \"John\",\n  \"lastName\": \"Doe\",\n  \"email\": \"john.updated@example.com\"\n}\n```\n\n**Note:** Client update/delete only works for clients with existing appointments.\n\n#### Delete Client\n\n```bash\nDELETE /acuity-scheduling/api/v1/clients\nContent-Type: application/json\n\n{\n  \"firstName\": \"John\",\n  \"lastName\": \"Doe\"\n}\n```\n\n### Blocks\n\n#### List Blocks\n\n```bash\nGET /acuity-scheduling/api/v1/blocks\n```\n\n**Query Parameters:**\n- `max` - Maximum results (default: 100)\n- `minDate` - Blocks on or after this date\n- `maxDate` - Blocks on or before this date\n- `calendarID` - Filter by calendar\n\n#### Get Block\n\n```bash\nGET /acuity-scheduling/api/v1/blocks/{id}\n```\n\n#### Create Block\n\n```bash\nPOST /acuity-scheduling/api/v1/blocks\nContent-Type: application/json\n\n{\n  \"start\": \"2026-02-15T12:00\",\n  \"end\": \"2026-02-15T13:00\",\n  \"calendarID\": 1234,\n  \"notes\": \"Lunch break\"\n}\n```\n\n**Response:**\n```json\n{\n  \"id\": 9589304654,\n  \"calendarID\": 13499175,\n  \"start\": \"2026-02-15T12:00:00-0800\",\n  \"end\": \"2026-02-15T13:00:00-0800\",\n  \"notes\": \"Lunch break\",\n  \"description\": \"Sunday, February 15, 2026 12:00pm - 1:00pm\"\n}\n```\n\n#### Delete Block\n\n```bash\nDELETE /acuity-scheduling/api/v1/blocks/{id}\n```\n\nReturns 204 No Content on success.\n\n### Forms\n\n#### List Forms\n\n```bash\nGET /acuity-scheduling/api/v1/forms\n```\n\n**Response:**\n```json\n[\n  {\n    \"id\": 123,\n    \"name\": \"Client Intake Form\",\n    \"appointmentTypeIDs\": [456, 789],\n    \"fields\": [\n      {\n        \"id\": 1,\n        \"name\": \"How did you hear about us?\",\n        \"type\": \"dropdown\",\n        \"options\": [\"Google\", \"Friend\", \"Social Media\"],\n        \"required\": true\n      }\n    ]\n  }\n]\n```\n\n### Labels\n\n#### List Labels\n\n```bash\nGET /acuity-scheduling/api/v1/labels\n```\n\n**Response:**\n```json\n[\n  {\"id\": 23116714, \"name\": \"Checked In\", \"color\": \"green\"},\n  {\"id\": 23116715, \"name\": \"Completed\", \"color\": \"pink\"},\n  {\"id\": 23116713, \"name\": \"Confirmed\", \"color\": \"yellow\"}\n]\n```\n\n## Pagination\n\nAcuity Scheduling uses the `max` parameter to limit results. Use `minDate` and `maxDate` to paginate through date ranges:\n\n```bash\n# First page\nGET /acuity-scheduling/api/v1/appointments?max=100&minDate=2026-01-01&maxDate=2026-01-31\n\n# Next page\nGET /acuity-scheduling/api/v1/appointments?max=100&minDate=2026-02-01&maxDate=2026-02-28\n```\n\n## Code Examples\n\n### JavaScript\n\n```javascript\nconst response = await fetch(\n  'https://api.maton.ai/acuity-scheduling/api/v1/appointments?max=10',\n  {\n    headers: {\n      'Authorization': `Bearer ${process.env.MATON_API_KEY}`\n    }\n  }\n);\nconst appointments = await response.json();\n```\n\n### Python\n\n```python\nimport os\nimport requests\n\nresponse = requests.get(\n    'https://api.maton.ai/acuity-scheduling/api/v1/appointments',\n    headers={'Authorization': f'Bearer {os.environ[\"MATON_API_KEY\"]}'},\n    params={'max': 10}\n)\nappointments = response.json()\n```\n\n## Notes\n\n- Datetime values must be parseable by PHP's `strtotime()` function\n- Timezones use IANA format (e.g., \"America/New_York\", \"America/Los_Angeles\")\n- Client update/delete requires clients to have existing appointments\n- Rescheduling requires the new datetime to be an available time slot\n- Use `excludeForms=true` for faster appointment list responses\n- IMPORTANT: When using curl commands, use `curl -g` when URLs contain brackets to disable glob parsing\n- IMPORTANT: When piping curl output to `jq` 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.\n\n## Error Handling\n\n| Status | Meaning |\n|--------|---------|\n| 400 | Invalid request (e.g., time not available, client not found) |\n| 401 | Invalid or missing Maton API key |\n| 404 | Resource not found |\n| 429 | Rate limited |\n| 4xx/5xx | Passthrough error from Acuity API |\n\n### Troubleshooting: API Key Issues\n\n1. Check that the `MATON_API_KEY` environment variable is set:\n\n```bash\necho $MATON_API_KEY\n```\n\n2. Verify the API key is valid by listing connections:\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/connections')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n### Troubleshooting: Invalid App Name\n\n1. Ensure your URL path starts with `acuity-scheduling`. For example:\n\n- Correct: `https://api.maton.ai/acuity-scheduling/api/v1/appointments`\n- Incorrect: `https://api.maton.ai/api/v1/appointments`\n\n## Resources\n\n- [Acuity Scheduling API Quick Start](https://developers.acuityscheduling.com/reference/quick-start)\n- [Appointments API](https://developers.acuityscheduling.com/reference/get-appointments)\n- [Availability API](https://developers.acuityscheduling.com/reference/get-availability-dates)\n- [Calendars API](https://developers.acuityscheduling.com/reference/get-calendars)\n- [Clients API](https://developers.acuityscheduling.com/reference/clients)\n- [OAuth2 Documentation](https://developers.acuityscheduling.com/docs/oauth2)\n- [Maton Community](https://discord.com/invite/dBfFAcefs2)\n- [Maton Support](mailto:support@maton.ai)\n","tags":{"latest":"1.0.3"},"stats":{"comments":0,"downloads":5986,"installsAllTime":5,"installsCurrent":5,"stars":3,"versions":4},"createdAt":1770420088246,"updatedAt":1781739757511},"latestVersion":{"version":"1.0.3","createdAt":1777591205601,"changelog":"- Updated all API base URLs from gateway.maton.ai and ctrl.maton.ai to api.maton.ai for consistency and clarity.\n- Revised connection management instructions and endpoints to use api.maton.ai throughout.\n- Clarified that specifying the Maton-Connection header is required if multiple connections exist.\n- Added a \"Security & Permissions\" section to emphasize user approval for all write operations.\n- Removed the LICENSE.txt file.","license":"MIT-0"},"metadata":{"setup":[{"key":"MATON_API_KEY","required":true}],"os":null,"systems":null},"owner":{"handle":"byungkyu","userId":"s174c3s2kc1ehqj1ytzntezj2983e2aj","displayName":"byungkyu","image":"https://avatars.githubusercontent.com/u/16563684?v=4"},"moderation":null}