Manage events through the Calendar API.
Base URL: https://open.feishu.cn/open-apis/calendar/v4
Authentication and Token Acquisition
From feishu_skills root directory, execute the shared script:
TOKEN="$(./scripts/get_feishu_token.sh)"
Request headers uniformly use Authorization: Bearer ${TOKEN}。
If a business API returns token invalid, expired, or 401, force refresh and then retry the original request only once:
TOKEN="$(./scripts/get_feishu_token.sh --force-refresh)"
Environment Variables:
FEISHU_APP_IDFEISHU_APP_SECRET
Local Cache: ./.feishu_token_cache.json(reuse directly if not expired, refresh 5 minutes in advance by default)
Event Operations
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Create Event | /calendars/{calendar_id}/events |
POST | {"summary":"会议标题","start_time":{"timestamp":"1770508800"},"end_time":{"timestamp":"1770512400"}} |
Create a new event |
| Get Event | /calendars/{calendar_id}/events/{event_id} |
GET | - | Query event details |
| Update Event | /calendars/{calendar_id}/events/{event_id} |
PATCH | {"summary":"新标题"} |
Modify event |
| Delete Event | /calendars/{calendar_id}/events/{event_id} |
DELETE | - | Delete event |
| Search Events | /calendars/{calendar_id}/events/search |
POST | {"query":"关键词","start_time":{"timestamp":"1770508800"}} |
Conditional search |
| Get Event List | /calendars/{calendar_id}/events |
GET | - | Query all events under a calendar |
Create Event:
{
"summary": "会议标题",
"start_time": {"timestamp": "1770508800"},
"end_time": {"timestamp": "1770512400"},
"attendees": [{"type": "user", "attendee_id": "ou_xxx"}]
}
attendees type: user / chat / resource(Meeting Room)
Event Attendees
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Get Attendees | /calendars/{calendar_id}/events/{event_id}/attendees |
GET | - | Query attendee list |
| Add Attendees | /calendars/{calendar_id}/events/{event_id}/attendees |
POST | {"attendees":[{"type":"user","attendee_id":"ou_xxx"}]} |
Invite attendees |
| Delete Attendees | /calendars/{calendar_id}/events/{event_id}/attendees/{attendee_id} |
DELETE | - | Remove attendees |
| Get Participating Group Members | /calendars/{calendar_id}/events/{event_id}/attendees/chat_members |
GET | - | Query group participating members |
Calendar Management
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Get Calendar List | /calendars |
GET | Query parameters:page_size=50&page_token=xxx |
Query all calendars (paginated) |
| Get Primary Calendar | /calendars/primary |
GET | - | Query the user's primary calendar |
| Create Calendar | /calendars |
POST | {"summary":"日历名称","description":"描述","permissions":"public"} |
Create a shared calendar |
| Get Calendar | /calendars/{calendar_id} |
GET | - | Query calendar details |
| Update Calendar | /calendars/{calendar_id} |
PATCH | {"summary":"新名称"} |
Modify calendar |
| Delete Calendar | /calendars/{calendar_id} |
DELETE | - | Delete calendar |
| Search Calendars | /calendars/search |
POST | {"query":"关键词"} |
Search calendars |
Calendar Subscriptions and ACL
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Get ACL List | /calendars/{calendar_id}/acls |
GET | - | Query calendar permissions |
| Create ACL | /calendars/{calendar_id}/acls |
POST | {"role":"reader","scope":{"type":"user","user_id":"ou_xxx"}} |
Add permission |
| Delete ACL | /calendars/{calendar_id}/acls/{acl_id} |
DELETE | - | Remove permission |
| Subscribe to Calendar | /calendars/{calendar_id}/subscribe |
POST | - | Subscribe to calendar changes |
| Unsubscribe | /calendars/{calendar_id}/unsubscribe |
POST | - | Cancel calendar subscription |
| Subscribe to Event | /calendars/{calendar_id}/events/subscribe |
POST | - | Subscribe to event changes |
| Unsubscribe from Event | /calendars/{calendar_id}/events/unsubscribe |
POST | - | Cancel event subscription |
ACL role: none / free_busy_reader / reader / writer / owner
Meeting Room Management
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Get Meeting Room List | /rooms |
GET | - | Query all meeting rooms |
| Get Meeting Room | /rooms/{room_id} |
GET | - | Query meeting room details |
| Query meeting room availability | /rooms/{room_id}/freebusy |
GET | - | Query meeting room available time |
Create a schedule and occupy a meeting room
Key to occupying a meeting room: in attendees add type: "resource" attendees,attendee_id fill in the meeting room's room_id。
Complete process:
# 1. 获取会议室列表,拿到 room_id
curl -X GET "https://open.feishu.cn/open-apis/calendar/v4/rooms?page_size=50" \
-H "Authorization: Bearer YOUR_TOKEN"
# 2. (可选)查询会议室在目标时间段是否空闲
curl -X GET "https://open.feishu.cn/open-apis/calendar/v4/rooms/{room_id}/freebusy?start_time=1770508800&end_time=1770512400" \
-H "Authorization: Bearer YOUR_TOKEN"
# 3. 创建日程,attendees 中加入会议室
curl -X POST "https://open.feishu.cn/open-apis/calendar/v4/calendars/primary/events" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"summary": "团队会议",
"start_time": {"timestamp": "1770508800"},
"end_time": {"timestamp": "1770512400"},
"attendees": [
{"type": "user", "attendee_id": "ou_xxx"},
{"type": "resource", "attendee_id": "omcxxxxxxxxxxxxx"}
]
}'
⚠️ If the meeting room is already occupied during that time period, the creation request will return a conflict error. Please query availability before booking.
Common parameter description
Time format:
timestamp: second-level timestamp (e.g."1770508800")date: date string (e.g."2026-03-07")
Pagination parameters:
page_size: number per page (default 50, maximum 500)page_token: pagination token (obtained from the previous response)
user_id_type: user ID type
open_id(default)user_idunion_id
Test example
Get calendar list:
curl -X GET "https://open.feishu.cn/open-apis/calendar/v4/calendars?page_size=10" \
-H "Authorization: Bearer ${TOKEN}"
Create schedule:
curl -X POST "https://open.feishu.cn/open-apis/calendar/v4/calendars/primary/events" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"summary": "团队会议",
"start_time": {"timestamp": "1709798400"},
"end_time": {"timestamp": "1709802000"}
}'
Best practices
- Use second-level timestamps for time
- Specify type in attendees(user/chat/resource)
- Pagination query: for large amounts of data, use page_token for pagination
- Primary calendar: for a user's personal calendar, use
primaryas calendar_id