Zoho Bookings

v1.0.2

Zoho Bookings API integration with managed OAuth. Manage appointments, services, staff, and workspaces. Use this skill when users want to book appointments,...

0· 509·0 current·0 all-time
MIT-0
Download zip
LicenseMIT-0 · Free to use, modify, and redistribute. No attribution required.
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
medium confidence
Purpose & Capability
Name/description (Zoho Bookings integration) align with the runtime instructions: all examples call a Maton gateway and connection controller to proxy Zoho Bookings API requests. Requesting a MATON_API_KEY is consistent with using a managed gateway.
Instruction Scope
Instructions only perform network calls to maton.ai gateway and ctrl.maton.ai for connection management and to connect.maton.ai to finish OAuth; they do not reference local files, unrelated env vars, or other system state. Note: runtime behavior relies entirely on a third‑party proxy service (Maton) which will see proxied requests and manage OAuth tokens.
Install Mechanism
Instruction-only skill with no install spec and no code files — nothing is written to disk by the skill package itself. Lowest install risk.
Credentials
Only a single env var (MATON_API_KEY) is required and is used consistently in examples. The requested credential is proportional to the gateway-based architecture. There are no unrelated credentials requested.
Persistence & Privilege
always is false and the skill is user-invocable; it does not request persistent system-wide privileges or modify other skills. Autonomous invocation is allowed by default but not an additional privilege here.
Assessment
This skill is internally consistent: it proxies Zoho Bookings calls through Maton and requires a MATON_API_KEY. Before installing, verify you trust maton.ai/ctrl.maton.ai/connect.maton.ai because Maton will see API requests and hold OAuth tokens on your behalf. Confirm Maton's ownership and privacy/security practices (there's no homepage in the registry entry beyond URLs in SKILL.md), prefer using a dedicated Maton account or API key with minimal scope, store the MATON_API_KEY securely, and rotate the key if you later revoke access. Because the skill is instruction-only, there is no bundled code to audit; your main risk is trusting the external gateway service rather than the skill package itself.

Like a lobster shell, security has layers — review code before you run it.

latestvk97asmabtp2ap56by8cm3phnf181fkat

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

Runtime requirements

🧠 Clawdis
EnvMATON_API_KEY

SKILL.md

Zoho Bookings

Access the Zoho Bookings API with managed OAuth authentication. Manage appointments, services, staff, and workspaces with full CRUD operations.

Quick Start

# List workspaces
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/workspaces')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Base URL

https://gateway.maton.ai/zoho-bookings/bookings/v1/json/{endpoint}

The gateway proxies requests to www.zohoapis.com/bookings/v1/json and automatically injects your OAuth token.

Authentication

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"

Getting Your API Key

  1. Sign in or create an account at maton.ai
  2. Go to maton.ai/settings
  3. Copy your API key

Connection Management

Manage your Zoho Bookings OAuth connections at https://ctrl.maton.ai.

List Connections

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=zoho-bookings&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

Create Connection

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'zoho-bookings'}).encode()
req = urllib.request.Request('https://ctrl.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

Get Connection

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.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": "3c358231-7ca7-4a63-8a3c-3a9d21be53ca",
    "status": "ACTIVE",
    "creation_time": "2026-02-18T00:17:23.498742Z",
    "last_updated_time": "2026-02-18T00:18:59.299114Z",
    "url": "https://connect.maton.ai/?session_token=...",
    "app": "zoho-bookings",
    "metadata": {}
  }
}

Open the returned url in a browser to complete OAuth authorization.

Delete Connection

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.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

Specifying Connection

If you have multiple Zoho Bookings connections, specify which one to use with the Maton-Connection header:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/workspaces')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '3c358231-7ca7-4a63-8a3c-3a9d21be53ca')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

If omitted, the gateway uses the default (oldest) active connection.

API Reference

Workspaces

Fetch Workspaces

GET /zoho-bookings/bookings/v1/json/workspaces

Query Parameters:

ParameterTypeDescription
workspace_idstringFilter by specific workspace ID

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/workspaces')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "response": {
    "returnvalue": {
      "data": [
        {
          "name": "Main Office",
          "id": "4753814000000048016"
        }
      ]
    },
    "status": "success"
  }
}

Create Workspace

POST /zoho-bookings/bookings/v1/json/createworkspace
Content-Type: application/x-www-form-urlencoded

Form Parameters:

ParameterTypeRequiredDescription
namestringYesWorkspace name (2-50 chars, no special characters)

Example:

python <<'EOF'
import urllib.request, os, json
from urllib.parse import urlencode
form_data = urlencode({'name': 'New York Office'}).encode()
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/createworkspace', data=form_data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Services

