Skip to content
BuzzTake
MenuClose
DocumentationPost to many accounts

How to post to many social media accounts at once

Last updated

Publish one post on up to 100 accounts with a single call. Each account gets its own action, its own result and its own charge, so one account that fails does not stop the rest.

You need a BuzzTake API key, your workspace id and accounts with status active in that workspace.

1. List the accounts to post from

GET/v1/workspaces/{workspace_id}/accounts

Request
curl "https://api.buzztake.com/v1/workspaces/$WORKSPACE_ID/accounts?status=active&limit=100" \
  -H "Authorization: Bearer $BUZZTAKE_API_KEY"

Each account in accounts has its platform, its status and actions, the action types it supports. Keep the ids of the accounts whose actions include post. Add &platform=x to list one platform.

2. Group the accounts by what their platform needs

Every account in a batch gets the same parameters. So put accounts whose platforms take the same post in one batch, and send the others their own. BuzzTake does not shorten text or add media for a platform. Fields a platform does not use are ignored: X ignores title, for example.

PlatformA post needs
X, Threads, Bluesky, MastodonText, media or both. Bluesky posts are limited to 300 characters and Threads posts to 500.
LinkedIn, FacebookText, media or both, on the member's own profile.
Instagram1 to 20 photos or videos. The caption is at most 2,200 characters.
TikTokExactly one video.
YouTubeOne video and a title for an upload, or text with up to five images for a channel post.
PinterestExactly one image or video, and the board name in destination.
RedditA title and a community in destination.
TelegramText only, and a channel or group in destination.

For photos and videos, upload each file once to the workspace and pass its id in media; the quickstart shows the upload. For posts into a subreddit, a group or a channel, seehow to post to a subreddit, Facebook group or Telegram channel.

3. Send one post to the whole group

POST/v1/workspaces/{workspace_id}/actions

Send account_ids, 1 to 100 different ids, with type: "post" and the post's parameters at the top level. wait holds the request for up to that many seconds, at most 120.

curl

curl
curl https://api.buzztake.com/v1/workspaces/$WORKSPACE_ID/actions \
  -H "Authorization: Bearer $BUZZTAKE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: launch-2026-10-30" \
  -d '{
    "account_ids": ["0199a1b2-...", "0199b2c3-...", "0199c3d4-..."],
    "type": "post",
    "text": "Dark mode is live. Turn it on in Settings.",
    "wait": 60
  }'

JavaScript

JavaScript
const api = "https://api.buzztake.com/v1";
const workspace = process.env.WORKSPACE_ID;
const headers = {
  Authorization: `Bearer ${process.env.BUZZTAKE_API_KEY}`,
  "Content-Type": "application/json",
};

// Active accounts on platforms where text alone makes a post.
const TEXT_PLATFORMS = ["x", "threads", "bluesky", "mastodon", "linkedin", "facebook"];
const list = await fetch(
  `${api}/workspaces/${workspace}/accounts?status=active&limit=100`,
  { headers },
);
if (!list.ok) throw new Error(`${list.status}: ${await list.text()}`);
const { accounts } = await list.json();
const targets = accounts.filter(
  (account) => TEXT_PLATFORMS.includes(account.platform) && account.actions.includes("post"),
);

const res = await fetch(`${api}/workspaces/${workspace}/actions`, {
  method: "POST",
  headers: { ...headers, "Idempotency-Key": "launch-2026-10-30" },
  body: JSON.stringify({
    account_ids: targets.map((account) => account.id),
    type: "post",
    text: "Dark mode is live. Turn it on in Settings.",
    wait: 60,
  }),
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { actions } = await res.json();
for (const action of actions) {
  console.log(action.account_id, action.status, action.result?.url ?? action.error?.message ?? "");
}

Python

Python
import os
import requests

api = "https://api.buzztake.com/v1"
workspace = os.environ["WORKSPACE_ID"]
headers = {"Authorization": f"Bearer {os.environ['BUZZTAKE_API_KEY']}"}

# Active accounts on platforms where text alone makes a post.
TEXT_PLATFORMS = {"x", "threads", "bluesky", "mastodon", "linkedin", "facebook"}
listing = requests.get(
    f"{api}/workspaces/{workspace}/accounts",
    params={"status": "active", "limit": 100},
    headers=headers,
    timeout=30,
)
if not listing.ok:
    raise SystemExit(f"{listing.status_code}: {listing.text}")
targets = [
    account for account in listing.json()["accounts"]
    if account["platform"] in TEXT_PLATFORMS and "post" in account["actions"]
]

resp = requests.post(
    f"{api}/workspaces/{workspace}/actions",
    headers={**headers, "Idempotency-Key": "launch-2026-10-30"},
    json={
        "account_ids": [account["id"] for account in targets],
        "type": "post",
        "text": "Dark mode is live. Turn it on in Settings.",
        "wait": 60,
    },
    timeout=70,
)
if not resp.ok:
    raise SystemExit(f"{resp.status_code}: {resp.text}")
for action in resp.json()["actions"]:
    detail = (action.get("result") or {}).get("url") or (action.get("error") or {}).get("message", "")
    print(action["account_id"], action["status"], detail)

The batch is checked as a whole before anything runs. If one account is in another workspace, or cannot post, or the balance cannot pay for all of them, the answer is an error and no action is created. Each post costs 10 credits per account, so 50 accounts cost 500 credits.

Tip: The Idempotency-Key header makes the call safe to repeat. A repeat with the same key and body returns the same actions and posts nothing new. See how to retry API calls without posting twice.

Over MCP, the run_on_accounts tool takes the same account_ids, type and parameters.

4. Read every result

actions comes back in the order of account_ids. The status is 200 when every action finished inside wait, and 202 when some are still queued or running.

202 Accepted (trimmed)
{
  "actions": [
    {
      "id": "0199d1e2-...",
      "account_id": "0199a1b2-...",
      "type": "post",
      "status": "succeeded",
      "result": { "type": "created", "url": "https://x.com/acme_demo/status/1", "id": "1" },
      "credits": 10
    },
    {
      "id": "0199d3e4-...",
      "account_id": "0199b2c3-...",
      "type": "post",
      "status": "running",
      "result": null
    },
    {
      "id": "0199d5e6-...",
      "account_id": "0199c3d4-...",
      "type": "post",
      "status": "failed",
      "error": { "code": "rejected", "message": "the platform rejected the action: ..." }
    }
  ]
}
  • succeeded: result.url is the new post.
  • queued or running: read the action again until it finishes.
  • failed: error.code and error.message say why. A write that fails before the page changes is refunded.
Read one unfinished action
curl "https://api.buzztake.com/v1/actions/$ACTION_ID?wait=60" \
  -H "Authorization: Bearer $BUZZTAKE_API_KEY"

To try the failed accounts again, send a new batch with only their ids and a new Idempotency-Key. The old key would return the failed actions again.

Common errors

422 invalid_input
"account_ids holds 1 to 100 different account ids." Split a longer list into batches of 100, each with its own key.
422 invalid_input
"Account 0199b2c3-... is not in this workspace." All ids must be in the workspace in the path.
422 unsupported
The detail starts with the account id and lists what that account can do.
402 insufficient_credits
price_credits is the price of the whole batch and balance_credits the balance. Nothing was queued.
Action error invalid_input
The platform needs something the post lacks, such as "invalid input: an Instagram post needs at least one photo or video". Its credits are refunded.
Action error rejected
The platform refused the post, for example as a duplicate. Change the text and post again.

See also

To run this on your own accounts, create a BuzzTake account, then add an account and an API key.