Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Upload-Post CLI

The official command line for Upload-Post. Publish, schedule and track posts on TikTok, Instagram, YouTube, LinkedIn, Facebook, X, Threads, Pinterest, Bluesky, Google Business, Discord, Telegram and more, from your terminal, your scripts or an AI agent.

npx @upload-post/cli post video -p my-brand --platforms tiktok,instagram,youtube \
  -m ./clip.mp4 -t "Launch day" --wait

It is built on the official upload-post SDK and only uses endpoints documented at docs.upload-post.com.

Install

# run it without installing
npx @upload-post/cli --help

# or install the `upload-post` command globally
npm install -g @upload-post/cli
upload-post --help

Requires Node.js 18 or newer.

Authentication

Get an API key at app.upload-post.com/api-keys, then:

upload-post login            # asks for the key, checks it, saves it
upload-post whoami           # which account and plan the key belongs to

login stores the key in ~/.config/upload-post/config.json (or $XDG_CONFIG_HOME/upload-post/config.json), readable only by you (mode 600). It can also read the key from stdin: echo "$KEY" | upload-post login.

The key is looked up in this order, first match wins:

  1. --api-key <key>
  2. the UPLOAD_POST_API_KEY environment variable
  3. the saved config file

upload-post logout deletes the saved key.

Commands

Command What it does
login / logout Save or remove your API key
whoami Account email and plan behind the key
profiles [username] Your profiles and the accounts connected to each (and which need reconnecting)
post video|photos|text|document Publish now, schedule, or add to the queue
status <request_id|job_id> Per-platform result of an upload
scheduled Scheduled and queued posts that have not run yet
cancel <job_id> Cancel a scheduled/queued post (its credits are refunded)
history Past uploads, one row per platform
analytics <profile> Followers, reach, views... per platform
comments list|reply Read and answer comments (Instagram, Facebook, YouTube, LinkedIn, TikTok, X, Threads, Bluesky)
dms list|send Instagram direct messages

Every command has --help with examples, e.g. upload-post post video --help.

Publishing

# Video to several platforms, wait for the result
upload-post post video -p my-brand --platforms tiktok,instagram,youtube \
  -m ./clip.mp4 -t "Launch day" -d "Longer description for YouTube/LinkedIn" --wait

# Photo carousel (local files and URLs can be mixed)
upload-post post photos -p my-brand --platforms instagram,threads \
  -m ./1.jpg ./2.jpg https://cdn.example.com/3.jpg -t "Behind the scenes"

# Text post, scheduled in a timezone
upload-post post text -p my-brand --platforms x,linkedin,threads -t "We just shipped" \
  --schedule 2026-10-01T09:00:00 --timezone Europe/Madrid

# Next free slot of the profile's queue
upload-post post text -p my-brand --platforms linkedin -t "Weekly tip" --queue

# LinkedIn document (PDF, PPT, PPTX, DOC, DOCX)
upload-post post document -p my-brand -m ./deck.pdf -t "Q3 results"

Common options:

Option Meaning
-p, --profile <name> Profile to publish from (or UPLOAD_POST_PROFILE)
--platforms <list> Comma-separated, e.g. tiktok,instagram,x. X is x
-t, --title <text> Title / caption. For text posts, the text itself
-d, --description <text> Longer text used by LinkedIn, Facebook, YouTube and Pinterest
-m, --media <paths or URLs> The video, photos or document
--schedule <ISO 8601> Publish later (up to 365 days ahead)
--timezone <IANA> Timezone for --schedule; UTC by default
--queue Add to the next free queue slot
--first-comment <text> First comment after publishing
-o, --option key=value Any platform-specific API field (repeatable, see below)
--idempotency-key <key> Sending the same key again within 24 h never publishes twice
-w, --wait Block until every platform has a final result
--timeout <seconds> Limit for --wait (default 900)
--dry-run Print the exact request, send nothing

Reddit is temporarily unavailable in Upload-Post (the API answers 503 reddit_unavailable), so the CLI refuses it up front.

Platform-specific options

Everything platform-specific goes through --option, with the API field name exactly as written in the docs (video, photos, text, document). Repeat it for several fields; repeat a [] field for arrays. Prefix a value with @ to send a local file.

