Install
openclaw skills install @gaolfun/calcom-integrationIntegrate with Cal.com to list event types, create/cancel bookings, get available slots, manage availability, and retrieve user info via the REST API.
openclaw skills install @gaolfun/calcom-integrationThis skill enables the following operations against the Cal.com REST API (v2):
All API calls target https://api.cal.com/v1. Authentication uses a Bearer token (API key).
Before using this skill, you must have:
johnsmith or 123456)Store these in your OpenClaw environment or skill config:
CAL_COM_API_KEY=your_calcom_api_key_here
CAL_COM_USERNAME=your_calcom_username_here
Endpoint: GET /event-types
Headers:
Authorization: Bearer {CAL_COM_API_KEY}
Content-Type: application/json
Example cURL:
curl -s "https://api.cal.com/v1/event-types" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}"
Example Response (success):
{
"event_types": [
{
"id": "evt_abc123",
"slug": "30-min-meeting",
"title": "30 Minute Meeting",
"duration": 30,
"description": "A quick 30-minute call",
"active": true
},
{
"id": "evt_def456",
"slug": "60-min-consultation",
"title": "60 Minute Consultation",
"duration": 60,
"description": "Deep dive session",
"active": true
}
]
}
Failure Response:
{
"error": "unauthorized",
"message": "Invalid or expired API key."
}
Endpoint: POST /bookings
Headers:
Authorization: Bearer {CAL_COM_API_KEY}
Content-Type: application/json
Request Body:
{
"eventTypeId": "evt_abc123",
"startTime": "2026-07-10T14:00:00Z",
"endTime": "2026-07-10T14:30:00Z",
"attendee": {
"name": "Jane Doe",
"email": "jane.doe@example.com",
"timezone": "Asia/Shanghai"
},
"notes": "Looking forward to the call"
}
Example cURL:
curl -s -X POST "https://api.cal.com/v1/bookings" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"eventTypeId": "evt_abc123",
"startTime": "2026-07-10T14:00:00Z",
"endTime": "2026-07-10T14:30:00Z",
"attendee": {
"name": "Jane Doe",
"email": "jane.doe@example.com",
"timezone": "Asia/Shanghai"
}
}'
Example Response (success):
{
"booking": {
"id": "bk_xyz789",
"uid": "bk_xyz789",
"eventTypeId": "evt_abc123",
"title": "30 Minute Meeting",
"startTime": "2026-07-10T14:00:00Z",
"endTime": "2026-07-10T14:30:00Z",
"status": "accepted",
"attendees": [
{
"name": "Jane Doe",
"email": "jane.doe@example.com"
}
]
}
}
Failure Response:
{
"error": "booking_conflict",
"message": "The requested time slot is no longer available."
}
Endpoint: DELETE /bookings/{uid}
Headers:
Authorization: Bearer {CAL_COM_API_KEY}
Example cURL:
curl -s -X DELETE "https://api.cal.com/v1/bookings/bk_xyz789" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}"
Example Response (success):
{
"booking": {
"id": "bk_xyz789",
"status": "cancelled"
},
"message": "Booking cancelled successfully."
}
Failure Response:
{
"error": "not_found",
"message": "Booking with UID bk_xyz789 not found."
}
Endpoint: GET /bookings
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status: upcoming, past, cancelled |
limit | integer | Max results (default: 20, max: 100) |
cursor | string | Pagination cursor |
Example cURL:
curl -s "https://api.cal.com/v1/bookings?status=upcoming&limit=10" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}"
Example Response (success):
{
"bookings": [
{
"id": "bk_xyz789",
"uid": "bk_xyz789",
"title": "30 Minute Meeting",
"startTime": "2026-07-10T14:00:00Z",
"endTime": "2026-07-10T14:30:00Z",
"status": "accepted",
"eventType": {
"slug": "30-min-meeting",
"title": "30 Minute Meeting"
},
"attendees": [
{
"name": "Jane Doe",
"email": "jane.doe@example.com"
}
]
}
],
"nextPageCursor": null
}
Endpoint: GET /slots
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
eventTypeId | string | The event type ID to check |
startTime | ISO 8601 | Range start (e.g., 2026-07-10T00:00:00Z) |
endTime | ISO 8601 | Range end (e.g., 2026-07-15T23:59:59Z) |
Example cURL:
curl -s "https://api.cal.com/v1/slots?eventTypeId=evt_abc123&startTime=2026-07-10T00:00:00Z&endTime=2026-07-15T23:59:59Z" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}"
Example Response (success):
{
"slots": [
{
"startTime": "2026-07-10T09:00:00Z",
"endTime": "2026-07-10T09:30:00Z",
"available": true
},
{
"startTime": "2026-07-10T10:00:00Z",
"endTime": "2026-07-10T10:30:00Z",
"available": true
},
{
"startTime": "2026-07-10T10:30:00Z",
"endTime": "2026-07-10T11:00:00Z",
"available": false
}
]
}
Endpoint: POST /schedules (create) or PATCH /schedules/{id} (update)
Headers:
Authorization: Bearer {CAL_COM_API_KEY}
Content-Type: application/json
Request Body (create):
{
"name": "My Working Hours",
"timezone": "Asia/Shanghai",
"weeklyAvailability": [
{
"day": "Monday",
"startTime": "09:00",
"endTime": "18:00"
},
{
"day": "Tuesday",
"startTime": "09:00",
"endTime": "18:00"
},
{
"day": "Wednesday",
"startTime": "09:00",
"endTime": "18:00"
},
{
"day": "Thursday",
"startTime": "09:00",
"endTime": "18:00"
},
{
"day": "Friday",
"startTime": "09:00",
"endTime": "17:00"
}
],
"dateOverrides": [
{
"date": "2026-07-04",
"startTime": "10:00",
"endTime": "14:00"
}
]
}
Example cURL:
curl -s -X POST "https://api.cal.com/v1/schedules" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "My Working Hours",
"timezone": "Asia/Shanghai",
"weeklyAvailability": [
{"day": "Monday", "startTime": "09:00", "endTime": "18:00"},
{"day": "Tuesday", "startTime": "09:00", "endTime": "18:00"},
{"day": "Wednesday", "startTime": "09:00", "endTime": "18:00"},
{"day": "Thursday", "startTime": "09:00", "endTime": "18:00"},
{"day": "Friday", "startTime": "09:00", "endTime": "17:00"}
]
}'
Example Response (success):
{
"schedule": {
"id": "sc_abc123",
"name": "My Working Hours",
"timezone": "Asia/Shanghai",
"weeklyAvailability": [
{"day": "Monday", "startTime": "09:00", "endTime": "18:00"}
],
"dateOverrides": []
}
}
Endpoint: GET /users/me
Example cURL:
curl -s "https://api.cal.com/v1/users/me" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}"
Example Response (success):
{
"user": {
"id": "123456",
"username": "johnsmith",
"email": "john.smith@example.com",
"timezone": "Asia/Shanghai",
"weekStart": "Monday",
"defaultEventDuration": 30,
"locale": "en"
}
}
Always returns a structured JSON block with a status field set to "success":
{
"status": "success",
"action": "list_event_types",
"data": { ... }
}
Always returns a structured JSON block with a status field set to "error":
{
"status": "error",
"action": "create_booking",
"error": "booking_conflict",
"message": "The requested time slot is no longer available."
}
User: "What event types do I have set up on Cal.com?"
Agent: I'll list your Cal.com event types now.
curl -s "https://api.cal.com/v1/event-types" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}"
Parsed Response:
{
"status": "success",
"action": "list_event_types",
"data": {
"event_types": [
{"id": "evt_abc123", "slug": "30-min-meeting", "title": "30 Minute Meeting", "duration": 30},
{"id": "evt_def456", "slug": "60-min-consultation", "title": "60 Minute Consultation", "duration": 60},
{"id": "evt_ghi789", "slug": "15-min-intro", "title": "15 Minute Intro Call", "duration": 15}
]
}
}
Summary for User: You have 3 active event types on Cal.com:
| Title | Duration | Slug |
|---|---|---|
| 15 Minute Intro Call | 15 min | 15-min-intro |
| 30 Minute Meeting | 30 min | 30-min-meeting |
| 60 Minute Consultation | 60 min | 60-min-consultation |
User: "Book a 30-minute meeting with Jane Doe at jane.doe@example.com for July 10th at 2 PM Shanghai time."
Agent: Creating a booking for July 10, 2026 at 14:00 Shanghai time (UTC+8).
curl -s -X POST "https://api.cal.com/v1/bookings" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"eventTypeId": "evt_abc123",
"startTime": "2026-07-10T06:00:00Z",
"endTime": "2026-07-10T06:30:00Z",
"attendee": {
"name": "Jane Doe",
"email": "jane.doe@example.com",
"timezone": "Asia/Shanghai"
}
}'
Parsed Response:
{
"status": "success",
"action": "create_booking",
"data": {
"booking": {
"id": "bk_xyz789",
"title": "30 Minute Meeting",
"startTime": "2026-07-10T06:00:00Z",
"endTime": "2026-07-10T06:30:00Z",
"status": "accepted",
"attendees": [{"name": "Jane Doe", "email": "jane.doe@example.com"}]
}
}
}
Summary for User: ✅ Booking confirmed!
bk_xyz789User: "What slots are available next week for the 60-minute consultation?"
Agent: Checking available slots for your 60-minute consultation from July 13–17, 2026.
curl -s "https://api.cal.com/v1/slots?eventTypeId=evt_def456&startTime=2026-07-13T00:00:00Z&endTime=2026-07-17T23:59:59Z" \
-H "Authorization: Bearer ${CAL_COM_API_KEY}"
Parsed Response:
{
"status": "success",
"action": "get_available_slots",
"data": {
"slots": [
{"startTime": "2026-07-13T02:00:00Z", "endTime": "2026-07-13T03:00:00Z", "available": true},
{"startTime": "2026-07-13T03:00:00Z", "endTime": "2026-07-13T04:00:00Z", "available": true},
{"startTime": "2026-07-14T02:00:00Z", "endTime": "2026-07-14T03:00:00Z", "available": true},
{"startTime": "2026-07-14T04:00:00Z", "endTime": "2026-07-14T05:00:00Z", "available": false},
{"startTime": "2026-07-15T02:00:00Z", "endTime": "2026-07-15T03:00:00Z", "available": true}
]
}
}
Summary for User: Available 60-minute slots next week (Shanghai timezone):
(UTC times shown; subtract 8 hours for Shanghai local time.)
OpenClaw Integration).bookings:read, bookings:write, event-types:read, schedules:read, schedules:write.cal.com/{username}.Set the following environment variables or OpenClaw config entries:
CAL_COM_API_KEY=cal_v2_your_generated_key_here
CAL_COM_USERNAME=your_username_here
Test your setup by asking:
"Get my Cal.com user info"
If successful, you'll see your profile returned. If you get an unauthorized error, double-check that your API key is valid and has not expired.
429 Too Many Requests responses.Retry-After header for the exact wait time.2026-07-10T14:00:00+08:00) or pure UTC (Z)./users/me).evt_abc123) in API calls, not slugs, for reliability.404 errors./event-types list before creating a booking.status: "cancelled" but are not deleted from the system.status before attempting cancellation to avoid a not_found error.PATCH /schedules/{id} endpoint performs a full replace, not a merge.timezone) in an update will reset them to Cal.com defaults.https://api.cal.com/v1
https://your-calcom-instance.com/api/v1
/api/v2/docs.| Version | Date | Change |
|---|---|---|
| 1.0.0 | 2026-07-04 | Initial ClawHub release |
Skill ID: cal-com | Compatible with Cal.com API v2