Skip to main content
Publishing through SocialAPI is asynchronous: an HTTP success means SocialAPI accepted the post, not that every platform has published it. The post has a status, and each platform it goes to is a target in targets[] with its own status, platform_post_id, permalink, and error. Read them with GET /v1/posts/{pid} or receive them in the post.published, post.partial, and post.failed webhook events.

Endpoints

Publish and read the result

Publish to 2 targets at once:
Response (HTTP 201):
The post is publishing and each target is pending or publishing, because delivery runs after the response. Read the post again until its status is published, partial, or failed, or wait for the webhook:
Response (HTTP 200) after the Threads target published and the Facebook target failed:
The post is partial: 1 target published and 1 failed. POST /v1/posts/{pid}/retry re-sends only the failed targets.

Response codes

POST /v1/posts and POST /v1/posts/{pid}/publish return the post object with one of these HTTP statuses: 207 and 422 appear only when delivery finishes before SocialAPI builds the response. Do not rely on them: read status and each target’s status on every response, whatever the HTTP status. POST /v1/posts/{pid}/retry returns 200 with {"success": true}, and the post goes back to publishing. Other statuses on these endpoints are errors in the standard envelope: 400 publishing.validation_failed when the post fails validation (the issues are in error.meta.issues), 409 resource.conflict for duplicate content, 409 post.state_invalid when the post is not in a state the endpoint accepts, 400 publishing.no_targets when the post has no publishable targets, 400 post.no_retryable_deliveries when a retry finds no failed target, and 429 publishing.velocity_limit or 429 validation.post_limit_exhausted. See Errors. SocialAPI ignores request fields it does not recognize, so a misspelled field is not an error: the post is created without it. Send only the documented field names, and read the post back with GET /v1/posts/{pid} when a missing field would be costly.

Post status

A post has one of these statuses. SocialAPI derives it from the statuses of the post’s targets. A draft or scheduled post moves to publishing when you publish it. A post that is published, partial, or failed stays in that status until you retry, unpublish, or delete it. SocialAPI sends one post.published, post.partial, or post.failed event when the post reaches that status. See Webhook events.

Target fields

Each item of targets[] is the delivery of the post to one connected account, and one Facebook Page or Pinterest board when the account has more than one. Target status means: On TikTok, the platform can confirm a post before it reports the post’s ID. The target is then published with no platform_post_id and no permalink, and both appear after SocialAPI checks again. A TikTok draft sent with post_mode: "inbox" stays published with no platform_post_id or permalink: the post exists only in the creator’s TikTok app. SocialAPI sets a target to failed with system.internal when it stays in publishing for more than 1 hour without a final answer from the platform, or for more than 2 hours when the platform keeps reporting it as in progress.

Target errors

A failed target carries an error object with 4 fields: Surface error.message to your users instead of a generic retry prompt. Target errors appear in 2 places:
  • targets[].error on every post response: POST /v1/posts, POST /v1/posts/{pid}/publish, GET /v1/posts, and GET /v1/posts/{pid}.
  • results[].error in the post.partial and post.failed webhook events. The payload is {post_id, status, results}, and each item of results has account_id, brand_id, page_id, platform, status, platform_post_id, permalink, and error. The webhook error holds code and message only.
Target errors do not appear in GET /v1/events: an event has error_message and error_category, with no error_code. These codes describe delivery itself. A failure that comes from the platform has a platform.{platform}.* code described on the platform’s page.
  • publishing.delivery.account_load_failed: SocialAPI could not load the connected account when it started sending. Reconnect the account.
  • account.permission_missing: the account did not have the posts.write permission when the delivery ran. Add the permission, then retry.
  • publishing.delivery.page_resolve_failed: SocialAPI could not resolve the Facebook Page for the target.
  • publishing.delivery.timeout: sending did not finish before SocialAPI’s time limit for one delivery (15 minutes).
  • validation.publish: a scheduled post failed validation when its time arrived. error.message names the problem. SocialAPI does not retry it.
  • platform.{platform}.publish_failed: the platform failed the request without a more specific code.
  • system.internal: SocialAPI stopped waiting for a stuck target (see above).
Retry a failed or partial post with POST /v1/posts/{pid}/retry. It re-sends only the failed targets, resets them to pending, clears their errors, and costs 1 post credit. See Plans and usage.

Verify media before you publish

Media uploaded with the presigned flow has a status, and only ready media publishes. A media file is pending until you call POST /v1/media/{id}/verify, ready after verification, and failed when the file is missing or the upload would exceed your storage quota. When you publish or schedule a post that references media that is not ready, POST /v1/posts returns 400 publishing.validation_failed, and error.meta.issues contains an issue for field media with the message media {id} is not ready or not found. Draft posts skip this check and run it when you publish. With skip_validation: true, the post is accepted and the target fails at delivery. See Media for the upload flow.

Delete a post

DELETE /v1/posts/{pid} returns HTTP 200, not 204. What it does depends on the post’s status: Response (HTTP 200) for a post published to Threads and TikTok, when Threads removed its copy and TikTok cannot delete posts:
A target the platform did not delete stays published, so SocialAPI shows what is still live. Deleting a post costs no credits and sends post.deleted when SocialAPI removes the post.

Unpublish a post

POST /v1/posts/{pid}/unpublish removes the published copies from the platforms and keeps the post. Send {"account_id": "..."} to remove one target only. Targets removed from the platform become unpublished. The post is partial while another target is still published, failed when none is published and one target failed, and cancelled when every target was removed. See Platform support for what each platform can delete.
Response (HTTP 200), when every targeted copy was removed:
SocialAPI sends post.unpublished when at least one target is removed, including on a 501 or 500 response.

Scopes

See Scoped API keys.

Use from an AI agent

Last modified on October 18, 2026