upload-post post video -p my-brand --platforms tiktok,youtube,instagram -m ./clip.mp4 -t "Demo" \
  --option privacy_level=SELF_ONLY \
  --option privacyStatus=unlisted \
  --option tags[]=demo --option tags[]=launch \
  --option media_type=REELS \
  --option tiktok_title="Short caption for TikTok" \
  --option thumbnail=@./thumb.jpg

Field names are taken as-is, so they follow the docs even where they are camelCase (YouTube's privacyStatus, categoryId...). Check what will be sent with --dry-run before publishing.

Tracking

upload-post status 1a2b3c4d5e            # request_id from an upload
upload-post status 1a2b3c4d5e --wait     # keep polling until it is final
upload-post scheduled -p my-brand
upload-post cancel a1b2c3d4e5f6
upload-post history --limit 20 --status failed

Uploads run asynchronously. Without --wait, post returns as soon as Upload-Post accepts the post and prints its request_id. Scheduled and queued posts return a job_id instead.

Analytics, comments, DMs

upload-post analytics my-brand                       # every connected platform
upload-post analytics my-brand --platforms instagram,tiktok --json

upload-post comments list -p my-brand --platform youtube --post-id dQw4w9WgXcQ
upload-post comments reply -p my-brand --platform instagram --comment-id 1789 --message "Thanks!"
upload-post comments reply -p my-brand --platform instagram --comment-id 1789 --message "Check your DMs" --private

upload-post dms list -p my-brand
upload-post dms send -p my-brand --recipient-id 17841400123456789 --message "Hi!"

For AI agents

The CLI is designed to be driven by agents such as Claude Code, Codex or Cursor, as well as by CI jobs.

  • Always pass --json. stdout then carries exactly one JSON document, for success and for errors alike. Progress messages go to stderr.

  • Pass --wait when you publish, so the command returns only when every platform has a final result, with the post URLs:

    upload-post post video -p my-brand --platforms tiktok,instagram -m ./clip.mp4 -t "Hi" --wait --json
    {
      "success": true,
      "request_id": "1a2b3c4d5e",
      "job_id": null,
      "upload": { "success": true, "request_id": "1a2b3c4d5e", "total_platforms": 2 },
      "status": {
        "status": "completed",
        "completed": 2,
        "total": 2,
        "results": [
          { "platform": "tiktok", "success": true, "post_url": "https://www.tiktok.com/@brand/video/..." },
          { "platform": "instagram", "success": true, "post_url": "https://www.instagram.com/reel/..." }
        ]
      }
    }
  • Branch on the exit code, not on text:

    Code Meaning
    0 Success
    1 The API returned an error, or could not be reached
    2 Invalid command line (unknown flag, missing option, bad value)
    3 No API key, or the key was rejected (HTTP 401)
    4 The post finished but at least one platform failed
    5 --wait timed out; the upload keeps running, check it with status
  • Errors keep the API's own message, plus the HTTP status and the full response:

    { "success": false, "error": { "message": "Invalid API key", "code": "http_401", "exit_code": 3, "status": 401, "response": { "success": false, "message": "Invalid API key" } } }
  • Retrying is safe with --idempotency-key. If a publish times out, rerun it with the same key instead of posting twice.

  • Use --dry-run to show a user exactly what will be published before doing it.

  • Authenticate with UPLOAD_POST_API_KEY in the environment rather than --api-key, so the key does not end up in shell history or logs. Set UPLOAD_POST_PROFILE to skip --profile.

  • Start with upload-post profiles --json to find profile names and the platforms connected to each. An account with reauth_required: true has to be reconnected in the dashboard before it can publish.

Environment variables

Variable Purpose
UPLOAD_POST_API_KEY API key
UPLOAD_POST_PROFILE Default profile for post, comments and dms
UPLOAD_POST_BASE_URL API base URL (default https://api.upload-post.com/api)
XDG_CONFIG_HOME Where the config directory lives (default ~/.config)

Development

npm install
npm test            # vitest, SDK and network mocked
npm run typecheck
npm run build       # tsup -> dist/cli.js (ESM)
node dist/cli.js --help

License

MIT

About

Upload-Post CLI: publish, schedule and track social media posts from your terminal or AI coding agent (npx @upload-post/cli)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages