关于 buffer
用于通过 Buffer 的 GraphQL API 管理社交媒体内容的技能,涵盖组织与频道查询、帖子和串文排期,以及保存创意。
主要功能
- 01列出组织和频道
- 02筛选并分页查看帖子
- 03创建并排期文本或图片帖子
- 04排期 Twitter/X 串文
- 05保存创意并编辑已排期帖子
适用场景
- 01查看某组织的已排期帖子
- 02为社交频道添加待发布帖子
- 03排期 Twitter/X 串文
- 04保存社交内容创意以供后续使用
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dgalarza/ agent-skills --skill buffer安装后在 Claude Code 中输入/buffer确认已加载。
附带文件references/api-reference.md
详细介绍
Buffer 社交媒体排期
设置
需要设置 BUFFER_API_TOKEN 环境变量。请在此生成令牌:
https://publish.buffer.com/settings/api
发起 API 调用前,请确认令牌已设置:
if [ -z "$BUFFER_API_TOKEN" ]; then
echo "Error: BUFFER_API_TOKEN is not set. Get your token at https://publish.buffer.com/settings/api"
exit 1
fi
API 配置
- 端点:
https://api.buffer.com - 方法: POST(所有请求均为 GraphQL)
- Content-Type:
application/json - 身份验证:
Authorization: Bearer $BUFFER_API_TOKEN - User-Agent:
Mozilla/5.0— 必须设置,以避免 Cloudflare 返回 403 错误
Curl 模板
所有 API 调用都遵循此模式:
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d '{"query": "<GRAPHQL_QUERY>", "variables": <VARIABLES_JSON>}'
始终通过 jq 管道处理,以便输出易于阅读。使用 jq -e 检测错误。
重要: 对于包含 GraphQL 变量(例如 $input)的查询,即使在单引号内,Shell 也可能会展开 $input。请使用临时文件并通过 -d @file 传入,以避免此问题:
cat > /tmp/buffer_payload.json << 'EOF'
{"query": "<GRAPHQL_QUERY>", "variables": <VARIABLES_JSON>}
EOF
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d @/tmp/buffer_payload.json | jq .
不含变量的简单查询可以直接使用内联 -d。
模式检测
解析用户的意图,以确定要执行的操作:
| 意图 | 模式 | 示例 |
|---|---|---|
| 列出组织 | organizations | “显示我的 Buffer 组织” |
| 列出频道 | channels | “我有哪些频道?” |
| 查看帖子 | posts | “显示我已排期的帖子” |
| 创建文本帖子 | create-post | “安排一条内容为……的推文” |
| 创建 Twitter/X 话题串 | create-thread | “在 X 上发布一个话题串……” |
| 创建图片帖子 | create-post | “将这张图片发布到 Instagram” |
| 保存想法 | create-idea | “保存一个关于……的想法” |
| 账户信息 | account | “显示我的 Buffer 账户” |
大多数操作都需要 organizationId。如果用户未指定,请先获取组织信息。如果只有一个组织,则自动使用该组织。
模式:获取组织
获取用户的组织信息。这通常是需要进行的第一个调用。
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d '{"query": "{ account { organizations { id name ownerEmail } } }"}' | jq .
保存响应中的 organizationId,供后续调用使用。
模式:获取频道
列出某个组织的频道(社交媒体账户)。
cat > /tmp/buffer_payload.json << 'EOF'
{"query": "query GetChannels($input: ChannelsInput!) { channels(input: $input) { id name displayName service avatar isQueuePaused } }", "variables": {"input": {"organizationId": "<ORG_ID>"}}}
EOF
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d @/tmp/buffer_payload.json | jq .
以易于阅读的格式展示结果,包括频道名称、服务(例如 twitter、instagram、linkedin)和队列状态。
模式:获取帖子
查询帖子,并支持筛选、排序和分页。
cat > /tmp/buffer_payload.json << 'EOF'
{"query": "query GetPosts($input: PostsInput!) { posts(input: $input) { edges { node { id text status dueAt sentAt createdAt channelService externalLink } cursor } pageInfo { hasNextPage endCursor } totalCount } }", "variables": {"input": {"organizationId": "<ORG_ID>", "filter": {"status": "scheduled"}, "sort": {"field": "dueAt", "direction": "desc"}}}}
EOF
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d @/tmp/buffer_payload.json | jq .
可用的筛选字段(status、channelIds、日期范围)、排序选项和分页详情,请参阅 references/api-reference.md。
模式:创建文本帖子
创建并排期一条文本帖子。
cat > /tmp/buffer_payload.json << 'EOF'
{"query": "mutation CreatePost($input: CreatePostInput!) { createPost(input: $input) { ... on PostActionSuccess { post { id text status dueAt } } ... on MutationError { message } } }", "variables": {"input": {"channelId": "<CHANNEL_ID>", "text": "<POST_CONTENT>", "schedulingType": "automatic", "mode": "addToQueue"}}}
EOF
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d @/tmp/buffer_payload.json | jq .
必填字段
- channelId(String!):要发布到的频道
- text(String!):帖子内容
排期选项
- schedulingType:
automatic(由 Buffer 选择时间)或notification(发送提醒) - mode:控制帖子的发布时间。实际的 GraphQL 枚举为
ShareMode,只有四个值:addToQueue、shareNow、shareNext、customScheduled(注意末尾有d,不是customSchedule)。没有recommendedTime这个值;如果在任何地方看到相关引用,那就是错误的。如有疑问,请通过架构内省确认:__type(name: "ShareMode") { enumValues { name } }。 - dueAt(String):ISO 8601 日期时间;当 mode 为
customScheduled时必填。示例:"2026-03-15T14:00:00Z"
完整的字段定义和枚举值,请参阅 references/api-reference.md。
响应处理
该变更操作会返回联合类型。请始终检查成功和错误两种情况:
# Check if the response contains an error
result=$(curl -s -X POST https://api.buffer.com -H "User-Agent: Mozilla/5.0" ...)
echo "$result" | jq -e '.data.createPost.message' > /dev/null 2>&1 && {
echo "Error: $(echo "$result" | jq -r '.data.createPost.message')"
} || {
echo "$result" | jq '.data.createPost.post'
}
提及 LinkedIn 页面(公司/展示页)
如需在预定帖子中 @提及 LinkedIn 公司或展示页,请将该页面的完整 LinkedIn URL 直接粘贴到帖子 text 中。发布时,LinkedIn 会将已识别的公司/展示页 URL 转换为正式的 @提及标签——无需查找组织 ID 或构建注释负载。
示例:
https://www.linkedin.com/company/<slug>
https://www.linkedin.com/showcase/<slug>
已确认可用的示例:https://www.linkedin.com/showcase/docusigndevs(Docusign Developers 展示页)。
**底层机制(很少需要):**架构确实提供了 metadata.linkedin.annotations(类型为 AnnotationInputLinkedIn),可将 text 中的确切子字符串(start、length)标记为提及,并关联显式的 id/entity(LinkedIn 组织 URN)、link、localizedName 和 vanityName。Buffer 自带的撰写器可能就是通过这种方式实现提及选择器的。此 API 没有公开查询可将页面 URL 或 vanity name 解析为组织 URN,因此仅凭此 API 自行构建此负载并不实用——将页面 URL 粘贴到 text 中是可靠的方法。
模式:创建 Twitter/X 主题串
Twitter/X 主题串通过 createPost mutation 上的 metadata.twitter.thread 字段创建。主题串是一个 ThreadedPostInput 对象数组,每个对象都有一个 text 字段(以及可选的 assets)。
**重要:**主题串中的第一条推文必须包含在 thread 数组中。顶层 text 字段也必填,但 Buffer 使用主题串数组在其界面中呈现所有推文。请在这两个位置都填写第一条推文的相同文本。
cat > /tmp/buffer_payload.json << 'EOF'
{"query": "mutation CreatePost($input: CreatePostInput!) { createPost(input: $input) { ... on PostActionSuccess { post { id text status dueAt } } ... on MutationError { message } } }", "variables": {"input": {"channelId": "<CHANNEL_ID>", "text": "<FIRST_TWEET_TEXT>", "schedulingType": "automatic", "mode": "addToQueue", "metadata": {"twitter": {"thread": [{"text": "<FIRST_TWEET_TEXT>"}, {"text": "<SECOND_TWEET_TEXT>"}, {"text": "<THIRD_TWEET_TEXT>"}]}}}}}
EOF
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d @/tmp/buffer_payload.json | jq .
主题串结构
- 顶层
text:必填。使用第一条推文的文本。 metadata.twitter.thread:ThreadedPostInput对象数组。每个对象包含:text(String):推文内容assets(AssetsInput,可选):该条推文的图片
thread数组中的第一项应与顶层text一致(这是 Buffer 显示为第 1 条推文的内容)。- 后续所有项都会成为主题串中的回复推文。
主题串提示
- 主题串中的每条推文都必须符合 Twitter 的字符限制(280 个字符)。
- 主题串作为一个整体进行排期,并一次性发布。
- 可通过每个
ThreadedPostInput上的assets字段为单条推文附加图片。
模式:创建图片帖子
与文本帖子相同,但需包含带图片 URL 的 assets 字段。
cat > /tmp/buffer_payload.json << 'EOF'
{"query": "mutation CreatePost($input: CreatePostInput!) { createPost(input: $input) { ... on PostActionSuccess { post { id text status dueAt } } ... on MutationError { message } } }", "variables": {"input": {"channelId": "<CHANNEL_ID>", "text": "<POST_CONTENT>", "schedulingType": "automatic", "mode": "addToQueue", "assets": {"images": [{"url": "<IMAGE_URL>"}]}}}}
EOF
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d @/tmp/buffer_payload.json | jq .
图片必须是可公开访问的 URL。可在 images 数组中包含多张图片。
模式:创建想法
保存想法以供日后使用。
cat > /tmp/buffer_payload.json << 'EOF'
{"query": "mutation CreateIdea($input: CreateIdeaInput!) { createIdea(input: $input) { ... on Idea { id content { title text services } } } }", "variables": {"input": {"organizationId": "<ORG_ID>", "content": {"title": "<IDEA_TITLE>", "text": "<IDEA_BODY>", "services": ["twitter", "linkedin"]}}}}
EOF
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d @/tmp/buffer_payload.json | jq .
IdeaContentInput 字段详情(title、text、services、tags)请参阅 references/api-reference.md。
**注意:**标签必须是包含 id 和 color 字段的现有标签对象——使用前请先获取现有标签。
模式:获取账户
**注意:**使用标准 API 令牌权限范围时,完整账户查询(
id、name、timezone)会失败。请改用 Get Organizations 确认账户身份。
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d '{"query": "{ account { organizations { id name ownerEmail } } }"}' | jq .
模式:编辑现有帖子
使用 editPost mutation 更新已排期的帖子(例如,在链接可用后添加 LinkedIn 首条评论中的实际链接)。
cat > /tmp/buffer_payload.json << 'EOF'
{"query": "mutation EditPost($input: EditPostInput!) { editPost(input: $input) { ... on PostActionSuccess { post { id status dueAt channelService } } ... on MutationError { message } } }", "variables": {"input": {"id": "<POST_ID>", "text": "<FULL_POST_TEXT_AGAIN>", "metadata": {"linkedin": {"firstComment": "<COMMENT_TEXT>"}}}}}
EOF
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d @/tmp/buffer_payload.json | jq .
**注意事项:**即使 EditPostInput 中的 text 是可选的,且你并不打算更改它,editPost 也会拒绝未同时发送 text 的请求(即仅发送 metadata 或其他字段的请求),并报错:"Invalid post: Post must have either text or media." 无论实际要更新什么字段,都请始终重新发送完整的现有 text。
常见工作流
安排帖子
当用户想要安排帖子时,采用以下多步工作流:
- 获取组织 → 提取
organizationId - 获取渠道 → 显示可用渠道,让用户选择(或按服务名称匹配)
- 创建帖子 → 使用选定的
channelId和帖子内容
如果用户指定了服务(例如“发布到 Twitter”),请将其与渠道的 service 字段进行匹配。
查看队列
- 获取组织 → 提取
organizationId - 使用
filter: { status: "scheduled" }和sort: { field: "dueAt", direction: "asc" }获取帖子 - 按日期分组显示帖子,并附上渠道信息
集思广益并保存想法
- 获取组织 → 提取
organizationId - 帮助用户起草想法内容
- 使用标题、文本、标签和目标服务创建想法
Schema 检查
在尝试执行变更或查询不确定的字段之前,请先检查 Schema。不要猜测——API 可用范围有限。
列出所有可用的变更:
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d '{"query": "{ __schema { mutationType { fields { name } } } }"}' | jq '[.data.__schema.mutationType.fields[].name]'
列出所有可用的查询:
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d '{"query": "{ __schema { queryType { fields { name } } } }"}' | jq '[.data.__schema.queryType.fields[].name]'
检查特定类型上的字段:
curl -s -X POST https://api.buffer.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "User-Agent: Mozilla/5.0" \
-d '{"query": "{ __type(name: \"<TYPE_NAME>\") { fields { name type { name kind } } } }"}' | jq '.data.__type.fields[]'
错误处理
GraphQL 错误
检查每个响应顶层的 errors 数组:
result=$(curl -s -X POST https://api.buffer.com ...)
errors=$(echo "$result" | jq -r '.errors // empty')
if [ -n "$errors" ]; then
echo "GraphQL Error:"
echo "$result" | jq '.errors[].message'
exit 1
fi
变更错误
变更会返回联合类型。务必处理 MutationError 变体:
{
"data": {
"createPost": {
"message": "Validation failed: text is required"
}
}
}
常见问题
- 403 Forbidden(错误代码 1010):Cloudflare 正在拦截请求。每次调用 curl 时都必须包含
-H "User-Agent: Mozilla/5.0"。 - 401 Unauthorized:令牌无效或已过期。请在 https://publish.buffer.com/settings/api 重新生成令牌。
- 缺少 organizationId:大多数查询都需要组织 ID。请先获取组织。
- 无效的 channelId:请确认该渠道存在且属于当前组织。
- dueAt 已过期:使用
customScheduled时,dueAt必须设置为未来时间。