API Status Get API Key

Your First Post

Let's walk through creating your first post with the Buffer API. By the end, you'll have a post scheduled in your queue.

Prerequisites: A Buffer account with at least one connected channel, and an API key. See Authentication if you don't have a key yet.

Time: ~5 minutes

Step 1: Get your organization ID

First, query your account to find your organization ID:

query GetOrganizations {
  account {
    organizations {
      id
      name
    }
  }
}
curl -X POST 'https://api.buffer.com' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{"query": "query GetOrganizations {\n  account {\n    organizations {\n      id\n      name\n    }\n  }\n}"}'
async function getOrganizations() {
  const response = await fetch('https://api.buffer.com', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_API_KEY',
    },
    body: JSON.stringify({
      query: `
      query GetOrganizations {
        account {
          organizations {
            id
            name
          }
        }
      }
      `,
    }),
  });

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

getOrganizations();
import requests

query = """
query GetOrganizations {
  account {
    organizations {
      id
      name
    }
  }
}
"""

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 = '
query GetOrganizations {
  account {
    organizations {
      id
      name
    }
  }
}
';

$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);

You'll get a response like this:

{
  "data": {
    "account": {
      "organizations": [
        { "id": "your_org_id", "name": "My Company" }
      ]
    }
  }
}

Copy the id from the response. You'll need it in the next step.

Step 2: Get your channel ID

Now query your channels using the organization ID from Step 1:

query GetChannels {
  channels(input: { organizationId: "your_org_id" }) {
    id
    name
    service
  }
}
curl -X POST 'https://api.buffer.com' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{"query": "query GetChannels {\n  channels(input: { organizationId: \"your_org_id\" }) {\n    id\n    name\n    service\n  }\n}"}'
async function getChannels() {
  const response = await fetch('https://api.buffer.com', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_API_KEY',
    },
    body: JSON.stringify({
      query: `
      query GetChannels {
        channels(input: { organizationId: "your_org_id" }) {
          id
          name
          service
        }
      }
      `,
    }),
  });

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

getChannels();
import requests

query = """
query GetChannels {
  channels(input: { organizationId: "your_org_id" }) {
    id
    name
    service
  }
}
"""

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 = '
query GetChannels {
  channels(input: { organizationId: "your_org_id" }) {
    id
    name
    service
  }
}
';

$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);

This returns all your connected social profiles:

{
  "data": {
    "channels": [
      { "id": "your_channel_id", "name": "My Twitter", "service": "twitter" },
      { "id": "your_other_channel_id", "name": "My Instagram", "service": "instagram" }
    ]
  }
}

Pick the channel you want to post to and copy its id.

Step 3: Create your post

Now create a post using the channel ID from Step 2:

