Skip to main content
Publishing creates content on a provider. Review the draft before you publish it.
1

Create a draft Post

Create one Post for each channel. A draft uses a channel instead of a destination.
Send this body to POST /workspaces/{workspace_id}/posts.Before you write X copy, get the selected Destination. Inspect capabilities.body_text_limit in the response. Each X thread item uses that Destination’s effective limit. Refresh Destinations after an X subscription change.
2

Store the Post version

Store the returned Post id and version. Use them when you publish the draft.
3

Publish the same Post

Send the draft Post and its destination to POST /workspaces/{workspace_id}/posts/publish. If the group contains multiple draft Posts, include every Post in this request.
Add a unique Idempotency-Key header.OpenPMM returns after it accepts the state change. It does not wait for the provider. Immediate, nonterminal publication returns 202 Accepted and a Retry-After header. The response contains every Post ID and all stored receipts. OpenPMM returns status 422 when a file needs your decision.
4

Check the Post status

Use GET /workspaces/{workspace_id}/posts/{post}. The response includes lifecycle fields, receipts, and available_actions. Use include=attempts to get sanitized provider attempt diagnostics. A queued Post can include deferred and a future next-attempt time. The reason is publishing_velocity for a local dispatch delay or provider_cooldown when OpenPMM is waiting before it contacts that destination again. A failed Post stays failed while the deferral reports when OpenPMM can try it again.Poll only while terminal and action_required are both false. Stop when the Post is terminal or needs action. Do not send Publish Posts again. Use retry_safety before you retry a failed Post.
A timeout does not prove that publishing failed. Retry with the same idempotency key.
A direct or scheduled Post uses destination_id instead of channel. Put destination-specific settings in destination_options. For example, an Instagram Post needs { "instagram": { "placement": "post" } }. OpenPMM checks these settings during Create Post and Publish Post. If a required setting is missing, the API returns publisher_validation_failed with status 422.
For Facebook, one attached video uses the reel placement automatically. Do not send a facebook member in destination_options. The API rejects this retired input. If one destination reaches a provider publishing limit, only that destination’s Post fails. OpenPMM continues the other destination Posts. Use confirmed manual Retry later for the affected Post. An X body item above the connected Destination’s limit fails with x_character_limit_exceeded. Shorten the item and retry. OpenPMM checks the capability again immediately before publishing a long X item, so a scheduled Post can fail safely before it creates provider content if the account was downgraded.