关于 contentstudio
通过 CLI 和托管的 MCP 服务管理社交媒体内容的 ContentStudio 技能。它涵盖工作区、账号、帖子和媒体操作,并要求认证、确认工作区,以及在发布或执行其他变更前进行防护检查。
主要功能
- 01连接托管的 ContentStudio MCP
- 02管理工作区和社交账号
- 03创建和管理帖子与媒体
- 04处理列表结果分页
- 05变更前执行试运行
适用场景
- 01安排或管理社交媒体帖子
- 02按工作区查看账号和媒体
- 03发布或发送前检查变更
MCP 相关
该技能通过账号 OAuth 连接至 https://mcp.contentstudio.io/mcp 上的托管 ContentStudio MCP 服务。优先使用可用的 MCP 工具;任务不受支持或 MCP 工具不可用时,改用 CLI。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ contentstudioio/ contentstudio-agent --skill contentstudio安装后在 Claude Code 中输入/contentstudio确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitignoremcp.jsonLICENSEpackage.jsonCHANGELOG.mdREADME.mdpackage-lock.json.claude-plugin/marketplace.jsonplugin.json.cursor-plugin/plugin.json.github/workflows/check-skill-sync.yml.grok-plugin/plugin.jsonscripts/verify-analytics.shsrc/cliCtx.tsapi.tsconfig.tssrc/commands/aiVideo.tsanalytics.tsapprovalWorkflows.tsauth.tsanalyticsReports.tscomments.tsconnect.tsfacebook.tscontentCategories.tscrud.tslookups.tsplannerShareLinks.tsmedia.tsscheduling.ts详细介绍
托管 MCP 服务(Cursor、Grok Bot、Grok Build 插件)
将此技能作为插件安装后,它还会连接托管的 ContentStudio MCP 服务:https://mcp.contentstudio.io/mcp。用户首次使用时,通过 OAuth 使用 ContentStudio 账号登录。无需 API 密钥。
如果有可用的 ContentStudio MCP 工具(例如 fetch_workspaces、fetch_posts、create_post),请优先使用。仅当 MCP 工具未连接,或 MCP 工具无法完成任务时,才使用下方的 CLI。使用任何会发布、删除或批准帖子的工具前,请先向用户说明将执行的操作,并等待用户确认。
如果尚未安装,请安装 ContentStudio CLI
npm install -g contentstudio-cli
# or
pnpm install -g contentstudio-cli
npm 发布页:https://www.npmjs.com/package/contentstudio-cli contentstudio-agent GitHub:https://github.com/contentstudioio/contentstudio-agent contentstudio API 文档:https://api.contentstudio.io/api-docs 官方网站:https://contentstudio.io
| 属性 | 值 |
|---|---|
| name | contentstudio |
| description | 用于通过 ContentStudio 公共 API 安排帖子并管理媒体和账号的社交媒体自动化 CLI |
| allowed-tools | Bash(contentstudio:*) |
⚠️ 需要身份验证
运行任何 contentstudio CLI 命令前,必须先完成身份验证。 没有有效的 API 密钥,所有命令都会失败。
开始操作前,先检查身份验证状态:
contentstudio auth:status
如果 has_api_key 为 false,请通过以下两种方式之一进行身份验证。用户可以前往 ContentStudio Dashboard → Settings → API Keys 生成密钥。
- API 密钥(交互式)——将密钥保存到 CLI 配置文件中:
contentstudio auth:login --api-key cs_...
- 环境变量(无头模式 / Agent 运行时)——CLI 会从环境中读取
CONTENTSTUDIO_API_KEY,且此变量的优先级高于配置文件:
export CONTENTSTUDIO_API_KEY=cs_...
无头部署说明(OpenClaw、CI、守护进程): shell 中的
export不会持久保存在服务进程中。请在 Agent 的实际运行环境中设置CONTENTSTUDIO_API_KEY,例如 systemdEnvironment=(systemctl edit)、EnvironmentFile=,或 Docker-e/ composeenvironment:,然后重启服务。要求显式声明所需环境变量的运行时(例如 OpenClaw 的requires.env)会一直处于阻止状态,直到此变量存在于进程环境中。
然后确认已选定工作区:
contentstudio --json workspaces:current
如果 active_workspace_id 为 null,请列出工作区并询问用户要选择哪一个:
contentstudio --json workspaces:list
contentstudio workspaces:use <workspace_id>
Agent 调用规则
- 始终在子命令前传入
--json,以获得稳定、可解析的输出。 - 封装格式:
- 成功:
{"ok": true, "data": <payload>, "pagination"?: {...}} - 错误:
{"ok": false, "error": {"type": "<ErrorType>", "message": "...", "http_status": <int>, "hint": "..."}}
- 成功:
- 出错时退出码为非零值。 同时检查
returncode和ok。 - 仅解析 stdout——面向用户的消息会输出到 stderr。
- 执行任何变更操作(帖子 / 评论 / 媒体)前,先使用
--dry-run运行,以确认负载正确。--dry-run不会调用 API。 - “Share link”含义不明确——请询问用户具体指哪一种。 两种互不相关的功能都使用此名称:与客户分享已安排的帖子(用于评论 / 审批),以及分享实时的分析仪表板。此 API 仅支持第一种,可通过
planner-share-links:*访问;分享仪表板则只能在 Web 应用中进行。如果用户没有说明指哪一种,请先询问再执行任何操作——不要假设是 CLI 恰好支持的那一种。完整说明请见 Planner share links 下方的提示框。
执行变更操作前确认目标工作区
CLI 会静默地默认使用当前活动工作区(由 workspaces:use 设置)。对于只读调用(workspaces:list、accounts:list、posts:list、media:list 等),使用活动工作区即可。
但对于任何变更操作——accounts:connect、accounts:add-bluesky、accounts:add-facebook-group、accounts:remove、posts:create、posts:update、posts:delete、posts:approve、posts:reject、comments:add、media:upload、workspaces:update、workspaces:delete、labels:create、labels:update、labels:delete、campaigns:create、campaigns:update、campaigns:delete、team:add、team:update、team:remove、categories:create、categories:update、categories:delete、categories:shuffle、category-slots:create、category-slots:update、category-slots:delete、approval-workflows:create、approval-workflows:update、approval-workflows:delete、approval-workflows:duplicate、approval-workflows:set-default、approval-workflows:remove-default、planner-share-links:create、planner-share-links:update、planner-share-links:delete、planner-share-links:send-invitations、所有 inbox:* 写入操作(inbox:send、inbox:comment-add、inbox:comment-delete、inbox:review-reply、inbox:update、inbox:tag-* 等),以及 ai-video:generate / ai-video:run-tool / ai-video:cancel-job——你都必须先向用户确认工作区,即使已经有活动工作区也不例外。不要假设他们想要在当前活动工作区中执行变更。
AI 视频生成会消耗额度。 不带
--dry-run调用ai-video:generate和ai-video:run-tool时,会立即提交实际(计费)任务——如果支持相关标志,先运行ai-video:estimate,向用户展示预估结果和费用,然后对实际调用使用--dry-run,再正式运行。ai-video:cancel-job也可能会对已消耗的部分工作收费——未经确认,不要代用户取消任务。
收件箱写入会直接面向客户。
inbox:send、inbox:comment-add和inbox:review-reply会将文本发布给真实社交平台上的真实用户,而且无法通过服务提供商撤回。务必先使用--dry-run,向用户展示确切的消息文本,并在发送前获得明确批准。绝不要一步完成撰写并向客户发送回复。
(workspaces:create 是唯一一个不限定工作区的写入操作——它会创建一个全新的工作区,并忽略当前活动工作区。)
操作步骤:
- 运行
contentstudio --json workspaces:current,查看当前活动工作区。 - 告诉用户:“您当前的活动工作区是
<name>(<id>)。您想在此工作区中连接账号/发布/删除,还是在其他工作区中操作?” - 如果用户选择其他工作区,运行
workspaces:list,让他们选择,然后:- 运行
workspaces:use <id>切换默认工作区;或 - 在单次变更调用中传入
--workspace <id>(一次性操作时优先采用——不会更改活动工作区)。
- 运行
- 然后才能运行变更命令。
即使用户的请求看起来暗示要使用活动工作区(“连接一个 Facebook 公共主页”、“创建一篇草稿帖子”),这也是强制要求——他们可能刚刚在脑海中切换了上下文,却忘了 CLI 当前活动的是哪个工作区。
分页——主动处理,不要悄悄截断
当结果数量超过单页容量时,所有列表命令在 JSON 模式下都会返回一个 pagination 块:
{
"ok": true,
"data": [ /* current page of items */ ],
"pagination": {
"current_page": 1,
"per_page": 10,
"total": 48,
"last_page": 5,
"from": 1,
"to": 10,
"has_more": true
}
}
强制规则:每当 pagination.has_more === true,都表示用户的数据比当前返回的更多。绝不能悄悄将当前页视为“全部结果”。选择以下三种策略之一:
-
询问用户(对含义不明确的请求,默认采用此策略):
“我检索到了 48 个工作区中的 10 个。你希望我继续获取其余工作区,还是目前这 10 个就够用了?”
-
自动分页——如果用户的请求表明他们想要全部结果(例如“列出我的所有账户”“显示每一篇草稿”“删除所有排队中的帖子”):
- 使用
--per-page <total>再次调用,一次性获取所有结果:contentstudio --json workspaces:list --per-page 48 - 或者当
total很大(>200)且需要控制单页数据量时,逐页迭代--page 2、--page 3……--page <last_page>。
- 使用
-
筛选,而非分页——如果用户请求的是特定内容(例如“仅限 Facebook 账户”),使用相关筛选标志(
--platform facebook、--search "..."、--status draft),而不是分页。结果集更小 = 无需分页。
Agent 的快速决策树
Did the user say "all" / "every" / "complete list" / "every single"?
→ YES: auto-paginate using --per-page <pagination.total>
→ NO:
Did the user give a specific count? ("show me top 5", "first 20 posts")
→ YES: respect that count; use --per-page accordingly
→ NO:
pagination.has_more === true?
→ YES: ASK the user before assuming you have everything
→ NO: you have all the data; proceed
示例
用户:“列出我的工作区” Agent 应该:
- 运行
contentstudio --json workspaces:list --per-page 50(设置较大的默认值,通常可避免分页) - 如果
pagination.has_more仍为 true,则告知用户:“我找到了 N 个工作区中的 50 个。要我获取全部 N 个吗?”
用户:“删除我所有的草稿帖子” Agent 应该:
- 运行
contentstudio --json posts:list --status draft --per-page 1,查看total - 运行
contentstudio --json posts:list --status draft --per-page <total>,获取全部帖子 - 遍历
data[]并逐一删除 - 绝不能只删除第一页的内容,然后报告“已完成”
用户:“显示我的 Facebook 账户” Agent 应该:
- 使用
--platform facebook筛选——通常只会返回 0 个或少量结果,无需担心分页 - 如果
has_more仍为 true(Facebook 账户超过 20 个),先询问用户,再自动获取
会分页的端点
所有 *:list 命令都会分页:
workspaces:list、accounts:list、posts:list、comments:list、media:list、campaigns:list、categories:list、labels:list、team:list、approval-workflows:list、planner-share-links:list、ai-video:jobs。
category-slots:list 和 planner-share-links:activity 一次性返回全部结果,且不包含 pagination 块——一个类别只有少量时段,而 activity 会返回自己的 total。
非列表命令(auth:whoami、posts:create、posts:delete、media:upload、ai-video:tools、ai-video:models、ai-video:job 等)绝不会在其信封中包含 pagination。
命令参考
所有命令的调用格式为 contentstudio <group>:<command>。
身份验证
| 命令 | 用途 |
|---|---|
auth:login --api-key cs_... | 存储并验证 API 密钥 |
auth:logout | 清除已存储的凭据 |
auth:whoami | 访问 /me 并返回用户信息 |
auth:status | 显示本地配置(密钥已隐藏) |
工作区
| 命令 | 用途 |
|---|---|
workspaces:list | 列出用户的工作区 |
workspaces:use <id> | 设置当前工作区 |
workspaces:current | 显示当前工作区 |
workspaces:create --name <n> --logo <url> --timezone <tz> [--super-admin-id <id>] [--note <t>] [--instagram-posting-method api|mobile] [--first-day-day <Day> --first-day-key <0-6>] | 创建新工作区(不限定于工作区) |
workspaces:update [<id>] [--name] [--logo] [--timezone] [--note] [--instagram-posting-method] [--first-day-day --first-day-key] | 更新工作区(默认为当前工作区;至少需要 1 个字段) |
workspaces:delete <id> | 删除工作区 |
workspaces:limits | 计划权益及剩余额度(参见下文的批量操作前检查限制) |
workspaces:create / workspaces:update: |
--name≤35 个字符,只能包含字母、空格、数字和句点。--logo必须是 URL;--timezone是 IANA 字符串(例如Asia/Karachi)。--super-admin-id(仅用于 create)— 要在其名下创建工作区的账户所有者;当你管理多个超级管理员时,此参数为必填项。- 一周的第一天通过一对标志指定:
--first-day-day <Sunday..Saturday>+--first-day-key <index>,其中 key 是该日期的索引(Sunday=0 … Saturday=6)。两者共同构成first_day: {day, key}。 - 如果省略
<id>,workspaces:update默认使用当前工作区,并且至少需要一个字段。 - 错误:删除失败时返回
WORKSPACE_DELETE_FAILED(422);工作区不存在时返回 404。
批量操作前检查限额。 workspaces:limits 通过一次开销很低的调用返回
{ plan, limits[], usage_reset }。此结果不会缓存——每次请求都会实时生成,因此能反映你刚刚完成的写入操作。
在执行任何批量操作(创建二十篇帖子、上传一个媒体文件夹、生成图片)之前运行此命令,不要等到操作进行到一半才发现达到上限,让用户只能得到一个未完成的任务。
limits[]中的每个条目都是{ key, label, used, limit, remaining, scope, is_unlimited, is_on_plan, unit, period, resets_at, note }。scope决定used/remaining实际统计的范围;估算批量操作规模前必须先查看它:account— 数值在账户的所有工作区之间共享。social_accounts的remaining: 3表示整个账户还能添加三个,而不是当前工作区还能添加三个。账户范围的 key:workspaces、social_accounts、team_members、listening_topics、automations、media_storage。workspace— 仅限当前工作区。包括八项额度计数:x_posting_credits、listening_mentions、ai_text_credits、ai_image_credits、ai_video_credits、video_clip_credits、ai_auto_reply_credits、api_credits。
key是稳定标识符——切勿根据label或note进行分支处理。 两者均经过本地化:后端会在 8 种语言中通过limits.labels.<key>解析label,并在运行时根据多个本地化片段组合生成note,因此非英语账户使用的 API key 会为同一条目返回不同的显示文本。- 单独来看,
limit: null含义不明确——应查看布尔值:is_unlimited: true表示没有上限;is_on_plan: false表示套餐完全不包含此功能(这是硬性零额度,并非无限)。切勿将 nulllimit/remaining显示为0。 unit为count或bytes(只有media_storage使用bytes)。period为monthly或lifetime;对于monthly条目,resets_at是 ISO 8601 时间戳;对于lifetime条目,则为null。- 这 14 个 key 始终全部存在:
workspaces、social_accounts、team_members、x_posting_credits、listening_topics、listening_mentions、ai_text_credits、ai_image_credits、ai_video_credits、video_clip_credits、ai_auto_reply_credits、automations、media_storage、api_credits。 api_credits是 API 调用和 webhook 投递共用的一个额度池——在此处消耗额度也会减少另一方可用的额度。usage_reset(last_reset_at/next_reset_at,带偏移量的 ISO 8601 时间戳)说明每月计数器何时重置。- 响应正文中没有
rate_limit和cache块。 每个调用方的速率上限会通过X-RateLimit-Limit/X-RateLimit-Remaining响应头发布;429会表现为RateLimitError(退出码 5)。
社交账号(读取 + 连接)
| 命令 | 用途 |
|---|---|
accounts:list [--platform <p>] [--search <q>] | 列出已连接的社交账号 |
platforms:list | 列出支持连接新账号的平台 |
accounts:connect <platform> | 生成一次性 OAuth URL,用于连接新账号 |
accounts:connect <platform> --reconnect --account-id <id> | 刷新已过期或无效的账号 |
accounts:add-bluesky --handle <h> --app-password <p> | 连接 Bluesky 账号(无需浏览器,使用应用密码) |
accounts:add-facebook-group --name <n> [--image <url>] | 手动添加 Facebook 群组连接 |
accounts:remove <account_id> | 移除(断开连接)社交账号。account_id 是 accounts:list 中该账号的 id。需要 save_social 权限(否则返回 403)。 |
accounts:list 的 --platform 筛选值:facebook、linkedin、twitter、instagram、youtube、tiktok、pinterest、gmb。
accounts:connect 的 <platform> 值:facebook、facebook-profile、instagram、instagram-via-facebook、twitter、linkedin、pinterest、tiktok、youtube、threads、gmb、tumblr。
AI Agent 的账号连接流程:
- 运行
platforms:list,查看支持的平台以及各自使用的方法(oauth/credentials/manual)。 - 对于 OAuth 平台(大多数平台),调用
accounts:connect <platform>,并向用户展示返回的 URL——用户可在浏览器中打开该 URL 进行授权。CLI 本身不会处理凭据。 - 对于 Bluesky,请向用户索取其 handle 和 app-password(引导用户前往 https://bsky.app/settings/app-passwords),然后调用
accounts:add-bluesky。 - 对于 Facebook 群组,只需调用
accounts:add-facebook-group --name "..."。
帖子
| 命令 | 用途 |
|---|---|
posts:list [--status draft|scheduled|...] [--date-from] [--date-to] | 列出帖子 |
posts:get <post_id> | 读取一篇帖子(返回内容与该帖在 posts:list 中对应的行完全相同) |
posts:create -c "text" -i <account> -t <publish_type> [-s "YYYY-MM-DD HH:MM:SS"] [-m <image_url>] | 创建帖子(快捷模式) |
posts:create -c "text" -t content_category --content-category-id <cat_id> | 创建内容类别帖子(账号来自该类别) |
posts:create -c "text" -i <fb_account> -t draft --facebook-carousel '<json>' | 创建 Facebook 轮播帖子(2–10 张卡片) |
posts:create -c "text" -i <threads_account> -t draft --threads '<json>' | 创建 Threads 多帖串联帖子(最多 10 项) |
posts:create -c "text" -i <twitter_account> -t draft --twitter '<json>' | 创建 Twitter/X 串联推文帖子(最多 10 条推文) |
posts:create -c "text" -i <account> -t draft --first-comment "..." --first-comment-account <id> | 创建带首条评论的帖子 |
posts:create -c "text" -i <linkedin_account> -t draft --post-type poll --linkedin-options '<json>' | 创建 LinkedIn 投票帖子(仅文本) |
posts:create -c "text" -i <ig_account> -t draft --post-type reel --video-url <url> --instagram-trial-reel | 创建 Instagram 试用版 Reels(优先向非关注者展示) |
posts:create -c "common text" -i <fb_account> -i <tiktok_account> -t draft -m <img_url> --platform-overrides '<json>' | 在多个平台发布同一篇帖子,并按平台覆盖内容 |
posts:create -c "text" -i <account> -t scheduled -s "..." --repeat-type Week --repeat-times 4 --repeat-gap 1 | 创建重复发布的帖子(生成 4 篇相互独立的子帖子) |
posts:create --body /path/to/body.json | 使用完整的 JSON 正文创建帖子 |
posts:update <post_id> [same flags as posts:create] | 更新现有帖子(正文格式相同)。帖子已发布或正在处理后,更新将被拒绝(422) |
posts:delete <post_id> [--delete-from-social] | 删除帖子 |
posts:approve <post_id> [--comment "..."] | 批准待处理的帖子 |
posts:reject <post_id> [--comment "..."] | 拒绝待处理的帖子 |
-t / --publish-type 的取值:scheduled、draft、queued、content_category。(scheduled 和 draft 需要 -s / --scheduled-at。)没有立即发布类型——如需立即发送,请将发布时间安排在下一分钟。 |
posts:get <post_id> 返回单篇帖子,其有效载荷与该帖子在 posts:list 中对应行的内容相同——写入后可用它重新读取单篇帖子,而不必重新列出所有帖子。已删除的帖子、其他工作区中的帖子和格式错误的 ID 均会返回 404,因此 404 并不能证明该 ID 从未存在。
posts:update <post_id> 接受与 posts:create 完全相同的标志和请求体(包括 --body 和快捷模式)——它会向 /workspaces/{w}/posts/{post_id} 发送 PUT 请求。后端仅允许在帖子状态不是 published 或 processing 时更新(否则会返回 422)。如需更改已附加的工作流,请在更新时使用下面的 --approval-workflow-action。
posts:create / posts:update 快捷模式标志:
-c / --content(必填)— 帖子文本。-i / --account <id>(可重复)— 要发布到的账户 ID。除非提供了--content-category-id,否则必填。--content-category-id <id>— 设置顶层content_category_id。**当--publish-type content_category时,后端要求提供此参数。**设置后,账户将从类别中派生,因此不必提供--account(可以省略)。对于内容类别帖子,请使用此参数代替--account。-s / --scheduled-at "YYYY-MM-DD HH:MM:SS"— 定时发布时间。CLI 会将任何可解析的日期规范化为YYYY-MM-DD HH:MM:SS(后端要求的date_format),并以纯本地时间字符串的形式发送。API 会按照工作区的时区读取该时间,而非 UTC — 因此请传入用户希望帖子发布的本地时间;如果不确定时区,请通过workspaces:current获取。scheduling:best-times已返回该时区的时段,可以直接传入。-m / --image-url <url>(可重复)、--video-url <url>、--media-id <id>(可重复)— 媒体。--post-type <type>— 例如feed、reel、carousel、story、poll。当post_type=carousel且附加了 2 张或更多图片时,后端会自动将帖子判定为轮播帖。投票必须同时使用--post-type poll和纯文本的--linkedin-options投票块(不能包含媒体)。--label <id>(可重复,最多 20 个)→labels。--campaign-id <id>→campaign_id。- 同时使用
--repeat-type Day|Week|Month、--repeat-times <1-30>和--repeat-gap <1-99>→scheduling.repeat。三者必须一并提供(否则 CLI 会在本地报错);CLI 会始终随它们发送enabled: true,只要存在repeat键,后端就要求该值。- **仅适用于
--publish-type scheduled。**对于draft、queued和content_category,CLI 会拒绝执行,并在调用发出前于本地报错。 - 当
--repeat-type Day时,--repeat-gap必须 ≥3(发布编辑器不允许更短的每日重复间隔)。 - 会创建 N 个独立的子帖子,而非一个循环重复的帖子 — 编辑或删除父帖子不会影响子帖子。子帖子不会包含 Twitter/X 和 YouTube 账户。每个子帖子都会继承帖子的审批人。
- **更新时绝不会继承重复设置。**不带重复标志的
posts:update不会创建子帖子,因此对重复帖子执行读取-修改-写入是安全的:往返处理不会意外地重新生成整个系列。 - 在读取数据时(
posts:get/posts:list),scheduling.repeat的结构为{is_parent, is_child, parent_id, type, times, gap}— 不包含enabled键,该键仅用于请求。不要直接将读取到的repeat块传回更新,并期望它具有相同含义。
- **仅适用于
--linkedin-options '<json>'→linkedin_options(LinkedIn 账户)。传入 JSON 对象;CLI 会在本地解析(无效 JSON →ConfigError),并原样发送。- 结构:
{ "title"?: <string>, "poll"?: { "question": <≤140>, "options": <string[2..4], each ≤30>, "duration": "ONE_DAY" | "THREE_DAYS" | "SEVEN_DAYS" | "FOURTEEN_DAYS" } } - 投票必须搭配
--post-type poll和纯文本内容(不能包含图片或视频)。后端会验证;不符合要求时返回 422。
- 结构:
--facebook-collaborator <user_id>(可重复,最多 10 个)→facebook_options.collaborators(Facebook 账户)。会与--facebook-carousel/--facebook-background-id合并。--instagram-collaborator <user_id>(可重复,最多 3 个)→instagram_options.collaborators(Instagram 账户)。与--instagram-trial-reel同时使用时会被拒绝(422)。--instagram-trial-reel(布尔值,默认false)→instagram_options.trial_reel.enabled。发布 Instagram试播 Reels — 首先向非关注者展示,因此不会出现在个人主页网格或关注者的信息流中。--instagram-trial-reel-graduation SS_PERFORMANCE|MANUAL(默认SS_PERFORMANCE)→instagram_options.trial_reel.graduation_strategy。SS_PERFORMANCE允许 Instagram 在表现良好时自动将其转为正式 Reels 并展示给关注者;MANUAL则要求在 Instagram 应用中手动转为正式 Reels(Instagram 没有相关 API)。- 必须准确使用
--post-type reel(不能用feed+reel),并附带视频 —feed、carousel、story均不允许。CLI 不会预先验证;后端会返回 422。 - 与
--instagram-collaborator同时使用时会被拒绝(422)。与试播 Reels 同时使用时,分享到快拍会被静默忽略(不会拒绝)。 - 当工作区通过移动应用向 Instagram 发布帖子时不可用(
instagram_posting_option=mobile)。
--platform-overrides '<json>'→platform_overrides(顶层设置,适用于帖子中的任意平台)。传入以平台为键的 JSON 对象(平台包括facebook、instagram、twitter、linkedin、pinterest、youtube、tiktok、gmb、tumblr、threads、bluesky、telegram);CLI 会在本地解析(无效 JSON →ConfigError),并原样发送。- 每个平台的结构:
{ "content": { "text"?: <string>, "post_type"?: <string>, "media"?: { "images"?: <url[] ≤10>, "video"?: <url> } } }。 text和post_type会分别与顶层通用content合并 — 仅包含media的覆盖项仍会继承通用的text/post_type。media是整体替换:如果某个平台的覆盖项中的content包含media键,该平台的媒体就完全由覆盖项定义(对于覆盖项中省略的images/video字段,不会回退使用通用媒体)。完全省略media则会整体继承通用的content.media。此机制是为了适配部分平台(例如 TikTok),这些平台无法支持图片和视频混合发布。- 完全省略
--platform-overrides时,会向每个目标平台发布相同的顶层content。 - 覆盖项中的图片只能使用 URL(不能使用
media_ids),并遵循与顶层媒体相同的验证规则(最多 10 张图片;同一覆盖项中不能混用图片和视频)。
- 每个平台的结构:
- 审批 — 两种互斥系统(只能使用其中一种):
- 旧版
--approver <user_id>(可重复)+--approve-option anyone|everyone(默认anyone)+--approval-notes "..."→ 仅当提供至少一个审批人时构建approval: {approvers, approve_option, notes}。帖子创建者不能作为审批人。anyone= 任意一个审批人通过即可;everyone= 所有人都必须通过。 - 工作流
--approval-workflow-id <id>+--approval-workflow-notes "..."→approval_workflow: {workflow_id, notes?}— 附加一个工作流(创建和更新时均可用)。通过approval-workflows:list获取其 ID(id)。 - 工作流(仅限更新)
--approval-workflow-action restart|resume|renotify_current|keep|remove+--approval-workflow-notes "..."→approval_workflow: {workflow_action, notes?}— 修改已附加的工作流。仅适用于posts:update。 --approval-workflow-id/--approval-workflow-action必须且只能提供一个,且--approver不能与任何--approval-workflow-*标志同时使用。违反这些规则时,CLI 会在本地报错(ConfigError)。
- 旧版
--facebook-background-id <id>→facebook_options.facebook_background_id(仅限纯文本 Facebook 帖子;附带媒体时会被拒绝)。通过facebook:text-backgrounds获取有效 ID。--facebook-carousel '<json>'→facebook_options.carousel(仅限 Facebook 账户)。传入 JSON 对象;CLI 会在本地解析(无效 JSON →ConfigError),并添加is_carousel_post: true。它会与--facebook-background-id合并(两者不会互相覆盖)。后端会验证卡片数量、CTA 和各项限制;不符合要求时返回 422。- 结构:
{ "cards": [ { "image": <url, required>, "link": <url, required>, "title"?: <≤255>, "description"?: <≤1000> } ], "call_to_action"?, "end_card"?: <bool>, "end_card_url"?: <url>, "accounts"?: <string[]> } - 卡片数最少 2 张,最多 10 张。Facebook 账户 ID 仍应放在顶层
-i / --account中(或放在carousel.accounts中)。 call_to_action可取以下 33 个值之一:NO_BUTTON、ADD_TO_CART、APPLY_NOW、BET_NOW、BOOK_TRAVEL、BUY_NOW、BUY_TICKETS、CALL_NOW、CONTACT_US、DOWNLOAD、GET_DIRECTIONS、GET_OFFER、GET_QUOTE、GO_LIVE、INSTALL_MOBILE_APP、LEARN_MORE、LIKE_PAGE、LISTEN_MUSIC、OPEN_LINK、ORDER_NOW、PLAY_GAME、REGISTER_NOW、REQUEST_TIME、SAVE、MESSAGE_PAGE、WHATSAPP_MESSAGE、SHOP_NOW、SIGN_UP、SUBSCRIBE、USE_APP、WATCH_MORE、WATCH_VIDEO。
- 结构:
--threads '<json>'→threads_options(仅限 Threads 账户)。传入由主题帖组成的 JSON 数组;CLI 会在本地解析(无效 JSON →ConfigError),设置has_multi_threads: true和multi_threads: <array>。Threads 账户 ID 应放在顶层-i / --account中。- 结构:
[ { "message": <string>, "media"?: <url[] ≤10>, "media_ids"?: <string[] ≤10> } ] - **最多 10 项。**每项必须包含
message或media。Threads 允许混合媒体。后端会验证各项限制;超过限制时返回 422。
- 结构:
--twitter '<json>'→twitter_options(仅限 Twitter/X 账户)。传入由推文组成的 JSON 数组;CLI 会在本地解析(无效 JSON →ConfigError),设置has_threaded_tweets: true和threaded_tweets: <array>。Twitter 账户 ID 应放在顶层-i / --account中。其用法与--threads类似,但适用于 Twitter 串文。- 结构:
[ { "message": <string>, "media"?: <url[] ≤10>, "media_ids"?: <string[] ≤10> } ] - **最多 10 条推文。**每条推文必须包含
message或media。Twitter 不允许单条推文混用媒体(不能同时包含图片和视频),且每条推文最多只能包含 1 个视频。CLI 不会验证推文内容 — 后端会强制执行这些限制;违反时返回 422。
- 结构:
--first-comment "<message>"→first_comment(最多 2000 个字符)。CLI 会构建first_comment: { message, accounts? }。通过--first-comment-account <id>(可重复)指定账户。--first-comment-account <id>(可重复)→first_comment.accounts。**提供--first-comment消息时,后端要求至少提供一个账户,且这些账户必须是帖子主--accountID 的子集。**CLI 不会在客户端强制阻止 — 省略--first-comment-account时,后端会返回 422。 (--facebook-carousel、--facebook-collaborator、--instagram-collaborator、--instagram-trial-reel、--instagram-trial-reel-graduation、--linkedin-options、--platform-overrides、--threads和--twitter仅适用于快捷模式。--bodyJSON 模式原生支持facebook_options(轮播 + 协作者)、instagram_options(collaborators+trial_reel)、linkedin_options、threads_options、twitter_options、first_comment、approval、approval_workflow和顶层的platform_overrides——需要组合多个平台选项块的帖子请使用此模式。)
现在,posts:list 的负载会为每篇帖子包含 linkedin_options 和 approval_workflow(以及现有字段)——它们会自动显示在 --json 输出中。
排期 — 最佳发布时间
| 命令 | 用途 |
|---|---|
scheduling:best-times | 根据已连接账号的历史数据,为工作区推荐排序后的发布时间段 |
scheduling:best-times --account <platform>:<account_id> | 将分析范围限定为特定账号(可重复指定) |
scheduling:best-times --global-slots <n> --per-account-slots <n> | 设置返回的推荐数量(每项为 1–24) |
scheduling:best-times --entities '<json>' | 完整实体数组,用于为每个账号指定发布时间段数量 |
时间段是一个推荐的发布时间:某个工作日的某个小时。时间段按推荐程度从高到低排列,因此 --global-slots 3 表示最适合发布的三个小时。
- 时间始终采用工作区时区,并通过
meta.timezone返回。此处没有时区参数。它与posts:create --scheduled-at使用的时钟相同,因此可以直接按该时间段安排发布——不要先将其转换为 UTC。 - 省略
--account可分析所有已连接账号。 否则,请传入<platform>:<account_id>,其中两部分均取自同一行accounts:list(其platform和_id),例如--account facebook:<account_id>。支持的平台:facebook、instagram、linkedin、twitter、tiktok、youtube、pinterest、threads、gmb、tumblr、bluesky、telegram。 --entities '[{"id":"<account_id>","type":"facebook","slots":3}]'可用于为不同账号设置不同的发布时间段数量;不能与--account同时使用。--global-slots(API 默认值为 5)用于设置合并后的global视图大小;--per-account-slots(API 默认值为 3)用于设置各账号列表的大小。两者的取值范围均为 1–24,CLI 会在发起请求前进行验证。它们都不会改变底层分析结果或heatmap_matrix;后者始终包含所有有信号的小时。
响应结构(JSON 封套中的 data):
meta—{generated_at, timezone, warnings[], missing_entities[], ai_fallback_entities[]}。global— 对分析过的账号进行汇总:top_recommendations[](每项为{rank, day, date, time, score, platform_breakdown},其中time是不带其他内容的小时字符串,例如"14"= 14:00),以及heatmap_matrix.data(稀疏的[hour, day_index, score]三元组,day_index中 0 = 星期一)和dates_key。如果没有账号拥有可用数据,则为null。individual— 按账号 ID 索引的相同细分数据;每项包含platform和source(data_driven或 AI 后备结果)。
工作区数据不足时仍会返回 HTTP 200。 历史记录不足的账号会列在 meta.missing_entities 中,且 global 可能为 null——这是成功读取,不是错误。请告知用户哪些账号被跳过,而不要报告失败。列在 meta.ai_fallback_entities 中的账号对应的是估算值,而非测量结果——呈现时请说明这一点。
错误:未知账号或工作区没有已连接账号时返回 422;优化器暂时不可用时返回 502(BackendError)——请重试,而不要报告没有数据。
读取操作安全。 scheduling:best-times 仅执行读取,因此无需使用 --dry-run,也无需确认工作区。从推荐时间段安排帖子属于变更操作,因此该步骤仍须遵守常规的 --dry-run 和工作区确认规则。
评论 / 内部备注
| 命令 | 用途 |
|---|---|
comments:list <post_id> | 列出帖子的评论 |
comments:add <post_id> "message" [--note] [--mention <user_id>] | 添加公开评论或内部备注 |
媒体库
| 命令 | 用途 |
|---|---|
media:list [--type images|videos] [--sort recent|...] | 列出媒体资源 |
media:upload --file <local_path> | 上传本地文件 |
media:upload --url <external_url> | 从外部 URL 导入 |
AI 图片
| 命令 | 用途 |
|---|---|
images:tools | 此 API 可调用的图片工具,以及每种工具所需的输入和控制选项 |
images:models | images:generate 接受的模型标识符 |
images:brand | {configured, enabled} — --use-brand 是否会应用任何内容 |
images:generate -p "<prompt>" | 提示词 → 图片,并保存到媒体库 |
images:generate -p "<edit>" --image-url <url> | 编辑现有图片,而非从头生成 |
images:product-image --product-image-url <url> | 重新布置产品照片 |
images:headshot --image-url <url> | 根据人物照片生成专业头像 |
images:face-swap --target-image-url <url> --face-image-url <url> | 将一张图片中的人脸替换到另一张图片的主体上 |
images:outfit-swap --target-image-url <url> --outfit-image-url <url> | 虚拟试穿 |
images:upscale --image-url <url> | 提高图片分辨率 |
images:remove-background --image-url <url> | 从背景中抠出主体 |
images:tool <tool_key> --body '<json>' | 调用任意工具及其完整控制选项(通过此方式可使用 image-to-image 的 style、aspect_ratio、image_resolution、image_quality、多个 attachments、reference_image_urls) |
每次生成都会返回相同的载荷,其中 data.media_id 是传递给 posts:create --media-id 的句柄。 这两个步骤是发布 AI 图片的常规方式 — 请参阅示例部分中的先生成后发布配方。
{ "ok": true, "data": {
"media_id": "66f1a2b3c4d5e6f708192a3b", // → posts:create --media-id
"url": "https://storage.googleapis.com/.../generated.png",
"width": 1024, "height": 1024, "mime_type": "image/png",
"model_used": "nano-banana-pro", // may differ from --model
"brand_applied": false,
"credits": { "consumed": 1, "available": 412 },
"persist_error": null } }
media_id是持久有效的标识;url不是。 将url用于预览或作为下一个工具的输入。不要保存它——与persist_error一同返回的url是临时的服务提供方链接。- 调用 200 done 前,检查
persist_error(或media_id !== null)。 图片已生成并扣费,但无法保存:media_storage_full表示工作区媒体存储空间已满(重试会再扣一笔额度,而且仍会失败);其他错误值得重试一次。告诉用户立即下载url。 - 工具可以串联使用。 一次调用返回的媒体库
url可作为下一次调用的有效输入(生成 → 放大 → 移除背景)。每次调用都会单独扣费。 - 传入的每个图片 URL 都必须可供图片服务通过 http(s) 公开获取——不能需要身份验证,不能是已过期的签名 URL,不能来自私有存储桶,也不能是本地路径。先使用
media:upload --file上传本地文件,再传入返回的 URL。服务无法下载的 URL 会触发ValidationError(IMAGE_INPUT_REJECTED),而不是服务中断。 - 生成速度慢且会扣费。 服务端截止时间为 120s;CLI 会等待 150s(使用
--timeout <seconds>更改)。这些调用不会重试——它们不会使用内置的 429/5xx 重试机制,因为重新生成可能会再消耗一笔图片额度。请谨慎重试,不要循环重试。 --model是可选项。 省略时使用服务默认值。费用各不相同(大多数模型消耗 1 个图片额度,gpt-image-2消耗 5 个,gpt-image-2.5-flare消耗 3 个,gpt-image-2.5-sunburst消耗 5 个),因此请查看credits.consumed,不要想当然。images:models会列出每个模型的credits_per_image。所有列出的模型,包括gpt-image-2.5-flare和gpt-image-2.5-sunburst,都支持生成和编辑(--image-url)。--background <auto|opaque|transparent>用于设置图片背景(作为image_background发送)。只有gpt-image-2.5-flare和gpt-image-2.5-sunburst会使用此设置;其他所有模型都会静默忽略。为徽标、贴纸和抠图使用--background transparent,并搭配这两个模型之一。model_used不是images:models的取值之一——它会带有服务提供方前缀返回(fal-ai/nano-banana-pro、pixelcut/background-removal),表示回退后实际运行的模型。请报告此值;切勿将它与--model做相等比较。images:tools中的controls描述的是底层工具,而非公开载荷。 从中获取--resolution/--aspect-ratio的取值,但如果某个控件没有对应的标志,就完全无法发送——upscale列出model和upscale_factor,但这两者都不在 API 的工具载荷中。同样,headshot和face-swap上的accepts_instructions: true也无法使用:只有images:product-image支持--instructions。发送不受支持的字段会被静默丢弃,因此看起来会像是生效了。--dimensions可设为square、square_hd、portrait_4_5或landscape_16_9,且仅适用于文本→图片。具体像素尺寸由模型决定——请读取返回的width/height。其他任何值都会在调用前被 CLI 拒绝。- 品牌知识是布尔值,且为只读。
--use-brand仅适用于images:generate;它会在服务端解析,不会接受或返回品牌 ID 或品牌内容。没有品牌资料时使用--use-brand会返回brand_applied: false,而非报错——images:brand会提前告知你。工具命令和images:generate --image-url始终会报告brand_applied: false——编辑和工具不会应用品牌知识。 - 所有生成命令上的
--dry-run都会打印端点和请求正文,但不会发起调用。可用它在消耗额度前向用户展示提示词。三个发现命令属于读取操作,无需使用--dry-run。 - 速率限制:每分钟 30 次请求,并与同一账户下 ContentStudio 应用自身的 AI 使用量共享。发生
RateLimitError时,需等待整整一分钟。 - 视频工具(
image-to-video、motion-control、lip-sync、talking-avatar)不属于此 API;请求其中任意工具都会触发NotFoundError(TOOL_NOT_FOUND),与未知键的处理方式相同。 images:tools返回空列表表示目录暂时无法访问,而非工作区没有工具。请重试,不要告诉用户没有可用工具。- 示例工作区为只读:三个发现命令可以正常使用,两种生成路径都会返回 403。
AI 视频
| 命令 | 用途 |
|---|---|
ai-video:tools | 列出已启用的 AI 视频工具(key、label、description?、inputs[]、controls[]) |
ai-video:models | 列出 ai-video:generate / ai-video:estimate 可选择的所有模型(key、provider、modes[]、supported_resolutions?、supported_durations?、supported_ratios?、supports_audio?、默认值) |
ai-video:estimate [--duration] [--model] [--resolution] [--mode text-to-video|image-to-video|reference-to-video] [--audio] [--aspect-ratio] [--enhance-prompt] | 估算实际积分和耗时。不提交任务,也不扣费 |
ai-video:generate --prompt "..." [--image-url | --reference-image-url <url> (repeatable)] [--model] [--duration] [--resolution] [--aspect-ratio] [--audio] [--enhance-prompt] [--style] [--use-brand] | 提交异步视频生成任务 |
ai-video:run-tool motion-control --image-url <url> --video-url <url> | 将驱动视频中的动作应用到源图像 |
ai-video:run-tool lip-sync --video-url <url> --audio-url <url> | 让视频中的嘴部动作与音轨同步 |
ai-video:run-tool talking-avatar --image-url <url> --audio-url <url> | 根据音频将静态图像制作成会说话的虚拟形象 |
ai-video:jobs [--status queued|processing|completed|failed|cancelled] [--page] [--per-page] | 分页列出通过此 API 提交的视频任务(不包含聊天/内部工具任务) |
ai-video:job <job_id> | 查看单个任务状态 — 终态时返回本地快照,否则实时轮询 |
ai-video:cancel-job <job_id> | 取消仍在进行的任务。已消耗的部分工作可能会产生费用 |
ai-video:generate 说明:
- 必须提供
--prompt,最多 1000 个字符。 - 不提供
--image-url和--reference-image-url时,使用文生视频模式。--image-url会切换到图生视频模式。--reference-image-url(可重复,最多 8 个)会切换到参考图生视频模式。--image-url和--reference-image-url不能同时使用 — 如果同时设置,CLI 会在本地抛出ConfigError。 --use-brand(默认为 false)会在服务端解析品牌素材 — 没有--brand-id标志;后端不接受该参数。- 响应中的
data:{ job_id, status_url (指向 ai-video:job 的相对路径), status, estimated_credits, estimated_seconds? }。轮询ai-video:job <job_id>(或直接获取status_url),直到status为终态。
ai-video:run-tool <tool_key> 说明:
tool_key是ai-video:tools返回的键之一 — 目前包括motion-control、lip-sync、talking-avatar。CLI 会在发送前于本地校验所需的输入组合(motion-control→ 图像+视频,lip-sync→ 视频+音频,talking-avatar→ 图像+音频);缺少必需标志时会抛出ConfigError。- 不提供预估值 — 响应中的
estimated_credits/estimated_seconds始终为null。如果上述标志未涵盖较新的工具,请运行ai-video:tools查看每个工具声明的inputs[]/controls[]。
ai-video:jobs / ai-video:job / ai-video:cancel-job 说明:
ai-video:jobs只会返回通过此 API 提交的任务 — 聊天/内部工具生成的任务不会显示。- 任务
status为queued、processing、completed、failed或cancelled之一。stage/message/result/credits/brand_applied会根据状态而显示。 - 如果任务已完成、失败或已取消,
ai-video:cancel-job会返回 409(ConflictError)及JOB_ALREADY_TERMINAL— 不确定时,请先检查ai-video:job <job_id>。
AI 视频专属错误(以及下方标准表格中的错误):403 INSUFFICIENT_VIDEO_CREDITS(积分不足 — 显示为 AuthError)、403 STORAGE_LIMIT_EXCEEDED(显示为 AuthError)、404 TOOL_NOT_FOUND / JOB_NOT_FOUND(NotFoundError)、409 JOB_ALREADY_TERMINAL(ConflictError)、502 AI_SERVICE_UNAVAILABLE / 504 AI_SERVICE_TIMEOUT(BackendError — 短暂退避后可安全重试)。
查找表(读取)
| 命令 | 用途 |
|---|---|
campaigns:list | 列出营销活动(文件夹) |
categories:list | 列出内容类别 |
labels:list | 列出标签 |
team:list | 列出工作区团队成员 |
approval-workflows:list | 列出审批工作流(使用某个条目的 id 作为 --approval-workflow-id) |
每个 approval-workflows:list 条目均为 { id, name, is_default, levels: [{ level_number, title, rule, members: [{ user_id }] }] }。将 id 用作 posts:create / posts:update 的 --approval-workflow-id。
与该组中的其他命令一样,approval-workflows:list 需要 manage_workflow 权限——请参阅下方的审批工作流(写入)。categories:list 是内容类别(写入)+ 发布时段的入口。
内容类别(写入)+ 发布时段
内容类别是一个常青内容池:放入其中的帖子会分配到该类别每周的时段,而不是单独指定时间。使用 categories:list 查找类别,然后:
| 命令 | 用途 |
|---|---|
categories:get <category_id> | 读取一个类别——响应会内嵌 slots[],因此无需再次调用 |
categories:create --name <n> --color <color_N> [--account <id>…] [--allowed-member <user_id>…] | 创建类别 |
categories:update <category_id> [--name] [--color] [--account…] [--allowed-member…] | 部分更新 |
categories:delete <category_id> | 删除类别 |
categories:shuffle <category_id> | 将该类别即将发布的帖子重新分配到各个时段 |
category-slots:list <category_id> | 列出该类别每周的时段 |
category-slots:next <category_id> [--post-id <id>] | 确定下一个空闲时段 |
category-slots:create <category_id> --day <d> --hour <h> --minute <m> --period AM|PM | 添加一个时段 |
category-slots:update <category_id> <slot_id> [--day] [--hour] [--minute] [--period] | 部分更新一个时段 |
category-slots:delete <category_id> <slot_id> | 删除一个时段 |
--name最多 100 个字符;--color为color_1…color_20(与标签/营销活动使用相同的枚举值)。- 可重复使用的
--account接受跨平台混合的单个扁平列表社交账号 ID,而不是按平台划分的映射。可重复使用的--allowed-member接受团队成员的 user id;每个 ID 都必须属于工作区团队,否则调用会返回 422。 - 两个写入命令都会替换传入的数组:
categories:update --account a1会使该类别只保留一个账号。 --day使用小写(sunday…saturday)。--hour使用 12 小时制,范围为0–12,并与--period AM|PM配合使用;12 会规范化为 0,因此小时 12 +AM表示午夜,小时 12 +PM表示正午。--minute的范围为0–59。CLI 会将两者都作为 JSON 整数发送——字符串"12"会绕过后端的正午规范化,并持久化一个调度器无法匹配的小时值。- 时段行包含
weekday_sorting(星期日 = 0)——这是调度器排序使用的索引,因此应按此排序,而不是根据名称重新推导星期顺序。 - 对没有即将发布帖子的类别运行
categories:shuffle,会通过成功响应返回{"shuffled_posts_count": 0}。零是正常结果,不是失败——应报告为“没有内容可重新分配”,而不是错误。 category-slots:next返回{next_slot, timezone, scheduled}。next_slot: null会在 200 响应中返回,表示该类别没有即将到来的时段。--post-id用于查询特定帖子将占用哪个时段;scheduled: true表示返回的是该帖子已有的时间,而非空闲时段。- 错误:
CONTENT_CATEGORY_NOT_FOUND(404)、CONTENT_CATEGORY_ACCESS_DENIED(403)、CONTENT_CATEGORY_IS_GLOBAL(422——无法通过 API 编辑或删除全局类别)、CONTENT_CATEGORY_INVALID_ACCOUNT(422)、CONTENT_CATEGORY_SHUFFLE_FAILED(422)、CONTENT_CATEGORY_SLOT_NOT_FOUND(404)、CONTENT_CATEGORY_SLOT_DUPLICATE(422——该星期/时间已被占用)。
审批工作流(写入)
| 命令 | 用途 |
|---|---|
approval-workflows:get <workflow_id> | 读取一个工作流 |
approval-workflows:create --name <n> --levels '<json>' [--draft] | 创建工作流 |
approval-workflows:update <workflow_id> [--name] [--levels '<json>'] [--draft] [--confirmed] | 部分更新 |
approval-workflows:delete <workflow_id> [--force] | 删除工作流 |
approval-workflows:duplicate <workflow_id> | 将其复制为新的工作流 |
approval-workflows:set-default <workflow_id> | 将其设为工作区默认工作流 |
approval-workflows:remove-default <workflow_id> | 清除默认标记 |
approval-workflows:cascade-job <cascade_job_id> | 查询后台级联任务 |
- 此组中的每条命令(包括
approval-workflows:list)都需要manage_workflow权限。 有权读取帖子的调用者仍可能在此处收到 403;这是权限问题,不是密钥错误,因此不要让用户为此运行auth:login。 --name最多 120 个字符。--levels是 JSON 数组:[{"level_number":1,"title":"Editors","rule":"anyone"|"everyone","members":[{"user_id":"<id>"}]}]。level_number在载荷中必须唯一,每个级别中的成员 ID 必须唯一,且每位成员都必须属于该工作区团队。--draft→is_draft。无成员配置的级别会使工作流成为草稿,无论标记为何值;草稿不能设为默认工作流——对草稿运行set-default会返回CANNOT_SET_DRAFT_AS_DEFAULT(422)。- 创建/更新时不接受
is_default——请使用set-default将其设为默认工作流。 - 更新时使用
--confirmed会将编辑后的工作流重新应用于已在审核中的帖子。 此时会返回带有cascade_job_id的 202 响应,而不是工作流;写入已完成,但重新应用仍在进行中。请使用approval-workflows:cascade-job <id>查询,直到status变为终态,再告知用户更改已全面生效。不使用--confirmed时,编辑只会影响今后的帖子。 - 存在正在处理的帖子时,删除会被拒绝:返回 422
REQUIRES_FORCE_DELETE,并附带context.in_flight_posts_count。请向用户显示该数量并取得明确同意,然后再使用--force重新运行——强制删除会删除工作流并清理这些帖子(202 +cascade_job_id)。当刚刚删除的是工作区默认工作流时,响应还会带有was_default: true;在另一个工作流被设为默认之前,工作区将没有默认工作流,请告知用户。 - 错误:
APPROVAL_WORKFLOW_NOT_FOUND(404)、CANNOT_SET_DRAFT_AS_DEFAULT(422)、REQUIRES_FORCE_DELETE(422)、CASCADE_JOB_NOT_FOUND(404)。
规划器分享链接
规划器分享链接是一个公开 URL,可向工作区外的人员展示已安排的帖子, 并可选择允许他们评论或批准。
停止——两个互不相关的功能都叫“分享链接”。 如果用户说了“分享链接”“分享一个链接”“给客户端发送一个链接”或其他未明确指出是哪种功能的话,运行任何操作前都要先询问。不要猜测,也不要根据上下文推断。它们会通过不同的端点创建不同的记录,不能互换。
大致询问:
“在 ContentStudio 中,有两种不同的功能都叫分享链接——您想要哪一种? (a)规划器分享链接——向客户展示实际排期的帖子,并可让他们评论或批准/拒绝这些帖子。 (b)分析分享链接——向客户展示实时的分析仪表板/报告:粉丝增长、互动情况、热门帖子。仅显示只读数据,不包含帖子。”
然后:
- (a)→
planner-share-links:*(本节)。正常继续操作。- (b)→ 告知他们这里无法提供此功能。 分析仪表板分享没有公共 API 端点——它仅存在于 Web 应用使用的内部会话认证 API 中,API 密钥无法访问。明确说明这一点,并指引他们前往 ContentStudio Web 应用(Analytics → 报告 → Share)。不要运行
share-links:*并寄希望于它能奏效;请参阅分析:报告、排期、分享链接中的警告。回答(b)时说“我无法在这里帮您完成,但可以告诉您在哪里操作”是正确做法。悄悄创建规划器链接,只因为这是可用的功能,则是不对的——用户要的是数据,结果却收到帖子。
只有在用户已明确指出所需功能时才跳过提问——“规划器分享链接”“让客户批准这些帖子” →(a);“分析分享链接”“分享报告/仪表板” →(b)——或者他们显然是在继续处理本次对话中你已创建的特定链接时,才可跳过。跳过提问仍意味着要按用户明确指出的分支作答:(b)明确无误时,应直接说明“这里无法提供此功能”,而不是创建规划器链接。
| 命令 | 用途 |
|---|---|
planner-share-links:list | 列出工作区的规划器分享链接 |
planner-share-links:get <link_id> | 查看一个链接 |
planner-share-links:create --name <n> [--plan <post_id>…] [--note <id>…] [--scope] [--view] [--calendar-date] [--password] [--single-post] [--allow-comments] [--allow-approval-actions] [--show-notes] [--social-selections '<json>'] | 创建链接 |
planner-share-links:update <link_id> [same fields, plus --disabled / --approval-flow / --approval-email / --approval-option] | 部分更新 |
planner-share-links:delete <link_id> | 删除链接 |
planner-share-links:send-invitations <link_id> --email <e>… --approval-option anyone|everyone | 开启审批,并通过电子邮件邀请 1–10 位审核者 |
planner-share-links:activity <link_id> [--type comment|action] | 查看客户在链接另一端的操作 |
<link_id>是 RECORD id(资源的id),而不是可分享 URL 中公开的link_idslug。该资源会同时返回两者——传入 slug 会得到 404。--name长度为 3–255 个字符,只能包含字母、数字和空格。不允许使用标点符号,因为名称会直接转换为公开 URL 中的 slug。“Q3 Review!”会失败;“Q3 Review”可以。- 每次创建都必须提供
--plan/--note其中之一,包括日历时间范围链接——即使时间范围超出这些帖子,产品也会为可见帖子创建快照。 --scope selection|future|all(默认值为selection),--view list|calendar|compact_list(默认值为list)。future和all仅适用于日历(需要--view calendar),必须提供--calendar-date,且不能收集外部审批(对它们使用--allow-approval-actions会被拒绝)。反过来,selection不允许使用--calendar-date。该参数为自由格式,例如"2026-01-01 - 2026-03-31"。--single-post需要--scope selection和且仅有一个--plan。--password(≥4 个字符)会启用--password-protected;更新时传入--no-password-protected可取消保护。--plan和filters仅用于创建:更新端点会直接拒绝该字段,而不是接受后悄悄丢弃。若要更改链接显示的帖子,请新建链接。- 响应绝不会包含
password或approval_tokens。尚未处理的邀请会以派生字段outstanding_invitations_count显示。 planner-share-links:activity按时间从新到旧返回{total, data[]},每条记录为{type, post_id, name, email, comment, action, created_at}。--type可筛选评论或操作;省略则返回两者。- 如果客户端合作只是暂时暂停,优先使用
planner-share-links:update <id> --disabled,而非:delete——停用可恢复,删除则不可恢复。 - 错误:
SHARE_LINK_NOT_FOUND(404)、SHARE_LINK_TOKEN_REVOKE_FAILED(422)。
标签(写入)
| 命令 | 用途 |
|---|---|
labels:create --name <n> --color <color_N> | 创建标签 |
labels:update <label_id> [--name] [--color] | 更新标签 |
labels:delete <label_id> | 删除标签 |
营销活动(写入)
| 命令 | 用途 |
|---|---|
campaigns:create --name <n> --color <color_N> | 创建营销活动 |
campaigns:update <campaign_id> [--name] [--color] | 更新营销活动 |
campaigns:delete <campaign_id> | 删除营销活动 |
对于标签和营销活动:--name 最多 100 个字符;--color 必须是枚举值 color_1 … color_20 之一。更新时,传入 --name 和/或 --color(传入的每个参数都必须提供值)。
团队成员(写入)
| 命令 | 用途 |
|---|---|
team:add --email <e> --role <r> [--membership team|client] [--permissions '<json>'] | 邀请成员 |
team:update <member_id> --role <r> --permissions '<json>' [--membership] | 更新成员的角色/权限 |
team:remove <member_id> [--confirmed] | 移除成员 |
member_id是成员关系 ID——team:list中的member_id字段(不是用户的id,这是一个单独的字段)。--role(必填):admin、approver或collaborator。--email(team:add必填):单个电子邮件地址。--membership(可选):team(内部成员)或client(外部成员;不会显示在内部备注中)。默认值为team。--permissions(team:add可选,team:update必填):以字符串形式传入、与角色相关的 JSON 对象(例如--permissions '{"addSocial":true}')。JSON 无效 → 本地ConfigError;角色/键组合无效 → 后端返回 422。team:update执行部分合并——仅更改你发送的键;更改角色时,会移除新角色不适用的布尔键。- 通用布尔值(适用于任何角色):
accessSharedFolder、allow_workflow_management。 - admin:完全访问权限——仅适用
hasBillingAccess布尔值。 - collaborator 布尔值:
addBlog、addSocial、addSource、addTopic、viewTeam、rescheduleQueue、postsReview、changeFBGroupPublishAs、hasListeningAccess。 - approver 布尔值:
approverCanEditPost、approverCanAddNotes、approverCanCreatePost(否则 approver 只能批准/拒绝)。 - 账户访问数组(适用于任何角色;必须是工作区中真实且已连接账户的 ID,否则返回 422):
facebook、instagram、threads、twitter、linkedin、pinterest、telegram、youtube、tiktok、tumblr、tumblr_blogs、tumblr_profiles、bluesky、gmb。 - 博客数组(适用于任何角色;不验证是否存在):
wordpress、medium、shopify、webflow。 content_categories(适用于任何角色;必须是工作区中真实类别的 ID,否则返回 422):内容类别 ID 数组。
- 通用布尔值(适用于任何角色):
team:remove:如果成员参与了审批工作流或正在处理的帖子,后端会返回错误代码REQUIRES_REMOVAL_CONFIRMATION(422)——使用--confirmed重新运行(发送?confirmed=true)以继续。404 =TEAM_MEMBER_NOT_FOUND。
社交账户(写入)
| 命令 | 用途 |
|---|---|
accounts:remove <account_id> [--dry-run] | 移除(断开)社交账户(DELETE /workspaces/{w}/accounts/{account_id}) |
account_id是accounts:list中该账户的id。- 需要
save_social权限——没有此权限的调用方会收到 403。 - 错误:401(API 密钥错误/缺失)、403(缺少
save_social)、404(工作区中找不到账户)、422(移除失败)。成功时返回 200,且data数组为空。 - 此命令会修改数据——先用
--dry-run预览,并确认工作区。
Facebook 辅助工具
| 命令 | 用途 |
|---|---|
facebook:text-backgrounds | 列出 Facebook 彩色背景预设(纯文本帖子中将 id 用作 facebook_options.facebook_background_id) |
社交收件箱
收件箱将三种类型的项目统一为元素:conversation(私信)、
post(带评论的帖子)和 review。inbox:list 是入口命令——
其他所有命令都需要传入它返回的 ID。
应传入哪个 ID
收件箱命令所需的 ID 来自每个 inbox:list 行中的 element_details 对象。使用 element_details.element_id——所有针对元素的命令都接受此 ID。
| 命令 | 要传入的 ID |
|---|---|
inbox:update (--element) | element_details.element_id |
inbox:tag-attach / inbox:tag-detach | element_details.element_id |
inbox:mark-read | element_details.element_id |
inbox:contact / inbox:contact-update | element_details.element_id |
inbox:messages / send / notes / note-add / bookmarks | element_details.element_id(t_… 格式) |
inbox:comments / inbox:comment-add | element_details.post_id |
值的形式如下:
element_details.element_id—t_10000000000000001(会话)或100000000000000001_200000000000000002(帖子)element_details.post_id—900000000000001_100000000000000001
该行顶层的 element_ref 是内部引用,不是命令参数 — 请始终从 element_details 获取 ID。
如果命令返回空列表或报告未找到项目,请先根据此表确认 ID,再向用户说明结果。
大多数写入操作还需要:
platform_id— 项目所属的已连接社交账号。后端会通过该账号的令牌回复。每个inbox:list行都有platform_id,也可以从accounts:list获取。- 列表行中的平台字段是
platform(而不是platform_type),但写入命令使用--platform-type。
读取
| 命令 | 用途 |
|---|---|
inbox:list | 搜索收件箱。--type conversation|post|review(可重复),--action all|marked_done|archived|assigned,--search,--tag,--channels '{"facebook":["<acct>"]}',--page,--limit |
inbox:summary | 按类别统计数量 — 快速回答“有未读内容吗?” |
inbox:messages <conversation_id> | 查看私信会话中的消息。ID = element_details.element_id。--sort-order asc|desc |
inbox:comments <post_id> | 查看帖子的评论(含线程)。ID = element_details.post_id |
inbox:notes <conversation_id> | 查看内部备注(仅团队可见)。ID = element_details.element_id。支持分页 |
inbox:bookmarks <conversation_id> | 查看已加星标的消息。ID = element_details.element_id。支持分页 |
inbox:contact <element_ref> | 查看该项目对应的联系人资料 |
inbox:tags | 查看工作区的收件箱标签目录 |
回复 — 面向客户,发送前请确认
| 命令 | 用途 |
|---|---|
inbox:send <conversation_id> | 发送私信(ID = element_details.element_id)。需要 --platform-type facebook|instagram、--platform-id,以及 --message 和/或 --file。--idempotency-key 可避免重试时重复发送 |
inbox:comment-add <post_id> | 评论帖子。--comment-id 用于发布线程回复;--private-reply 用于改为发送 Facebook 私信;--attachment <path> 用于附加文件 |
inbox:review-reply <review_id> | 添加或替换评论回复(upsert)。--platform-id,--reply |
inbox:note-add <conversation_id> | 添加内部备注。--mention <user_id>(可重复)。客户不可见 |
分流与审核
| 命令 | 用途 |
|---|---|
inbox:mark-read <element_ref> | 标记为已读(幂等) |
inbox:update | 批量更改状态。使用 --element(可重复,最多 100 个),并且从 --status done|pending、--archived、--assigned 中恰好选择一个(搭配 --assigned-to '{"id":"<user>"}') |
inbox:comment-hide / inbox:comment-unhide <comment_id> | 隐藏/取消隐藏。取消隐藏需要 --platform-type 和 --platform-id |
inbox:comment-like / inbox:comment-unlike <comment_id> | 仅支持 Facebook |
inbox:comment-delete <comment_id> | 删除。需要 --platform-type 和 --platform-id;LinkedIn 还需要 --comment-urn |
inbox:star / inbox:unstar <message_id> | 为消息加星标/取消星标 |
inbox:message-delete <message_id> | 软删除消息。--platform-id |
inbox:review-reply-delete <review_id> | 删除评论回复。--platform-id |
inbox:contact-update <element_ref> | 使用 --platform-id,并可搭配 --name、--email、--phone、--company 中的任意选项 |
| 标签 |
| 命令 | 用途 |
|---|---|
inbox:tag-create | --name(≤50)、--color — 十六进制值,例如 #33aa55。(较早创建的标签可能显示为 color_1,但 API 现在会拒绝这种格式。) |
inbox:tag-update <tag_id> | --name 和/或 --color |
inbox:tag-delete | --tag <id>(可重复指定,批量操作) |
inbox:tag-merge | 将标签合并到一个新标签中:--name、--color、--tag(可重复指定) |
inbox:tag-attach <element_ref> | --tag(可重复指定)、--platform-id、--inbox-type |
inbox:tag-detach <element_ref> <tag_id> | --platform-id、--inbox-type |
收件箱分页说明。 收件箱列表命令使用 --limit,而不是
--per-page(--per-page 可作为别名使用)。上述章节中的分页规则
保持不变:如果 pagination.has_more 为 true,不要将第一页报告为整个收件箱。
收件箱页面大小为 200。 对于超过此大小的收件箱,应使用
--page 1、--page 2,……一直翻页到pagination.last_page,而不是将--limit提高到 200 以上。
收件箱限制。 CLI 会在本地验证这些限制,因此在发送任何请求之前就会触发
ConfigError:
| 限制 | 适用命令 |
|---|---|
--limit ≤ 200 | inbox:list、inbox:messages、inbox:comments |
每次调用最多 100 个 --element refs | inbox:update |
| 每次调用只能执行一项操作 | inbox:update — --status、--archived 和 --assigned 互斥;请分别运行命令 |
| 标签名称 ≤ 50 个字符 | inbox:tag-create |
批量更新的部分成功。 部分元素已更新、其余未更新时,inbox:update 会返回 HTTP 207,并在
missing_ids 中列出未更新的元素。CLI 会将此情况报告为警告。当 missing_ids
不为空时,请告知用户哪些元素未发生更改,不要声称批量操作已全部完成。
inbox:contact-update 会更新整个联系人。 联系人代表一个人,
而不是单个元素的属性,因此更改会应用于工作区中该账户下此联系人的所有元素。响应中的
updated_count 表示已更新的元素数量。运行此命令前,请向用户说明此影响范围。
inbox:contact 会返回个人数据。 包含最终客户的电子邮件和电话号码。
只返回用户实际要求的字段;未经用户要求,不要在摘要中倾倒整条记录,也不要将其粘贴到持久化位置。
inbox:messages 包含活动事件。 一个会话既包含消息,也包含团队活动记录。活动条目的
message: null,并带有一个 action 块(MARKED_AS_DONE、PENDING、ARCHIVED 等),其中会注明执行操作的队友姓名;这些条目会计入
total_messages 和分页结果。需要获取客户消息时,请筛选 action == null — 不要将活动条目计作消息、将其引用为客户文本,或将其视为最新回复。CLI 在人类可读模式下会将其显示为 — marked as done — 行。
回复是嵌套的,不会单独分页。 在 inbox:comments 中,回复位于每个会话的
children 下 — 它们不是独立的顶层行。分页统计的是会话(total_threads),而不是单条评论,因此分页信息中的“12 条评论”实际表示 12 个会话,其中可能包含更多回复。
发送时遇到 409 的处理方式。 对于 inbox:send 和 inbox:comment-add,409
表示投递结果无法确定 — 消息可能已送达客户,也可能没有。CLI 会将其显示为 ConflictError。不要
自动重试:使用 inbox:messages 读取会话,确认消息是否已送达,并在再次发送前告知用户检查结果。
确认发送结果。 inbox:send 会返回 sent_message.id_status。如果其值为
unavailable,则表示平台已接受消息,但没有返回 ID,因此之后无法通过 ID 核对 — 请报告消息已发送,但投递情况尚未确认。
收件箱专属响应。 inbox:* 命令返回 502,表示收件箱服务暂时无法访问,而不是条目不存在——稍等片刻后重试。inbox:list 返回空结果,表示成功读取但内容为空:应报告为“没有匹配的对话”,而不是“未找到”。
分析
跨 Facebook、Instagram、YouTube、Pinterest、LinkedIn、Google Business Profile、TikTok、Twitter/X、Meta Ads 和 Google Ads 的只读性能报告,以及跨网络的 Campaigns & Labels 报告(共 133 条命令,每个后端端点对应一条——没有通用直通命令)。
大多数命令需要 --platform-id(已连接的账户,可从 accounts:list 获取),以及日期范围或原生帖子 ID。广告和 Campaign/Label 系列命令是例外——详见下文:
- 日期范围报告 —
--start-date/--end-date(YYYY-MM-DD,两者都必填)。大多数命令还可选用:--timezone(IANA 名称,默认值为 UTC)、--date(替代格式'YYYY-MM-DD - YYYY-MM-DD',会覆盖日期范围)、--limit/--offset、--order-by(可选项因命令而异——请查看--help),以及数组筛选项,如--media-type、--hashtags、--entity-type(多个值需重复指定该标志)。 - 单条目查询(
*-single-post、*-single-pin、*-single-tweet、*-single-video)—--platform-id+--post-id(平台原生 ID,不是 ContentStudio 内部 ID)。无需日期范围。 - AI 洞察命令(
*-ai-insights)还需要--type(精简卡片使用aiInsightsSummary,完整报告使用aiInsightsDetailed)和--language(ISO 639-1,默认值为en)。两个广告平台也各有一条此类命令。 - 广告报告(
analytics:meta-ads-*、analytics:google-ads-*)需要--account-id——即广告账户(Meta 上的act_…,Google 上的客户 ID,可从analytics:meta-ads-accounts/analytics:google-ads-accounts获取),而不是--platform-id。表格命令还支持--limit/--offset、--search、--order-by/--order-dir和 ID 筛选项(--campaign-id、--ad-set-id、--ad-group-id);图表命令还支持--metric和--level。analytics:*-ads-accounts无需账户——它用于查找账户。 - Campaigns & Labels(
analytics:campaigns-labels-*)是唯一使用 POST 的报告:筛选项为列表,因此需重复指定标志——--campaigns <id> --campaigns <id>、--labels <id>,以及每个网络对应的一组账户列表(--facebook-accounts、--instagram-accounts,等等)。只有--start-date/--end-date是必填项。
运行 contentstudio analytics:<command> --help,查看任一命令的确切选项——不同端点的必填项、可选项和枚举值各不相同。
所有分析命令都是只读的——Campaign/Label 命令使用 POST 仅仅是因为其筛选项为数组——因此这些命令都不接受 --dry-run(该标志仅用于此 CLI 中其他会修改数据的命令)。
如果命令返回 ANALYTICS_UPSTREAM_ERROR(HTTP 200 且 status: false,通常还带有 upstream_status: 401),表示 ContentStudio 后端自身的分析处理流程在上游发生故障——不是请求错误。应报告为“分析服务暂时不可用”,不要循环重试完全相同的调用,也不要据此认定账户或工作区有问题。
Facebook(12)
| 命令 | 用途 | 必需参数 |
|---|---|---|
analytics:facebook-ai-insights | Facebook AI 生成的洞察 | --platform-id, --start-date, --end-date |
analytics:facebook-audience-growth | Facebook 粉丝/关注者随时间的增长 | --platform-id, --start-date, --end-date |
analytics:facebook-audience-location | Facebook 受众所在地(按国家/城市细分);--country 可缩小城市列表范围 | --platform-id, --start-date, --end-date |
analytics:facebook-engagement | Facebook 专页互动随时间的变化 | --platform-id, --start-date, --end-date |
analytics:facebook-get-top-posts | Facebook 热门帖子,可按 media_type 筛选 | --platform-id, --start-date, --end-date |
analytics:facebook-impressions | Facebook 专页展示次数随时间的变化 | --platform-id, --start-date, --end-date |
analytics:facebook-overview-top-posts | Facebook 热门帖子(概览小组件) | --platform-id, --start-date, --end-date |
analytics:facebook-publishing-behaviour | Facebook 按展示类型统计的互动随时间的变化 | --platform-id, --start-date, --end-date |
analytics:facebook-reels | Facebook Reels 表现随时间的变化 | --platform-id, --start-date, --end-date |
analytics:facebook-single-post | 按 ID 获取单条 Facebook 帖子 | --platform-id, --post-id |
analytics:facebook-summary | Facebook 汇总 KPI——当前与上一时期对比 | --platform-id, --start-date, --end-date |
analytics:facebook-video-insights | Facebook 视频观看时长和播放次数随时间的变化 | --platform-id, --start-date, --end-date |
Instagram(15)
| 命令 | 用途 | 必需参数 |
|---|---|---|
analytics:instagram-active-users | 按小时和星期几统计 Instagram 活跃用户 | --platform-id, --start-date, --end-date |
analytics:instagram-ai-insights | Instagram AI 生成的洞察 | --platform-id, --start-date, --end-date |
analytics:instagram-audience-growth | Instagram 关注者随时间的增长 | --platform-id, --start-date, --end-date |
analytics:instagram-country-city | Instagram 受众国家/城市细分;--country 可缩小城市列表范围 | --platform-id, --start-date, --end-date |
analytics:instagram-demographics-age | Instagram 受众年龄/性别细分 | --platform-id, --start-date, --end-date |
analytics:instagram-engagement | Instagram 帖子互动随时间的变化 | --platform-id, --start-date, --end-date |
analytics:instagram-get-top-posts | Instagram 热门帖子,可按 hashtag 筛选 | --platform-id, --start-date, --end-date |
analytics:instagram-hashtags | 按互动量统计的 Instagram 热门 hashtag | --platform-id, --start-date, --end-date |
analytics:instagram-impressions | Instagram 帖子展示次数随时间的变化 | --platform-id, --start-date, --end-date |
analytics:instagram-publishing-behaviour | Instagram 按媒体类型统计的帖子互动随时间的变化 | --platform-id, --start-date, --end-date |
analytics:instagram-reels-performance | Instagram Reels 互动和观看时长随时间的变化 | --platform-id, --start-date, --end-date |
analytics:instagram-single-post | 按 ID 获取单条 Instagram 帖子 | --platform-id, --post-id |
analytics:instagram-stories-performance | Instagram 快拍展示次数、覆盖人数和互动随时间的变化 | --platform-id, --start-date, --end-date |
analytics:instagram-summary | Instagram 汇总 KPI——当前与上一时期对比 | --platform-id, --start-date, --end-date |
analytics:instagram-top-posts | Instagram 表现最佳的帖子 | --platform-id, --start-date, --end-date |
YouTube(20)
| 命令 | 用途 | 必需参数 |
|---|---|---|
analytics:youtube-ai-insights | YouTube AI 生成的洞察 | --platform-id, --start-date, --end-date |
analytics:youtube-demographics | YouTube 受众人口统计信息——年龄与性别、设备类型、订阅者变化 | --platform-id, --start-date, --end-date |
analytics:youtube-engagement-trend | YouTube 随时间变化的累计互动趋势 | --platform-id, --start-date, --end-date |
analytics:youtube-engagement-trend-daily | YouTube 每日增量互动趋势 | --platform-id, --start-date, --end-date |
analytics:youtube-find-video | YouTube 流量来源细分(观众如何找到视频) | --platform-id, --start-date, --end-date |
analytics:youtube-least-posts | 按观看次数和互动量排序的 YouTube 表现最差视频 | --platform-id, --start-date, --end-date |
analytics:youtube-performance-schedule | 按发布日期分组的 YouTube 视频表现指标 | --platform-id, --start-date, --end-date |
analytics:youtube-publishing-behaviour | YouTube 随时间发布的帖子及内容类型细分 | --platform-id, --start-date, --end-date |
analytics:youtube-single-video | 按 ID 获取单个 YouTube 视频 | --platform-id, --post-id |
analytics:youtube-sorted-top-posts | 按可配置指标排序的 YouTube 视频 | --platform-id, --start-date, --end-date |
analytics:youtube-subscriber-trend | YouTube 随时间变化的累计订阅者趋势 | --platform-id, --start-date, --end-date |
analytics:youtube-subscriber-trend-daily | YouTube 每日增量订阅者趋势 | --platform-id, --start-date, --end-date |
analytics:youtube-summary | YouTube 摘要 KPI——当前时段与上一时段对比 | --platform-id, --start-date, --end-date |
analytics:youtube-top-geographies | YouTube 热门地理位置——按观看次数、观看时长、观看持续时间和观看百分比预先排序的国家/地区 | --platform-id, --start-date, --end-date |
analytics:youtube-top-posts | 按观看次数和互动量排序的 YouTube 热门视频 | --platform-id, --start-date, --end-date |
analytics:youtube-video-sharing | YouTube 分享平台细分 | --platform-id, --start-date, --end-date |
analytics:youtube-views-trend | YouTube 累计观看次数,按订阅者/非订阅者细分 | --platform-id, --start-date, --end-date |
analytics:youtube-views-trend-daily | YouTube 每日增量观看趋势 | --platform-id, --start-date, --end-date |
analytics:youtube-watch-time-trend | YouTube 累计观看时长,按订阅者/非订阅者细分 | --platform-id, --start-date, --end-date |
analytics:youtube-watch-time-trend-daily | YouTube 每日增量观看时长趋势 | --platform-id, --start-date, --end-date |
Pinterest(14)
| 命令 | 用途 | 必需参数 |
|---|---|---|
analytics:pinterest-ai-insights | Pinterest AI 生成的洞察 | --platform-id, --start-date, --end-date |
analytics:pinterest-engagement-trend | Pinterest 随时间变化的累计互动趋势 | --platform-id, --start-date, --end-date |
analytics:pinterest-engagement-trend-daily | Pinterest 每日互动增量趋势 | --platform-id, --start-date, --end-date |
analytics:pinterest-follower-trend | Pinterest 随时间变化的累计粉丝趋势 | --platform-id, --start-date, --end-date |
analytics:pinterest-follower-trend-daily | Pinterest 每日粉丝增量趋势 | --platform-id, --start-date, --end-date |
analytics:pinterest-impressions-trend | Pinterest 随时间变化的累计展示量趋势 | --platform-id, --start-date, --end-date |
analytics:pinterest-impressions-trend-daily | Pinterest 每日展示量增量趋势 | --platform-id, --start-date, --end-date |
analytics:pinterest-pin-performance | Pinterest Pin 随时间变化的表现指标 | --platform-id, --start-date, --end-date |
analytics:pinterest-pin-posting | Pinterest 随时间变化的累计 Pin 发布活动 | --platform-id, --start-date, --end-date |
analytics:pinterest-pin-posting-daily | Pinterest 每日 Pin 发布活动增量 | --platform-id, --start-date, --end-date |
analytics:pinterest-pin-rollup | Pinterest Pin 表现汇总——当前周期与上一周期对比 | --platform-id, --start-date, --end-date |
analytics:pinterest-single-pin | 按 ID 获取单个 Pinterest Pin | --platform-id, --post-id |
analytics:pinterest-summary | Pinterest 汇总 KPI——当前周期与上一周期对比 | --platform-id, --start-date, --end-date |
analytics:pinterest-top-pins | Pinterest 表现最佳和最差的 Pin | --platform-id, --start-date, --end-date |
LinkedIn(11)
| 命令 | 用途 | 必需参数 |
|---|---|---|
analytics:linkedin-ai-insights | LinkedIn AI 生成的洞察 | --platform-id, --start-date, --end-date |
analytics:linkedin-audience-growth | LinkedIn 粉丝数量随时间的增长情况 | --platform-id, --start-date, --end-date |
analytics:linkedin-followers-demographics | 按行业、国家/地区及其他维度划分的 LinkedIn 粉丝人口统计信息 | --platform-id, --start-date, --end-date |
analytics:linkedin-get-top-posts | LinkedIn 热门帖子,可按话题标签和媒体类型筛选 | --platform-id, --start-date, --end-date |
analytics:linkedin-hashtags | 按互动量排名的 LinkedIn 热门话题标签 | --platform-id, --start-date, --end-date |
analytics:linkedin-page-views | 随时间变化的 LinkedIn 页面浏览量(桌面端与移动端) | --platform-id, --start-date, --end-date |
analytics:linkedin-posts-per-days | 按星期几分布的 LinkedIn 帖子数量 | --platform-id, --start-date, --end-date |
analytics:linkedin-publishing-behaviour | 随时间变化的 LinkedIn 帖子互动量(按媒体类型划分) | --platform-id, --start-date, --end-date |
analytics:linkedin-single-post | 按 ID 获取单条 LinkedIn 帖子 | --platform-id, --post-id |
analytics:linkedin-summary | LinkedIn 汇总 KPI——当前周期与上一周期对比 | --platform-id, --start-date, --end-date |
analytics:linkedin-top-posts | LinkedIn 表现最佳的帖子 | --platform-id, --start-date, --end-date |
Google Business Profile(GMB)(10)
| Command | 用途 | 必填项 |
|---|---|---|
analytics:gmb-actions | GMB 客户操作(点击、来电、路线查询)随时间的变化 | --platform-id, --start-date, --end-date |
analytics:gmb-ai-insights | GMB AI 生成的洞察 | --platform-id, --start-date, --end-date |
analytics:gmb-impressions | GMB 展示量按渠道和设备的时间变化 | --platform-id, --start-date, --end-date |
analytics:gmb-media-activity | GMB 媒体(照片/视频)活动随时间的变化 | --platform-id, --start-date, --end-date |
analytics:gmb-publishing-behavior | GMB 帖子发布量随时间的变化及主题类型细分 | --platform-id, --start-date, --end-date |
analytics:gmb-reviews | GMB 评价——评分、分布和每日活动 | --platform-id, --start-date, --end-date |
analytics:gmb-search-keywords | 使商家信息出现在搜索结果中的 GMB 热门搜索关键词 | --platform-id, --start-date, --end-date |
analytics:gmb-single-post | 按 ID 获取单条 GMB 帖子 | --platform-id, --post-id |
analytics:gmb-summary | GMB 摘要 KPI——当前周期与上一周期对比 | --platform-id, --start-date, --end-date |
analytics:gmb-top-posts | GMB 表现最佳的帖子 | --platform-id, --start-date, --end-date |
TikTok(8)
| Command | 用途 | 必填项 |
|---|---|---|
analytics:tiktok-ai-insights | TikTok AI 生成的洞察 | --platform-id, --start-date, --end-date |
analytics:tiktok-engagement-trend | TikTok 每日互动趋势随时间的变化 | --platform-id, --start-date, --end-date |
analytics:tiktok-follower-trend | TikTok 粉丝数和观看量趋势随时间的变化 | --platform-id, --start-date, --end-date |
analytics:tiktok-publishing-behaviour | TikTok 每日帖子发布量和互动细分随时间的变化 | --platform-id, --start-date, --end-date |
analytics:tiktok-single-post | 按 ID 获取单条 TikTok 帖子 | --platform-id, --post-id |
analytics:tiktok-sorted-top-posts | 按可配置指标排序的 TikTok 帖子 | --platform-id, --start-date, --end-date |
analytics:tiktok-summary | TikTok 摘要 KPI——当前周期与上一周期对比 | --platform-id, --start-date, --end-date |
analytics:tiktok-top-posts | TikTok 表现最佳和最差的帖子 | --platform-id, --start-date, --end-date |
Twitter/X(7)
| Command | 用途 | 必填项 |
|---|---|---|
analytics:twitter-credits-used | 工作区的 Twitter API 积分使用情况 | --platform-id, --start-date, --end-date |
analytics:twitter-engagement-impression | Twitter 互动量和展示量趋势随时间的变化 | --platform-id, --start-date, --end-date |
analytics:twitter-followers-trend | Twitter 粉丝数趋势随时间的变化 | --platform-id, --start-date, --end-date |
analytics:twitter-least-tweets | Twitter 表现最差的推文 | --platform-id, --start-date, --end-date |
analytics:twitter-single-tweet | 按 ID 获取单条 Twitter/X 推文 | --platform-id, --post-id |
analytics:twitter-summary | Twitter 摘要 KPI——当前周期与上一周期对比 | --platform-id, --start-date, --end-date |
analytics:twitter-top-tweets | Twitter 表现最佳的推文 | --platform-id, --start-date, --end-date |
Meta Ads(11)
| 命令 | 用途 | 必需参数 |
|---|---|---|
analytics:meta-ads-accounts | 列出已连接的 Meta 广告账户 | — |
analytics:meta-ads-ad-sets | 广告组及各广告组的指标 | --account-id, --start-date, --end-date |
analytics:meta-ads-ads | 广告及各广告的指标和创意详情 | --account-id, --start-date, --end-date |
analytics:meta-ads-ai-insights | 为广告账户生成的 AI 洞察 | --account-id, --start-date, --end-date, --type |
analytics:meta-ads-campaigns | 广告系列及各广告系列的指标 | --account-id, --start-date, --end-date |
analytics:meta-ads-demographics | 按年龄和性别、地区或国家划分的受众细分 | --account-id, --start-date, --end-date |
analytics:meta-ads-performance-by-level | 按广告系列、广告组或广告细分的一项指标 | --account-id, --start-date, --end-date |
analytics:meta-ads-performance-by-placement | 按发布平台和版位细分的一项指标 | --account-id, --start-date, --end-date |
analytics:meta-ads-performance-over-time | 一项或多项指标的每日时间序列 | --account-id, --start-date, --end-date |
analytics:meta-ads-results-by-objective | 按广告系列目标分组的成效和支出 | --account-id, --start-date, --end-date |
analytics:meta-ads-summary | Meta Ads 核心 KPI——当前周期与上一周期对比 | --account-id, --start-date, --end-date |
Google Ads(17)
| 命令 | 用途 | 必需参数 |
|---|---|---|
analytics:google-ads-accounts | 列出已连接的 Google Ads 账户 | — |
analytics:google-ads-ad-groups | 广告组及各广告组的指标 | --account-id, --start-date, --end-date |
analytics:google-ads-ads | 广告及各广告的指标 | --account-id, --start-date, --end-date |
analytics:google-ads-ai-insights | 为广告账户生成的 AI 洞察 | --account-id, --start-date, --end-date, --type |
analytics:google-ads-campaigns | 广告系列及各广告系列的指标 | --account-id, --start-date, --end-date |
analytics:google-ads-conversion-actions | 账户上配置的转化操作 | --account-id, --start-date, --end-date |
analytics:google-ads-conversion-funnel | 转化漏斗——从展示到转化 | --account-id, --start-date, --end-date |
analytics:google-ads-conversions-by-action | 按转化操作分组的转化次数 | --account-id, --start-date, --end-date |
analytics:google-ads-conversions-over-time | 随时间变化的转化次数 | --account-id, --start-date, --end-date |
analytics:google-ads-demographics | 按年龄、性别和位置划分的受众细分 | --account-id, --start-date, --end-date |
analytics:google-ads-keywords | 关键词及各关键词的指标 | --account-id, --start-date, --end-date |
analytics:google-ads-performance-by-level | 按广告系列、广告组或广告细分的一项指标 | --account-id, --start-date, --end-date |
analytics:google-ads-performance-by-type | 按广告系列类型细分的一项指标 | --account-id, --start-date, --end-date |
analytics:google-ads-performance-over-time | 一项或多项指标的每日时间序列 | --account-id, --start-date, --end-date |
analytics:google-ads-search-terms | 搜索词及各搜索词的指标 | --account-id, --start-date, --end-date |
analytics:google-ads-shopping | 购物广告系列的商品表现 | --account-id, --start-date, --end-date |
analytics:google-ads-summary | Google Ads 核心 KPI——当前周期与上一周期对比 | --account-id, --start-date, --end-date |
广告系列与标签(5)
| Command | 用途 | 必填 |
|---|---|---|
analytics:campaigns-labels-breakdown | 按营销活动和标签统计总数,并对比当前与上一时段 | --start-date, --end-date |
analytics:campaigns-labels-insights-breakdown | 按营销活动和标签统计每日时间序列 | --start-date, --end-date |
analytics:campaigns-labels-posts | 所选营销活动和标签的单条帖子数据表 | --start-date, --end-date |
analytics:campaigns-labels-summary | 营销活动和标签的摘要 KPI——对比当前与上一时段 | --start-date, --end-date |
analytics:campaigns-labels-top-posts | 所选营销活动和标签在各网络上的前 5 条帖子 | --start-date, --end-date |
分析:报告、计划和分享链接
报告采用异步处理。reports:generate 会立即返回一个 id,实际工作会在其他地方进行,因此切勿将创建响应视为已完成的报告——请轮询 reports:get <id> --wait,或传入 --callback-url,以便系统主动通知,而不是由你主动查询。报告在 status 为 completed 且 export_url 已填充时即表示完成;failed 也是终态,而 reports:retry 会根据已存储的定义重新运行,无需重新构建请求。
请先使用 reports:options,不要凭空猜测:它会返回此工作区可生成的报告类型,以及每种类型接受的版块;产品自身的版块选择器读取的也是同一份目录。
两种竞品类型需要的是竞品集合,而非账号。
facebook_competitor 和 instagram_competitor 根据已保存的集合生成,因此需要 --competitor-report-id(来自 competitor-reports:list),并会忽略 --accounts。将集合 id 放进 --accounts 是很容易犯的错误;系统会在发出调用前拒绝该请求——过去这种做法会被接受、随后丢弃,几分钟后才显示为“Combined report generation failed”。
⚠️
share-links:*命令无法使用——每个命令都会返回 404。 它们指向/api/v1/workspaces/{w}/analytics/share-links,但根本不存在这样的路由。分析分享链接仅存在于内部 SPA API(/api/analytics/share-link/create|list|update|delete,路径段为单数,动词也不同),而该 API 使用 API 密钥无法通过的会话/JWT 身份验证——因此也不能简单地将这些命令改指向该 API。不要将此问题当作身份验证、工作区或密钥问题来排查,也不要重试。 调用方无法修复此问题。如果用户想分享分析仪表板,请告知他们公共 API 不提供此功能,并引导他们前往 ContentStudio Web 应用(Analytics → 报告 → Share)。
本节的其他所有内容——
reports:*、report-schedules:*、competitor*:*——均不受影响,且可正常使用。
分享分析仪表板是 Web 应用专属功能。 客户端无需账号也能查看实时数据仪表板,但该链接必须在 Web 应用中创建;此 API 不提供此功能(见上方警告)。链接创建后不会过期——它会一直有效,直到有人在应用中停用或删除它;如果客户合作只是暂时暂停,停用是可撤销的选项。此类链接独立于任何生成的报告:它展示的是实时仪表板,而不是 PDF。
不要将其与 planner-share-links:* 混淆;后者用于分享已排期的帖子,以便客户评论/审批,且在此处完全受支持。当用户只说“分享链接”时,请先询问他们指的是哪一种,再进行任何操作——参见 Planner 分享链接下的提示框。
report-schedules:run 会请求立即发送,但 API 只会确认请求,不会返回报告 id。请使用 report-schedules:get 确认,并检查 last_run_at 是否已更新,然后再告知用户报告已发送。
分析:竞争对手
“报告”一词指代两种不同的内容。竞争对手报告是已保存的竞争对手集合,用于进行基准比较——它没有状态,也不会生成文件。比较数据需通过 competitors:compare 单独读取。
配置顺序很重要:先运行 competitors:search,因为竞争对手是一个对象(competitor_id 加上 name),而不是一个单独的 ID。competitor-reports:create 接受简写形式 --competitors 'id:Name,id:Name' 或 JSON 数组,并会为你展开内容。
无法跟踪的页面会返回带有 reason 的空结果——这是一次成功的读取,不是错误。请告知用户哪个页面无法跟踪以及原因,而不要报告失败。
competitor-reports:update 会替换整个集合,因此请发送所有要保留的竞争对手,而不只是新增的那个。
读取比较数据时,请留意每一行的 state。只有 Processed 才表示该时间段的测量已完成——其他状态的竞争对手显示为零,意味着未测量,而不是互动量为零。切勿将这些值作为结果展示。
示例
验证已存储的密钥是否有效
contentstudio --json auth:whoami
# → {"ok": true, "data": {"id": "...", "email": "...", "full_name": "..."}}
查找可用于发布内容的 Facebook 账号
contentstudio --json accounts:list --platform facebook --per-page 10
# Pick an _id, e.g. <account_id>
创建帖子示例
创建会修改数据的帖子前,务必先使用 --dry-run 预览 — 它会返回 {"ok": true, "data": {"dry_run": true, "endpoint": "...", "body": {...}}},且绝不会调用 API。移除 --dry-run 即可实际创建。
1. 纯文本草稿
contentstudio --json posts:create \
-c "Our new blog is live!" \
-i <account_id> \
-t draft
2. 文本 + 单张图片,设置日期定时发布
contentstudio --json posts:create \
-c "Our new blog is live! https://example.com/post" \
-i <account_id> \
-t scheduled \
-s "2026-05-01 10:00:00" \
-m https://example.com/hero.jpg
3. 文本 + 多张图片(重复使用 -m)
contentstudio --json posts:create \
-c "Gallery drop 📸" \
-i <account_id> \
-t scheduled \
-s "2026-05-02 09:00:00" \
-m https://example.com/1.jpg \
-m https://example.com/2.jpg \
-m https://example.com/3.jpg
4. 文本 + 视频
contentstudio --json posts:create \
-c "Watch our launch reel 🎬" \
-i <account_id> \
-t scheduled \
-s "2026-05-03 12:00:00" \
--video-url https://example.com/launch.mp4
5. 排队发布的帖子(加入发布队列;不指定具体时间)
contentstudio --json posts:create \
-c "Filler post for the queue" \
-i <account_id> \
-t queued
6. 内容分类帖子(账号来自该分类 — 不要使用 --account)
# Find a category id first:
contentstudio --json categories:list
# --content-category-id is required for -t content_category:
contentstudio --json posts:create \
-c "Evergreen tip of the day" \
-t content_category \
--content-category-id <category_id>
7. 需要审批工作流的帖子(两位审批人,且都必须批准)
contentstudio --json posts:create \
-c "Quarterly results announcement" \
-i <account_id> \
-t scheduled \
-s "2026-05-05 08:00:00" \
--approver <user_id_1> \
--approver <user_id_2> \
--approve-option everyone \
--approval-notes "Legal + comms must both sign off"
8. 带标签和营销活动的帖子(重复使用 --label)
contentstudio --json posts:create \
-c "Spring sale kickoff" \
-i <account_id> \
-t scheduled \
-s "2026-05-06 10:00:00" \
--label <label_id_1> \
--label <label_id_2> \
--campaign-id <campaign_id>
9. Facebook 彩色背景文本帖子(纯文本,无媒体)
# Get a valid background id first:
contentstudio --json facebook:text-backgrounds
contentstudio --json posts:create \
-c "Big news coming soon!" \
-i <facebook_account_id> \
-t draft \
--facebook-background-id <background_id>
10. Facebook 轮播帖子(仅限 Facebook;2–10 张卡片)— 先预览,再创建
# Preview:
contentstudio --json posts:create --dry-run \
-c "Shop the new collection" \
-i <facebook_account_id> \
-t scheduled \
-s "2026-07-01 10:00:00" \
--facebook-carousel '{"cards":[{"image":"https://e.com/1.jpg","link":"https://e.com/p1","title":"Tee","description":"100% cotton"},{"image":"https://e.com/2.jpg","link":"https://e.com/p2","title":"Hoodie"},{"image":"https://e.com/3.jpg","link":"https://e.com/p3","title":"Cap"}],"call_to_action":"SHOP_NOW","end_card":true,"end_card_url":"https://e.com/shop"}'
# Drop --dry-run to create. The CLI adds "is_carousel_post": true.
轮播帖子和带彩色背景的文本帖子(--facebook-background-id,示例 9)是两种不同的 Facebook 格式 — 请二选一,不要在同一帖子中同时使用。FB 账号 ID 放在 -i / --account 中。
11. Threads 多帖串(仅限 Threads;最多 10 条串联内容)— 先预览,再创建
contentstudio --json posts:create --dry-run \
-c "🧵 A thread on shipping CLIs" \
-i <threads_account_id> \
-t draft \
--threads '[{"message":"1/ Start small."},{"message":"2/ Ship a demo.","media":["https://e.com/demo.mp4"]},{"message":"3/ Iterate in public."}]'
# Drop --dry-run to create. The CLI adds "has_multi_threads": true.
顶层的 -c / --content 是主帖;每个 --threads 项都是按顺序串联的回复。不要在这些项中重复主帖文本(将它们编号为 1/、2/,……,作为续帖)。每个项都需要 message 或 media。
12. 带首条评论的帖子(发布后自动发布评论;例如“链接在简介中”)— 先预览,再创建
contentstudio --json posts:create --dry-run \
-c "New drop is live 🎉" \
-i <account_id> \
-t draft \
--first-comment "🔗 link in bio" \
--first-comment-account <account_id>
# Drop --dry-run to create. --first-comment-account is REQUIRED by the backend
# and must be a subset of the -i / --account IDs, else the API returns a 422.
13. Twitter/X 串推文(仅限 Twitter;最多 10 条推文)— 先预览,再创建
contentstudio --json posts:create --dry-run \
-c "Why we built a CLI 🧵" \
-i <twitter_account_id> \
-t draft \
--twitter '[{"message":"1/ Start with the contract."},{"message":"2/ Show, don'\''t tell.","media":["https://e.com/x.jpg"]},{"message":"3/ Ship it."}]'
# Drop --dry-run to create. The CLI adds "has_threaded_tweets": true.
# Twitter rule: no mixed media in one tweet (no images+video together), max 1 video per tweet.
顶层的 -c / --content 是主推文;每个 --twitter 项都是按顺序串联的后续推文。不要在这些项中重复主推文文本(将这些项编号为 1/、2/,……,作为续推文)。每个项都需要 message 或 media。Twitter 账号 ID 放在 -i / --account 中。
14. 通过 --body <file.json> 完全控制请求体(快捷标志未涵盖的任何字段)
如果需要快捷标志之外的字段(例如按平台设置的 platform_overrides、twitter_options/threads_options、timezone、hide_client 等),请使用 --body。除下面所述的 ID 标准化外,JSON 会按原样发送,因此请根据 accounts 所属的平台构建请求体 — Facebook 轮播请求体、Threads 请求体和 Twitter 请求体是不同的帖子,不是一个组合请求。
引用标签和营销活动时,请使用 ID,而不是 labels:list / campaigns:list 返回的对象。 API 接受 "labels": ["<label_id>"] 和 "campaign_id": "<campaign_id>",而定时发布时间字段是 scheduling.scheduled_at,不是 execute_time。CLI 会重写它能识别的格式({ "id": … } / { "_id": … }、单独的 campaign 键、execute_time),并拒绝不带任何 ID 的标签或营销活动,因此,基于列表输出编写的请求体仍可正常提交。对于无法重写的内容,现在会返回指出字段名称的 400 验证错误 — errors: { "labels.0": [...] } — 而不是过去返回的 500 {"message": "Server Error"}。无论如何都请按文档规定的格式编写:标准化只是安全保障,不是约定格式。
// /tmp/post.json — a Facebook carousel via the full body schema
{
"content": { "text": "Shop the collection" },
"accounts": ["<facebook_account_id>"],
"scheduling": { "publish_type": "scheduled", "scheduled_at": "2026-07-01 10:00:00" },
"facebook_options": {
"carousel": {
"is_carousel_post": true,
"cards": [
{ "image": "https://e.com/1.jpg", "link": "https://e.com/p1", "title": "Tee" },
{ "image": "https://e.com/2.jpg", "link": "https://e.com/p2", "title": "Hoodie" }
],
"call_to_action": "SHOP_NOW",
"end_card": true,
"end_card_url": "https://e.com/shop"
}
},
"labels": ["<label_id>"],
"campaign_id": "<campaign_id>",
"approval": { "approvers": ["<user_id>"], "approve_option": "anyone", "notes": "please review" }
}
contentstudio --json posts:create --body /tmp/post.json
对于 Threads 或 Twitter/X 串帖,请使用包含该账号和相应区块的请求体 — 例如 { "content": {...}, "accounts": ["<threads_account_id>"], "scheduling": {...}, "threads_options": { "has_multi_threads": true, "multi_threads": [...] } }(Twitter/X 则使用 twitter_options.threaded_tweets)。
在最佳时间安排帖子
# 1. Ask for the best slots. Omit --account for every connected account.
contentstudio --json scheduling:best-times --global-slots 3
# → data.meta.timezone e.g. "Asia/Karachi"
# data.global.top_recommendations[0] {rank: 1, day: "Wednesday",
# date: "2026-08-19", time: "14", score: 100}
# data.meta.missing_entities accounts with too little history (skipped)
# 2. Narrow it to the account you're actually posting to.
# <platform>:<account_id> — both from one accounts:list row.
contentstudio --json scheduling:best-times \
--account facebook:<account_id> --per-account-slots 3
# 3. Show the user the ranked slots and let them pick. Then schedule at that
# slot's date + hour AS-IS — the times are already workspace-local, so
# converting to UTC would move the post.
contentstudio --json posts:create \
-c "Launch day is here." \
-i <account_id> \
-t scheduled \
-s "2026-08-19 14:00:00" \
--dry-run
# 4. Drop --dry-run once the user approves the time and the text.
如果 data.global 为 null,说明工作区的历史数据不足 — 不要报告错误。说明哪些账号已跳过(meta.missing_entities),并提出改为在用户选择的时间安排发布。
生成并发布图片(分两步)
# 0. Optional: see what is available. Both are configuration, so cache them.
contentstudio --json images:models
contentstudio --json images:tools
# 1. Show the user the prompt first — generating costs an image credit.
contentstudio --json images:generate \
-p "Flat-lay of autumn coffee beans on linen, warm daylight" \
--dimensions square_hd --dry-run
# 2. Generate. Takes seconds; --json gives you data.media_id.
MEDIA_ID=$(contentstudio --json images:generate \
-p "Flat-lay of autumn coffee beans on linen, warm daylight" \
--dimensions square_hd | jq -r '.data.media_id')
# 3. Attach it. media_id goes in as --media-id, unchanged.
contentstudio --json posts:create \
-c "Autumn blend is back." -i <account_id> -t draft \
--media-id "$MEDIA_ID" --dry-run
# 4. Drop --dry-run once the user approves the image and the text. That creates a
# draft; to send it instead, swap `-t draft` for
# `-t scheduled -s "YYYY-MM-DD HH:MM:SS"`. There is no publish-now type —
# --publish-type takes scheduled|draft|queued|content_category.
如果返回的 media_id 为 null,请查看 persist_error:图片已存在于 data.url,但尚未进入媒体库,因此 posts:create --media-id 没有可用的媒体。请修复原因(media_storage_full → 释放存储空间),或趁服务提供方的链接尚未过期,立即使用该 URL。
编辑和串联操作方式相同:将一个结果的 url 作为下一个操作的输入:
# Edit an existing image (the prompt describes the change, not the whole picture)
contentstudio --json images:generate \
-p "Make the background a snowy street at dusk" \
--image-url https://example.com/base.png
# Clean up a product shot, then restage it
URL=$(contentstudio --json images:remove-background \
--image-url https://example.com/mug.png | jq -r '.data.url')
contentstudio --json images:product-image --product-image-url "$URL" \
--instructions "on a marble kitchen counter, morning light"
# A tool's own controls — the escape hatch reaches every field the API declares
contentstudio --json images:tool image-to-image --body '{
"prompt": "same mug, editorial magazine styling",
"attachments": ["https://example.com/mug.png"],
"aspect_ratio": "4:5"
}' --dry-run
只传入图片服务能够下载的 URL。若要使用本地文件,请先上传:
URL=$(contentstudio --json media:upload --file ./mug.png | jq -r '.data.url')
contentstudio --json images:upscale --image-url "$URL"
列出最近的草稿帖子
contentstudio --json posts:list --status draft --per-page 5
删除帖子(并从社交平台删除)
contentstudio --json posts:delete <post_id> --delete-from-social
为帖子添加内部备注(私密)
contentstudio --json comments:add <post_id> "Double-check the link" --note
为单次调用指定其他工作区
contentstudio --json --workspace <other_ws_id> posts:list --per-page 3
处理收件箱:找出未回复的私信并回复一条
# 1. Cheap check first — is there anything to do?
contentstudio --json inbox:summary
# 2. List open conversations
contentstudio --json inbox:list --type conversation --action all --limit 20
# → per row: element_ref, platform, platform_id,
# element_details.element_id ← THIS is the conversation id
# 3. Read the thread. Use element_details.element_id (looks like t_1234...),
# NOT element_ref — element_ref here returns an empty list.
contentstudio --json inbox:messages t_10000000000000001 --sort-order desc --limit 10
# 4. Find the account that owns the thread (gives you --platform-id)
contentstudio --json accounts:list --platform facebook
# 5. Preview the reply — ALWAYS do this, and show the text to the user
contentstudio --json inbox:send <conversation_id> \
--platform-type facebook \
--platform-id <account_id> \
--message "Hi! Your order shipped this morning — tracking is on the way." \
--dry-run
# 6. Only after the user approves, drop --dry-run
回复一条评论,然后隐藏一条垃圾评论
# Threaded reply. <post_id> is element_details.post_id, not element_ref.
contentstudio --json inbox:comment-add <post_id> \
--platform-type facebook --platform-id <account_id> \
--comment-id <comment_id> \
--message "Thanks for the kind words!" --dry-run
# Hide spam rather than deleting it (reversible)
contentstudio --json inbox:comment-hide <comment_id> --dry-run
批量清除对话
contentstudio --json inbox:update \
--element <element_ref_1> --element <element_ref_2> \
--status done --dry-run
为对话添加跟进标签
contentstudio --json inbox:tags # find or create a tag id
contentstudio --json inbox:tag-attach <element_ref> \
--tag <tag_id> --platform-id <account_id> --inbox-type conversation --dry-run
错误处理
error.type | http_status | 常见提示 |
|---|---|---|
AuthError | 401, 403 | 使用有效密钥运行 auth:login。 |
NotFoundError | 404 | 资源不存在,或不属于此工作区。 |
ValidationError | 422 | API 返回的 Laravel 风格字段错误已展平。 |
ConflictError | 409 | 资源已存在,或发送操作的交付结果尚未确定。重试发送前请先确认。 |
RateLimitError | 429 | 稍等片刻后重试。AI 图片命令的速率限制为每分钟 30 次,需要等待完整的一分钟。 |
CreditLimitError | 403 | AI 图片额度(images:*)不足。请充值或等待额度周期刷新;本次未扣费。重新运行 auth:login 无法解决此问题。 |
BackendError | 5xx or network | 短暂退避后重试。 |
ConfigError | — (local) | 缺少 API 密钥或工作区;请运行 auth:login 或传入标志。 |
仅凭 error.type 无法判断的两件事。
posts:*遇到验证失败时返回 400,其他所有端点则返回 422。 400 会映射为通用的ContentStudioError(退出码 1),而不是ValidationError——因此,绝不要仅根据状态码或错误类型来判断“这是不是验证问题?”。- 应根据稳定的
error_code进行分支判断。 API 的响应正文会原样保存在error.response中,因此应根据error.response.error_code的值进行判断:VALIDATION_ERROR、CONTENT_CATEGORY_NOT_FOUND、CONTENT_CATEGORY_ACCESS_DENIED、CONTENT_CATEGORY_IS_GLOBAL、CONTENT_CATEGORY_SHUFFLE_FAILED、CONTENT_CATEGORY_INVALID_ACCOUNT、CONTENT_CATEGORY_SLOT_NOT_FOUND、CONTENT_CATEGORY_SLOT_DUPLICATE、APPROVAL_WORKFLOW_NOT_FOUND、CANNOT_SET_DRAFT_AS_DEFAULT、REQUIRES_FORCE_DELETE、CASCADE_JOB_NOT_FOUND、SHARE_LINK_NOT_FOUND、SHARE_LINK_TOKEN_REVOKE_FAILED、RATE_LIMIT_EXCEEDED。
另外,有两种成功响应也别误认为是失败:200 响应中包含 next_slot: null(category-slots:next),以及 200 响应中包含 shuffled_posts_count: 0(categories:shuffle)。两者都是有效响应。
不要使用此技能的情况
- 用户询问如何运行自己的 ContentStudio 后端(Laravel 源码);此 CLI 只与已部署的 API 通信。
- v1 API 未提供的任务(例如更改账单信息、首次连接社交账号——这些操作需在 ContentStudio 网页 UI 中完成)。
此技能的权威版本由本文件顶部 frontmatter 中的 version: 字段指定。