Skip to main content
A post is a planned publication. It carries text, optional media, and per-network settings, targets exactly one profile, and moves through a predictable lifecycle from creation to publication. To publish the same content to several profiles, send one request with several items: POST /workspaces/{workspace}/posts takes a posts array of 1 to 10 items, one per target profile. Every post created by the same request shares a group_id, so the batch stays linked.

Creating posts

The response is 201 Created with data as an array of the created posts. Both share the same group_id:
To fetch a batch later, filter the index by group: GET /workspaces/{workspace}/posts?filters[group_id]=2f39.... Each item needs at least one of content, media_ids, or link. A non-draft item also needs profile_id, status, and publish_type.
profile_id is the only field that names the target profile, in requests and in responses. status, publish_type, and publication_method take the words listed on this page and nothing else; any other value is 422.
Post creation through the API is capped per workspace owner: 200 requests per rolling 24 hours when the owner is on Pro, 500 on Business. Requests from every member’s token count toward the owner’s cap, and each request counts once regardless of how many items it carries. See Rate limits.

Anatomy of a post

List, create, show, update, and retry all return the same shape:

Lifecycle

When creating a non-draft post, send status explicitly ("waiting", or "needs_approval" to route it through review) along with publish_type. Which statuses you may set depends on your role: editors with Require approval access on a profile can only create draft and needs_approval posts there, and can’t move an existing post to waiting with an update either (422). See Permissions.

Approving through the API

An admin approves a needs_approval post by updating its status to waiting:
The post keeps the publish_type and scheduled_for it was submitted with, and the same request can change them like any other update. Setting waiting follows the same role rules as creating a post, so an editor with Full access on the profile can approve too, while an editor with Require approval access gets 422. To send the post back to its author instead, set "status": "draft".

Publish types

The publish_type field controls when a post goes live: The dashboard refers to these as Post now, Schedule, and Add to queue. A fourth value, recurring, appears in responses and in the filters[publish_type] filter for posts that repeat on a schedule. Recurrence is configured in the dashboard only; the API cannot create recurring posts.

How scheduled_for is interpreted

scheduled_for is ISO 8601, and the rules are explicit:
  1. If the value carries an offset (2026-12-25T09:00:00Z or +02:00), that absolute instant is used.
  2. If the value is a bare datetime (2026-12-25T09:00:00) and the item has a timezone field (IANA name, for example America/New_York), the wall-clock time is interpreted in that timezone.
  3. With neither, the value is treated as UTC.
The account’s timezone setting never affects API scheduling, and every datetime in responses (scheduled_for, published_at, created_at, updated_at) is reported in UTC. The value must be in the future, and posts created through the API can be scheduled at most 90 days ahead.

Queues and timeslots

Each profile has a configurable queue: a recurring weekly schedule of timeslots (for example “Tue 9am, Thu 2pm, Sat 11am”). Posts created with publish_type: "queue_using_timeslots" are assigned to the next available slot automatically. Slots are managed in the dashboard under the account’s Queue Publish Times settings; the profile’s has_queue field tells you whether any exist. Queueing a post for a profile without timeslots returns 422. Changing a profile’s timeslots in the dashboard reschedules the posts already waiting in its queue, so their scheduled_for can change. A queued post that no longer fits any timeslot gets scheduled_for: null and isn’t published until the queue has a slot for it again.

Media

Attach media by setting media_ids to an array of IDs from the media library. A post takes up to 8 media IDs. Every ID must belong to the same workspace, and its file must be in the library: an item that is still processing (a URL import downloading), one whose import failed, or an ID from presign whose upload never happened returns 422. See Media status. Within that cap, each network has its own rules, which the API validates when you create the post:
  • X: up to 4 images, or 1 video.
  • Instagram feed: 1 image or video, or several for a carousel.
  • Instagram Reels and Stories: media is required.
  • TikTok and YouTube Shorts: exactly 1 video.
  • Facebook and LinkedIn: varies by post type.
An invalid combination returns 422 with a descriptive message. The response lists attached media twice: media_ids (UUIDs) and media (each with media_id, type, width, height, and duration).

Per-network parameters

Network-specific settings live in platform_content, keyed by platform slug. Each post item only reads the block matching its own profile’s network, so you can attach the same platform_content object to every item in a batch:
The accepted keys are facebook, instagram, tiktok, youtube, linkedin, pinterest, threads, and bluesky. Any other key is rejected with 422, as is a contentType outside post, reels, story, and trial reel. Settings keys are accepted in both camelCase and snake_case (privacyLevel and privacy_level both work), and content_type is accepted as an alias of contentType. Every block also accepts a content string that replaces the post’s content on that platform. See Per-network settings for the full list per network. For posts that carry a link, an optional preview object overrides the preview card on networks that render one: title, description, url, and images (an array of image URLs). Leave it out to let the network build its own preview.

Publication method

publication_method is auto by default: PublishBuddy publishes the post itself. Set it to notification to have PublishBuddy send a push notification to the mobile app at publish time so a person finishes the post by hand. This only works when push notifications are enabled in the user’s settings, and some profiles are locked to one method, in which case the API tells you which one in a 422.

Updating and rescheduling

PUT /posts/{post} updates a post that has not been published yet (draft, needs_approval, waiting, or failed). Besides content fields (content, media_ids, link, labels, platform_content, preview, comments, publication_method), you can change:
  • status: to draft, needs_approval, or waiting, subject to your role. Moving a needs_approval post to waiting approves it (see Lifecycle).
  • scheduled_for (same interpretation rules as create) to move a fixed-datetime post. It is only accepted when the post is, or becomes, schedule_using_fixed_datetime.
  • publish_type: switch between queue_using_timeslots, schedule_using_fixed_datetime (requires scheduled_for), and now. A draft cannot be moved to the queue; set status to waiting in the same request.
Once a post is published, updates are rejected with 403. A post that is currently publishing can still have its content changed, but rescheduling it (a new scheduled_for or publish_type) returns 422.

Deleting

DELETE /posts/{post} removes a post that has not been published, including one that is currently publishing. Deleting a published post returns 409 Conflict; the content is already in the social network’s hands.

Retrying a failed post

PUT /posts/{post}/retry resets a failed post to waiting and clears its error_message. A post that was scheduled for a fixed time publishes immediately; a queued post is placed back in the queue. Fix the cause first (usually a disconnected profile or media the network rejected), otherwise the retry fails the same way. Retrying a post whose status is not failed returns 409.

Comments

Posts support follow-up comments: first comments posted to the network after the post goes live (for example hashtags in the first comment on Instagram). Set them with the comments array. Each comment needs text or one media ID in media_ids (one per comment), plus an optional delay (delay_n from 1 to 100, with delay_type minutes, hours, or days). Comments come back on the post as comments, each with its own id, which you pass back when updating an existing comment.

Next

Schedule posts

A walkthrough of all three publish types.

Media library

Uploading and organising assets that posts can use.