Skip to content
BuzzTake
MenuClose
DocumentationPost a thread

How to post a thread on X, Threads, Bluesky or Mastodon

Last updated

A thread is a post followed by more posts that continue it. BuzzTake publishes the whole thread in one post action: the first post goes in text and the others in thread, in order.

You need a BuzzTake API key and an active account on X, Threads, Bluesky or Mastodon.

1. Check that the platform has threads

PlatformThreadsNotes
XYesMedia goes on the first post only.
ThreadsYesEach part is at most 500 characters.
BlueskyYesEach part is at most 300 characters.
MastodonYesEach part replies to the one before. Later parts carry no media and use the default visibility.
Facebook, LinkedIn, RedditNoThe action fails with invalid_input. Post once, then reply to your own post.
Instagram, TikTok, YouTube, Pinterest, TelegramNothread is ignored and only the first post goes out.
Warning: On the platforms in the last row, a thread posts only its first part and the action still succeeds. Send threads only to the four platforms that have them.

2. Split the text into parts

BuzzTake does not split or shorten text. thread holds up to 25 parts after the first post, and no part may be empty. Check each part against the platform's limit before you send it:

JavaScript

JavaScript
// Paragraphs become parts. Check each part against the platform's limit.
const draft = `BuzzTake posts threads now.

Send the first post in text and the rest in thread.

One action, one charge.`;
const [text, ...thread] = draft.split(/\n\s*\n/).map((part) => part.trim()).filter(Boolean);
const LIMIT = 300; // Bluesky
const tooLong = [text, ...thread].filter((part) => [...part].length > LIMIT);
if (tooLong.length > 0) throw new Error(`${tooLong.length} part(s) over ${LIMIT} characters`);
if (thread.length > 25) throw new Error("A thread takes at most 25 more parts.");

Python

Python
# Paragraphs become parts. Check each part against the platform's limit.
draft = """BuzzTake posts threads now.

Send the first post in text and the rest in thread.

One action, one charge."""
parts = [part.strip() for part in draft.split("\n\n") if part.strip()]
text, thread = parts[0], parts[1:]
LIMIT = 300  # Bluesky
too_long = [part for part in parts if len(part) > LIMIT]
if too_long:
    raise SystemExit(f"{len(too_long)} part(s) over {LIMIT} characters")
if len(thread) > 25:
    raise SystemExit("A thread takes at most 25 more parts.")

3. Post the thread

POST/v1/accounts/{id}/actions

Send type: "post" with text and thread. Add media to put photos or videos on the first post. A thread takes longer than one post, so give wait more time, up to 120 seconds.

curl

curl
curl https://api.buzztake.com/v1/accounts/$ACCOUNT_ID/actions \
  -H "Authorization: Bearer $BUZZTAKE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: thread-launch-1" \
  -d '{
    "type": "post",
    "text": "BuzzTake posts threads now.",
    "thread": [
      "Send the first post in text and the rest in thread.",
      "One action, one charge."
    ],
    "wait": 90
  }'

JavaScript

JavaScript
const res = await fetch(
  `https://api.buzztake.com/v1/accounts/${process.env.ACCOUNT_ID}/actions`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.BUZZTAKE_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": "thread-launch-1",
    },
    body: JSON.stringify({ type: "post", text, thread, wait: 90 }),
  },
);
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const action = await res.json();
console.log(action.status, action.result?.url ?? action.error?.message ?? "");

Python

Python
import os
import requests

resp = requests.post(
    f"https://api.buzztake.com/v1/accounts/{os.environ['ACCOUNT_ID']}/actions",
    headers={
        "Authorization": f"Bearer {os.environ['BUZZTAKE_API_KEY']}",
        "Idempotency-Key": "thread-launch-1",
    },
    json={"type": "post", "text": text, "thread": thread, "wait": 90},
    timeout=100,
)
if not resp.ok:
    raise SystemExit(f"{resp.status_code}: {resp.text}")
action = resp.json()
print(action["status"], (action.get("result") or {}).get("url") or action.get("error"))

The whole thread is one action and costs 10 credits, the price of one post. Over MCP, call the post tool with the same text and thread.

4. Read the result

200 OK (trimmed)
{
  "type": "post",
  "status": "succeeded",
  "params": {
    "text": "BuzzTake posts threads now.",
    "thread": ["Send the first post in text and the rest in thread.", "One action, one charge."]
  },
  "result": { "type": "created", "url": "https://bsky.app/profile/acme.bsky.social/post/3l...", "id": "3l..." },
  "credits": 10
}

result is created, with the url and id the platform gives the new thread. If the action is still running when the wait ends, you get 202; read it again with GET /v1/actions/{id}?wait=60. Do not send the post again: the first request is still working.

5. Post the same thread from several accounts

The batch route takes thread like any other parameter. Every account gets the same parts, so keep each part within the smallest limit in the batch: 300 characters when a Bluesky account is in it.

POST/v1/workspaces/{workspace_id}/actions

One thread, three accounts
curl https://api.buzztake.com/v1/workspaces/$WORKSPACE_ID/actions \
  -H "Authorization: Bearer $BUZZTAKE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: thread-launch-all-1" \
  -d '{
    "account_ids": ["0199a1b2-...", "0199b2c3-...", "0199c3d4-..."],
    "type": "post",
    "text": "BuzzTake posts threads now.",
    "thread": ["Send the first post in text and the rest in thread.", "One action, one charge."],
    "wait": 90
  }'

Common errors

422 invalid_input
"thread items must not be empty"
422 invalid_input
"thread has more than 25 items"
Action error invalid_input
"invalid input: Bluesky posts are limited to 300 characters", or the same for Threads at 500. Nothing was posted and the credits are refunded. Shorten the part and post again with a new Idempotency-Key.
Action error invalid_input
"invalid input: LinkedIn has no threads; post once and comment instead". Facebook and Reddit refuse a thread the same way.

See also

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