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
201 Created with data as an array of the created posts. Both share the same group_id:
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.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 aneeds_approval post by updating its status to waiting:
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
Thepublish_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:
- If the value carries an offset (
2026-12-25T09:00:00Zor+02:00), that absolute instant is used. - If the value is a bare datetime (
2026-12-25T09:00:00) and the item has atimezonefield (IANA name, for exampleAmerica/New_York), the wall-clock time is interpreted in that timezone. - With neither, the value is treated as UTC.
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 withpublish_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 settingmedia_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.
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 inplatform_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:
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.
Link previews
For posts that carry alink, 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: todraft,needs_approval, orwaiting, subject to your role. Moving aneeds_approvalpost towaitingapproves 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 betweenqueue_using_timeslots,schedule_using_fixed_datetime(requiresscheduled_for), andnow. A draft cannot be moved to the queue; setstatustowaitingin the same request.
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 thecomments 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.