Install
openclaw skills install cal-comCal.com API integration with managed OAuth. Create and manage event types, bookings, schedules, and availability. Use this skill when users want to manage scheduling, create bookings, configure event types, or check availability. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Requires network access and valid Maton API key.
openclaw skills install cal-comAccess the Cal.com API with managed OAuth authentication. Create and manage event types, bookings, schedules, calendars, and webhooks.
# Get your profile
python3 <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/cal-com/v2/me')
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/cal-com/v2/{resource}
Maton proxies requests to api.cal.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 Cal.com OAuth connections at https://api.maton.ai.
python3 <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=cal-com&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
python3 <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'cal-com'}).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
python3 <<'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-12T22:52:17.140998Z",
"last_updated_time": "2026-02-12T22:55:20.376189Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "cal-com",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python3 <<'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 Cal.com connections, specify which one to use with the Maton-Connection header:
python3 <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/cal-com/v2/me')
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 /cal-com/v2/me
Response:
{
"status": "success",
"data": {
"id": 2152180,
"email": "user@example.com",
"name": "User Name",
"avatarUrl": "https://...",
"bio": "",
"timeFormat": 12,
"defaultScheduleId": null,
"weekStart": "Sunday",
"timeZone": "America/New_York"
}
}
PATCH /cal-com/v2/me
Content-Type: application/json
{
"bio": "Updated bio",
"name": "New Name"
}
GET /cal-com/v2/event-types
With username filter:
GET /cal-com/v2/event-types?username={username}
Response:
{
"status": "success",
"data": {
"eventTypeGroups": [
{
"teamId": null,
"bookerUrl": "https://cal.com",
"profile": {
"slug": "username",
"name": "User Name"
},
"eventTypes": [
{
"id": 4716831,
"title": "30 min meeting",
"slug": "30min",
"length": 30,
"hidden": false
}
]
}
]
}
}
GET /cal-com/v2/event-types/{eventTypeId}
POST /cal-com/v2/event-types
Content-Type: application/json
{
"title": "Meeting",
"slug": "meeting",
"length": 30
}
Required fields:
title - Event type nameslug - URL slug (must be unique)length - Duration in minutesResponse:
{
"status": "success",
"data": {
"id": 4745911,
"title": "Meeting",
"slug": "meeting",
"length": 30,
"locations": [{"type": "integrations:daily"}],
"hidden": false,
"userId": 2152180
}
}
PATCH /cal-com/v2/event-types/{eventTypeId}
Content-Type: application/json
{
"title": "Updated Meeting Title",
"description": "Updated description"
}
DELETE /cal-com/v2/event-types/{eventTypeId}
GET /cal-com/v2/event-types/{eventTypeId}/webhooks
POST /cal-com/v2/event-types/{eventTypeId}/webhooks
Content-Type: application/json
{
"subscriberUrl": "https://example.com/webhook",
"triggers": ["BOOKING_CREATED"],
"active": true
}
Available triggers: BOOKING_CREATED, BOOKING_RESCHEDULED, BOOKING_CANCELLED, BOOKING_CONFIRMED, BOOKING_REJECTED, BOOKING_REQUESTED, BOOKING_PAYMENT_INITIATED, BOOKING_NO_SHOW_UPDATED, MEETING_ENDED, MEETING_STARTED, RECORDING_READY, INSTANT_MEETING, RECORDING_TRANSCRIPTION_GENERATED
GET /cal-com/v2/event-types/{eventTypeId}/webhooks/{webhookId}
PATCH /cal-com/v2/event-types/{eventTypeId}/webhooks/{webhookId}
Content-Type: application/json
{
"active": false
}
DELETE /cal-com/v2/event-types/{eventTypeId}/webhooks/{webhookId}
GET /cal-com/v2/bookings
With filters:
GET /cal-com/v2/bookings?status=upcoming
GET /cal-com/v2/bookings?status=past
GET /cal-com/v2/bookings?status=cancelled
GET /cal-com/v2/bookings?status=accepted
GET /cal-com/v2/bookings?take=10
Response:
{
"status": "success",
"data": {
"bookings": [
{
"id": 15893969,
"uid": "gZJNR7FQG2qLsBqnFdxAPE",
"title": "30 min meeting between User and Guest",
"startTime": "2026-02-13T17:00:00.000Z",
"endTime": "2026-02-13T17:30:00.000Z",
"status": "ACCEPTED"
}
],
"totalCount": 1,
"nextCursor": null
}
}
GET /cal-com/v2/bookings/{bookingUid}
POST /cal-com/v2/bookings
Content-Type: application/json
{
"eventTypeId": 4716831,
"start": "2026-02-13T17:00:00Z",
"timeZone": "America/New_York",
"language": "en",
"responses": {
"name": "Guest Name",
"email": "guest@example.com"
},
"metadata": {}
}
Required fields:
eventTypeId - ID of the event typestart - Start time in ISO 8601 format (must be an available slot)timeZone - Valid IANA timezonelanguage - Language code (e.g., "en")responses.name - Attendee nameresponses.email - Attendee emailResponse:
{
"status": "success",
"data": {
"id": 15893969,
"uid": "gZJNR7FQG2qLsBqnFdxAPE",
"title": "30 min meeting between User and Guest Name",
"startTime": "2026-02-13T17:00:00.000Z",
"endTime": "2026-02-13T17:30:00.000Z",
"status": "ACCEPTED",
"location": "integrations:daily"
}
}
POST /cal-com/v2/bookings/{bookingUid}/cancel
Content-Type: application/json
{
"cancellationReason": "Reason for cancellation"
}
GET /cal-com/v2/schedules/default
GET /cal-com/v2/schedules/{scheduleId}
POST /cal-com/v2/schedules
Content-Type: application/json
{
"name": "Work Hours",
"timeZone": "America/New_York",
"isDefault": false
}
Response:
{
"status": "success",
"data": {
"id": 1243030,
"name": "Work Hours",
"isManaged": false,
"workingHours": [
{
"days": [1, 2, 3, 4, 5],
"startTime": 540,
"endTime": 1020
}
]
}
}
PATCH /cal-com/v2/schedules/{scheduleId}
Content-Type: application/json
{
"name": "Updated Schedule Name"
}
DELETE /cal-com/v2/schedules/{scheduleId}
GET /cal-com/v2/slots/available?eventTypeId={eventTypeId}&startTime={startTime}&endTime={endTime}
Parameters:
eventTypeId - Required. The event type IDstartTime - Required. Start of range (ISO 8601)endTime - Required. End of range (ISO 8601)Response:
{
"status": "success",
"data": {
"slots": {
"2026-02-13": [
{"time": "2026-02-13T17:00:00.000Z"},
{"time": "2026-02-13T17:30:00.000Z"},
{"time": "2026-02-13T18:00:00.000Z"}
],
"2026-02-14": [
{"time": "2026-02-14T14:00:00.000Z"}
]
}
}
}
POST /cal-com/v2/slots/reserve
Content-Type: application/json
{
"eventTypeId": 4716831,
"slotUtcStartDate": "2026-02-20T14:00:00Z",
"slotUtcEndDate": "2026-02-20T14:30:00Z"
}
Response:
{
"status": "success",
"data": "968ed924-83fb-4da7-969e-eaa621643535"
}
GET /cal-com/v2/calendars
Response:
{
"status": "success",
"data": {
"connectedCalendars": [
{
"integration": {
"name": "Google Calendar",
"type": "google_calendar"
},
"calendars": [...]
}
]
}
}
GET /cal-com/v2/conferencing
Response:
{
"status": "success",
"data": [
{
"id": 1769268,
"type": "google_video",
"appId": "google-meet"
}
]
}
GET /cal-com/v2/conferencing/default
GET /cal-com/v2/webhooks
POST /cal-com/v2/webhooks
Content-Type: application/json
{
"subscriberUrl": "https://example.com/webhook",
"triggers": ["BOOKING_CREATED"],
"active": true
}
GET /cal-com/v2/webhooks/{webhookId}
PATCH /cal-com/v2/webhooks/{webhookId}
Content-Type: application/json
{
"active": false
}
DELETE /cal-com/v2/webhooks/{webhookId}
GET /cal-com/v2/teams
GET /cal-com/v2/verified-resources/emails
Bookings use cursor-based pagination with take and nextCursor:
GET /cal-com/v2/bookings?take=10
Response includes pagination info:
{
"data": {
"bookings": [...],
"totalCount": 25,
"nextCursor": "abc123"
}
}
For next page:
GET /cal-com/v2/bookings?take=10&cursor=abc123
const response = await fetch(
'https://api.maton.ai/cal-com/v2/event-types',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
import os
import requests
response = requests.get(
'https://api.maton.ai/cal-com/v2/event-types',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()
length field in event types is in minutes/v2/slots/available firstGET /v2/schedules endpoint may return 500 errors; use GET /v2/schedules/{id} insteadcurl -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 Cal.com connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 404 | Resource not found |
| 409 | Conflict (duplicate resource) |
| 429 | Rate limited |
| 500 | Cal.com API error |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python3 <<'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
cal-com. For example:https://api.maton.ai/cal-com/v2/mehttps://api.maton.ai/v2/meGET /cal-com/v2/slots/available?eventTypeId={id}&startTime=...&endTime=...
eventTypeIdstart (must match an available slot)timeZonelanguageresponses.nameresponses.email