Documentation

MarketingCLI lets you post content to social media via a REST API or CLI. Connect your account in the dashboard, generate an API key, and start posting from any HTTP client, script, or AI agent.

Authentication

All API requests require a Bearer token. Generate an API key from your dashboard.

Header
Authorization: Bearer mk_live_YOUR_API_KEY

API keys start with mk_live_. Keep them secret.

Base URL

http://marketingcli.dev/api/v1

All endpoint paths below are relative to this base URL.

API Reference

GET /accounts

List all social media accounts connected to your user. Filter by platform with ?platform=tiktok.

Example
curl http://marketingcli.dev/api/v1/accounts \
  -H "Authorization: Bearer mk_live_..."
Response 200
{
  "data": [
    {
      "id": "a1b2c3d4-e5f6-...",
      "platform": "tiktok",
      "username": "yourhandle",
      "display_name": "Your Name",
      "is_active": true
    }
  ]
}
GET /accounts/{account_id}

Get a single account's details, including platform-specific data.

Example
curl http://marketingcli.dev/api/v1/accounts/ACCOUNT_ID \
  -H "Authorization: Bearer mk_live_..."
Response 200
{
  "data": {
    "id": "a1b2c3d4-e5f6-...",
    "platform": "tiktok",
    "username": "yourhandle",
    "display_name": "Your Name",
    "is_active": true,
    "platform_data": { "privacy_level_options": ["PUBLIC_TO_EVERYONE", "SELF_ONLY"] }
  }
}
POST /accounts/{account_id}/posts

Upload media files and post to a connected social media account. Media requirements (count, type) depend on the platform.

Form Parameters

Parameter Type Required Description
imagesfile[]YesMedia files to upload
titlestringNoPost title (max 150 chars)
descriptionstringNoPost description / caption with hashtags
platform_optionsJSON stringNoPlatform-specific settings (see Platform Options below)
Example (TikTok)
curl -X POST http://marketingcli.dev/api/v1/accounts/ACCOUNT_ID/posts \
  -H "Authorization: Bearer mk_live_..." \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "title=5 Tips for Better Sleep" \
  -F "description=Here are my favorite tips. #sleep #wellness #fyp" \
  -F 'platform_options={"privacy_level": "PUBLIC_TO_EVERYONE"}'
Response 202
{
  "data": {
    "post_id": "a1b2c3d4-e5f6-...",
    "publish_id": "7349201485921038337",
    "status": "processing"
  }
}
POST /accounts/{account_id}/posts/json

Post using pre-hosted media URLs instead of file uploads. Same parameters as the upload endpoint, but image_urls replaces images.

Example (TikTok)
curl -X POST http://marketingcli.dev/api/v1/accounts/ACCOUNT_ID/posts/json \
  -H "Authorization: Bearer mk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "image_urls": [
      "https://example.com/slide1.jpg",
      "https://example.com/slide2.jpg"
    ],
    "title": "5 Tips for Better Sleep",
    "description": "Here are my favorite tips. #sleep #wellness #fyp",
    "platform_options": {
      "privacy_level": "PUBLIC_TO_EVERYONE",
      "auto_add_music": true
    }
  }'

Response format is identical to the upload endpoint (202 with post_id).

Platform Options

Each platform accepts different options via the platform_options field. Pass these as a JSON object (or JSON string for multipart uploads).

TikTok

Option Type Default Description
privacy_levelstringSELF_ONLYPUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, SELF_ONLY
disable_commentboolfalseDisable comments on the post
auto_add_musicbooltrueLet TikTok auto-add background music
photo_cover_indexint0Index of the image to use as cover

TikTok requires 2-35 images per slideshow post. Supported formats: JPEG, PNG, WebP.

Instagram

Option Type Default Description
location_idstringnoneFacebook Place ID for location tagging
user_tagsarraynoneTag users: [{"username": "user", "x": 0.5, "y": 0.5}]
collaboratorsarraynoneInvite collaborators by username

Instagram supports 1 image (single post) or 2-10 images (carousel). Requires an Instagram Professional account linked to a Facebook Page. Caption is built from title + description.

GET /posts/{post_id}/status

Check the current status of a post. Poll this after creating a post.

Example
curl http://marketingcli.dev/api/v1/posts/a1b2c3d4-e5f6-.../status \
  -H "Authorization: Bearer mk_live_..."

Status values

sentSent to platform, awaiting processing
processingPlatform is processing the post
publishedSuccessfully published
failedFailed (check fail_reason)
Response 200
{
  "data": {
    "post_id": "a1b2c3d4-e5f6-...",
    "publish_id": "7349201485921038337",
    "status": "published",
    "fail_reason": null,
    "created_at": "2026-03-25T20:06:00+00:00",
    "published_at": "2026-03-25T20:07:12+00:00"
  }
}
GET /posts

List your recent posts, newest first.

Query Parameters

limit1-100, default 20
offsetPagination offset, default 0
Response 200
{
  "data": [
    {
      "post_id": "a1b2c3d4-e5f6-...",
      "publish_id": "7349201485921038337",
      "status": "published",
      "title": "5 Tips for Better Sleep",
      "image_count": 4,
      "created_at": "2026-03-25T20:06:00+00:00"
    }
  ]
}
GET /usage

Get your current billing period usage and limits.

Example
curl http://marketingcli.dev/api/v1/usage \
  -H "Authorization: Bearer mk_live_..."
