This guide assumes you’ve already followed the Quickstart: you’ve got an API token, a workspace ID, and at least one connected social profile. Here we’ll go deeper into what each step does and the options you have at each one.
1. Choose a target profile
A post targets exactly one profile. Decide where the post should land first.
Pick the relevant profile from the response (note its id and the network it belongs to, which determines what fields apply). See Social profiles for the per-network field guide.
If your post needs an image or video, upload it first. Send the file itself, or a public URL to it:
The id in data[0] is the id you’ll reference from the post. A file, or an image by URL, comes back active (201) and is ready to use. A video by URL comes back processing (202): poll GET /media_contents/{id} until its status is active before you attach it. See Upload and manage media for the details and for files over 200 MB, or reuse an existing media library file if you already have one.
For text-only posts (e.g. an X update with no image), skip this step entirely.
3. Create the post
The request wraps posts in a posts array of 1 to 10 items, one per target profile. All posts from one request share a group_id. For a non-draft item the minimum fields are profile_id, content (or media_ids / link), status, and publish_type.
The response is 201 Created with data as an array of the created posts. The actual handoff to the social network happens asynchronously. The post moves from waiting to publishing to published.
4. Wait for it to publish
Poll the post until its status leaves publishing:
When status becomes published:
published_at contains the publish timestamp (UTC)
social_post_id holds the ID the analytics endpoints use for the post
post_url, the post’s public URL on the network, fills in with the next daily analytics sync (up to 24 hours later); it is null until then
If status becomes failed:
error_message explains why
- The most common causes are: expired profile connection, media that violates the network’s spec (size, aspect ratio, duration), or rate limiting on the social network’s side
Polling every 5 to 10 seconds is plenty. Most posts complete within seconds. For high-volume integrations, consider polling only the posts you’ve recently created instead of the whole list endpoint.
5. Inspect the result
For a successful Instagram post you might see:
post_url stays null until the next daily analytics sync (up to 24 hours after publishing) has fetched the link from the network, so poll the post again later if you need it. Once the post has metrics, the profile analytics endpoint lists it under the same social_post_id, with post_id pointing back at this post:
Profile analytics need the Pro or Business plan; see Analytics.
That’s it. You’ve published programmatically. Now learn how to schedule for later or queue across the week.