feishu
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWe drive the Feishu Open Platform API
with . The user's OAuth is in
; every call sends it as . All endpoints live under .
curl + jquser_access_token$FEISHU_TOKENAuthorization: Bearer $FEISHU_TOKENhttps://open.feishu.cn/open-apisCalls run in the user's context (their docs, calendar, messages) — only
data the user can access and only the scopes they granted at connect time
(docs / sheets / base / drive / calendar / IM / wiki / task / contacts).
我们通过调用飞书开放平台API。用户的OAuth 存储在中;每次调用都会以的形式携带该令牌。所有接口端点均位于下。
curl + jquser_access_token$FEISHU_TOKENAuthorization: Bearer $FEISHU_TOKENhttps://open.feishu.cn/open-apis调用将在用户上下文中执行(访问用户的文档、日历、消息)——仅能访问用户有权限查看的数据,且仅使用用户在连接时授予的权限范围(文档/表格/多维表格/云盘/日历/即时通讯/知识库/任务/联系人)。
Response shape & error handling
响应格式与错误处理
Every Feishu response is .
means success; any non-zero is an error — surface
to the user. Always check it:
{"code": 0, "msg": "success", "data": {…}}code == 0codemsgsh
resp=$(curl -sS … )
echo "$resp" | jq 'if .code == 0 then .data else error("Feishu \(.code): \(.msg)") end'Common error codes:
| code | meaning | what to do |
|---|---|---|
| access token invalid / expired | tell the user to reconnect Feishu in 连接 settings |
| no permission (scope not granted) | the connect-time scope is missing — reconnect and grant it |
| resource not found / no access | the user can't see that doc / sheet / app — double-check the token/id |
飞书的每个响应格式均为。表示请求成功;任何非零均代表错误——需将内容展示给用户。请务必检查该字段:
{"code": 0, "msg": "success", "data": {…}}code == 0codemsgsh
resp=$(curl -sS … )
echo "$resp" | jq 'if .code == 0 then .data else error("Feishu \(.code): \(.msg)") end'常见错误码:
| 错误码 | 含义 | 处理方式 |
|---|---|---|
| 访问令牌无效/过期 | 告知用户在连接设置中重新连接飞书 |
| 无权限(未授予对应权限范围) | 缺少连接时的权限范围——重新连接并授予对应权限 |
| 资源未找到/无访问权限 | 用户无法查看该文档/表格/应用——请核实令牌或资源ID |
Recipes
操作示例
Verify auth (always run first)
验证授权(请始终先执行此步骤)
sh
curl -sS https://open.feishu.cn/open-apis/authen/v1/user_info \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then {name: .data.name, open_id: .data.open_id, email: .data.email} else . end'sh
curl -sS https://open.feishu.cn/open-apis/authen/v1/user_info \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then {name: .data.name, open_id: .data.open_id, email: .data.email} else . end'Docs (docx)
文档(docx)
A Feishu doc URL looks like . The
is the last path segment.
https://…feishu.cn/docx/<document_id>document_idRead a document's plain text:
sh
curl -sS "https://open.feishu.cn/open-apis/docx/v1/documents/DOCUMENT_ID/raw_content" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq -r 'if .code == 0 then .data.content else "ERR \(.code): \(.msg)" end'List a document's blocks (structured content):
sh
curl -sS "https://open.feishu.cn/open-apis/docx/v1/documents/DOCUMENT_ID/blocks?page_size=500" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {block_id, block_type}] else . end'Create a new empty document (optionally inside a folder):
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/docx/v1/documents" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg title "会议纪要 2026-07-01" '{title: $title}')" \
| jq 'if .code == 0 then {document_id: .data.document.document_id} else . end'Append a text block to a document (insert at the end of the document body —
is also the root block id):
DOCUMENT_IDsh
curl -sS -X POST "https://open.feishu.cn/open-apis/docx/v1/documents/DOCUMENT_ID/blocks/DOCUMENT_ID/children" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg text "由助手追加的一段内容。" '
{children: [{block_type: 2, text: {elements: [{text_run: {content: $text}}]}}]}')" \
| jq 'if .code == 0 then "appended" else . end'飞书文档的URL格式为。是URL路径的最后一段。
https://…feishu.cn/docx/<document_id>document_id读取文档纯文本内容:
sh
curl -sS "https://open.feishu.cn/open-apis/docx/v1/documents/DOCUMENT_ID/raw_content" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq -r 'if .code == 0 then .data.content else "ERR \(.code): \(.msg)" end'列出文档的结构化内容块:
sh
curl -sS "https://open.feishu.cn/open-apis/docx/v1/documents/DOCUMENT_ID/blocks?page_size=500" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {block_id, block_type}] else . end'创建新的空白文档(可选择创建在指定文件夹内):
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/docx/v1/documents" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg title "会议纪要 2026-07-01" '{title: $title}')" \
| jq 'if .code == 0 then {document_id: .data.document.document_id} else . end'向文档追加文本块(插入到文档正文末尾——同时也是根内容块ID):
DOCUMENT_IDsh
curl -sS -X POST "https://open.feishu.cn/open-apis/docx/v1/documents/DOCUMENT_ID/blocks/DOCUMENT_ID/children" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg text "由助手追加的一段内容。" '
{children: [{block_type: 2, text: {elements: [{text_run: {content: $text}}]}}]}')" \
| jq 'if .code == 0 then "appended" else . end'Spreadsheets (sheets v2)
电子表格(sheets v2)
A sheet URL looks like .
A range is , e.g. . List sheet ids via
the metainfo endpoint first if you don't have one.
https://…feishu.cn/sheets/<spreadsheet_token><sheetId>!<A1:range>abc123!A1:D10Read a range:
sh
curl -sS "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/SPREADSHEET_TOKEN/values/RANGE" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then .data.valueRange.values else . end'Append rows after the last non-empty row:
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/SPREADSHEET_TOKEN/values_append" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{valueRange: {range: "SHEET_ID!A1:B1", values: [["张三", 100], ["李四", 200]]}}')" \
| jq 'if .code == 0 then .data.updates else . end'飞书表格的URL格式为。数据范围格式为,例如。若未获取sheetId,可先通过元信息接口列出所有sheetId。
https://…feishu.cn/sheets/<spreadsheet_token><sheetId>!<A1:range>abc123!A1:D10读取指定范围的数据:
sh
curl -sS "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/SPREADSHEET_TOKEN/values/RANGE" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then .data.valueRange.values else . end'在最后一行非空行后追加数据行:
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/SPREADSHEET_TOKEN/values_append" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{valueRange: {range: "SHEET_ID!A1:B1", values: [["张三", 100], ["李四", 200]]}}')" \
| jq 'if .code == 0 then .data.updates else . end'Base / 多维表格 (bitable v1)
多维表格(Base / bitable v1)
A Base URL looks like . Get
from .
https://…feishu.cn/base/<app_token>table_id…/bitable/v1/apps/APP_TOKEN/tablesList records:
sh
curl -sS "https://open.feishu.cn/open-apis/bitable/v1/apps/APP_TOKEN/tables/TABLE_ID/records?page_size=100" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {record_id, fields}] else . end'Create a record:
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/bitable/v1/apps/APP_TOKEN/tables/TABLE_ID/records" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{fields: {"标题": "新任务", "状态": "待办"}}')" \
| jq 'if .code == 0 then {record_id: .data.record.record_id} else . end'飞书多维表格的URL格式为。可通过接口获取。
https://…feishu.cn/base/<app_token>…/bitable/v1/apps/APP_TOKEN/tablestable_id列出表格记录:
sh
curl -sS "https://open.feishu.cn/open-apis/bitable/v1/apps/APP_TOKEN/tables/TABLE_ID/records?page_size=100" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {record_id, fields}] else . end'创建新记录:
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/bitable/v1/apps/APP_TOKEN/tables/TABLE_ID/records" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{fields: {"标题": "新任务", "状态": "待办"}}')" \
| jq 'if .code == 0 then {record_id: .data.record.record_id} else . end'Drive files
云盘文件
List files in a folder (omit for the root):
folder_tokensh
curl -sS "https://open.feishu.cn/open-apis/drive/v1/files?folder_token=FOLDER_TOKEN&page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.files[] | {name, type, token, url}] else . end'列出指定文件夹内的文件(省略则列出根目录文件):
folder_tokensh
curl -sS "https://open.feishu.cn/open-apis/drive/v1/files?folder_token=FOLDER_TOKEN&page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.files[] | {name, type, token, url}] else . end'Calendar (v4)
日历(v4)
List the user's calendars (the primary one has ):
type: "primary"sh
curl -sS "https://open.feishu.cn/open-apis/calendar/v4/calendars?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.calendar_list[] | {calendar_id, summary, type}] else . end'List events in a time window (epoch-seconds strings):
sh
curl -sS "https://open.feishu.cn/open-apis/calendar/v4/calendars/CALENDAR_ID/events?start_time=1751299200&end_time=1751385600&page_size=100" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {summary, start: .start_time, end: .end_time, event_id}] else . end'Create an event (times are epoch-seconds strings):
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/calendar/v4/calendars/CALENDAR_ID/events" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{summary: "项目评审", start_time: {timestamp: "1751302800"}, end_time: {timestamp: "1751306400"}}')" \
| jq 'if .code == 0 then {event_id: .data.event.event_id} else . end'列出用户的日历(主日历的为):
type"primary"sh
curl -sS "https://open.feishu.cn/open-apis/calendar/v4/calendars?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.calendar_list[] | {calendar_id, summary, type}] else . end'列出指定时间范围内的日历事件(时间戳为秒级时间戳字符串):
sh
curl -sS "https://open.feishu.cn/open-apis/calendar/v4/calendars/CALENDAR_ID/events?start_time=1751299200&end_time=1751385600&page_size=100" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {summary, start: .start_time, end: .end_time, event_id}] else . end'创建日历事件(时间戳为秒级时间戳字符串):
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/calendar/v4/calendars/CALENDAR_ID/events" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{summary: "项目评审", start_time: {timestamp: "1751302800"}, end_time: {timestamp: "1751306400"}}')" \
| jq 'if .code == 0 then {event_id: .data.event.event_id} else . end'Tasks (v2)
任务(v2)
List the user's tasks:
sh
curl -sS "https://open.feishu.cn/open-apis/task/v2/tasks?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {summary, completed_at, task_guid: .guid}] else . end'Create a task:
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/task/v2/tasks" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{summary: "准备周会材料"}')" \
| jq 'if .code == 0 then {task_guid: .data.task.guid} else . end'列出用户的任务:
sh
curl -sS "https://open.feishu.cn/open-apis/task/v2/tasks?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {summary, completed_at, task_guid: .guid}] else . end'创建新任务:
sh
curl -sS -X POST "https://open.feishu.cn/open-apis/task/v2/tasks" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{summary: "准备周会材料"}')" \
| jq 'if .code == 0 then {task_guid: .data.task.guid} else . end'Wiki
知识库
List wiki spaces, then nodes within a space:
sh
curl -sS "https://open.feishu.cn/open-apis/wiki/v2/spaces?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {space_id, name}] else . end'
curl -sS "https://open.feishu.cn/open-apis/wiki/v2/spaces/SPACE_ID/nodes?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {title, node_token, obj_type}] else . end'先列出知识库空间,再列出指定空间内的节点:
sh
curl -sS "https://open.feishu.cn/open-apis/wiki/v2/spaces?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {space_id, name}] else . end'
curl -sS "https://open.feishu.cn/open-apis/wiki/v2/spaces/SPACE_ID/nodes?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {title, node_token, obj_type}] else . end'Send an IM message
发送即时消息
Send to a user by (use for a group
chat). must be a JSON string, so it's double-encoded:
open_idreceive_id_type=chat_idcontentsh
curl -sS -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg rid "ou_xxx" --arg text "你好,这是助手发送的消息。" '
{receive_id: $rid, msg_type: "text", content: ({text: $text} | tostring)}')" \
| jq 'if .code == 0 then {message_id: .data.message_id} else . end'通过向用户发送消息(若发送到群组,需将设为)。必须为JSON字符串,因此需要进行双重编码:
open_idreceive_id_typechat_idcontentsh
curl -sS -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg rid "ou_xxx" --arg text "你好,这是助手发送的消息。" '
{receive_id: $rid, msg_type: "text", content: ({text: $text} | tostring)}')" \
| jq 'if .code == 0 then {message_id: .data.message_id} else . end'Notes
注意事项
- Confirm destructive or outward-facing actions (sending a message, creating a calendar invite, posting to a shared doc) with the user before running them.
- Pagination: list endpoints return /
data.page_token; passdata.has_moreto fetch the next page.page_token=… - When the user pastes a Feishu link, extract the token/id from the URL path rather than asking them for it.
- 在执行具有破坏性或对外操作(发送消息、创建日历邀请、向共享文档写入内容)前,请先与用户确认。
- 分页处理:列表类接口会返回/
data.page_token;传递data.has_more参数可获取下一页数据。page_token=… - 当用户粘贴飞书链接时,请从URL路径中提取令牌/ID,而非向用户索要。