Skip to content
BrainyShorts Docs
Esc
navigateopen⌘Jpreview
On this page

Quickstart

Go from an API key to a scheduled post with curl.

This walks through the REST API end to end: list accounts, upload a video, and schedule it. If you use Claude, Cursor, or ChatGPT, the MCP server does the same thing without a key.

Every request goes to https://www.brainyshorts.com. Don’t use api.brainyshorts.com.

Get a key and connect an account

Sign in at brainyshorts.com, connect a social account, and create a key at Dashboard → API keys.

export BRAINY_API_KEY="ba_sk_..."
export BRAINY="https://www.brainyshorts.com/api/cli"

List connected accounts

curl -s "$BRAINY/accounts" -H "Authorization: Bearer $BRAINY_API_KEY"
{
  "accounts": [
    { "id": "3f0c...", "platform": "instagram", "account_handle": "@example", "token_valid": true, "created_at": "..." }
  ]
}

Keep the id and platform of each account you want to post to.

Reserve an upload

BrainyShorts checks the file’s hashes before it accepts it, so compute them first.

FILE=clip.mp4
SIZE=$(wc -c < "$FILE" | tr -d ' ')
SHA256=$(shasum -a 256 "$FILE" | cut -d' ' -f1)
MD5=$(openssl md5 -r "$FILE" | cut -d' ' -f1)

curl -s -X POST "$BRAINY/media/uploads" \
  -H "Authorization: Bearer $BRAINY_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"content_type\":\"video/mp4\",\"content_length\":$SIZE,\"content_sha256\":\"$SHA256\",\"content_md5\":\"$MD5\"}" \
  > reservation.json

content_type is one of image/jpeg, image/png, image/webp, or video/mp4. The response holds an asset_id, a presigned upload_url, and the exact upload_headers to send.

If the response says "already_uploaded": true, you uploaded this exact file before. Skip the next two steps and use media.public_url.

Upload the bytes

Send every header from upload_headers exactly as returned. The URL is signed against them, so a missing or changed header fails.

HEADERS=()
while IFS= read -r h; do HEADERS+=(-H "$h"); done \
  < <(jq -r '.upload_headers | to_entries[] | "\(.key): \(.value)"' reservation.json)

curl -s -X PUT "$(jq -r .upload_url reservation.json)" "${HEADERS[@]}" --data-binary @"$FILE"

Complete the upload

curl -s -X PATCH "$BRAINY/media/uploads" \
  -H "Authorization: Bearer $BRAINY_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"asset_id\":\"$(jq -r .asset_id reservation.json)\"}" \
  > media.json

The response has a public_url on storage.brainyshorts.com, a domain every supported platform accepts.

Schedule the post

curl -s -X POST "$BRAINY/posts" \
  -H "Authorization: Bearer $BRAINY_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<JSON
{
  "title": "Launch teaser",
  "caption": "Something new is coming.",
  "media_type": "video",
  "media_urls": ["$(jq -r .public_url media.json)"],
  "targets": [{ "social_account_id": "3f0c...", "platform": "instagram" }],
  "action": "schedule",
  "scheduled_at": "2026-10-01T17:00:00Z"
}
JSON

The response is { "post": {...}, "social_posts": [...] }, with one social_posts entry per target. BrainyShorts publishes it at scheduled_at.

Next steps

Was this page helpful?