mutation CreateFirstPost {
  createPost(input: {
    text: "Hello from the Buffer API!",
    channelId: "your_channel_id",
    schedulingType: automatic,
    mode: addToQueue
  }) {
    ... on PostActionSuccess {
      post {
        id
        text
        dueAt
      }
    }
    ... on MutationError {
      message
    }
  }
}
curl -X POST 'https://api.buffer.com' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{"query": "mutation CreateFirstPost {\n  createPost(input: {\n    text: \"Hello from the Buffer API!\",\n    channelId: \"your_channel_id\",\n    schedulingType: automatic,\n    mode: addToQueue\n  }) {\n    ... on PostActionSuccess {\n      post {\n        id\n        text\n        dueAt\n      }\n    }\n    ... on MutationError {\n      message\n    }\n  }\n}"}'
async function createFirstPost() {
  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 CreateFirstPost {
        createPost(input: {
          text: "Hello from the Buffer API!",
          channelId: "your_channel_id",
          schedulingType: automatic,
          mode: addToQueue
        }) {
          ... on PostActionSuccess {
            post {
              id
              text
              dueAt
            }
          }
          ... on MutationError {
            message
          }
        }
      }
      `,
    }),
  });

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

createFirstPost();
import requests

query = """
mutation CreateFirstPost {
  createPost(input: {
    text: "Hello from the Buffer API!",
    channelId: "your_channel_id",
    schedulingType: automatic,
    mode: addToQueue
  }) {
    ... on PostActionSuccess {
      post {
        id
        text
        dueAt
      }
    }
    ... 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 CreateFirstPost {
  createPost(input: {
    text: "Hello from the Buffer API!",
    channelId: "your_channel_id",
    schedulingType: automatic,
    mode: addToQueue
  }) {
    ... on PostActionSuccess {
      post {
        id
        text
        dueAt
      }
    }
    ... 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);

A successful response looks like this:

{
  "data": {
    "createPost": {
      "post": {
        "id": "your_post_id",
        "text": "Hello from the Buffer API!",
        "dueAt": "2026-03-05T14:30:00.000Z"
      }
    }
  }
}

Step 4: Verify in Buffer

Open your Buffer dashboard. You should see your new post in the queue for the channel you selected. With mode: addToQueue, we've assigned it to the next available time slot.

Scheduling options

The example above used mode: addToQueue, which adds the post to the next available time slot. You can also schedule a post for a specific time:

mutation CreateScheduledPost {
  createPost(input: {
    text: "Scheduled for a specific time",
    channelId: "your_channel_id",
    schedulingType: automatic,
    mode: customScheduled,
    dueAt: "2026-03-10T15:00:00.000Z"
  }) {
    ... on PostActionSuccess {
      post {
        id
        text
        dueAt
      }
    }
    ... on MutationError {
      message
    }
  }
}
curl -X POST 'https://api.buffer.com' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{"query": "mutation CreateScheduledPost {\n  createPost(input: {\n    text: \"Scheduled for a specific time\",\n    channelId: \"your_channel_id\",\n    schedulingType: automatic,\n    mode: customScheduled,\n    dueAt: \"2026-03-10T15:00:00.000Z\"\n  }) {\n    ... on PostActionSuccess {\n      post {\n        id\n        text\n        dueAt\n      }\n    }\n    ... on MutationError {\n      message\n    }\n  }\n}"}'
async function createScheduledPost() {
  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 CreateScheduledPost {
        createPost(input: {
          text: "Scheduled for a specific time",
          channelId: "your_channel_id",
          schedulingType: automatic,
          mode: customScheduled,
          dueAt: "2026-03-10T15:00:00.000Z"
        }) {
          ... on PostActionSuccess {
            post {
              id
              text
              dueAt
            }
          }
          ... on MutationError {
            message
          }
        }
      }
      `,
    }),
  });

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

createScheduledPost();
import requests

query = """
mutation CreateScheduledPost {
  createPost(input: {
    text: "Scheduled for a specific time",
    channelId: "your_channel_id",
    schedulingType: automatic,
    mode: customScheduled,
    dueAt: "2026-03-10T15:00:00.000Z"
  }) {
    ... on PostActionSuccess {
      post {
        id
        text
        dueAt
      }
    }
    ... 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 CreateScheduledPost {
  createPost(input: {
    text: "Scheduled for a specific time",
    channelId: "your_channel_id",
    schedulingType: automatic,
    mode: customScheduled,
    dueAt: "2026-03-10T15:00:00.000Z"
  }) {
    ... on PostActionSuccess {
      post {
        id
        text
        dueAt
      }
    }
    ... 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 dueAt field accepts an ISO 8601 datetime string in UTC.

Handling errors

If something goes wrong, the response includes a MutationError with a message field instead of PostActionSuccess:

{
  "data": {
    "createPost": {
      "message": "Channel not found"
    }
  }
}

Common issues:

  • Invalid channelId - double-check you copied the right ID from Step 2
  • Missing required fields - text and channelId are always required
  • Queue limit reached: your channel's queue is full

Always include ... on MutationError { message } in your mutations to catch errors. See Error Handling for more details.

Next steps