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 Login

Connect a Business or Creator account directly through Instagram in Accounts. No linked Facebook Page is required. MarketingCLI currently supports single images and carousels of 2-10 images; Reels, Stories, collaborators, location tags, and user tags are not implemented. Omit platform_options for Instagram.

The title and description become the caption (combined maximum 2200 characters). File uploads are converted to JPEG and padded to fit the supported aspect ratio without cropping. Hosted URLs must already serve public HTTPS JPEG images, up to 8 MB each, with an aspect ratio from 4:5 to 1.91:1.

Instagram submissions publish automatically once processing completes. There is no TikTok-style inbox draft step. The initial response is processing; publish_id identifies the container used to track processing. Only a successful publish response or Instagram's PUBLISHED container status is reported as published.

curl -X POST http://marketingcli.dev/api/v1/accounts/INSTAGRAM_ACCOUNT_ID/posts \
  -H "Authorization: Bearer $MARKETINGCLI_API_KEY" \
  -F "[email protected]" \
  -F "title=Party Fundraisers" \
  -F "description=Parents host parties. Guests buy seats. Schools raise funds. #schoolfundraiser"

Meta app setup instructions

Meta Setup for Instagram Login

  1. In Meta for Developers, create or select the MarketingCLI app and add the Instagram product/use case. Choose API setup with Instagram login, not Facebook Login.
  2. Use a Professional Instagram account (Business or Creator). For development testing, add your account as an Instagram tester and accept the invitation. A Facebook Page is not required.
  3. In Instagram business login settings, register the exact redirect URI https://marketingcli.dev/auth/instagram/callback.
  4. Configure the app domain marketingcli.dev, website https://marketingcli.dev, privacy policy https://marketingcli.dev/privacy, terms https://marketingcli.dev/terms, and data deletion instructions https://marketingcli.dev/privacy#data-deletion.
  5. Copy the Instagram App ID and Instagram App Secret from the Instagram product's setup panel into the server variables below. These may differ from the parent Meta app's credentials.
  6. For customers outside your app's development roles, request the required access through App Review for instagram_business_basic and instagram_business_content_publish. Complete Meta's business verification if requested and switch the app to Live after approval. A review recording should demonstrate connecting an account and publishing a photo or carousel.
INSTAGRAM_APP_ID=your_instagram_app_id
INSTAGRAM_APP_SECRET=your_instagram_app_secret
INSTAGRAM_REDIRECT_URI=https://marketingcli.dev/auth/instagram/callback
INSTAGRAM_API_VERSION=v24.0

Redeploy after setting these variables, then use Accounts → Connect Instagram. Test one photo and one carousel, and confirm they are visible on Instagram. Long-lived tokens are renewed automatically during their final week of validity; revoked or expired authorization requires reconnecting.

GET /posts/{post_id}/status

Query the platform for the latest status of an existing post. A 202 submission response only means processing has started. Poll every 10 seconds while processing; do not upload again to check delivery.

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

Status values

sentPlatform confirmed inbox delivery. For TikTok, open the upload notification in the mobile app's Inbox to edit and publish. This does not mean the post is live.
unconfirmedOlder submission with no verified delivery status yet. Refresh its status.
processingPlatform is processing the post
publishedSuccessfully published
failedFailed (check fail_reason)

Status responses include platform_status, status_checked_at, and delivery_confirmed_at. TikTok's SEND_TO_USER_INBOX confirms an inbox notification; only PUBLISH_COMPLETE confirms publication. A 502 means the status check was unavailable. Retry the check, not the upload.

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