API Status Get API Key

Create Threaded Post

Threaded posts (for example a Twitter/X thread or a Bluesky, Threads, or Mastodon thread) are created with the createPost mutation by passing a thread array inside the service-specific metadata. Each entry in the array is one post in the thread, and they are published in order, each replying to the previous one.

Important: every post in the thread - including the first one - must be provided as an item in the thread array. The thread array is the source of truth for what gets published. The top-level text on CreatePostInput should be set to the same value as the first item in the thread array so the two stay in sync.

For example, for a three-post thread you have to provide all three posts as thread entries, and the top-level text repeats the first entry's text.

mutation CreateThreadedPost {
  createPost(
    input: {
      text: "This is the first post in my thread."
      channelId: "some_channel_id"
      schedulingType: automatic
      mode: addToQueue
      metadata: {
        twitter: {
          thread: [
            { text: "This is the first post in my thread." }
            { text: "Here's the second post, replying to the first." }
            { text: "And the third post wraps everything up." }
          ]
        }
      }
    }
  ) {
    ... on PostActionSuccess {
      post {
        id
        status
      }
    }
    ... on MutationError {
      message
    }
  }
}
curl -X POST 'https://api.buffer.com' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{"query": "mutation CreateThreadedPost {\n  createPost(\n    input: {\n      text: \"This is the first post in my thread.\"\n      channelId: \"some_channel_id\"\n      schedulingType: automatic\n      mode: addToQueue\n      metadata: {\n        twitter: {\n          thread: [\n            { text: \"This is the first post in my thread.\" }\n            { text: \"Here's the second post, replying to the first.\" }\n            { text: \"And the third post wraps everything up.\" }\n          ]\n        }\n      }\n    }\n  ) {\n    ... on PostActionSuccess {\n      post {\n        id\n        status\n      }\n    }\n    ... on MutationError {\n      message\n    }\n  }\n}"}'
async function createThreadedPost() {
  const response = await fetch('https://api.buffer.com', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_API_KEY',
    },
    body: JSON.stringify({
      query: `
      mutation CreateThreadedPost {
        createPost(
          input: {
            text: "This is the first post in my thread."
            channelId: "some_channel_id"
            schedulingType: automatic
            mode: addToQueue
            metadata: {
              twitter: {
                thread: [
                  { text: "This is the first post in my thread." }
                  { text: "Here's the second post, replying to the first." }
                  { text: "And the third post wraps everything up." }
                ]
              }
            }
          }
        ) {
          ... on PostActionSuccess {
            post {
              id
              status
            }
          }
          ... on MutationError {
            message
          }
        }
      }
      `,
    }),
  });

  const data = await response.json();
  console.log(JSON.stringify(data, null, 2));
}

createThreadedPost();
import requests

query = """
mutation CreateThreadedPost {
  createPost(
    input: {
      text: "This is the first post in my thread."
      channelId: "some_channel_id"
      schedulingType: automatic
      mode: addToQueue
      metadata: {
        twitter: {
          thread: [
            { text: "This is the first post in my thread." }
            { text: "Here's the second post, replying to the first." }
            { text: "And the third post wraps everything up." }
          ]
        }
      }
    }
  ) {
    ... on PostActionSuccess {
      post {
        id
        status
      }
    }
    ... on MutationError {
      message
    }
  }
}
"""

response = requests.post(
    "https://api.buffer.com",
    headers={
        "Content-Type": "application/json",
        "Authorization": "Bearer YOUR_API_KEY",
    },
    json={
        "query": query,
    },
)

data = response.json()
print(data)
<?php

$query = '
mutation CreateThreadedPost {
  createPost(
    input: {
      text: "This is the first post in my thread."
      channelId: "some_channel_id"
      schedulingType: automatic
      mode: addToQueue
      metadata: {
        twitter: {
          thread: [
            { text: "This is the first post in my thread." }
            { text: "Here's the second post, replying to the first." }
            { text: "And the third post wraps everything up." }
          ]
        }
      }
    }
  ) {
    ... on PostActionSuccess {
      post {
        id
        status
      }
    }
    ... on MutationError {
      message
    }
  }
}
';

$payload = [
    'query' => $query,
];

$ch = curl_init('https://api.buffer.com');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_API_KEY',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
print_r($data);

The same pattern applies to the other services that support threads - swap twitter for bluesky, threads, or mastodon in the metadata object. Each ThreadedPostInput also accepts an ordered assets list if you want to attach media to an individual post in the thread.