Access the Zoho Calendar API with managed OAuth authentication. Manage calendars and events with full CRUD operations, including recurring events and attendee management.
# List calendars
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-calendar/api/v1/calendars')
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/zoho-calendar/api/v1/{endpoint}
Maton proxies requests to calendar.zoho.com/api/v1 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 Zoho Calendar OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=zoho-calendar&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': 'zoho-calendar'}).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": "zoho-calendar",
"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 Zoho Calendar 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-calendar/api/v1/calendars')
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 /zoho-calendar/api/v1/calendars
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-calendar/api/v1/calendars')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"calendars": [
{
"uid": "fda9b0b4ad834257b622cb3dc3555727",
"name": "My Calendar",
"color": "#8cbf40",
"textcolor": "#FFFFFF",
"timezone": "PST",
"isdefault": true,
"category": "own",
"privilege": "owner"
}
]
}
GET /zoho-calendar/api/v1/calendars/{calendar_uid}
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-calendar/api/v1/calendars/fda9b0b4ad834257b622cb3dc3555727')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
POST /zoho-calendar/api/v1/calendars?calendarData={json}
Required Fields:
name - Calendar name (max 50 characters)color - Hex color code (e.g., #FF5733)Optional Fields:
textcolor - Text color hex codedescription - Calendar description (max 1000 characters)timezone - Calendar timezoneinclude_infreebusy - Show as Busy/Free (boolean)public - Visibility level (disable, freebusy, or view)Example:
python <<'EOF'
import urllib.request, os, json, urllib.parse
calendarData = {
"name": "Work Calendar",
"color": "#FF5733",
"textcolor": "#FFFFFF",
"description": "My work calendar"
}
url = f'https://api.maton.ai/zoho-calendar/api/v1/calendars?calendarData={urllib.parse.quote(json.dumps(calendarData))}'
req = urllib.request.Request(url, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"calendars": [
{
"uid": "86fb9745076e4672ae4324f05e1f5393",
"name": "Work Calendar",
"color": "#FF5733",
"textcolor": "#FFFFFF"
}
]
}
DELETE /zoho-calendar/api/v1/calendars/{calendar_uid}
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-calendar/api/v1/calendars/86fb9745076e4672ae4324f05e1f5393', 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
Response:
{
"calendars": [
{
"uid": "86fb9745076e4672ae4324f05e1f5393",
"calstatus": "deleted"
}
]
}
GET /zoho-calendar/api/v1/calendars/{calendar_uid}/events?range={json}
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| ----------- | ------ | ------------- |
range | JSON object | Required. Start and end dates in format {"start":"yyyyMMdd","end":"yyyyMMdd"}. Max 31-day span. |
byinstance | boolean | If true, recurring event instances are returned separately |
timezone | string | Timezone for datetime values |
Example:
python <<'EOF'
import urllib.request, os, json, urllib.parse
from datetime import datetime, timedelta
today = datetime.now()
end_date = today + timedelta(days=7)
range_param = json.dumps({
"start": today.strftime("%Y%m%d"),
"end": end_date.strftime("%Y%m%d")
})
url = f'https://api.maton.ai/zoho-calendar/api/v1/calendars/fda9b0b4ad834257b622cb3dc3555727/events?range={urllib.parse.quote(range_param)}'
req = urllib.request.Request(url)
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"events": [
{
"uid": "c63e8b9fcb3e48c2a00b16729932d636@zoho.com",
"title": "Team Meeting",
"dateandtime": {
"timezone": "America/Los_Angeles",
"start": "20260206T100000-0800",
"end": "20260206T110000-0800"
},
"isallday": false,
"etag": "1770368451507",
"organizer": "user@example.com"
}
]
}
GET /zoho-calendar/api/v1/calendars/{calendar_uid}/events/{event_uid}
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-calendar/api/v1/calendars/fda9b0b4ad834257b622cb3dc3555727/events/c63e8b9fcb3e48c2a00b16729932d636@zoho.com')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
POST /zoho-calendar/api/v1/calendars/{calendar_uid}/events?eventdata={json}
Required Fields (in eventdata):
dateandtime - Object with start, end, and optionally timezoneyyyyMMdd'T'HHmmss'Z' (GMT) for timed eventsyyyyMMdd for all-day eventsOptional Fields:
title - Event namedescription - Event details (max 10,000 characters)location - Event location (max 255 characters)isallday - Boolean for all-day eventsisprivate - Boolean to hide details from non-delegatescolor - Hex color codeattendees - Array of attendee objectsreminders - Array of reminder objectsrrule - Recurrence rule string (e.g., FREQ=DAILY;COUNT=5)Example:
python <<'EOF'
import urllib.request, os, json, urllib.parse
from datetime import datetime, timedelta
start_time = datetime.utcnow() + timedelta(hours=1)
end_time = start_time + timedelta(hours=1)
eventdata = {
"title": "Team Meeting",
"dateandtime": {
"timezone": "America/Los_Angeles",
"start": start_time.strftime("%Y%m%dT%H%M%SZ"),
"end": end_time.strftime("%Y%m%dT%H%M%SZ")
},
"description": "Weekly team sync",
"location": "Conference Room A"
}
url = f'https://api.maton.ai/zoho-calendar/api/v1/calendars/fda9b0b4ad834257b622cb3dc3555727/events?eventdata={urllib.parse.quote(json.dumps(eventdata))}'
req = urllib.request.Request(url, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"events": [
{
"uid": "c63e8b9fcb3e48c2a00b16729932d636@zoho.com",
"title": "Team Meeting",
"dateandtime": {
"timezone": "America/Los_Angeles",
"start": "20260206T100000-0800",
"end": "20260206T110000-0800"
},
"etag": "1770368451507",
"estatus": "added"
}
]
}
PUT /zoho-calendar/api/v1/calendars/{calendar_uid}/events/{event_uid}?eventdata={json}
Required Fields:
dateandtime - Start and end timesetag - Current etag value (from Get Event Details)Optional Fields: Same as Create Event
Example:
python <<'EOF'
import urllib.request, os, json, urllib.parse
from datetime import datetime, timedelta
start_time = datetime.utcnow() + timedelta(hours=2)
end_time = start_time + timedelta(hours=1)
eventdata = {
"title": "Updated Team Meeting",
"dateandtime": {
"timezone": "America/Los_Angeles",
"start": start_time.strftime("%Y%m%dT%H%M%SZ"),
"end": end_time.strftime("%Y%m%dT%H%M%SZ")
},
"etag": 1770368451507
}
url = f'https://api.maton.ai/zoho-calendar/api/v1/calendars/fda9b0b4ad834257b622cb3dc3555727/events/c63e8b9fcb3e48c2a00b16729932d636@zoho.com?eventdata={urllib.parse.quote(json.dumps(eventdata))}'
req = urllib.request.Request(url, method='PUT')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
DELETE /zoho-calendar/api/v1/calendars/{calendar_uid}/events/{event_uid}
Required Header:
etag - Current etag value of the eventExample:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/zoho-calendar/api/v1/calendars/fda9b0b4ad834257b622cb3dc3555727/events/c63e8b9fcb3e48c2a00b16729932d636@zoho.com', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('etag', '1770368451507')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"events": [
{
"uid": "c63e8b9fcb3e48c2a00b16729932d636@zoho.com",
"estatus": "deleted",
"caluid": "fda9b0b4ad834257b622cb3dc3555727"
}
]
}
When creating or updating events, include attendees:
{
"attendees": [
{
"email": "user@example.com",
"permission": 1,
"attendance": 1
}
]
}
Permission levels: 0 (Guest), 1 (View), 2 (Invite), 3 (Edit)
Attendance: 0 (Non-participant), 1 (Required), 2 (Optional)
{
"reminders": [
{
"action": "popup",
"minutes": 30
},
{
"action": "email",
"minutes": 60
}
]
}
Actions: email, popup, notification
Use the rrule field with iCalendar RRULE format:
{
"rrule": "FREQ=DAILY;COUNT=5;INTERVAL=1"
}
Examples:
FREQ=DAILY;COUNT=5;INTERVAL=1FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU;UNTIL=20250817T064600ZFREQ=MONTHLY;INTERVAL=1;BYDAY=TU;BYSETPOS=-1;COUNT=2const response = await fetch(
'https://api.maton.ai/zoho-calendar/api/v1/calendars',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
import os
import requests
response = requests.get(
'https://api.maton.ai/zoho-calendar/api/v1/calendars',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()
eventdata or calendarData query parameteryyyyMMdd'T'HHmmss'Z' (GMT) or yyyyMMdd for all-day eventsrange parameter for listing events cannot exceed 31 daysetag is required for update and delete operations - always get the latest etag before modifyingetag must be passed as a header, not a query parametercurl -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| Status | Meaning |
|---|---|
| -------- | --------- |
| 400 | Missing Zoho Calendar connection, missing required parameter, or invalid request |
| 401 | Invalid or missing Maton API key, or OAuth scope mismatch |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Zoho Calendar API |
| Error | Description |
|---|---|
| ------- | ------------- |
ETAG_MISSING | etag header required for delete operations |
EXTRA_PARAM_FOUND | Invalid parameter in request |
INVALID_DATA | Malformed request data |
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
zoho-calendar. For example:https://api.maton.ai/zoho-calendar/api/v1/calendarshttps://api.maton.ai/api/v1/calendars共 2 个版本