Install as a skill:
npx skills add d4interactive/contentstudio-agentContentStudio CLI — schedule social-media posts, manage media, accounts, comments, and approvals across Facebook, LinkedIn, Twitter/X, Instagram, YouTube, TikTok, Pinterest, and Google Business Profile through the ContentStudio public API.
The contentstudio CLI provides a command-line interface for developers and AI agents to drive a ContentStudio workspace from the terminal — scheduling posts, uploading media, managing approvals, and auditing accounts/campaigns/labels — using the same API your dashboard does.
- Drive ContentStudio from anywhere — bash scripts, CI/CD pipelines, AI agents (Claude Code, Cursor, OpenCode, Codex), n8n workflows, custom automations.
- JSON output for agents — every command supports
--jsonreturning a stable{"ok": true, "data": ...}envelope. - Dry-run safety — preview every mutating call before sending it, so AI agents (and humans) never publish by accident.
- No SaaS lock-in to your CLI tooling — talks directly to the production ContentStudio API over HTTPS; no proxy, no extra service.
npm install -g contentstudio-cli
# or
pnpm install -g contentstudio-cliVerify:
contentstudio --version
contentstudio --helpIf you use an AI assistant (Claude Code, Cursor, OpenCode, Codex, Augment, IBM Bob, etc.), install the SKILL.md so the agent can drive this CLI on your behalf:
npx skills add d4interactive/contentstudio-agentPick which agents to install into in the interactive prompt. The SKILL.md is dropped into each agent's skill directory (e.g. ~/.claude/skills/contentstudio/SKILL.md).
Authentication uses an API key issued from your ContentStudio dashboard.
contentstudio auth:login --api-key cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxThis stores your key at ~/.config/contentstudio/config.json (file mode 0600, dir 0700) and verifies it via a /me round-trip.
# Check current auth status (key redacted)
contentstudio auth:status
# Verify the stored key is still valid
contentstudio --json auth:whoami
# Remove stored credentials
contentstudio auth:logoutFor CI/CD or one-off invocations, set the key in your environment instead of persisting:
export CONTENTSTUDIO_API_KEY=cs_...
export CONTENTSTUDIO_WORKSPACE_ID=601b773d2149273f48039ec2 # optional
export CONTENTSTUDIO_BASE_URL=https://api.contentstudio.io/api/v1 # optionalEnv vars take priority over the persisted config when both are present.
ContentStudio Dashboard → Settings → API Keys → Generate new key.
# 1. Auth (once)
contentstudio auth:login --api-key cs_...
# 2. Pick a workspace
contentstudio workspaces:list
contentstudio workspaces:use <workspace_id>
# 3. List the social accounts connected to that workspace
contentstudio accounts:list --platform facebook
# 4. Create a draft post (safe — won't publish to social)
contentstudio posts:create \
--content "Hello from contentstudio CLI" \
--account <account_id> \
--publish-type draft
# 5. Schedule a real post for 2 minutes from now
contentstudio posts:create \
-c "Hello from automation 👋" \
-i <account_id> \
-t scheduled \
-s "$(date -d '+2 minutes' '+%F %T')" \
-m https://picsum.photos/400contentstudio --json workspaces:list
contentstudio --json workspaces:list --per-page 50Returns workspace IDs, names, slugs, timezones.
contentstudio workspaces:current
contentstudio workspaces:use <workspace_id>contentstudio --json accounts:list # all accounts
contentstudio --json accounts:list --platform facebook # filter
contentstudio --json accounts:list --search "barcelona" # search by name--platform values: facebook, linkedin, twitter, instagram, youtube, tiktok, pinterest, gmb.
contentstudio --json campaigns:list
contentstudio --json categories:list
contentstudio --json labels:list
contentstudio --json team:listAll support --page, --per-page, and --search filters.
Three ways to add new accounts to a workspace, depending on the platform.
contentstudio --json platforms:listReturns all 12+ supported platforms with their connection_method (oauth, credentials, or manual) and the endpoint to call.
OAuth platforms (Facebook, LinkedIn, Twitter, Instagram, YouTube, TikTok, Pinterest, GMB, Threads, Tumblr)
contentstudio --json accounts:connect facebook
# Returns a one-time authorization_url — open it in your browser to authorize.To reconnect an existing account that's expired or invalid:
contentstudio --json accounts:connect facebook --reconnect --account-id <existing_account_id>Available <platform> values: facebook, facebook-profile, instagram, instagram-via-facebook, twitter, linkedin, pinterest, tiktok, youtube, threads, gmb, tumblr.
Generate an app password at https://bsky.app/settings/app-passwords first, then:
contentstudio --json accounts:add-bluesky \
--handle yourname.bsky.social \
--app-password xxxx-xxxx-xxxx-xxxx--dry-run output but it's still sent to ContentStudio's API over HTTPS.
contentstudio --json accounts:add-facebook-group \
--name "My Community Group" \
--image https://example.com/group-cover.jpgThe image URL is optional.
All three connect commands support --dry-run to preview the payload without calling the API.
There are two ways to create a post: shortcut flags for simple cases, or --body <file.json> for the full schema.
# Scheduled post to a Facebook page with one image
contentstudio posts:create \
-c "Our latest blog post is live!" \
-i <account_id> \
-t scheduled \
-s "2026-05-01 10:00:00" \
-m https://example.com/hero.jpgOptions:
| Flag | Purpose |
|---|---|
-c, --content |
Post text |
-i, --account |
Social account ID. Repeatable for multi-account posts. |
-t, --publish-type |
scheduled | draft | queued | content_category |
-s, --scheduled-at |
Schedule date "YYYY-MM-DD HH:MM:SS" |
-m, --image-url |
External image URL. Repeatable. |
--video-url |
External video URL |
--media-id |
ID of media in your library (from media:list). Repeatable. |
--post-type |
feed | reel | story | feed+reel | feed+story | feed+reel+story | carousel | carousel+story | video | shorts |
--dry-run |
Print the body that would be POSTed and exit (no API call) |
Repeat -i for each account:
contentstudio posts:create \
-c "Cross-platform announcement 🚀" \
-i <facebook_id> \
-i <linkedin_id> \
-i <twitter_id> \
-t scheduled \
-s "2026-05-01 09:00:00"# Find a media ID
contentstudio --json media:list --type images
# Reference it by ID instead of URL
contentstudio posts:create \
-c "Post with library asset" \
-i <account_id> \
-t draft \
--media-id <media_library_id>For platform-specific options (TikTok privacy, YouTube category, GMB topic, approval workflow, first-comment, labels, campaigns, etc.), write a JSON body and pass it via --body:
contentstudio --json posts:create --body /tmp/post.jsonBody schema:
For agents (and cautious humans), every mutating command supports --dry-run — it prints the request body and exits without calling the API:
contentstudio --json posts:create --dry-run \
-c "Test" -i <account_id> -t scheduled -s "2026-05-01 10:00"
# → {"ok": true, "data": {"dry_run": true, "endpoint": "...", "body": {...}}}contentstudio --json posts:list # all recent
contentstudio --json posts:list --status draft --per-page 5
contentstudio --json posts:list --status scheduled --status published
contentstudio --json posts:list --date-from 2026-04-01 --date-to 2026-04-30# Just delete from ContentStudio
contentstudio --json posts:delete <post_id>
# Also delete from the connected social platforms
contentstudio --json posts:delete <post_id> --delete-from-social
# Limit the cross-platform delete to specific accounts
contentstudio --json posts:delete <post_id> --account <account_id> --delete-from-social
# Preview without deleting
contentstudio --json posts:delete <post_id> --dry-runcontentstudio --json posts:approve <post_id> --comment "LGTM, ship it"
contentstudio --json posts:reject <post_id> --comment "fix the link first"
# Preview without acting
contentstudio --json posts:approve <post_id> --dry-run# List all comments / notes on a post
contentstudio --json comments:list <post_id>
# Add a public comment
contentstudio --json comments:add <post_id> "Great work team!"
# Add an internal note (not visible to the public)
contentstudio --json comments:add <post_id> "Double-check the link before publishing" --note
# Mention team members
contentstudio --json comments:add <post_id> "Heads up" --mention <user_id> --mention <user_id>
# Preview
contentstudio --json comments:add <post_id> "test" --note --dry-runcontentstudio --json media:list # all
contentstudio --json media:list --type images --sort recent --per-page 20
contentstudio --json media:list --type videos
contentstudio --json media:list --search "campaign-2026"--sort values: recent, oldest, size, a2z, z2a.
Upload a local file:
contentstudio --json media:upload --file ./hero.jpgOr import from an external URL:
contentstudio --json media:upload --url https://example.com/asset.mp4Optionally place into a folder:
contentstudio --json media:upload --file ./hero.jpg --folder-id <folder_id>Preview (no upload):
contentstudio --json media:upload --url https://example.com/img.jpg --dry-runThe response includes an _id you can pass as --media-id when creating posts.
The full body schema accepts platform-specific options. These examples show the most common configurations.
contentstudio --json posts:create \
-c "Big news for our community 🎉" \
-i <facebook_page_id> \
-t scheduled \
-s "2026-05-01 10:00:00" \
-m https://example.com/announcement.jpgFor Facebook Reels or Stories, set --post-type:
contentstudio posts:create \
-c "Behind-the-scenes" \
-i <facebook_id> \
-t scheduled \
-s "2026-05-01 10:00:00" \
--video-url https://example.com/clip.mp4 \
--post-type reel+storycontentstudio --json posts:create \
-c "Excited to share our Q2 roadmap" \
-i <linkedin_id> \
-t scheduled \
-s "2026-05-01 09:00:00" \
-m https://example.com/roadmap.png# Single tweet with image
contentstudio --json posts:create \
-c "New release shipped 🚀" \
-i <twitter_id> \
-t scheduled \
-s "2026-05-01 10:00:00" \
-m https://example.com/preview.pngFor Instagram, control the post format with --post-type:
# Feed post
contentstudio posts:create \
-c "Caption with #hashtags" \
-i <instagram_id> \
-t scheduled \
-s "2026-05-01 10:00:00" \
-m https://example.com/photo.jpg \
--post-type feed
# Reel
contentstudio posts:create \
-c "" \
-i <instagram_id> \
-t scheduled \
-s "2026-05-01 10:00:00" \
--video-url https://example.com/reel.mp4 \
--post-type reel
# Story
contentstudio posts:create \
-c "" \
-i <instagram_id> \
-t scheduled \
-s "2026-05-01 10:00:00" \
-m https://example.com/story.jpg \
--post-type storyYouTube needs youtube_options — use a --body file:
cat > /tmp/yt-post.json <<'JSON'
{
"content": {
"text": "Description shown under the video",
"media": {"video": "https://example.com/clip.mp4"}
},
"accounts": ["<youtube_id>"],
"post_type": "shorts",
"post_video_title": "How we built ContentStudio CLI",
"scheduling": {"publish_type": "scheduled", "scheduled_at": "2026-05-01 10:00:00"},
"youtube_options": {
"title": "How we built ContentStudio CLI",
"privacy_status": "public",
"category": "EDUCATION",
"tags": ["cli", "automation", "social-media"],
"license": "youtube",
"made_for_kids": false
}
}
JSON
contentstudio --json posts:create --body /tmp/yt-post.jsoncat > /tmp/tt-post.json <<'JSON'
{
"content": {
"text": "Quick demo #fyp #tutorial",
"media": {"video": "https://example.com/tiktok.mp4"}
},
"accounts": ["<tiktok_id>"],
"scheduling": {"publish_type": "scheduled", "scheduled_at": "2026-05-01 10:00:00"},
"tiktok_options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"disable_comment": false,
"disable_duet": false,
"disable_stitch": false,
"auto_add_music": false,
"brand_content_toggle": false,
"disclose_commercial_content": false,
"is_aigc": false
}
}
JSON
contentstudio --json posts:create --body /tmp/tt-post.jsoncat > /tmp/pin-post.json <<'JSON'
{
"content": {
"text": "Check out our spring guide",
"media": {"images": ["https://example.com/pin.jpg"]}
},
"accounts": ["<pinterest_id>"],
"scheduling": {"publish_type": "scheduled", "scheduled_at": "2026-05-01 10:00:00"},
"pinterest_options": {
"title": "Spring 2026 Style Guide",
"link": "https://example.com/spring-guide"
}
}
JSON
contentstudio --json posts:create --body /tmp/pin-post.jsoncat > /tmp/gmb-post.json <<'JSON'
{
"content": {
"text": "Join our grand opening event",
"media": {"images": ["https://example.com/event.jpg"]}
},
"accounts": ["<gmb_account_id>"],
"scheduling": {"publish_type": "scheduled", "scheduled_at": "2026-05-01 10:00:00"},
"gmb_options": {
"topic_type": "EVENT",
"start_date": "2026-05-15",
"end_date": "2026-05-16",
"title": "Grand Opening",
"action_type": "BOOK",
"cta_link": "https://example.com/rsvp"
}
}
JSON
contentstudio --json posts:create --body /tmp/gmb-post.jsonThis CLI is designed to be driven by AI assistants. Three properties make it agent-friendly:
Every command supports --json returning a predictable shape:
// Success
{ "ok": true, "data": <payload> }
// Error
{
"ok": false,
"error": {
"type": "AuthError",
"message": "Invalid or revoked API key",
"http_status": 401,
"hint": "Run `contentstudio auth:login --api-key cs_...` to set a valid API key."
}
}Agents check both ok and the process exit code (non-zero on error).
Every mutating command (posts:create, posts:delete, posts:approve, posts:reject, comments:add, media:upload) supports --dry-run — the agent can validate a payload before committing.
The repo ships a SKILL.md agents can install with one command:
npx skills add d4interactive/contentstudio-agentAfter this, the agent automatically knows when to use the contentstudio CLI without prompting.
#!/bin/bash
# Daily content batch for a Facebook page
ACCOUNT="<facebook_page_id>"
CONTENT=(
"Monday motivation 💪"
"Tuesday tips: keep it simple"
"Wednesday wisdom from the team"
"Throwback Thursday"
"Friday vibes 🎉"
"Weekend prep — try this"
"Sunday reflections"
)
for i in "${!CONTENT[@]}"; do
DATE=$(date -d "+$((i+1)) day 09:00" '+%F %T')
contentstudio --json posts:create \
-c "${CONTENT[$i]}" \
-i "$ACCOUNT" \
-t scheduled \
-s "$DATE"
done#!/bin/bash
# Same content to FB + LinkedIn + Twitter at the same time
TIME="2026-05-01 10:00:00"
# List accounts and pick one per platform
FB=$(contentstudio --json accounts:list --platform facebook | jq -r '.data[0]._id')
LI=$(contentstudio --json accounts:list --platform linkedin | jq -r '.data[0]._id')
TW=$(contentstudio --json accounts:list --platform twitter | jq -r '.data[0]._id')
contentstudio --json posts:create \
-c "Big launch today 🚀" \
-i "$FB" -i "$LI" -i "$TW" \
-t scheduled \
-s "$TIME" \
-m https://example.com/launch.jpg#!/bin/bash
CUTOFF=$(date -d '-30 days' '+%Y-%m-%d')
contentstudio --json posts:list --status draft --date-to "$CUTOFF" --per-page 100 \
| jq -r '.data[]._id' \
| while read id; do
contentstudio --json posts:delete "$id"
done#!/bin/bash
ACCOUNT="<instagram_id>"
for img in ./photos/*.jpg; do
# Upload first to get a media library ID
RESP=$(contentstudio --json media:upload --file "$img")
MEDIA_ID=$(echo "$RESP" | jq -r '.data._id')
# Schedule a post with the uploaded media
TIME=$(date -d "+1 hour" '+%F %T')
contentstudio --json posts:create \
-c "$(basename "$img" .jpg)" \
-i "$ACCOUNT" \
-t scheduled \
-s "$TIME" \
--media-id "$MEDIA_ID" \
--post-type feed
done#!/bin/bash
TRUSTED_USER_ID="<user_id>"
contentstudio --json posts:list --status pending_approval --per-page 50 \
| jq -r --arg u "$TRUSTED_USER_ID" '.data[] | select(.created_by == $u) | ._id' \
| while read id; do
contentstudio --json posts:approve "$id" --comment "auto-approved (trusted creator)"
doneThe CLI wraps these 20 endpoints from the ContentStudio v1 public API. Base URL: https://api.contentstudio.io/api/v1.
| Method | Endpoint | CLI command |
|---|---|---|
| GET | /me |
auth:whoami |
| GET | /platforms |
platforms:list |
| GET | /facebook/text-backgrounds |
facebook:text-backgrounds |
| GET | /workspaces |
workspaces:list |
| GET | /workspaces/{w}/accounts |
accounts:list |
| POST | /workspaces/{w}/connect/{platform} |
accounts:connect <platform> |
| POST | /workspaces/{w}/add/bluesky |
accounts:add-bluesky |
| POST | /workspaces/{w}/add/facebook-group |
accounts:add-facebook-group |
| GET | /workspaces/{w}/campaigns |
campaigns:list |
| GET | /workspaces/{w}/content-categories |
categories:list |
| GET | /workspaces/{w}/labels |
labels:list |
| GET | /workspaces/{w}/team-members |
team:list |
| GET | /workspaces/{w}/media |
media:list |
| POST | /workspaces/{w}/media |
media:upload |
| GET | /workspaces/{w}/posts |
posts:list |
| POST | /workspaces/{w}/posts |
posts:create |
| DELETE | /workspaces/{w}/posts/{p} |
posts:delete |
| POST | /workspaces/{w}/posts/{p}/approval |
posts:approve, posts:reject |
| GET | /workspaces/{w}/posts/{p}/comments |
comments:list |
| POST | /workspaces/{w}/posts/{p}/comments |
comments:add |
Full OpenAPI 3.0 spec: https://api.contentstudio.io/api-docs.json Human-readable docs: https://api.contentstudio.io/guide
Stored at:
$XDG_CONFIG_HOME/contentstudio/config.json
# falls back to ~/.config/contentstudio/config.json
File mode 0600, parent dir 0700 — never world-readable.
Format:
{
"api_key": "cs_...",
"base_url": "https://api.contentstudio.io/api/v1",
"active_workspace_id": "<workspace_id>",
"active_workspace_name": "...",
"user": { "id": "...", "email": "...", "full_name": "..." }
}| Variable | Required | Default | Description |
|---|---|---|---|
CONTENTSTUDIO_API_KEY |
No* | — | API key (overrides stored config) |
CONTENTSTUDIO_WORKSPACE_ID |
No* | — | Active workspace (overrides stored config) |
CONTENTSTUDIO_BASE_URL |
No | https://api.contentstudio.io/api/v1 |
API base URL (override for staging) |
CONTENTSTUDIO_CONFIG_PATH |
No | ~/.config/contentstudio/config.json |
Custom config file path |
*Either run contentstudio auth:login once, or set CONTENTSTUDIO_API_KEY. Either run workspaces:use <id> once, set CONTENTSTUDIO_WORKSPACE_ID, or pass --workspace <id> per call.
The CLI provides typed errors with non-zero exit codes:
| Exit code | error.type |
HTTP status | Typical cause / hint |
|---|---|---|---|
| 1 | ContentStudioError |
varies | Generic — check message |
| 2 | AuthError |
401, 403 | Invalid/revoked key — run auth:login again |
| 3 | NotFoundError |
404 | Resource doesn't exist or wrong workspace |
| 4 | ValidationError |
422 | Malformed request — check message for field errors |
| 5 | RateLimitError |
429 | Too many calls — back off and retry |
| 6 | BackendError |
5xx / network | Upstream issue — retry with backoff |
| 1 | ConfigError |
— | Local config issue (no key/workspace set) — see hint |
The CLI auto-retries on 429 and 5xx (up to 2 attempts with exponential backoff). Connection timeouts also retry.
# Authentication
contentstudio auth:login --api-key cs_... # Persist key + verify
contentstudio auth:status # Show local config
contentstudio --json auth:whoami # Validate key against API
contentstudio auth:logout # Forget key
# Workspaces
contentstudio --json workspaces:list # List workspaces
contentstudio workspaces:use <workspace_id> # Set active workspace
contentstudio workspaces:current # Show active
# Discovery (workspace-scoped)
contentstudio --json accounts:list [--platform facebook] [--search "query"] # Connected accounts
contentstudio --json campaigns:list # Folders
contentstudio --json categories:list # Content categories
contentstudio --json labels:list # Labels
contentstudio --json team:list # Team members
# Posts
contentstudio --json posts:list [--status draft] [--date-from] [--date-to] # List posts
contentstudio --json posts:create -c "text" -i <account_id> -t draft # Create (shortcut)
contentstudio --json posts:create --body /path/to/post.json # Create (full body)
contentstudio --json posts:create [...] --dry-run # Preview, no API call
contentstudio --json posts:delete <post_id> [--delete-from-social] # Delete
contentstudio --json posts:approve <post_id> [--comment "..."] # Approve
contentstudio --json posts:reject <post_id> [--comment "..."] # Reject
# Comments / Notes
contentstudio --json comments:list <post_id> # List
contentstudio --json comments:add <post_id> "message" [--note] [--mention <id>] # Public comment / internal note
# Media
contentstudio --json media:list [--type images|videos] [--sort recent] # List
contentstudio --json media:upload --file <path> # Upload local file
contentstudio --json media:upload --url <url> # Import from URL
# Globals
contentstudio --version # Print version
contentstudio --help # Top-level help
contentstudio <group>:<verb> --help # Per-command help
contentstudio --json ... # JSON envelope output
contentstudio --workspace <id> ... # Per-call workspace override
contentstudio --base-url <url> ... # Per-call API base overrideThis package is built with TypeScript and bundled with tsup.
contentstudio-agent/
├── src/
│ ├── index.ts # CLI entry — yargs setup
│ ├── api.ts # HTTP client + endpoint wrappers
│ ├── config.ts # Persistent config (read/write/lock)
│ ├── errors.ts # Typed error hierarchy
│ ├── output.ts # JSON envelope + human renderer
│ ├── cliCtx.ts # Shared command glue (run, buildClient)
│ └── commands/
│ ├── auth.ts # auth:login, auth:logout, auth:whoami, auth:status
│ ├── workspaces.ts # workspaces:list, workspaces:use, workspaces:current
│ ├── lookups.ts # accounts/campaigns/categories/labels/team list commands
│ ├── posts.ts # posts:list, posts:create, posts:delete, posts:approve, posts:reject
│ ├── comments.ts # comments:list, comments:add
│ └── media.ts # media:list, media:upload
├── tests/ # vitest + nock unit + real-API E2E
├── skills/contentstudio/SKILL.md # symlink → ../../SKILL.md
├── .claude-plugin/ # Claude Code plugin manifest
├── SKILL.md # AI-agent skill content
├── README.md # This file
├── CHANGELOG.md
├── LICENSE # MIT
├── package.json
├── tsconfig.json
└── tsup.config.ts
npm run dev # tsup --watch (rebuild on save)
npm run build # tsup → dist/index.js
npm run start # node dist/index.js
npm test # vitest run (unit + CLI subprocess; E2E auto-skipped)
npm run test:watch # vitest in watch mode- Unit + CLI subprocess — runs by default with
npm test. Usesnockto mock HTTPS. No network required. - Real-API E2E — gated on env vars. Hits
api.contentstudio.iofor real:E2E covers create-draft → delete cycles via both the API client and the installed CLI binary.CONTENTSTUDIO_API_KEY=cs_... \ CONTENTSTUDIO_WORKSPACE_ID=... \ npm test
tsup produces a single CommonJS bundle at dist/index.js (~43 KB) with #!/usr/bin/env node shebang. The npm package ships only dist/, README.md, SKILL.md, CHANGELOG.md, and LICENSE.
- API keys live in
~/.config/contentstudio/config.jsonwith mode0600. - Keys are never echoed in CLI output (only a redacted prefix via
auth:status). - The
--jsonerror envelope never includes the key. - All API traffic is HTTPS; the client validates TLS certificates.
- 0 production dependency vulnerabilities (
npm audit --omit=dev).
- Fork the repo at https://github.com/d4interactive/contentstudio-agent
- Branch off
main - Make your changes; add/update tests
npm test— must stay green- Open a pull request
- npm: https://www.npmjs.com/package/contentstudio-cli
- GitHub: https://github.com/d4interactive/contentstudio-agent
- API guide: https://api.contentstudio.io/guide
- OpenAPI spec: https://api.contentstudio.io/api-docs
- ContentStudio: https://contentstudio.io
{ "content": { "text": "Hello world", "media": { "images": ["https://example.com/img.jpg"], "video": "https://example.com/clip.mp4", "media_ids": ["<media_library_id>"] } }, "accounts": ["<account_id>"], "post_type": "reel+story", "post_video_title": "My Video Title", "scheduling": { "publish_type": "scheduled", "scheduled_at": "2026-05-01 10:00:00" }, "first_comment": { "message": "🔗 link in bio", "accounts": ["<account_id>"] }, "labels": ["<label_id>"], "campaign_id": "<campaign_id>", "approval": { "approvers": ["<user_id>"], "approve_option": "anyone", "notes": "please review" }, "youtube_options": { "title": "...", "privacy_status": "public", "category": "EDUCATION", "tags": ["tag1"], "license": "youtube", "made_for_kids": false }, "tiktok_options": { "privacy_level": "PUBLIC_TO_EVERYONE", "disable_comment": false, "disable_duet": false, "disable_stitch": false, "auto_add_music": false }, "pinterest_options": { "title": "...", "link": "https://..." }, "gmb_options": { "topic_type": "EVENT", "start_date": "2026-05-01", "end_date": "2026-05-02", "title": "...", "action_type": "BOOK", "cta_link": "https://..." } }