DocumentationPost to many accounts
How to post to many social media accounts at once
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
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.
| Platform | A post needs |
|---|---|
| X, Threads, Bluesky, Mastodon | Text, media or both. Bluesky posts are limited to 300 characters and Threads posts to 500. |
| LinkedIn, Facebook | Text, media or both, on the member's own profile. |
| 1 to 20 photos or videos. The caption is at most 2,200 characters. | |
| TikTok | Exactly one video. |
| YouTube | One video and a title for an upload, or text with up to five images for a channel post. |
Exactly one image or video, and the board name in destination. | |
A title and a community in destination. | |
| Telegram | Text 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 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
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
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.
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.
{
"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.urlis the new post.queuedorrunning: read the action again until it finishes.failed:error.codeanderror.messagesay why. A write that fails before the page changes is refunded.
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_idsholds 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
detailstarts with the account id and lists what that account can do. - 402 insufficient_credits
price_creditsis the price of the whole batch andbalance_creditsthe 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
- Batch actions
- The post action
- How to post a thread on X, Threads, Bluesky or Mastodon
- How to post to a subreddit, Facebook group or Telegram channel
- How to retry API calls without posting twice
To run this on your own accounts, create a BuzzTake account, then add an account and an API key.