REST v2 API
Buffer-compatible endpoints at https://api.buffersass.dev/2 — channels, updates, analytics, webhooks and usage.
Conventions
Bearer auth on every call · JSON bodies · pagination via ?count= (max 50) and ?offset= · rate-limit headers on every authenticated response · errors use { "error": { code, message } } — see Errors.Account
GET
/2/userGet the authenticated accountResponse
{
"id": "usr_…", "name": "Your name",
"email": "dana@acme.dev", "plan": "developer",
"workspace": { "id": "wsp_…", "name": "Acme Inc",
"sandbox": false, "mode": "quickstart" },
"features": { "analytics_api": true, "approvals": true, "webhooks": true }
}Channels
GET
/2/channelsList connected channelsResponse
{
"data": [
{ "id": "cha_9a1…", "service": "x",
"service_username": "acmehq",
"service_display_name": "X (Twitter)",
"timezone": "UTC",
"schedules": [ { "days": ["mon","wed","fri"], "times": ["09:30","17:30"] } ],
"connected_at": "2026-10-12T08:00:00Z" }
]
}GET
/2/channels/:idGet one channelPOST
/2/channels/:id/connectConnect a networkConnects a new network to the workspace (subject to your plan's channel limit). OAuth, token storage and re-auth are handled for you.
Request
{ "service": "linkedin", "service_username": "acme-inc" }Response
{ "data": { "id": "cha_4b7…", "service": "linkedin", … }, "message": "Channel connected" }POST
/2/channels/:id/disconnectDisconnect a channelGET
/2/channels/:id/avatarChannel avatar (SVG)Updates — the posting core
POST
/2/updatesCreate updates (one per channel)| Parameter | Type | Description |
|---|---|---|
| channel_ids* | string[] | Target channels — one update is created per channel |
| text* | string | Post text; per-network character limits are enforced with `text_too_long` |
| media | Media[] | { url, thumbnail?, alt_text? } — normalized per network |
| scheduled_at | string | ISO 8601 timestamp. Omit → next queue slot (Add to Queue) |
| now | boolean | Publish immediately (still counts when the network accepts) |
| top | boolean | Schedule at the front of the queue |
| draft | boolean | Save as draft instead of scheduling |
| group_id | string | Your idempotency/grouping key for updates created together |
X-RateLimit-Remaining: 599
X-BufferSass-Workspace: wsp_…
Request
{
"channel_ids": ["cha_9a1…", "cha_4b7…"],
"text": "Ship day! v2.4 is live 🚀",
"media": [ { "url": "https://cdn.acme.dev/launch.png",
"alt_text": "Launch banner" } ],
"scheduled_at": "2026-11-10T14:30:00Z",
"top": false, "draft": false, "group_id": "launch-2-4"
}Response
{
"data": [
{ "id": "upd_7c2…", "group_id": "launch-2-4",
"channel_id": "cha_9a1…", "status": "scheduled",
"scheduled_at": "2026-11-10T14:30:00Z", "sent_at": null },
{ "id": "upd_7c3…", "group_id": "launch-2-4", … }
],
"message": "OK"
}GET
/2/updates/:idGet an updatePOST
/2/updates/:id/updateEdit a scheduled updateRequest
{ "text": "Updated copy ✍️", "scheduled_at": "2026-11-11T09:00:00Z" }POST
/2/updates/:id/destroyDelete an updatePOST
/2/updates/:id/approveApprove a pending updatePOST
/2/updates/:id/declineSend a pending update back to draftsPOST
/2/updates/:id/publish_nowPublish immediatelyPOST
/2/updates/:id/topMove to top of queueGET
/2/updates/:id/analyticsPer-update metricsResponse
{ "data": { "update_id": "upd_7c2…", "reach": 18420, "likes": 812, "comments": 96, "shares": 41, "clicks": 633 } }Queues, history & feeds
GET
/2/channels/:id/updates/scheduledA channel's queueRequest
GET /2/channels/:id/updates/scheduled?count=25&offset=0GET
/2/channels/:id/updates/sentA channel's sent historyGET
/2/feedRecent sent posts across channels (newest first)Analytics
GET
/2/channels/:id/analyticsLifetime totals + 30-day seriesResponse
{ "data": {
"channel_id": "cha_9a1…",
"lifetime": { "reach": 412880, "likes": 18322, "comments": 2014, "shares": 989, "clicks": 12887 },
"series": { "2026-11-07": { "reach": 18320, "posts": 2 }, … },
"post_count": 48
} }Webhooks
GET
/2/webhooksList webhook endpointsPOST
/2/webhooksCreate a webhook endpointDeliveries are signed — verify with the
whsec_ secret. See Webhooks.Request
{ "url": "https://hooks.acme.dev/buffersass",
"events": ["update.sent", "update.failed", "channel.connected"] }Response
{ "data": { "id": "whk_2e8…", "secret": "whsec_…", "active": true } }DELETE
/2/webhooks/:idDelete a webhook endpointUsage
GET
/2/usageCurrent-period meteringResponse
{ "data": {
"period": "2026-11", "plan": "developer",
"successful_posts": { "used": 1234, "limit": 5000, "overage_allowed": true },
"api_requests": { "used": 41202, "limit": 250000 },
"channels": { "used": 4, "limit": 15 }
} }