mcpField
C
contentstudio

contentstudio

github.com/contentstudioio营销与增长6130 次安装3 周前更新
代码仓库

关于 contentstudio

通过 CLI 和托管的 MCP 服务管理社交媒体内容的 ContentStudio 技能。它涵盖工作区、账号、帖子和媒体操作,并要求认证、确认工作区,以及在发布或执行其他变更前进行防护检查。

主要功能

  1. 01连接托管的 ContentStudio MCP
  2. 02管理工作区和社交账号
  3. 03创建和管理帖子与媒体
  4. 04处理列表结果分页
  5. 05变更前执行试运行

适用场景

  1. 01安排或管理社交媒体帖子
  2. 02按工作区查看账号和媒体
  3. 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 外,安装时一起下载的参考资料和脚本。

.gitignore
mcp.json
LICENSE
package.json
CHANGELOG.md
README.md
package-lock.json
.claude-plugin/
marketplace.json
plugin.json
.cursor-plugin/
plugin.json
.github/workflows/
check-skill-sync.yml
.grok-plugin/
plugin.json
scripts/
verify-analytics.sh
src/
cliCtx.ts
api.ts
config.ts
src/commands/
aiVideo.ts
analytics.ts
approvalWorkflows.ts
auth.ts
analyticsReports.ts
comments.ts
connect.ts
facebook.ts
contentCategories.ts
crud.ts
lookups.ts
plannerShareLinks.ts
media.ts
scheduling.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


属性值
namecontentstudio
description用于通过 ContentStudio 公共 API 安排帖子并管理媒体和账号的社交媒体自动化 CLI
allowed-toolsBash(contentstudio:*)

⚠️ 需要身份验证

运行任何 contentstudio CLI 命令前,必须先完成身份验证。 没有有效的 API 密钥,所有命令都会失败。

开始操作前,先检查身份验证状态:

contentstudio auth:status

如果 has_api_key 为 false,请通过以下两种方式之一进行身份验证。用户可以前往 ContentStudio Dashboard → Settings → API Keys 生成密钥。

  1. API 密钥(交互式)——将密钥保存到 CLI 配置文件中:
contentstudio auth:login --api-key cs_...
  1. 环境变量(无头模式 / Agent 运行时)——CLI 会从环境中读取 CONTENTSTUDIO_API_KEY,且此变量的优先级高于配置文件:
export CONTENTSTUDIO_API_KEY=cs_...

无头部署说明(OpenClaw、CI、守护进程): shell 中的 export 不会持久保存在服务进程中。请在 Agent 的实际运行环境中设置 CONTENTSTUDIO_API_KEY,例如 systemd Environment=(systemctl edit)、EnvironmentFile=,或 Docker -e / compose environment:,然后重启服务。要求显式声明所需环境变量的运行时(例如 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 是唯一一个不限定工作区的写入操作——它会创建一个全新的工作区,并忽略当前活动工作区。)

操作步骤:

  1. 运行 contentstudio --json workspaces:current,查看当前活动工作区。
  2. 告诉用户:“您当前的活动工作区是 <name>(<id>)。您想在此工作区中连接账号/发布/删除,还是在其他工作区中操作?”
  3. 如果用户选择其他工作区,运行 workspaces:list,让他们选择,然后:
    • 运行 workspaces:use <id> 切换默认工作区;或
    • 在单次变更调用中传入 --workspace <id>(一次性操作时优先采用——不会更改活动工作区)。
  4. 然后才能运行变更命令。

