buffer
$
npx mdskill add vm0-ai/vm0-skills/bufferSchedule and manage social media posts across multiple platforms.
- Handles scheduling, cross-posting, and queue management for social content.
- Integrates with Buffer API via GraphQL and personal API keys.
- Executes requests using POST methods with JSON query and variables.
- Delivers results through the Buffer platform's post status and channels.
SKILL.md
.github/skills/bufferView on GitHub ↗
---
name: buffer
description: Buffer API for social media post scheduling and channel management. Use when user mentions "Buffer", "bufferapp", "schedule post", "social media queue", "cross-post", or managing Twitter/X, LinkedIn, Instagram, Facebook, TikTok, Threads, Mastodon, Bluesky, Pinterest, YouTube, or Google Business posts through Buffer.
homepage: https://buffer.com
docs: https://developers.buffer.com
---
## Troubleshooting
If requests fail, run `zero doctor check-connector --env-name BUFFER_TOKEN` or `zero doctor check-connector --url https://api.buffer.com --method POST`
> **Beta API.** Buffer's public API is currently in **beta**. Personal API keys replace the legacy OAuth v1 API. Only organization **owners** can create keys (paid accounts: up to 5 keys, free accounts: 1 key). The legacy REST API at `api.bufferapp.com/1/*` still exists but is not accepting new developer applications and requires OAuth — it is not used by this connector.
## How It Works
Buffer is a social media scheduling platform. The beta API is **GraphQL-only**, served from a single endpoint. Every request is a `POST` with a JSON `{"query": "...", "variables": {...}}` body.
```
Account
└── Organizations
└── Channels (Twitter, LinkedIn, Instagram, Facebook, TikTok, Threads, Mastodon, Bluesky, Pinterest, YouTube, Google Business)
└── Posts (draft | scheduled | sent)
```
Base URL: `https://api.buffer.com`
## Authentication
All requests require a personal API key passed as a Bearer token:
```
Authorization: Bearer $BUFFER_TOKEN
Content-Type: application/json
```
Requests without a valid key return `401 Unauthorized`.
## Environment Variables
| Variable | Description |
|---|---|
| `BUFFER_TOKEN` | Buffer personal API key (from Developer Dashboard) |
## Key Operations
All calls hit the same endpoint: `POST https://api.buffer.com`. Change only the GraphQL document.
### 1. List Organizations
Write `/tmp/buffer_orgs.json`:
```json
{
"query": "query GetOrganizations { account { organizations { id name } } }"
}
```
```bash
curl -s -X POST "https://api.buffer.com" --header "Authorization: Bearer $BUFFER_TOKEN" --header "Content-Type: application/json" -d @/tmp/buffer_orgs.json
```
### 2. List Channels (Connected Social Accounts)
Write `/tmp/buffer_channels.json` — replace `<organization-id>` with an id from step 1:
```json
{
"query": "query GetChannels($organizationId: String!) { channels(input: { organizationId: $organizationId }) { id name service serviceId serviceType timezone } }",
"variables": { "organizationId": "<organization-id>" }
}
```
```bash
curl -s -X POST "https://api.buffer.com" --header "Authorization: Bearer $BUFFER_TOKEN" --header "Content-Type: application/json" -d @/tmp/buffer_channels.json
```
### 3. Create a Scheduled Post
Buffer publishes the same text to one or more channels. Write `/tmp/buffer_create_post.json` — replace `<channel-id>` with a channel id from step 2. `scheduledAt` is an ISO-8601 timestamp; omit it to add to the end of the queue.
```json
{
"query": "mutation CreatePost($input: PostCreateInput!) { createPost(input: $input) { id status scheduledAt text } }",
"variables": {
"input": {
"organizationId": "<organization-id>",
"channelIds": ["<channel-id>"],
"text": "Launching today: our new onboarding flow. Read more at https://example.com",
"scheduledAt": "2026-05-01T15:00:00Z",
"status": "scheduled"
}
}
}
```
```bash
curl -s -X POST "https://api.buffer.com" --header "Authorization: Bearer $BUFFER_TOKEN" --header "Content-Type: application/json" -d @/tmp/buffer_create_post.json
```
Valid `status` values:
- `draft` — saved as a draft, not queued
- `scheduled` — queued at `scheduledAt`
- `needsApproval` — posted to the approval queue
### 4. Create a Post with Media
Attach images or a video by passing a `media` object. Write `/tmp/buffer_create_image_post.json`:
```json
{
"query": "mutation CreatePost($input: PostCreateInput!) { createPost(input: $input) { id status } }",
"variables": {
"input": {
"organizationId": "<organization-id>",
"channelIds": ["<channel-id>"],
"text": "Ship log: weekly changelog is live.",
"media": {
"photos": [
{ "url": "https://example.com/screenshot.png", "altText": "Changelog screenshot" }
]
},
"status": "scheduled",
"scheduledAt": "2026-05-01T15:00:00Z"
}
}
}
```
```bash
curl -s -X POST "https://api.buffer.com" --header "Authorization: Bearer $BUFFER_TOKEN" --header "Content-Type: application/json" -d @/tmp/buffer_create_image_post.json
```
For video, swap `photos` for `video: { url: "<url>", thumbnailUrl: "<url>" }`.
### 5. List Pending/Scheduled Posts
Write `/tmp/buffer_posts.json`:
```json
{
"query": "query GetPosts($input: PostsInput!) { posts(input: $input) { edges { node { id status text scheduledAt channel { id service } } } pageInfo { hasNextPage endCursor } } }",
"variables": {
"input": {
"organizationId": "<organization-id>",
"status": ["scheduled"],
"first": 25
}
}
}
```
```bash
curl -s -X POST "https://api.buffer.com" --header "Authorization: Bearer $BUFFER_TOKEN" --header "Content-Type: application/json" -d @/tmp/buffer_posts.json | jq '.data.posts.edges[].node'
```
Change `status` to `["sent"]` for history, `["draft"]` for drafts, or `["needsApproval"]` for the approval queue.
### 6. Update a Post
Write `/tmp/buffer_update_post.json` — replace `<post-id>`:
```json
{
"query": "mutation UpdatePost($input: PostUpdateInput!) { updatePost(input: $input) { id text scheduledAt } }",
"variables": {
"input": {
"postId": "<post-id>",
"text": "Updated copy.",
"scheduledAt": "2026-05-02T15:00:00Z"
}
}
}
```
```bash
curl -s -X POST "https://api.buffer.com" --header "Authorization: Bearer $BUFFER_TOKEN" --header "Content-Type: application/json" -d @/tmp/buffer_update_post.json
```
### 7. Delete a Post
Write `/tmp/buffer_delete_post.json`:
```json
{
"query": "mutation DeletePost($input: PostDeleteInput!) { deletePost(input: $input) { id } }",
"variables": { "input": { "postId": "<post-id>" } }
}
```
```bash
curl -s -X POST "https://api.buffer.com" --header "Authorization: Bearer $BUFFER_TOKEN" --header "Content-Type: application/json" -d @/tmp/buffer_delete_post.json
```
### 8. Publish Immediately (Share Now)
Set `status: "scheduled"` and `scheduledAt` to a timestamp a few seconds in the past, or use the dedicated share mutation when available. For queue-top placement, omit `scheduledAt` and set `shareNext: true` in the input.
## Common Workflows
### Cross-Post to Multiple Channels
Put all target channel IDs in the same `channelIds` array. Buffer fans out one post per channel and returns a single parent post id.
```json
{
"query": "mutation CreatePost($input: PostCreateInput!) { createPost(input: $input) { id } }",
"variables": {
"input": {
"organizationId": "<organization-id>",
"channelIds": ["<twitter-channel-id>", "<linkedin-channel-id>", "<bluesky-channel-id>"],
"text": "Launching today.",
"status": "scheduled",
"scheduledAt": "2026-05-01T15:00:00Z"
}
}
}
```
### Paginate Sent Posts
```bash
# First page
curl -s -X POST "https://api.buffer.com" --header "Authorization: Bearer $BUFFER_TOKEN" --header "Content-Type: application/json" -d @/tmp/buffer_posts.json | jq '{next: .data.posts.pageInfo.endCursor, nodes: [.data.posts.edges[].node | {id, text, scheduledAt}]}'
```
Replace the `"first"` field in `input` with `"after": "<endCursor>"` to continue.
## Guidelines
1. **Send payloads as JSON files** with `-d @/tmp/filename.json` — do not inline complex GraphQL documents.
2. **Query introspection** is the fastest way to discover unfamiliar fields: `{"query": "{ __schema { queryType { fields { name } } } }"}`.
3. **Rate limits are per-client** and rolling — personal API keys share one bucket; if you have multiple keys, create a distinct key per integration.
4. **Analytics data is not exposed** in the beta API yet. For post-level stats, use Buffer's web dashboard.
5. **Do not edit posts** that have already been sent — Buffer's API currently rejects `updatePost` once `status: "sent"`.
6. **Organization IDs are stable**; cache them instead of re-querying on every request.
More from vm0-ai/vm0-skills
- account-reconciliationPerform account reconciliations comparing general ledger balances against subledgers, bank statements, or external records. Use for bank reconciliation, GL-to-subledger reconciliation, intercompany reconciliation, balance sheet reconciliation, reconciling item analysis, outstanding item aging, or clearing open items.
- agentphoneBuild AI phone agents with AgentPhone API. Use when the user wants to make phone calls, send/receive SMS, manage phone numbers, create voice agents, set up webhooks, or check usage — anything related to telephony, phone numbers, or voice AI.
- ahrefsAhrefs SEO API for backlink and keyword analysis. Use when user mentions
- amplitudeAmplitude product analytics API. Use when user mentions "Amplitude",
- analysis-qaQuality-check a data analysis before sharing — verify joins, aggregations, denominators, time ranges, and metric definitions. Detect pitfalls like survivorship bias, average-of-averages, join explosion, timezone mismatches, incomplete periods, and selection bias. Includes documentation templates for reproducible analyses.
- anthropic-managed-agentsAnthropic Managed Agents API for programmatically creating, running, and streaming AI agents on Anthropic's cloud infrastructure. Use when the user mentions "Managed Agents", "Anthropic agent sessions", or needs to create/run/stream an Anthropic agent with tool use (bash, git, web), attach GitHub repositories, or inject secrets via Vault. Do NOT use for standard Claude Messages API — use the Claude API skill instead.
- apifyApify web scraping platform. Use when user mentions "scrape website",
- asanaAsana API for tasks and projects. Use when user mentions "Asana", "asana.com",
- atlassianAtlassian API for Confluence and Jira. Use when user mentions "Confluence
- attioAttio REST API for AI-native CRM operations — manage companies, people, deals, and custom objects, plus notes, tasks, lists, and comments. Use when the user mentions "Attio", "CRM record", "create company", "add person", "list entry", "CRM note", or "CRM task".