Fetch Services

GET /zoho-bookings/bookings/v1/json/services?workspace_id={workspace_id}

Query Parameters:

ParameterTypeRequiredDescription
workspace_idstringYesWorkspace ID
service_idstringNoFilter by specific service ID
staff_idstringNoFilter by staff ID

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/services?workspace_id=4753814000000048016')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "response": {
    "returnvalue": {
      "data": [
        {
          "id": "4753814000000048054",
          "name": "Product Demo",
          "duration": "30 mins",
          "service_type": "APPOINTMENT",
          "price": 0,
          "currency": "USD",
          "assigned_staffs": ["4753814000000048014"],
          "assigned_workspace": "4753814000000048016",
          "embed_url": "https://example.zohobookings.com/portal-embed#/4753814000000048054",
          "let_customer_select_staff": true
        }
      ],
      "next_page_available": false,
      "page": 1
    },
    "status": "success"
  }
}

Create Service

POST /zoho-bookings/bookings/v1/json/createservice
Content-Type: application/x-www-form-urlencoded

Form Parameters:

ParameterTypeRequiredDescription
namestringYesService name
workspace_idstringYesWorkspace ID
durationintegerNoDuration in minutes
costnumberNoService price
pre_bufferintegerNoBuffer time before (minutes)
post_bufferintegerNoBuffer time after (minutes)
descriptionstringNoService description
assigned_staffsstringNoJSON array of staff IDs

Example:

python <<'EOF'
import urllib.request, os, json
from urllib.parse import urlencode
form_data = urlencode({
    'name': 'Consultation',
    'workspace_id': '4753814000000048016',
    'duration': '60'
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/createservice', data=form_data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Staff

Fetch Staff

GET /zoho-bookings/bookings/v1/json/staffs?workspace_id={workspace_id}

Query Parameters:

ParameterTypeRequiredDescription
workspace_idstringYesWorkspace ID
staff_idstringNoFilter by specific staff ID
service_idstringNoFilter by service ID
staff_emailstringNoFilter by email (partial match)

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/staffs?workspace_id=4753814000000048016')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "response": {
    "returnvalue": {
      "data": [
        {
          "id": "4753814000000048014",
          "name": "John Doe",
          "email": "john@example.com",
          "designation": "Consultant",
          "assigned_services": ["4753814000000048054"],
          "assigned_workspaces": ["4753814000000048016"],
          "embed_url": "https://example.zohobookings.com/portal-embed#/4753814000000048014"
        }
      ]
    },
    "status": "success"
  }
}

Appointments

Book Appointment

POST /zoho-bookings/bookings/v1/json/appointment
Content-Type: application/x-www-form-urlencoded

Form Parameters:

ParameterTypeRequiredDescription
service_idstringYesService ID
staff_idstringYes*Staff ID (*or resource_id/group_id)
from_timestringYesStart time: dd-MMM-yyyy HH:mm:ss (24-hour)
timezonestringNoTimezone (e.g., America/Los_Angeles)
customer_detailsstringYesJSON string with name, email, phone_number
notesstringNoAppointment notes
additional_fieldsstringNoJSON string with custom fields

Example:

python <<'EOF'
import urllib.request, os, json
from urllib.parse import urlencode
form_data = urlencode({
    'service_id': '4753814000000048054',
    'staff_id': '4753814000000048014',
    'from_time': '20-Feb-2026 10:00:00',
    'timezone': 'America/Los_Angeles',
    'customer_details': json.dumps({
        'name': 'Jane Smith',
        'email': 'jane@example.com',
        'phone_number': '+15551234567'
    })
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/appointment', data=form_data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "response": {
    "returnvalue": {
      "booking_id": "#NU-00001",
      "service_name": "Product Demo",
      "staff_name": "John Doe",
      "start_time": "20-Feb-2026 10:00:00",
      "end_time": "20-Feb-2026 10:30:00",
      "duration": "30 mins",
      "customer_name": "Jane Smith",
      "customer_email": "jane@example.com",
      "status": "upcoming",
      "time_zone": "America/Los_Angeles"
    },
    "status": "success"
  }
}

Get Appointment

GET /zoho-bookings/bookings/v1/json/getappointment?booking_id={booking_id}

Query Parameters:

ParameterTypeRequiredDescription
booking_idstringYesBooking ID (URL-encoded, e.g., %23NU-00001)

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/getappointment?booking_id=%23NU-00001')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Fetch Appointments

POST /zoho-bookings/bookings/v1/json/fetchappointment
Content-Type: application/x-www-form-urlencoded

Form Parameters:

Send parameters wrapped in a data field as JSON:

ParameterTypeDescription
from_timestringStart date: dd-MMM-yyyy HH:mm:ss
to_timestringEnd date: dd-MMM-yyyy HH:mm:ss
statusstringUPCOMING, CANCEL, COMPLETED, NO_SHOW, PENDING
service_idstringFilter by service
staff_idstringFilter by staff
customer_namestringFilter by customer name (partial match)
customer_emailstringFilter by email (partial match)
pageintegerPage number
per_pageintegerResults per page (max 100)

Example:

python <<'EOF'
import urllib.request, os, json
from urllib.parse import urlencode
form_data = urlencode({
    'data': json.dumps({
        'from_time': '17-Feb-2026 00:00:00',
        'to_time': '20-Feb-2026 23:59:59'
    })
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/fetchappointment', data=form_data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "response": {
    "returnvalue": {
      "response": [
        {
          "booking_id": "#NU-00001",
          "service_name": "Product Demo",
          "staff_name": "John Doe",
          "start_time": "20-Feb-2026 10:00:00",
          "customer_name": "Jane Smith",
          "status": "upcoming"
        }
      ],
      "next_page_available": false,
      "page": 1
    },
    "status": "success"
  }
}

Update Appointment

POST /zoho-bookings/bookings/v1/json/updateappointment
Content-Type: application/x-www-form-urlencoded

Form Parameters:

ParameterTypeRequiredDescription
booking_idstringYesBooking ID
actionstringYescompleted, cancel, or noshow

Example - Cancel Appointment:

python <<'EOF'
import urllib.request, os, json
from urllib.parse import urlencode
form_data = urlencode({
    'booking_id': '#NU-00001',
    'action': 'cancel'
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/updateappointment', data=form_data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Pagination

Appointments use page-based pagination:

python <<'EOF'
import urllib.request, os, json
from urllib.parse import urlencode
form_data = urlencode({
    'data': json.dumps({
        'from_time': '01-Feb-2026 00:00:00',
        'to_time': '28-Feb-2026 23:59:59',
        'page': 1,
        'per_page': 50
    })
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/zoho-bookings/bookings/v1/json/fetchappointment', data=form_data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response includes pagination info:

{
  "response": {
    "returnvalue": {
      "response": [...],
      "next_page_available": true,
      "page": 1
    },
    "status": "success"
  }
}

Code Examples

JavaScript

// Fetch workspaces
const response = await fetch(
  'https://gateway.maton.ai/zoho-bookings/bookings/v1/json/workspaces',
  {
    headers: {
      'Authorization': `Bearer ${process.env.MATON_API_KEY}`
    }
  }
);
const data = await response.json();

Python

import os
import requests

# Fetch services
response = requests.get(
    'https://gateway.maton.ai/zoho-bookings/bookings/v1/json/services',
    headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
    params={'workspace_id': '4753814000000048016'}
)
data = response.json()

Notes

  • Date/time format: dd-MMM-yyyy HH:mm:ss (e.g., 20-Feb-2026 10:00:00)
  • Booking IDs include # prefix (URL-encode as %23)
  • customer_details must be a JSON string, not an object
  • fetchappointment requires parameters wrapped in data field as JSON
  • Other POST endpoints use regular form fields
  • Service types: APPOINTMENT, RESOURCE, CLASS, COLLECTIVE
  • Status values: UPCOMING, CANCEL, ONGOING, PENDING, COMPLETED, NO_SHOW
  • Default pagination: 50 appointments per page (max 100)
  • If you receive a scope error, contact Maton support at support@maton.ai with the specific operations/APIs you need and your use-case
  • IMPORTANT: When using curl commands, use curl -g when URLs contain brackets to disable glob parsing
  • IMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments

Error Handling

StatusMeaning
400Missing Zoho Bookings connection or invalid request
401Invalid or missing Maton API key
429Rate limited
4xx/5xxPassthrough error from Zoho Bookings API

Rate Limits

PlanDaily Limit
Free250 calls/user
Basic1,000 calls/user
Premium3,000 calls/user
Zoho One3,000 calls/user

Troubleshooting: API Key Issues

  1. Check that the MATON_API_KEY environment variable is set:
echo $MATON_API_KEY
  1. Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.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

Troubleshooting: Invalid App Name

  1. Ensure your URL path starts with zoho-bookings. For example:
  • Correct: https://gateway.maton.ai/zoho-bookings/bookings/v1/json/workspaces
  • Incorrect: https://gateway.maton.ai/bookings/v1/json/workspaces

Resources

Files

2 total
Select a file
Select a file to preview.

Comments

Loading comments…