即使用户的请求看起来暗示要使用活动工作区(“连接一个 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,都表示用户的数据比当前返回的更多。绝不能悄悄将当前页视为“全部结果”。选择以下三种策略之一:

  1. 询问用户(对含义不明确的请求,默认采用此策略):

    “我检索到了 48 个工作区中的 10 个。你希望我继续获取其余工作区,还是目前这 10 个就够用了?”

  2. 自动分页——如果用户的请求表明他们想要全部结果(例如“列出我的所有账户”“显示每一篇草稿”“删除所有排队中的帖子”):

    • 使用 --per-page <total> 再次调用,一次性获取所有结果:
      contentstudio --json workspaces:list --per-page 48
      
    • 或者当 total 很大(>200)且需要控制单页数据量时,逐页迭代 --page 2、--page 3……--page <last_page>。
  3. 筛选,而非分页——如果用户请求的是特定内容(例如“仅限 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 应该:

  1. 运行 contentstudio --json workspaces:list --per-page 50(设置较大的默认值,通常可避免分页)
  2. 如果 pagination.has_more 仍为 true,则告知用户:“我找到了 N 个工作区中的 50 个。要我获取全部 N 个吗?”

用户:“删除我所有的草稿帖子” Agent 应该:

  1. 运行 contentstudio --json posts:list --status draft --per-page 1,查看 total
  2. 运行 contentstudio --json posts:list --status draft --per-page <total>,获取全部帖子
  3. 遍历 data[] 并逐一删除
  4. 绝不能只删除第一页的内容,然后报告“已完成”

用户:“显示我的 Facebook 账户” Agent 应该:

  1. 使用 --platform facebook 筛选——通常只会返回 0 个或少量结果,无需担心分页
  2. 如果 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 表示套餐完全不包含此功能(这是硬性零额度,并非无限)。切勿将 null limit / 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 的账号连接流程:

  1. 运行 platforms:list,查看支持的平台以及各自使用的方法(oauth / credentials / manual)。
  2. 对于 OAuth 平台(大多数平台),调用 accounts:connect <platform>,并向用户展示返回的 URL——用户可在浏览器中打开该 URL 进行授权。CLI 本身不会处理凭据。
  3. 对于 Bluesky,请向用户索取其 handle 和 app-password(引导用户前往 https://bsky.app/settings/app-passwords),然后调用 accounts:add-bluesky。
  4. 对于 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 消息时,后端要求至少提供一个账户,且这些账户必须是帖子主 --account ID 的子集。**CLI 不会在客户端强制阻止 — 省略 --first-comment-account 时,后端会返回 422。 (--facebook-carousel、--facebook-collaborator、--instagram-collaborator、--instagram-trial-reel、--instagram-trial-reel-graduation、--linkedin-options、--platform-overrides、--threads 和 --twitter 仅适用于快捷模式。--body JSON 模式原生支持 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:modelsimages: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_id slug。该资源会同时返回两者——传入 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-detachelement_details.element_id
inbox:mark-readelement_details.element_id
inbox:contact / inbox:contact-updateelement_details.element_id
inbox:messages / send / notes / note-add / bookmarkselement_details.element_id(t_… 格式)
inbox:comments / inbox:comment-addelement_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 ≤ 200inbox:list、inbox:messages、inbox:comments
每次调用最多 100 个 --element refsinbox: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-insightsFacebook AI 生成的洞察--platform-id, --start-date, --end-date
analytics:facebook-audience-growthFacebook 粉丝/关注者随时间的增长--platform-id, --start-date, --end-date
analytics:facebook-audience-locationFacebook 受众所在地(按国家/城市细分);--country 可缩小城市列表范围--platform-id, --start-date, --end-date
analytics:facebook-engagementFacebook 专页互动随时间的变化--platform-id, --start-date, --end-date
analytics:facebook-get-top-postsFacebook 热门帖子,可按 media_type 筛选--platform-id, --start-date, --end-date
analytics:facebook-impressionsFacebook 专页展示次数随时间的变化--platform-id, --start-date, --end-date
analytics:facebook-overview-top-postsFacebook 热门帖子(概览小组件)--platform-id, --start-date, --end-date
analytics:facebook-publishing-behaviourFacebook 按展示类型统计的互动随时间的变化--platform-id, --start-date, --end-date
analytics:facebook-reelsFacebook Reels 表现随时间的变化--platform-id, --start-date, --end-date
analytics:facebook-single-post按 ID 获取单条 Facebook 帖子--platform-id, --post-id
analytics:facebook-summaryFacebook 汇总 KPI——当前与上一时期对比--platform-id, --start-date, --end-date
analytics:facebook-video-insightsFacebook 视频观看时长和播放次数随时间的变化--platform-id, --start-date, --end-date

Instagram(15)

命令用途必需参数
analytics:instagram-active-users按小时和星期几统计 Instagram 活跃用户--platform-id, --start-date, --end-date
analytics:instagram-ai-insightsInstagram AI 生成的洞察--platform-id, --start-date, --end-date
analytics:instagram-audience-growthInstagram 关注者随时间的增长--platform-id, --start-date, --end-date
analytics:instagram-country-cityInstagram 受众国家/城市细分;--country 可缩小城市列表范围--platform-id, --start-date, --end-date
analytics:instagram-demographics-ageInstagram 受众年龄/性别细分--platform-id, --start-date, --end-date
analytics:instagram-engagementInstagram 帖子互动随时间的变化--platform-id, --start-date, --end-date
analytics:instagram-get-top-postsInstagram 热门帖子,可按 hashtag 筛选--platform-id, --start-date, --end-date
analytics:instagram-hashtags按互动量统计的 Instagram 热门 hashtag--platform-id, --start-date, --end-date
analytics:instagram-impressionsInstagram 帖子展示次数随时间的变化--platform-id, --start-date, --end-date
analytics:instagram-publishing-behaviourInstagram 按媒体类型统计的帖子互动随时间的变化--platform-id, --start-date, --end-date
analytics:instagram-reels-performanceInstagram Reels 互动和观看时长随时间的变化--platform-id, --start-date, --end-date
analytics:instagram-single-post按 ID 获取单条 Instagram 帖子--platform-id, --post-id
analytics:instagram-stories-performanceInstagram 快拍展示次数、覆盖人数和互动随时间的变化--platform-id, --start-date, --end-date
analytics:instagram-summaryInstagram 汇总 KPI——当前与上一时期对比--platform-id, --start-date, --end-date
analytics:instagram-top-postsInstagram 表现最佳的帖子--platform-id, --start-date, --end-date

YouTube(20)

命令用途必需参数
analytics:youtube-ai-insightsYouTube AI 生成的洞察--platform-id, --start-date, --end-date
analytics:youtube-demographicsYouTube 受众人口统计信息——年龄与性别、设备类型、订阅者变化--platform-id, --start-date, --end-date
analytics:youtube-engagement-trendYouTube 随时间变化的累计互动趋势--platform-id, --start-date, --end-date
analytics:youtube-engagement-trend-dailyYouTube 每日增量互动趋势--platform-id, --start-date, --end-date
analytics:youtube-find-videoYouTube 流量来源细分(观众如何找到视频)--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-behaviourYouTube 随时间发布的帖子及内容类型细分--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-trendYouTube 随时间变化的累计订阅者趋势--platform-id, --start-date, --end-date
analytics:youtube-subscriber-trend-dailyYouTube 每日增量订阅者趋势--platform-id, --start-date, --end-date
analytics:youtube-summaryYouTube 摘要 KPI——当前时段与上一时段对比--platform-id, --start-date, --end-date
analytics:youtube-top-geographiesYouTube 热门地理位置——按观看次数、观看时长、观看持续时间和观看百分比预先排序的国家/地区--platform-id, --start-date, --end-date
analytics:youtube-top-posts按观看次数和互动量排序的 YouTube 热门视频--platform-id, --start-date, --end-date
analytics:youtube-video-sharingYouTube 分享平台细分--platform-id, --start-date, --end-date
analytics:youtube-views-trendYouTube 累计观看次数,按订阅者/非订阅者细分--platform-id, --start-date, --end-date
analytics:youtube-views-trend-dailyYouTube 每日增量观看趋势--platform-id, --start-date, --end-date
analytics:youtube-watch-time-trendYouTube 累计观看时长,按订阅者/非订阅者细分--platform-id, --start-date, --end-date
analytics:youtube-watch-time-trend-dailyYouTube 每日增量观看时长趋势--platform-id, --start-date, --end-date

Pinterest(14)

命令用途必需参数
analytics:pinterest-ai-insightsPinterest AI 生成的洞察--platform-id, --start-date, --end-date
analytics:pinterest-engagement-trendPinterest 随时间变化的累计互动趋势--platform-id, --start-date, --end-date
analytics:pinterest-engagement-trend-dailyPinterest 每日互动增量趋势--platform-id, --start-date, --end-date
analytics:pinterest-follower-trendPinterest 随时间变化的累计粉丝趋势--platform-id, --start-date, --end-date
analytics:pinterest-follower-trend-dailyPinterest 每日粉丝增量趋势--platform-id, --start-date, --end-date
analytics:pinterest-impressions-trendPinterest 随时间变化的累计展示量趋势--platform-id, --start-date, --end-date
analytics:pinterest-impressions-trend-dailyPinterest 每日展示量增量趋势--platform-id, --start-date, --end-date
analytics:pinterest-pin-performancePinterest Pin 随时间变化的表现指标--platform-id, --start-date, --end-date
analytics:pinterest-pin-postingPinterest 随时间变化的累计 Pin 发布活动--platform-id, --start-date, --end-date
analytics:pinterest-pin-posting-dailyPinterest 每日 Pin 发布活动增量--platform-id, --start-date, --end-date
analytics:pinterest-pin-rollupPinterest Pin 表现汇总——当前周期与上一周期对比--platform-id, --start-date, --end-date
analytics:pinterest-single-pin按 ID 获取单个 Pinterest Pin--platform-id, --post-id
analytics:pinterest-summaryPinterest 汇总 KPI——当前周期与上一周期对比--platform-id, --start-date, --end-date
analytics:pinterest-top-pinsPinterest 表现最佳和最差的 Pin--platform-id, --start-date, --end-date

LinkedIn(11)

命令用途必需参数
analytics:linkedin-ai-insightsLinkedIn AI 生成的洞察--platform-id, --start-date, --end-date
analytics:linkedin-audience-growthLinkedIn 粉丝数量随时间的增长情况--platform-id, --start-date, --end-date
analytics:linkedin-followers-demographics按行业、国家/地区及其他维度划分的 LinkedIn 粉丝人口统计信息--platform-id, --start-date, --end-date
analytics:linkedin-get-top-postsLinkedIn 热门帖子,可按话题标签和媒体类型筛选--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-summaryLinkedIn 汇总 KPI——当前周期与上一周期对比--platform-id, --start-date, --end-date
analytics:linkedin-top-postsLinkedIn 表现最佳的帖子--platform-id, --start-date, --end-date

Google Business Profile(GMB)(10)

Command用途必填项
analytics:gmb-actionsGMB 客户操作(点击、来电、路线查询)随时间的变化--platform-id, --start-date, --end-date
analytics:gmb-ai-insightsGMB AI 生成的洞察--platform-id, --start-date, --end-date
analytics:gmb-impressionsGMB 展示量按渠道和设备的时间变化--platform-id, --start-date, --end-date
analytics:gmb-media-activityGMB 媒体(照片/视频)活动随时间的变化--platform-id, --start-date, --end-date
analytics:gmb-publishing-behaviorGMB 帖子发布量随时间的变化及主题类型细分--platform-id, --start-date, --end-date
analytics:gmb-reviewsGMB 评价——评分、分布和每日活动--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-summaryGMB 摘要 KPI——当前周期与上一周期对比--platform-id, --start-date, --end-date
analytics:gmb-top-postsGMB 表现最佳的帖子--platform-id, --start-date, --end-date

TikTok(8)

Command用途必填项
analytics:tiktok-ai-insightsTikTok AI 生成的洞察--platform-id, --start-date, --end-date
analytics:tiktok-engagement-trendTikTok 每日互动趋势随时间的变化--platform-id, --start-date, --end-date
analytics:tiktok-follower-trendTikTok 粉丝数和观看量趋势随时间的变化--platform-id, --start-date, --end-date
analytics:tiktok-publishing-behaviourTikTok 每日帖子发布量和互动细分随时间的变化--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-summaryTikTok 摘要 KPI——当前周期与上一周期对比--platform-id, --start-date, --end-date
analytics:tiktok-top-postsTikTok 表现最佳和最差的帖子--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-impressionTwitter 互动量和展示量趋势随时间的变化--platform-id, --start-date, --end-date
analytics:twitter-followers-trendTwitter 粉丝数趋势随时间的变化--platform-id, --start-date, --end-date
analytics:twitter-least-tweetsTwitter 表现最差的推文--platform-id, --start-date, --end-date
analytics:twitter-single-tweet按 ID 获取单条 Twitter/X 推文--platform-id, --post-id
analytics:twitter-summaryTwitter 摘要 KPI——当前周期与上一周期对比--platform-id, --start-date, --end-date
analytics:twitter-top-tweetsTwitter 表现最佳的推文--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-summaryMeta 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-summaryGoogle 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.typehttp_status常见提示
AuthError401, 403使用有效密钥运行 auth:login。
NotFoundError404资源不存在,或不属于此工作区。
ValidationError422API 返回的 Laravel 风格字段错误已展平。
ConflictError409资源已存在,或发送操作的交付结果尚未确定。重试发送前请先确认。
RateLimitError429稍等片刻后重试。AI 图片命令的速率限制为每分钟 30 次,需要等待完整的一分钟。
CreditLimitError403AI 图片额度(images:*)不足。请充值或等待额度周期刷新;本次未扣费。重新运行 auth:login 无法解决此问题。
BackendError5xx or network短暂退避后重试。
ConfigError— (local)缺少 API 密钥或工作区;请运行 auth:login 或传入标志。

仅凭 error.type 无法判断的两件事。

  1. posts:* 遇到验证失败时返回 400,其他所有端点则返回 422。 400 会映射为通用的 ContentStudioError(退出码 1),而不是 ValidationError——因此,绝不要仅根据状态码或错误类型来判断“这是不是验证问题?”。
  2. 应根据稳定的 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: 字段指定。

评论

支持 Markdown