CLI
Interface specification
This page is the interface specification for
@voxburst/cliversion0.2.x(covers0.2.0,0.2.1, and0.2.2).Verified binary:
@voxburst/cli@0.2.2— npmlatest, published 2026-05-20.If you have
0.2.0or0.2.1installed, this spec applies to your version without change — all flags,--jsonfield names, exit codes, and--fileschemas are identical across every0.2.xrelease.voxburst --version # confirm your version npm install -g @voxburst/cli@latest # upgrade to 0.2.2 if needed
Schema stability guarantee
JSON output fields: All field names, types, and enum values documented in this page are stable for the lifetime of 0.2.x. Scripts written against any 0.2.x release will continue to work without changes against any later 0.2.x release.
Additive changes only: New fields may be added to any --json output in a 0.2.x release. Removed or renamed fields signal a major version bump.
Flag compatibility guarantee
All flags documented in this page are stable for the lifetime of 0.2.x. Flag removal or rename requires a major version bump and a minimum 30-day deprecation notice.
Compatibility and deprecation policy
| Change type | Version signal | Notice |
|---|---|---|
| New flag or JSON field | 0.2.x patch | None required — additive |
| New command | 0.2.x or 0.3.x | None required — additive |
| Flag rename or removal | 1.0.0 (major) | 30-day deprecation notice |
| JSON field rename or removal | 1.0.0 (major) | 30-day deprecation notice |
| Exit code behavior change | 1.0.0 (major) | 30-day deprecation notice |
--file schema change (breaking) | 1.0.0 (major) | 30-day deprecation notice |
Post to social media directly from your terminal, scripts, and CI pipelines.
npm install -g @voxburst/cli # global install
npx @voxburst/cli --help # run without installingThe package name is @voxburst/cli but the command is voxburst. Do not run @voxburst/cli directly.
Automation contract (read this first)
Everything an operator needs to know before scripting against the CLI. Details are in the sections below; this is the canonical single-location summary.
Which commands are safe for scripting
| Command | --json | --quiet | Mutates state | Safe for CI | Notes |
|---|---|---|---|---|---|
post | ✅ | ✅ | Yes | ✅ | Creates and publishes a post |
schedule | ✅ | ✅ | Yes | ✅ | Creates a scheduled post |
validate | ✅ | ✗ | No | ✅ | Never mutates; always exits 0 |
posts list | ✅ | ✅ | No | ✅ | Read-only |
posts get | ✅ | ✗ | No | ✅ | Read-only |
posts delete | ✗ | ✅ | Yes | ⚠️ | Destructive — use carefully |
accounts list | ✅ | ✅ | No | ✅ | Read-only |
accounts connect | ✗ | ✗ | Yes | ❌ | Opens browser — not headless |
whoami | ✅ | ✗ | No | ✅ | Auth check |
status | ✅ | ✗ | No | ✅ | Read-only overview |
config set/get/list | ✗ | ✗ | Yes/No | ⚠️ | Mutates local config file |
login | ✗ | ✗ | Yes | ⚠️ | Use VOXBURST_API_KEY env var in CI instead |
analytics | ✅ | ✗ | No | ✅ | Read-only |
Exit codes
| Code | Meaning |
|---|---|
0 | Command completed — does not guarantee all platforms published |
1 | Infrastructure error (auth, network, bad args, rate limit, server error) |
Exit 0 ≠ success for post/schedule. Always check results[].status per platform.
validate always exits 0 — content failing platform rules is not an error. Check .[].valid.
JSON shape stability
- Fields documented in this page are stable for
voxburst@0.2.x - New fields may appear in any minor release — write scripts defensively:
jq '.field // empty' - Fields will not be removed or renamed without a major version bump
- The CLI status set (
draft,scheduled,published,failed) is a subset of the REST API — do not pass REST statuses to--status
Credential precedence
1. --api-key flag (where supported)
2. VOXBURST_API_KEY environment variable ← use this in CI
3. api-key in ~/.voxburst/config.json
4. (no key → exit 1)Partial success
post and schedule exit 0 when the post record is created, even if platform publishing fails. Check results[].status in every automation script:
RESULT=$(voxburst post "Hello" -p twitter,instagram --json)
FAILED=$(echo "$RESULT" | jq '[.results[] | select(.status=="failed")] | length')
[ "$FAILED" -gt 0 ] && { echo "Platform failure" >&2; exit 1; }Rate limits and retry
- HTTP 429 → exit 1, message to stderr
- CLI does not auto-retry
- Implement backoff in the calling script (see CI workflow example)
Install and upgrade
Global install
npm install -g @voxburst/cli
voxburst --helpIf voxburst is not found after installing:
# zsh (macOS default)
echo 'export PATH="$PATH:$(npm config get prefix)/bin"' >> ~/.zshrc && source ~/.zshrc
# bash
echo 'export PATH="$PATH:$(npm config get prefix)/bin"' >> ~/.bashrc && source ~/.bashrcUpgrade:
npm install -g @voxburst/cli@latest
voxburst --versionFirst-time operator workflow
Copy and paste this entire block. Every line is a real command.
# 1. Install
npm install -g @voxburst/cli
# 2. Set API key (get it from app.voxburst.io/settings/api)
voxburst login --api-key vb_live_xxxxxxxxxxxxx
# 3. Verify auth
voxburst whoami
# 4. List connected accounts — copy an account ID for the next step
voxburst accounts list --json
# 5. Validate content against your target platform before posting
voxburst validate "Hello from VoxBurst!" -p twitter --json
# 6. Post (replace acc_twitter_abc with your account ID from step 4)
voxburst post "Hello from VoxBurst!" -p twitter --json
# 7. Inspect the result — check .status and .results[].status
voxburst posts list --status published --json | head -40If step 3 fails with 401, regenerate your API key and repeat step 2.
If step 4 shows no accounts, run voxburst accounts connect twitter first.
Authentication
The CLI supports two authentication methods. API key auth is recommended for scripts, automation, and CI/CD. Cognito (email/password) is for interactive sessions.
API key (recommended)
voxburst login --api-key vb_live_xxxxxxxxxxxxx
# Stored in ~/.voxburst/config.json (permissions: 0600)Or via environment variable (takes precedence over config file):
export VOXBURST_API_KEY=vb_live_xxxxxxxxxxxxx
voxburst whoamiCredential precedence order:
VOXBURST_API_KEYenvironment variableapi-keyin~/.voxburst/config.json
Cognito (email/password)
voxburst login --email you@example.com
# Prompts for password interactively
voxburst login --email you@example.com --password yourpassCognito login stores a session token in ~/.voxburst/config.json. Tokens expire; re-run voxburst login if you receive 401 errors.
Verify auth
voxburst whoamiCredential storage and security
- Config file:
~/.voxburst/config.json - File permissions:
0600(owner read/write only) - Config directory:
~/.voxburst/(permissions:0700) - The API key is stored in plaintext at
0600— treat it like a password
Rotate credentials:
voxburst config set api-key vb_live_new_key_here
# Or unset entirely:
voxburst config delete api-keyConfig and environment variables
Config file reference
Stored at ~/.voxburst/config.json. Manage via voxburst config.
| Key | CLI flag | Description | Default |
|---|---|---|---|
api-key | voxburst config set api-key <value> | API key for authentication | — |
api-url | voxburst config set api-url <value> | API base URL override | https://api.voxburst.io |
default-platforms | voxburst config set default-platforms twitter,linkedin | Platforms used when -p is omitted | twitter |
voxburst config set api-key vb_live_xxxxxxxxxxxxx
voxburst config set default-platforms twitter,linkedin,instagram
voxburst config get api-key
voxburst config list # show all config
voxburst config delete api-key # remove a valueEnvironment variables
| Variable | Overrides | Description |
|---|---|---|
VOXBURST_API_KEY | api-key in config | API key (takes precedence over config file) |
VOXBURST_API_URL | api-url in config | API base URL override |
Environment variables always override config file values.
Exit codes
All CLI commands exit with a consistent code:
| Exit code | Meaning |
|---|---|
0 | Success |
1 | Any error (auth failure, validation failure, network error, platform failure, config error, bad arguments) |
The CLI does not currently distinguish between error categories by exit code. Use --json and parse the error field in scripts that need to distinguish failure types.
voxburst post "Hello" && echo "success" || echo "failed (exit $?)"JSON output schemas
Add --json to any command to get machine-readable output on stdout. Error output always goes to stderr regardless of --json.
Contract guarantee (voxburst@0.2.2): Every field in the tables below is present in the shipped binary. Fields will not be removed or renamed without a major version bump. New fields may be added in any release — write scripts defensively (jq '.field // empty'). Verify against your installed version with voxburst --version.
voxburst whoami --json
Success (exit 0):
{ "id": "usr_abc123", "email": "you@example.com", "name": "Your Name", "plan": "pro", "createdAt": "2026-01-01T00:00:00Z" }| Field | Type | Nullable | Values |
|---|---|---|---|
id | string | no | cuid2 ID |
email | string | no | |
name | string | yes | |
plan | string | no | free pro team enterprise |
createdAt | string | no | ISO 8601 UTC |
Failure (exit 1, stderr): Error: VoxBurst API Error (401): Invalid API key
voxburst accounts list --json
Success (exit 0):
{
"data": [
{ "id": "acc_twitter_abc", "platform": "twitter", "username": "mybrand", "displayName": "My Brand", "status": "active", "connectedAt": "2026-03-01T10:00:00Z" }
]
}| Field | Type | Nullable | Values |
|---|---|---|---|
data | array | no | Array of account objects |
data[].id | string | no | Account ID — use this in -p and --file |
data[].platform | string | no | twitter linkedin instagram facebook threads bluesky mastodon youtube |
data[].username | string | no | Platform handle |
data[].displayName | string | yes | Display name |
data[].status | string | no | active expired disconnected |
data[].connectedAt | string | no | ISO 8601 UTC |
Failure (exit 1, stderr): Error: VoxBurst API Error (401): Invalid API key
voxburst post "..." --json and voxburst schedule "..." --json
Success — published (exit 0):
{
"id": "post_abc123", "content": "Hello!", "platforms": ["twitter"],
"status": "published", "scheduledAt": null, "publishedAt": "2026-03-15T10:00:05Z", "createdAt": "2026-03-15T10:00:00Z",
"results": [{ "platform": "twitter", "accountId": "acc_twitter_abc", "status": "success", "postUrl": "https://x.com/mybrand/status/123" }]
}Success — scheduled (exit 0):
{
"id": "post_abc123", "content": "Hello!", "platforms": ["twitter"],
"status": "scheduled", "scheduledAt": "2026-06-01T15:00:00Z", "publishedAt": null, "createdAt": "2026-03-15T10:00:00Z",
"results": []
}Platform failure — CLI exits 0, check results[].status (exit 0):
{
"id": "post_abc123", "content": "Hello!", "platforms": ["twitter"],
"status": "failed", "scheduledAt": null, "publishedAt": null, "createdAt": "2026-03-15T10:00:00Z",
"results": [{ "platform": "twitter", "accountId": "acc_twitter_abc", "status": "failed", "error": "Content exceeds Twitter character limit", "postUrl": null }]
}Partial success: The CLI exits 0 even when platform publishing fails. Always check results[].status — the top-level status field reflects the post record state, not publication success. A post can have status: "published" with individual platform results showing "failed".
| Field | Type | Nullable | Values |
|---|---|---|---|
id | string | no | Post ID |
content | string | no | |
platforms | string[] | no | Platform names |
status | string | no | draft scheduled published failed (complete list for CLI 0.2.2) |
scheduledAt | string | yes | ISO 8601 UTC or null |
publishedAt | string | yes | ISO 8601 UTC or null |
createdAt | string | no | ISO 8601 UTC |
results | array | no | Empty for drafts/scheduled; per-platform publish results once attempted |
results[].platform | string | no | Platform name |
results[].accountId | string | no | Account ID |
results[].status | string | no | success failed |
results[].postUrl | string | yes | Live URL if published, null if failed |
results[].error | string | yes | Error message if failed, null if succeeded |
voxburst posts list --json
Success (exit 0): Array of post objects (same shape as post/schedule above, without results).
[
{ "id": "post_abc123", "content": "Hello world", "platforms": ["twitter"], "status": "scheduled", "scheduledAt": "2026-06-01T15:00:00Z", "createdAt": "2026-05-30T10:00:00Z" },
{ "id": "post_def456", "content": "Second post", "platforms": ["linkedin"], "status": "draft", "scheduledAt": null, "createdAt": "2026-05-29T09:00:00Z" }
]Empty result (exit 0): []
voxburst posts get <id> --json
Same shape as post --json above including results.
Not found (exit 1, stderr): Error: Post not found
voxburst validate "..." --json
All valid (exit 0):
[{ "valid": true, "platform": "twitter", "errors": [], "warnings": [] }]Validation failure (exit 0 — validation ran; check valid field per platform):
[
{ "valid": false, "platform": "instagram", "errors": [{ "code": "MEDIA_REQUIRED", "message": "Instagram requires at least one image or video", "field": "media" }], "warnings": [] },
{ "valid": true, "platform": "twitter", "errors": [], "warnings": [{ "code": "NO_HASHTAGS", "message": "Posts with hashtags typically get more reach on Twitter", "suggestion": "Consider adding 1-2 relevant hashtags" }] }
]validate always exits 0. Validation itself is not an error — it ran successfully. Check .[].valid to determine if content passes platform rules. Only infrastructure errors (auth, network) cause exit 1.
| Field | Type | Nullable | Values |
|---|---|---|---|
| Array root | array | no | One object per platform validated |
[].valid | boolean | no | true if no errors |
[].platform | string | no | Platform name |
[].errors | array | no | Empty if valid |
[].errors[].code | string | no | Machine-readable error code |
[].errors[].message | string | no | Human-readable message |
[].errors[].field | string | yes | Which field caused the error |
[].warnings | array | no | Non-blocking issues |
[].warnings[].code | string | no | |
[].warnings[].message | string | no | |
[].warnings[].suggestion | string | yes |
voxburst status --json
{
"user": { "id": "usr_abc", "email": "you@example.com", "plan": "pro" },
"accounts": { "data": [ ...account objects... ] },
"recentPosts": [ ...post objects... ]
}Formal JSON Schemas
Machine-readable JSON Schema (draft-07) for every --json output and the --file input. Use these to write validation, wrappers, and tests against the CLI without ambiguity.
voxburst whoami --json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["id", "email", "plan", "createdAt"],
"properties": {
"id": { "type": "string" },
"email": { "type": "string", "format": "email" },
"name": { "type": ["string", "null"] },
"plan": { "type": "string", "enum": ["free", "pro", "team", "enterprise"] },
"createdAt": { "type": "string", "format": "date-time" }
}
}voxburst accounts list --json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["data"],
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "platform", "username", "status", "connectedAt"],
"properties": {
"id": { "type": "string" },
"platform": { "type": "string", "enum": ["twitter","linkedin","instagram","facebook","threads","bluesky","mastodon","youtube","tiktok","pinterest","reddit","snapchat","telegram","google_business","whatsapp"] },
"username": { "type": "string" },
"displayName": { "type": ["string", "null"] },
"status": { "type": "string", "enum": ["active", "expired", "disconnected"] },
"connectedAt": { "type": "string", "format": "date-time" }
}
}
}
}
}voxburst post --json / voxburst schedule --json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["id", "content", "platforms", "status", "createdAt", "results"],
"properties": {
"id": { "type": "string" },
"content": { "type": "string" },
"platforms": { "type": "array", "items": { "type": "string" } },
"status": { "type": "string", "enum": ["draft", "scheduled", "published", "failed"] },
"scheduledAt": { "type": ["string", "null"], "format": "date-time" },
"publishedAt": { "type": ["string", "null"], "format": "date-time" },
"createdAt": { "type": "string", "format": "date-time" },
"results": {
"type": "array",
"items": {
"type": "object",
"required": ["platform", "accountId", "status"],
"properties": {
"platform": { "type": "string" },
"accountId": { "type": "string" },
"status": { "type": "string", "enum": ["success", "failed"] },
"postUrl": { "type": ["string", "null"] },
"error": { "type": ["string", "null"] }
}
}
}
}
}voxburst posts list --json
Array of post objects. Each item matches the post --json schema above minus the results field.
voxburst validate --json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"type": "object",
"required": ["valid", "platform", "errors", "warnings"],
"properties": {
"valid": { "type": "boolean" },
"platform": { "type": "string" },
"errors": {
"type": "array",
"items": {
"type": "object",
"required": ["code", "message"],
"properties": {
"code": { "type": "string" },
"message": { "type": "string" },
"field": { "type": ["string", "null"] }
}
}
},
"warnings": {
"type": "array",
"items": {
"type": "object",
"required": ["code", "message"],
"properties": {
"code": { "type": "string" },
"message": { "type": "string" },
"suggestion": { "type": ["string", "null"] }
}
}
}
}
}
}--file input schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["content"],
"properties": {
"content": { "type": "string", "minLength": 1 },
"platforms": { "type": "array", "items": { "type": "string" } },
"scheduledAt": { "type": "string", "format": "date-time", "description": "Always use UTC (Z suffix) in files" },
"media": {
"type": "array",
"items": {
"type": "object",
"required": ["path"],
"properties": {
"path": { "type": "string" },
"altText": { "type": ["string", "null"] }
}
}
}
},
"additionalProperties": false
}additionalProperties: false — unrecognised fields cause a parse error in 0.2.2.
Scheduling and timezone semantics
The CLI accepts datetimes in two formats:
| Format | Example | Behavior |
|---|---|---|
| ISO 8601 with timezone | 2026-06-01T15:00:00Z | UTC — recommended |
| ISO 8601 with offset | 2026-06-01T11:00:00-04:00 | Offset preserved |
| ISO 8601 without timezone | 2026-06-01T15:00:00 | Interpreted in local system timezone |
| Space-separated | 2026-06-01 15:00 | Interpreted in local system timezone |
Timezone gotcha: If you omit the timezone offset (e.g. 2026-06-01T15:00:00), the time is interpreted in the timezone of the machine running the CLI. This is correct for interactive use but can cause bugs in CI/CD — a GitHub Actions runner is UTC, a developer laptop may be UTC-5.
Always use explicit UTC (Z) in scripts and CI:
voxburst schedule "..." --at "2026-06-01T15:00:00Z"Examples — always append Z in scripts:
# ✅ UTC — safe in any environment
voxburst schedule "Launch post" --at "2026-06-01T15:00:00Z" -p twitter
# ✅ Offset — explicit, portable
voxburst schedule "Launch post" --at "2026-06-01T11:00:00-04:00" -p twitter
# ⚠️ No timezone — interpreted in local TZ; avoid in scripts
voxburst schedule "Launch post" --at "2026-06-01T15:00:00" -p twitter
# Validate a schedule time without committing
voxburst schedule "Test" --at "2026-06-01T15:00:00Z" --draft # creates a draft; inspect, then deleteFile input schema (--file)
The --file flag accepts a JSON file. This is the exact schema — any unrecognised field is silently ignored.
Field contract
| Field | Type | Required | Description |
|---|---|---|---|
content | string | Yes | Post text |
platforms | string[] | No | Lowercase platform names. Falls back to default-platforms config if omitted. |
scheduledAt | string | No | ISO 8601 datetime. Always use UTC (Z suffix) in files to avoid system-timezone bugs. |
media | object[] | No | Local media files to upload |
media[].path | string | Yes (if media present) | Absolute or relative path to image/video |
media[].altText | string | No | Accessibility alt text |
Example 1 — minimal (post now)
{
"content": "Hello from a file!"
}Example 2 — scheduled post
{
"content": "Weekly roundup — five things we shipped this week.",
"platforms": ["twitter", "linkedin"],
"scheduledAt": "2026-06-06T17:00:00Z"
}Always use UTC in files. "scheduledAt": "2026-06-06T17:00:00" (no Z) is parsed in the local timezone of the machine that runs voxburst post --file. A cron job on a UTC server and a developer on UTC-5 will schedule for different times. Add Z to be explicit.
Example 3 — media-rich post with alt text
{
"content": "Behind the scenes of our product launch 📸",
"platforms": ["instagram", "twitter"],
"scheduledAt": "2026-06-01T15:00:00Z",
"media": [
{ "path": "/home/user/images/launch-hero.jpg", "altText": "Team celebrating the product launch" },
{ "path": "/home/user/images/launch-dashboard.jpg", "altText": "Screenshot of the new dashboard" }
]
}voxburst post --file post.json
voxburst post --file post.json --json # get full JSON responseAccount connection and OAuth
List connected accounts
voxburst accounts list
voxburst accounts list --json # machine-readable
voxburst accounts list -q # IDs only, one per lineConnect a new account
voxburst accounts connect twitterThis opens a browser window for OAuth authorization. Complete the OAuth flow in the browser, then return to the terminal — the account will be confirmed as connected.
Platform-specific preconditions:
- Instagram: Must connect through Facebook; requires Business or Creator account
- LinkedIn: Approve all requested permissions including
w_member_social - Facebook: After connecting, select a Page via
voxburst accounts listand note the account ID - YouTube: Approve
youtube.uploadandyoutube.readonlyscopes - Bluesky: Uses app passwords, not OAuth — see
voxburst loginwith Bluesky-specific flow - Mastodon: Provide your instance URL when prompted
Headless / non-interactive: accounts connect always opens a browser — it cannot be run headlessly. For CI: connect accounts interactively first on a developer machine, confirm status: active with accounts list --json, then use the resulting account IDs in automation. Account IDs do not change after reconnection.
What happens step by step:
- CLI opens your default browser to the VoxBurst OAuth page
- You authorize the connection in the browser
- VoxBurst redirects to a localhost callback URL
- CLI receives the callback, stores the token, and prints confirmation
If the browser does not open: Copy the URL printed to your terminal and open it manually.
Disconnect an account
voxburst accounts disconnect <account-id>Reconnect an expired account
When voxburst accounts list --json shows "status": "expired", the OAuth token can no longer be refreshed silently. Any post attempt to that account will fail.
# Identify expired accounts
voxburst accounts list --json | jq '.data[] | select(.status == "expired") | {id, platform, username}'
# Reconnect
voxburst accounts connect twitter # opens browser; completes the full OAuth flow again
# Confirm
voxburst accounts list --json | jq '.data[] | select(.platform == "twitter") | .status'
# Should print: "active"Account IDs are stable across reconnection — your existing scripts using the account ID do not need to be updated after reconnecting an expired account.
Command reference
voxburst post
Create and publish a post immediately.
voxburst post "Hello world!"
voxburst post "Hello!" -p twitter,linkedin
voxburst post "Hello!" -p instagram -m /path/to/image.jpg
voxburst post --file post.json
voxburst post "Draft" --draft
voxburst post "Hello!" --json| Flag | Description |
|---|---|
[content] | Post text (positional argument, or omit with --file) |
-p, --platforms <list> | Comma-separated platforms. Default: default-platforms config |
-m, --media <paths> | Comma-separated media file paths |
-f, --file <path> | Read post from JSON file (see file schema) |
-d, --draft | Save as draft instead of publishing |
--json | Output result as JSON |
-q, --quiet | Minimal output (post ID only) |
Instagram requires at least one media file (-m) on every post. A text-only post to Instagram will fail.
voxburst schedule
Schedule a post for a future time. Shorthand for post --schedule.
voxburst schedule "Launch day!" --at "2026-06-01T15:00:00Z"
voxburst schedule "Launch day!" --at "2026-06-01T15:00:00Z" -p twitter,linkedin
voxburst schedule "Launch day!" --at "2026-06-01 15:00" -p twitter # local timezone
voxburst schedule "Launch day!" --at "2026-06-01T15:00:00Z" --json| Flag | Description |
|---|---|
<content> | Post text (required positional) |
--at <datetime> | Required. When to publish. See scheduling semantics. |
-p, --platforms <list> | Comma-separated platforms |
-m, --media <paths> | Comma-separated media file paths |
--json | Output result as JSON |
-q, --quiet | Minimal output |
voxburst validate
Check content against platform rules without creating a post.
voxburst validate "My post content"
voxburst validate "My post content" -p twitter,instagram
voxburst validate "My post content" --jsonReturns per-platform valid, errors, and warnings. See JSON output.
voxburst posts
Manage existing posts.
voxburst posts list
voxburst posts list --status scheduled
voxburst posts list --status draft --json
voxburst posts get post_abc123
voxburst posts get post_abc123 --json
voxburst posts delete post_abc123posts list flags:
| Flag | Description |
|---|---|
-s, --status <status> | Filter by status. Accepted values (complete list): draft, scheduled, published, failed |
-l, --limit <n> | Number of posts to return (default: 20) |
--offset <n> | Pagination offset (default: 0). CLI uses offset-based pagination, not cursor. |
--json | Output as JSON array |
-q, --quiet | Post IDs only, one per line |
voxburst accounts
voxburst accounts list
voxburst accounts list --json
voxburst accounts list -q # IDs only
voxburst accounts connect twitter
voxburst accounts disconnect acc_twitter_abcvoxburst analytics
voxburst analytics post post_abc123
voxburst analytics account acc_twitter_abc
voxburst analytics post post_abc123 --jsonvoxburst status
Show workspace overview: authenticated user, connected accounts, recent posts.
voxburst status
voxburst status --jsonvoxburst whoami
Show the authenticated user and active workspace.
voxburst whoami
voxburst whoami --jsonvoxburst config
Manage CLI configuration.
voxburst config set api-key vb_live_xxxxxxxxxxxxx
voxburst config set default-platforms twitter,linkedin
voxburst config get api-key
voxburst config list
voxburst config delete api-keyvoxburst webhooks
voxburst webhooks list
voxburst webhooks create --url https://example.com/hook --events post.published
voxburst webhooks delete hook_abc123voxburst login
voxburst login --api-key vb_live_xxxxxxxxxxxxx
voxburst login --email you@example.com # prompts for password
voxburst login --email you@example.com --password pass # non-interactivePlatform capability matrix (CLI)
Platform names in the CLI are lowercase (twitter, instagram, etc.).
| Platform | CLI name | Media required | First comment | Scheduling | Notes |
|---|---|---|---|---|---|
| Twitter / X | twitter | No | ✗ (via REST) | ✅ | Max 280 chars |
linkedin | No | ✗ (via REST) | ✅ | Max 3,000 chars | |
instagram | Yes | ✗ (via REST) | ✅ | Media always required; Business/Creator only | |
facebook | No | ✗ (via REST) | ✅ | Pages only | |
| Threads | threads | No | ✗ | ✅ | Requires Instagram account |
| YouTube | youtube | Yes (video) | ✗ (via REST) | ✅ | Video-only; 6 uploads/day |
| Bluesky | bluesky | No | ✗ | ✅ | Max 300 graphemes |
| Mastodon | mastodon | No | ✗ | ✅ | Limit varies by instance |
First comments via CLI are not currently supported. Use the REST API (firstComment field on POST /v1/posts) for first-comment workflows in scripts.
Automation and CI/CD
Shell script
#!/bin/bash
set -euo pipefail
# Set via environment — never hardcode
export VOXBURST_API_KEY="${VOXBURST_API_KEY}"
# Validate before posting
if ! voxburst validate "$CONTENT" -p twitter --json | jq -e '.[0].valid' > /dev/null 2>&1; then
echo "Validation failed" >&2
exit 1
fi
# Post and capture ID
POST_ID=$(voxburst post "$CONTENT" -p twitter -q)
echo "Posted: $POST_ID"Cron job
# Post every Monday at 9 AM UTC
0 9 * * 1 VOXBURST_API_KEY=vb_live_xxx /usr/local/bin/voxburst post --file /etc/voxburst/monday-post.json >> /var/log/voxburst.log 2>&1GitHub Actions
- name: Post to social media
env:
VOXBURST_API_KEY: ${{ secrets.VOXBURST_API_KEY }}
run: |
# Always use UTC timestamps in CI
npx @voxburst/cli schedule "Weekly update" \
--at "$(date -u -d '+1 hour' '+%Y-%m-%dT%H:%M:%SZ')" \
-p twitter,linkedin \
--jsonParse JSON output in scripts
# Check if post succeeded
RESULT=$(voxburst post "Hello" -p twitter --json)
STATUS=$(echo "$RESULT" | jq -r '.status')
if [ "$STATUS" = "published" ]; then
URL=$(echo "$RESULT" | jq -r '.results[0].postUrl')
echo "Published: $URL"
else
echo "Post failed with status: $STATUS" >&2
exit 1
fiRetry on failure
The CLI exits 1 on any failure but does not retry automatically. Implement retry in the calling script:
for i in 1 2 3; do
voxburst post "$CONTENT" -p twitter && break
echo "Attempt $i failed — retrying in 30s..." >&2
sleep 30
doneCI workflow example
A complete, copy-pasteable CI script with set -e, --json, per-platform failure checking, and retry logic:
#!/bin/bash
# voxburst-post.sh — canonical CI posting script
set -euo pipefail
CONTENT="${POST_CONTENT:-}"
PLATFORMS="${POST_PLATFORMS:-twitter,linkedin}"
SCHEDULE_AT="${POST_SCHEDULE_AT:-}" # ISO 8601 UTC, or empty to post now
MAX_RETRIES=3
if [ -z "$CONTENT" ]; then
echo "ERROR: POST_CONTENT is required" >&2
exit 1
fi
if [ -z "${VOXBURST_API_KEY:-}" ]; then
echo "ERROR: VOXBURST_API_KEY is not set" >&2
exit 1
fi
# Validate before posting — exit 1 if any platform fails validation
VALIDATION=$(voxburst validate "$CONTENT" -p "$PLATFORMS" --json)
INVALID=$(echo "$VALIDATION" | jq '[.[] | select(.valid == false)] | length')
if [ "$INVALID" -gt 0 ]; then
echo "ERROR: Content failed validation:" >&2
echo "$VALIDATION" | jq '[.[] | select(.valid == false)]' >&2
exit 1
fi
# Post with retry
for attempt in $(seq 1 $MAX_RETRIES); do
if [ -n "$SCHEDULE_AT" ]; then
RESULT=$(voxburst schedule "$CONTENT" --at "$SCHEDULE_AT" -p "$PLATFORMS" --json) && break
else
RESULT=$(voxburst post "$CONTENT" -p "$PLATFORMS" --json) && break
fi
if [ "$attempt" -lt "$MAX_RETRIES" ]; then
echo "Attempt $attempt failed — retrying in 30s..." >&2
sleep 30
else
echo "ERROR: All $MAX_RETRIES attempts failed" >&2
exit 1
fi
done
# Check per-platform results (CLI exits 0 even on platform failure)
FAILED=$(echo "$RESULT" | jq '[.results[] | select(.status == "failed")] | length')
if [ "$FAILED" -gt 0 ]; then
echo "WARNING: $FAILED platform(s) failed to publish:" >&2
echo "$RESULT" | jq '[.results[] | select(.status == "failed") | {platform, error}]' >&2
exit 1
fi
# Report success
POST_ID=$(echo "$RESULT" | jq -r '.id')
echo "SUCCESS: Post $POST_ID published"
echo "$RESULT" | jq '.results[] | {platform, postUrl}'Usage in GitHub Actions:
- name: Post weekly update
env:
VOXBURST_API_KEY: ${{ secrets.VOXBURST_API_KEY }}
POST_CONTENT: "Weekly update — five things we shipped."
POST_PLATFORMS: "twitter,linkedin"
POST_SCHEDULE_AT: "2026-06-06T17:00:00Z"
run: bash ./scripts/voxburst-post.shCI security
- Store
VOXBURST_API_KEYas a CI secret — never in code or logs - Use
--quietor--jsonto avoid key echoing in verbose output - Pin a version in CI for reproducibility:
npx @voxburst/cli@0.2.2
Error catalog and troubleshooting
All errors exit with code 1. Error messages go to stderr; --json does not suppress errors to stderr.
| Error | Cause | Fix |
|---|---|---|
VOXBURST_API_KEY environment variable is required | No API key configured | voxburst login --api-key vb_live_xxx or set VOXBURST_API_KEY |
401 Unauthorized | API key invalid or expired | Generate a new key at app.voxburst.io/settings/api |
No accounts connected | No social accounts linked | voxburst accounts connect twitter |
Platform not connected: instagram | Target platform not linked | voxburst accounts connect instagram |
Invalid datetime format | --at value not parseable | Use ISO 8601: --at "2026-06-01T15:00:00Z" |
Schedule time must be in the future | --at is in the past | Check timezone — naive times use local TZ |
File not found: post.json | --file path wrong | Use absolute path or check working directory |
Content is required | No content and no --file | Add content argument or --file flag |
429 Rate limit exceeded | Too many requests | Wait and retry; CLI does not auto-retry |
Instagram requires media | Posting text-only to Instagram | Add -m /path/to/image.jpg |
Media file not found | -m path invalid | Check the file path |
Account expired | OAuth token expired | voxburst accounts connect <platform> to reconnect |
Debug mode:
voxburst debug # prints config state and auth status without making API callsQuick recipes
Validate then publish
voxburst validate "My post content" -p twitter,instagram --json \
| jq -e 'map(select(.valid == false)) | length == 0' \
&& voxburst post "My post content" -p twitter,instagramSchedule a post from a file
cat > tonight.json << 'EOF'
{
"content": "Weekly roundup — five things we shipped this week.",
"platforms": ["twitter", "linkedin"],
"scheduledAt": "2026-06-06T17:00:00Z"
}
EOF
voxburst post --file tonight.json --jsonFetch recent scheduled posts
voxburst posts list --status scheduled --json | jq '.[] | {id, scheduledAt, content: .content[:60]}'Delete all draft posts
voxburst posts list --status draft -q | while read id; do
voxburst posts delete "$id" && echo "Deleted $id"
doneCross-post to multiple platforms
voxburst post "Announcing our new feature! 🚀" \
-p twitter,linkedin,threads \
--json | jq '.results[] | {platform, status, postUrl}'Security guidance
- Shell history: Avoid passing API keys as inline arguments. Use
voxburst loginorVOXBURST_API_KEYenv var instead of--api-keyin interactive shells to prevent key leakage in~/.bash_historyor~/.zsh_history. - CI secrets: Never print
VOXBURST_API_KEYin CI logs. Use your CI platform’s masked secrets feature. - Config file permissions:
~/.voxburst/config.jsonis created with0600(owner read/write only). Do not change these permissions. - Shared machines: On shared servers, prefer environment variables over config files — other users cannot read your environment.
- Key rotation: When rotating, set the new key first (
voxburst config set api-key <new>), then revoke the old key in VoxBurst Settings.
Automation contract
This section defines the complete behavioral contract for scripting against the CLI.
Exit codes
| Code | Meaning | Notes |
|---|---|---|
0 | Command succeeded | For post/schedule: the post was created. Does not mean all platforms published. Check results[].status. |
0 | validate ran (even if content invalid) | Content failing platform rules is not an error — it ran. Check .[].valid. |
1 | Any infrastructure error | Auth failure, network error, bad arguments, file not found, rate limit, server error |
The CLI does not use exit codes to distinguish error categories. Parse --json output and stderr message to identify the error type in scripts.
Partial success
The CLI exits 0 when a post is created, even if one or more platforms fail to publish. Example:
RESULT=$(voxburst post "Hello" -p twitter,instagram -m /img.jpg --json)
# Exit code: 0
# Check each platform individually:
echo "$RESULT" | jq '.results[] | select(.status == "failed") | {platform, error}'
# { "platform": "instagram", "error": "Aspect ratio invalid" }Always check results[].status in automation — never assume exit 0 means all platforms published.
Rate limits
- HTTP 429 responses cause exit code
1with a message to stderr:VoxBurst API Error (429): Rate limit exceeded - The CLI does not auto-retry rate limits
- Implement retry/backoff in the calling script (see CI workflow example)
JSON stability contract
- Fields listed in the schema tables above are stable for
voxburst@0.2.x - New fields may be added in any
0.2.xrelease — defensive scripting:jq '.field // empty' - Fields will not be removed or renamed without a major version bump and 30-day deprecation notice
--json vs --quiet in scripts
--json: full response object on stdout; errors on stderr--quiet/-q: IDs only on stdout (one per line); use for piping toxargsorwhile read- Never mix
--jsonand--quiet— they are mutually exclusive in intent
Versioning and compatibility
Version table
| CLI version | npm tag | Docs verified | Known doc/binary gaps |
|---|---|---|---|
0.2.2 | latest | This page | None known |
0.1.x | deprecated | — | — |
voxburst --version # confirm installed versionCompatibility guarantees
--json output: Stable field names and types for fields documented in this page. Additive changes (new fields) may occur in any 0.2.x release.
Command flags: Flags documented here are stable in 0.x. Removals or renames bump the major version.
Doc-to-binary parity: Status values, flag names, and JSON fields are verified against voxburst@0.2.2. The CLI exposes a subset of the REST API — REST statuses (partial, approved, publishing, etc.) are not valid --status filter values.
Upgrade:
npm install -g @voxburst/cli@latest
voxburst --versionOS-specific notes
macOS (zsh):
- Quotes in shell: use
"double quotes"for content with spaces or emoji - PATH setup: see install notes if
voxburstis not found
Linux (bash):
- Same as macOS; ensure Node.js 18+ is installed
- In cron: always use absolute paths (
/usr/local/bin/voxburst) and set env vars explicitly
Windows (PowerShell):
$env:VOXBURST_API_KEY = "vb_live_xxxxxxxxxxxxx"
npx @voxburst/cli post "Hello from PowerShell!"Use npx @voxburst/cli rather than voxburst directly on Windows unless you have the npm global bin in your PATH.
CLI contract changelog
Breaking changes (flag removals, JSON field removals, exit-code behavior changes) are listed here with the CLI version they were introduced in.
| Version | Released | Change type | Description |
|---|---|---|---|
0.2.2 | 2026-05-20 | Current npm latest | Internal fixes; no interface changes from 0.2.1 |
0.2.1 | 2026-05-20 | Fix | Internal fixes; no interface changes from 0.2.0 |
0.2.0 | — | Baseline | Initial 0.2.x interface — all docs in this page apply to 0.2.0+ |
0.1.x | — | Deprecated | Removed; flags from 0.1.x are no longer documented |
Interface compatibility across 0.2.x: Flags, JSON field names, exit codes, and --file schema are identical across 0.2.0, 0.2.1, and 0.2.2. These docs are the specification for all three versions.
How to read this changelog:
Breaking— requires changes to existing scriptsFix— previous behavior was incorrect; scripts relying on the old behavior should updateAdditive— new flag or JSON field added; existing scripts unaffectedDeprecated— feature will be removed in the next major version
Subscribe to @voxburst/cli on npm (npm info @voxburst/cli dist-tags) to monitor releases.