| name | buffer-api |
| description | Use when posting to Buffer, scheduling social media posts, fetching channels/organizations, or creating ideas via the Buffer GraphQL API |
Buffer API
Post to social media via Buffer's GraphQL API.
Quick Start
Endpoint: https://api.buffer.com
Auth: Authorization: Bearer YOUR_TOKEN
Method: POST with Content-Type: application/json
Workflow
digraph buffer_flow {
"Check /tmp/buffer-config.json" -> "Have org/channel IDs?" [label="read"]
"Have org/channel IDs?" -> "Query organizations" [label="no"]
"Have org/channel IDs?" -> "Check /tmp/buffer-posts.json" [label="yes"]
"Query organizations" -> "Query channels" -> "Save to /tmp/buffer-config.json"
"Save to /tmp/buffer-config.json" -> "Check /tmp/buffer-posts.json"
"Check /tmp/buffer-posts.json" -> "Query recent posts" [label="no recent data"]
"Check /tmp/buffer-posts.json" -> "Read platform guide" [label="have recent data"]
"Query recent posts" -> "Read platform guide"
"Read platform guide" -> "Draft post with recommendations"
"Draft post with recommendations" -> "Present to user for confirmation"
"Present to user for confirmation" -> "Create post" [label="confirmed"]
"Create post" -> "Save success to /tmp/buffer-posts.json"
}
State Files
Store IDs and post history to avoid repeated API calls.
/tmp/buffer-config.json - Query once, reuse:
{
"organizationId": "org_abc123",
"channels": {
"twitter": "chan_tw123",
"linkedin": "chan_li456",
"instagram": "chan_ig789"
}
}
/tmp/buffer-posts.json - Track successful posts:
{
"twitter": {
"lastPostTime": "2026-01-23T14:00:00.000Z",
"lastPostId": "post_123"
},
"linkedin": {
"lastPostTime": "2026-01-23T09:00:00.000Z",
"lastPostId": "post_456"
}
}
Before any API call: Check if data exists in temp files. Only query API if missing.
After successful post: Update /tmp/buffer-posts.json with the new post time.
Common Operations
Get Organizations
curl -X POST https://api.buffer.com \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "{ account { organizations { id name } } }"}'
Get Channels
curl -X POST https://api.buffer.com \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "{ channels(input: { organizationId: \"ORG_ID\" }) { id name service displayName } }"}'
Query Posts
Get Recent Sent Posts
curl -X POST https://api.buffer.com \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "query($input: PostsInput!, $first: Int) { posts(input: $input, first: $first) { edges { node { id text sentAt dueAt channelId } } } }",
"variables": {
"input": {
"organizationId": "ORG_ID",
"filter": { "status": ["sent"], "channelIds": ["CHANNEL_ID"] },
"sort": [{ "field": "dueAt", "direction": "desc" }]
},
"first": 10
}
}'
Get Scheduled Posts
curl -X POST https://api.buffer.com \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "query($input: PostsInput!) { posts(input: $input) { edges { node { id text dueAt channelId } } } }",
"variables": {
"input": {
"organizationId": "ORG_ID",
"filter": { "status": ["scheduled"], "channelIds": ["CHANNEL_ID"] },
"sort": [{ "field": "dueAt", "direction": "asc" }]
}
}
}'
Filter Options
| Filter | Values | Use |
|---|
status | draft, scheduled, sent, error | Filter by post state |
channelIds | Array of IDs | Filter by channel |
dueAt.start/end | ISO datetime | Date range for scheduled time |
Create Text Post
curl -X POST https://api.buffer.com \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation CreatePost($input: CreatePostInput!) { createPost(input: $input) { ... on PostActionSuccess { post { id text status dueAt } } ... on MutationError { message } } }",
"variables": {
"input": {
"text": "Your post text here",
"channelId": "CHANNEL_ID",
"schedulingType": "automatic",
"mode": "customScheduled",
"dueAt": "2026-01-23T12:00:00.000Z"
}
}
}'
Create Post with Image
Add assets to input:
{
"input": {
"text": "Post with image",
"channelId": "CHANNEL_ID",
"schedulingType": "automatic",
"mode": "customScheduled",
"dueAt": "2026-01-23T12:00:00.000Z",
"assets": {
"images": [{ "url": "https://example.com/image.jpg" }]
}
}
}
Create Idea
curl -X POST https://api.buffer.com \
-H "Authorization: Bearer $BUFFER_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation CreateIdea($input: CreateIdeaInput!) { createIdea(input: $input) { ... on Idea { id content { title text } } } }",
"variables": {
"input": {
"organizationId": "ORG_ID",
"content": {
"title": "Idea title",
"text": "Idea content"
}
}
}
}'
Drafting Posts
Before creating a post, read the platform guide and get user confirmation.
- Read platform guide (e.g.,
twitter.md, linkedin.md) for the target channel
- Check "My Examples" section in the guide to match the user's tone and style
- Apply recommendations: constraints, algorithm signals, optimal times, spacing
- Present draft to user with:
- The draft post text
- Why this approach should work (which signals it optimizes)
- Recommended posting time
- Wait for user confirmation - iterate until they're happy, then post
Platform Guides
Each guide includes constraints, algorithm signals, best practices, and My Examples section for tone matching.
Based on Buffer's analysis of 100M+ posts.
| Guide | Key Info |
|---|
twitter.md | Free 280 / Premium 25k chars, text beats video by 30%, best Wed 9am |
linkedin.md | 3000 chars (1248 first comment), carousels +278%, best Thu 10am |
instagram.md | 2200 chars (2196 first comment, 120 story), evening times |
threads.md | 500 chars (50 topics), pictures beat text by 60%, best Wed 7am |
tiktok.md | Video essential, watch time is king, best Sun 8pm |
bluesky.md | 300 chars, tech-savvy audience, no video yet |
mastodon.md | 500 chars, hashtags critical, chronological feed |
video.md | ffmpeg commands for resizing/converting |
Key Enums
| Field | Values |
|---|
schedulingType | automatic, notification |
mode | shareNow, shareNext, customScheduled, recommendedTime |
service | instagram, facebook, twitter, linkedin, pinterest, tiktok, googlebusiness, mastodon, youtube, threads, bluesky, startPage |
Common Mistakes
| Mistake | Fix |
|---|
| Querying org/channels every time | Check /tmp/buffer-config.json first |
| Not tracking post times | Save to /tmp/buffer-posts.json after success |
| Posting without confirmation | Always present draft and wait for user approval |
| Ignoring platform guide | Read guide before drafting |
Using customSchedule | Use customScheduled (with 'd') |
Missing dueAt with customScheduled | Always provide ISO 8601 datetime |
Using addToQueue mode | Use shareNow, shareNext, customScheduled, or recommendedTime |
Response Handling
Success returns PostActionSuccess with post data. Errors return MutationError with message. Always handle both:
... on PostActionSuccess { post { id status } }
... on MutationError { message }
On success: Update /tmp/buffer-posts.json with new post time.
API Limits
- 100 requests / 15 minutes
- 500 requests / day
- 10,000 requests / month