飞书调用手册

获取应用令牌并发送消息

从自建应用鉴权开始,向应用可用范围内的一位成员发送文本。

官方资料核对 2026-10-15示例代码,未进行真实接口实测
← 返回平台功能

接入准备

  • 自建应用启用机器人能力,开通 im:message:send_as_bot,并发布/启用版本。
  • 目标成员在应用可用范围内;open_id 必须属于当前应用。

准备环境变量

示例值需要替换为自己的凭证或资源 ID。代码在本机或服务端运行;密钥不应放进公开网页。

FEISHU_ACCESS_TOKEN
先运行应用消息场景的获取凭证操作,将响应 access_token 放入服务端环境变量;不是 App Secret。
终端
export FEISHU_ACCESS_TOKEN='replace_with_tenant_access_token'

以上 export 适用于 macOS / Linux 的终端,在同一终端内运行后续代码。Python 示例保存为 request.py 后执行 python3 request.py。

调用步骤

  1. 01

    开发者后台 → 凭证与基础信息取得 App ID 和 Secret,替换第一步请求体。

  2. 02

    获取令牌后,将响应 access_token 保存为 FEISHU_ACCESS_TOKEN。

  3. 03

    从 API 调试台的成员选择器、消息事件或获授权的通讯录接口取得用户 open_id,替换 receive_id。

  4. 04

    运行发送消息操作;如果改发群消息,将 receive_id_type 改为 chat_id,receive_id 改成群 ID,并先把应用机器人加入该群。

调用 01

获取自建应用令牌

当前 OAuth 端点支持 JSON,本例选 client_secret_post。先替换 body 中两个假凭证;不可同时添加 Basic 认证。

POSThttps://accounts.feishu.cn/oauth/v3/token

请求头

Content-Type
application/json

参数说明

参数表可左右滑动,查看完整说明。

字段 / 位置类型 / 必填说明
grant_type请求体string必填固定 client_credentials。
client_id请求体string必填本例认证方式必填,开发者后台 → 凭证与基础信息中的 App ID。
client_secret请求体string必填本例认证方式必填,同页 App Secret,仅在服务端保存。
scope请求体string可选可传空格分隔、已开通的应用身份权限;省略时按租户已开通权限签发。

调用代码

替换示例 ID 与请求体内容后运行。cURL 会报 HTTP 错误,业务状态还需按下方返回示例核对。

cURL
cat > request-body.json <<'JSON'
{
  "grant_type": "client_credentials",
  "client_id": "cli_replace_with_app_id",
  "client_secret": "replace_with_app_secret"
}
JSON

# 执行后核对返回 JSON 的业务状态;HTTP 200 仍可能包含业务错误。
curl --silent --show-error --fail-with-body \
  --request POST \
  --url "https://accounts.feishu.cn/oauth/v3/token" \
  --header "Content-Type: application/json" \
  --data-binary @request-body.json
Python 3
import json
import os
import re
import urllib.request
import urllib.error

def expand(value):
    return re.sub(r"\$\{([A-Z][A-Z0-9_]*)\}",
                  lambda match: os.environ[match.group(1)], value)

url = expand("https://accounts.feishu.cn/oauth/v3/token")
headers = {
    "Content-Type": expand("application/json"),
}
body = {
    "grant_type": "client_credentials",
    "client_id": "cli_replace_with_app_id",
    "client_secret": "replace_with_app_secret",
}
data = json.dumps(body, ensure_ascii=False).encode("utf-8")
request = urllib.request.Request(url, data=data, headers=headers, method="POST")
try:
    with urllib.request.urlopen(request, timeout=30) as response:
        result = json.load(response)
except urllib.error.HTTPError as error:
    print(f"HTTP {error.code}: {error.read().decode('utf-8', errors='replace')}")
    raise SystemExit(1)
print(json.dumps(result, ensure_ascii=False, indent=2))
if isinstance(result, dict) and "code" in result and result["code"] != 0:
    raise SystemExit("平台返回业务错误,请结合下方排错说明检查响应")
Node.js
// Node.js 22+,保存为 request.mjs 后运行 node request.mjs
function expand(value) {
  return value.replace(/\$\{([A-Z][A-Z0-9_]*)\}/g, (_, name) => {
    if (!process.env[name]) throw new Error(`缺少环境变量 ${name}`);
    return process.env[name];
  });
}

const url = expand("https://accounts.feishu.cn/oauth/v3/token");
const headers = Object.fromEntries(
  Object.entries({
  "Content-Type": "application/json"
}).map(([key, value]) => [key, expand(value)])
);
const body = {
  "grant_type": "client_credentials",
  "client_id": "cli_replace_with_app_id",
  "client_secret": "replace_with_app_secret"
};
const response = await fetch(url, {
  method: "POST",
  headers,
  body: JSON.stringify(body),
  signal: AbortSignal.timeout(30000),
});
const text = await response.text();
if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);
const result = JSON.parse(text);
console.log(JSON.stringify(result, null, 2));
if (Object.hasOwn(result, "code") && result["code"] !== 0) {
  throw new Error('平台返回业务错误,请结合下方排错说明检查响应');
}

返回示例

按官方字段整理的节选示意,使用虚构 ID,不是实测结果。保存 access_token,并以 expires_in 安排续期。 以下为结构示意,非本站实测结果。

JSON
{
  "code": 0,
  "access_token": "replace_with_returned_jwt",
  "expires_in": 7200,
  "token_type": "Bearer",
  "scope": "im:message:send_as_bot"
}

常见错误与排查

20002应用密钥不正确
确认 App ID、App Secret 属于同一个已启用自建应用。
20068申请了不允许的 scope
先完成权限开通和发布;只传支持应用身份的 scope。

