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}"}'
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(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}"}'
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(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}"}'
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(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}"}'
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(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