Response 200
{
  "data": {
    "plan": "pro",
    "posts_used": 42,
    "posts_limit": 300,
    "current_period_end": "2026-04-22T00:00:00+00:00"
  }
}

CLI

A command-line tool that wraps the API. Post from your terminal without writing any code.

Install

pip install git+https://github.com/davidedicillo/tikclock.git#subdirectory=cli

Then configure your API key:

# Save key to ~/.config/marketingcli/config.json
marketingcli configure --api-key mk_live_YOUR_KEY

# Or use an environment variable
export MARKETINGCLI_API_KEY=mk_live_YOUR_KEY

Commands

marketingcli accounts

List your connected social media accounts and their IDs.

$ marketingcli accounts
Connected accounts:
  yourhandle (a1b2c3d4-e5f6-...)

marketingcli post

Post media to a connected social media account.

# Basic post with title and description
marketingcli post -a ACCOUNT_ID \
  -t "5 Tips for Better Sleep" \
  -d "Here are my favorite tips for getting better rest. #sleep #wellness #fyp" \
  slide1.jpg slide2.jpg slide3.jpg

# Public post, no comments
marketingcli post -a ACCOUNT_ID --privacy PUBLIC_TO_EVERYONE --no-comments *.jpg

# JSON output (for AI agents and scripts)
marketingcli post -a ACCOUNT_ID -j slide1.jpg slide2.jpg

Options

-a, --account-idAccount ID (required)
-t, --titlePost title
-d, --descriptionPost description / caption with hashtags
--privacyPrivacy level (default: SELF_ONLY)
--no-commentsDisable comments
--no-musicDisable auto-add music
--cover INDEXCover image index (default: 0)
-j, --json-outputOutput raw JSON

marketingcli status POST_ID

Check the status of a post by its ID.

$ marketingcli status a1b2c3d4-e5f6-...
Post a1b2c3d4-e5f6-...
  Status:     published
  Publish ID: 7349201485921038337

marketingcli posts

List recent posts. Use -n 50 to change the limit.

$ marketingcli posts -n 5
Recent posts:
  a1b2c3d4...  published  5 Tips for Better Sleep  (4 images)
  b2c3d4e5...  sent       Untitled                 (2 images)

marketingcli usage

Show your current billing period usage and remaining posts.

$ marketingcli usage
Plan:  pro
Usage: 42 / 300 posts
Resets: 2026-04-22

For AI Agents

MarketingCLI is designed to be used by AI coding agents (Claude Code, Cursor, Windsurf, etc.). Here's how to integrate it.

MCP Server (Recommended)

The easiest way for AI agents to use MarketingCLI. Install the MCP server and agents get typed tools — no HTTP or doc reading needed.

Claude Code / Cursor config
{
  "mcpServers": {
    "marketingcli": {
      "command": "npx",
      "args": ["-y", "marketingcli-mcp"],
      "env": { "MARKETINGCLI_API_KEY": "mk_live_YOUR_KEY" }
    }
  }
}

Available tools

list_accountsList connected social media accounts, optionally filter by platform
get_accountGet details for a specific account
create_postCreate a post with image URLs, title, description, and platform options
get_post_statusCheck the status of a post (sent, processing, published, failed)
list_postsList recent posts with pagination
get_usageCheck current billing period usage and limits

Install: npm install -g marketingcli-mcp. Requires Node.js 18+.

Machine-readable reference

A plain-text API reference is also available at /llms.txt for agents that auto-discover documentation.

Using the CLI from an agent

Set the API key as an environment variable and always use -j for JSON output that's easy to parse programmatically:

export MARKETINGCLI_API_KEY=mk_live_YOUR_KEY

# Get account ID
ACCOUNT_ID=$(marketingcli accounts -j | jq -r '.data[0].id')

# Post images
RESULT=$(marketingcli post -a $ACCOUNT_ID -j \
  -t "5 Tips for Better Sleep" \
  -d "Here are my favorite tips. #sleep #wellness #fyp" \
  slide1.jpg slide2.jpg)

POST_ID=$(echo $RESULT | jq -r '.data.post_id')

# Check status
marketingcli status $POST_ID -j

End-to-end API workflow

A complete posting flow has 3 steps. Here's the full sequence with curl:

Step 1 — Get your account ID

curl http://marketingcli.dev/api/v1/accounts \
  -H "Authorization: Bearer mk_live_..."

# → { "data": [{ "id": "acc_123...", "username": "yourhandle" }] }

Step 2 — Post a slideshow

curl -X POST http://marketingcli.dev/api/v1/accounts/acc_123.../posts \
  -H "Authorization: Bearer mk_live_..." \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "title=5 Tips for Better Sleep" \
  -F "description=Here are my favorite tips. #sleep #wellness #fyp"

# → 202 { "data": { "post_id": "post_456...", "publish_id": "734...", "status": "processing" } }

Step 3 — Check status

curl http://marketingcli.dev/api/v1/posts/post_456.../status \
  -H "Authorization: Bearer mk_live_..."

# → { "data": { "post_id": "post_456...", "status": "published" } }

Tip for agents: Always check /api/v1/usage before posting to verify you haven't hit the monthly limit. Handle 402 (no subscription) and 429 (limit reached) gracefully.

Error Codes

All errors return JSON with a detail field describing the issue.

Code Meaning
400Bad request (invalid params, too few/many images)
401Invalid or missing API key
402Active subscription required
404Account or post not found
429Monthly post limit reached