调用注意

  • 有效期以 expires_in 为准,最长 2 小时;缓存复用,不要每个业务请求都取令牌。
  • 新版返回 access_token,不是历史版本的 tenant_access_token;JWT 存储预留至少 4 KB。
调用 02

发送应用文本消息

content 是 JSON 字符串,与 Webhook 的 content 对象不同。

POSThttps://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id

请求头

Authorization
Bearer ${FEISHU_ACCESS_TOKEN}
Content-Type
application/json; charset=utf-8

参数说明

参数表可左右滑动,查看完整说明。

字段 / 位置类型 / 必填说明
receive_id_typeQuerystring必填接收者类型;本例 open_id。还支持 chat_id、user_id、union_id、email;使用 user_id 另需相应字段权限。
receive_id请求体string必填与 receive_id_type 对应的 ID,替换为当前应用下的真实 open_id。
msg_type请求体string必填本例 text;图片/文件需先上传获取消息资源 key。
content请求体string必填将消息内容对象序列化成字符串,本例为包含 text 的 JSON 字符串。
uuid请求体string可选最长 50 字符;同一值在 1 小时内至多发送成功一次。相同业务重试可复用,新消息必须换值。

调用代码

替换示例 ID 与请求体内容后运行。cURL 会报 HTTP 错误,业务状态还需按下方返回示例核对。

cURL
cat > request-body.json <<'JSON'
{
  "receive_id": "ou_replace_with_user_open_id",
  "msg_type": "text",
  "content": "{\"text\":\"接入测试:应用消息已送出\"}"
}
JSON

# 执行后核对返回 JSON 的业务状态;HTTP 200 仍可能包含业务错误。
curl --silent --show-error --fail-with-body \
  --request POST \
  --url "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
  --header "Authorization: Bearer ${FEISHU_ACCESS_TOKEN}" \
  --header "Content-Type: application/json; charset=utf-8" \
  --data-binary @request-body.json
Python 3
import json
import os
import re
import urllib.request
import urllib.error

def expand(value):
    return re.sub(r"\$\{([A-Z][A-Z0-9_]*)\}",
                  lambda match: os.environ[match.group(1)], value)

url = expand("https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id")
headers = {
    "Authorization": expand("Bearer ${FEISHU_ACCESS_TOKEN}"),
    "Content-Type": expand("application/json; charset=utf-8"),
}
body = {
    "receive_id": "ou_replace_with_user_open_id",
    "msg_type": "text",
    "content": "{\"text\":\"接入测试:应用消息已送出\"}",
}
data = json.dumps(body, ensure_ascii=False).encode("utf-8")
request = urllib.request.Request(url, data=data, headers=headers, method="POST")
try:
    with urllib.request.urlopen(request, timeout=30) as response:
        result = json.load(response)
except urllib.error.HTTPError as error:
    print(f"HTTP {error.code}: {error.read().decode('utf-8', errors='replace')}")
    raise SystemExit(1)
print(json.dumps(result, ensure_ascii=False, indent=2))
if isinstance(result, dict) and "code" in result and result["code"] != 0:
    raise SystemExit("平台返回业务错误,请结合下方排错说明检查响应")
Node.js
// Node.js 22+,保存为 request.mjs 后运行 node request.mjs
function expand(value) {
  return value.replace(/\$\{([A-Z][A-Z0-9_]*)\}/g, (_, name) => {
    if (!process.env[name]) throw new Error(`缺少环境变量 ${name}`);
    return process.env[name];
  });
}

const url = expand("https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id");
const headers = Object.fromEntries(
  Object.entries({
  "Authorization": "Bearer ${FEISHU_ACCESS_TOKEN}",
  "Content-Type": "application/json; charset=utf-8"
}).map(([key, value]) => [key, expand(value)])
);
const body = {
  "receive_id": "ou_replace_with_user_open_id",
  "msg_type": "text",
  "content": "{\"text\":\"接入测试:应用消息已送出\"}"
};
const response = await fetch(url, {
  method: "POST",
  headers,
  body: JSON.stringify(body),
  signal: AbortSignal.timeout(30000),
});
const text = await response.text();
if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);
const result = JSON.parse(text);
console.log(JSON.stringify(result, null, 2));
if (Object.hasOwn(result, "code") && result["code"] !== 0) {
  throw new Error('平台返回业务错误,请结合下方排错说明检查响应');
}

返回示例

按官方字段整理的节选示意,使用虚构 ID,不是实测结果。保存 data.message_id,后续回复、更新或撤回会用到。 以下为结构示意,非本站实测结果。

JSON
{
  "code": 0,
  "msg": "success",
  "data": {
    "message_id": "om_example",
    "chat_id": "oc_example",
    "msg_type": "text",
    "body": {
      "content": "{\"text\":\"接入测试:应用消息已送出\"}"
    }
  }
}

常见错误与排查

230002机器人不在群内
把当前应用机器人加入目标群。
230006未启用机器人能力
在开发者后台启用机器人并发布。
230013目标用户不在机器人可用范围内
调整应用版本可用范围,确认用户在职及应用已启用。
230020触发发送频率限制
按业务队列减速并退避重试。

调用注意

  • 接口限额为 1000 次/分钟、50 次/秒,且可能叠加业务频控。
  • 成功需同时满足 HTTP 状态和 code=0;记录 log_id 方便定位,勿记录凭证。

注意事项

  • 第一步只适用于企业自建应用;商店应用的跨租户令牌流程不同。

核验来源

本站按官方资料整理本场景的必要调用步骤与代码,覆盖范围以本页列出的接口为准。官方资料用于追溯规范及查看变更。

  1. 01
  2. 02
    发送消息核验日期 2026-10-15

飞书的其他调用手册

← 返回飞书的全部功能