通过托管 OAuth 网关读写 Zoho 日历的日历与事件。
文档
zoho-bookings
试用通过 Maton API 代理,使用托管 OAuth 管理 Zoho Bookings 的预约、服务、员工和工作区。
它能做什么
通过 Maton 代理端点访问 Zoho Bookings API,OAuth 令牌由平台自动注入。使用 MATON_API_KEY 环境变量作为 Bearer Token 鉴权后,可对工作区、服务、员工和预约进行列表、查询和创建。支持通过 Maton-Connection 请求头在多个 Zoho Bookings 账号之间切换。所有写入操作执行前都需要用户明确确认。
什么时候用它
- 为客户在已有服务上下单预约
- 列出某个工作区下的服务及已分配员工
- 新建工作区或服务配置
- 管理多个 Zoho Bookings OAuth 连接
技能文档
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://api.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://api.maton.ai/zoho-bookings/bookings/v1/json/{endpoint}
Maton 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
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your Zoho Bookings OAuth connections at https://api.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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://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
Get Connection
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": "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://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
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://api.maton.ai/zoho-bookings/bookings/v1/json/workspaces')
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.
Security & Permissions
- Access is scoped to appointments, services, staff, and workspaces within the connected Zoho Bookings account.
- 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.
API Reference
Workspaces
Fetch Workspaces
GET /zoho-bookings/bookings/v1/json/workspaces
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
workspace_id | string | Filter by specific workspace ID |
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Workspace 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://api.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:
| Parameter | Type | Required | Description |
|---|---|---|---|
workspace_id | string | Yes | Workspace ID |
service_id | string | No | Filter by specific service ID |
staff_id | string | No | Filter by staff ID |
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Service name |
workspace_id | string | Yes | Workspace ID |
duration | integer | No | Duration in minutes |
cost | number | No | Service price |
pre_buffer | integer | No | Buffer time before (minutes) |
post_buffer | integer | No | Buffer time after (minutes) |
description | string | No | Service description |
assigned_staffs | string | No | JSON 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://api.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:
| Parameter | Type | Required | Description |
|---|---|---|---|
workspace_id | string | Yes | Workspace ID |
staff_id | string | No | Filter by specific staff ID |
service_id | string | No | Filter by service ID |
staff_email | string | No | Filter by email (partial match) |
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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:
| Parameter | Type | Required | Description |
|---|---|---|---|
service_id | string | Yes | Service ID |
staff_id | string | Yes* | Staff ID (*or resource_id/group_id) |
from_time | string | Yes | Start time: dd-MMM-yyyy HH:mm:ss (24-hour) |
timezone | string | No | Timezone (e.g., America/Los_Angeles) |
customer_details | string | Yes | JSON string with name, email, phone_number |
notes | string | No | Appointment notes |
additional_fields | string | No | JSON 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://api.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:
| Parameter | Type | Required | Description |
|---|---|---|---|
booking_id | string | Yes | Booking ID (URL-encoded, e.g., %23NU-00001) |
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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:
| Parameter | Type | Description |
|---|---|---|
from_time | string | Start date: dd-MMM-yyyy HH:mm:ss |
to_time | string | End date: dd-MMM-yyyy HH:mm:ss |
status | string | UPCOMING, CANCEL, COMPLETED, NO_SHOW, PENDING |
service_id | string | Filter by service |
staff_id | string | Filter by staff |
customer_name | string | Filter by customer name (partial match) |
customer_email | string | Filter by email (partial match) |
page | integer | Page number |
per_page | integer | Results 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://api.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:
| Parameter | Type | Required | Description |
|---|---|---|---|
booking_id | string | Yes | Booking ID |
action | string | Yes | completed, 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://api.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://api.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://api.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://api.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_detailsmust be a JSON string, not an objectfetchappointmentrequires parameters wrapped indatafield 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 -gwhen URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to
jqor other commands, environment variables like$MATON_API_KEYmay not expand correctly in some shell environments
Error Handling
| Status | Meaning |
|---|---|
| 400 | Missing Zoho Bookings connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Zoho Bookings API |
Rate Limits
| Plan | Daily Limit |
|---|---|
| Free | 250 calls/user |
| Basic | 1,000 calls/user |
| Premium | 3,000 calls/user |
| Zoho One | 3,000 calls/user |
Troubleshooting: API Key Issues
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
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
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
zoho-bookings. For example:
- Correct:
https://api.maton.ai/zoho-bookings/bookings/v1/json/workspaces - Incorrect:
https://api.maton.ai/bookings/v1/json/workspaces
Resources
相关技能
通过 OAuth 网关调度与管理 Zoom 会议、研讨会与云录制。
通过 OAuth 代理调用 Zoho Mail REST API,管理账户、文件夹、标签以及邮件收发。
通过 Maton 托管的 OAuth 代理读写 Zoho CRM 记录,所有写入操作均需用户确认。
通过托管 OAuth 连接 Zoho Inventory API,对商品、销售订单、发票、联系人、账单等记录进行读写。
通过托管 OAuth 读写 Zoho Recruit 的候选人、职位和面试数据。