Skip to main content

1. Overview

A Threads post goes live once Threads has accepted it. A text post needs no media. A post with media waits for Threads to process the file, for about 4 minutes at most.

2. Supported media

SocialAPI reads the media type from the file extension in the URL path, so query parameters (for example on a presigned upload URL) do not affect it. Text limit: 500 characters and 1 hashtag. More returns 400 publishing.validation_failed. Carousel limit: 2 to 20 items. A media list of 2 or more entries is a carousel. File limits apply to media you upload to SocialAPI (source_type: "media_id"). A file outside them fails validation with 400 publishing.validation_failed. A url item is not checked in advance. Threads accepts a pre-built container only as the single media item (source_type: "platform_attachment_id"). Combining it with other media returns 422 publishing.media.mixing_unsupported.

3. Create post

Use POST /v1/posts with targets targeting a Threads account. The text field becomes the post body.
Response (HTTP 201):
SocialAPI publishes in the background. The target moves from pending to publishing, then to published or failed. Poll GET /v1/posts/{pid} or subscribe to the post.published, post.partial, and post.failed webhook events. Publishing or scheduling costs 1 post credit; a draft is free (see Plans and credits).

Platform data fields

Send these keys in platform_data.threads on the post, which applies them to every Threads target. To set them for one target, send them flat in that target’s platform_data (targets[].platform_data, with no threads key). When both set the same key, the target’s value wins. SocialAPI forwards any additional keys in platform_data.threads that the table above lists for the post type you publish, and no others. Any other key is not sent, and the response lists it as a validation warning naming the key. reply_control needs the threads_manage_replies scope. An account holds it when its last connect was on or after 2026-10-17 and included the comments.write permission, or sent no permissions. On any other account, reply_control is not sent: the post publishes with Threads’ default, where everyone can reply, and the response carries a validation warning on reply_control. Reconnect the account with comments.write to apply it.

Scheduling

Set scheduled_at to an ISO 8601 timestamp (UTC) to defer publishing:

4. Update post

A published Threads post cannot be edited through SocialAPI. PATCH /v1/posts/{pid} returns 409 post.state_invalid for any post whose status is not draft, scheduled, or failed, with the message “Only draft, scheduled, or failed posts can be edited”. A post in draft, scheduled, or failed status can be edited with PATCH /v1/posts/{pid} before it publishes. To correct a published post, delete it with DELETE /v1/posts/{pid} and publish a new post.

5. Delete post

To remove only the Threads target of a cross-platform post, unpublish it by account_id. DELETE /v1/posts/{pid} always removes every target.
See Delete a post for how a cross-platform post is handled.

6. Retrieve posts

Use GET /v1/posts to list posts. Filter by platform or account:
Each post includes a targets array with per-platform status and engagement metrics:
Metrics notes: Likes and replies come from Threads insights, which need the threads_manage_insights scope. An account connected before 2026-10-17 does not hold it, so likes and comments stay 0 until the account is reconnected. Threads does not report shares or saves, so those stay 0. Account and post insights are in Threads insights.

7. Quirks, errors, and recovery

Media processing delay

A post with media waits for Threads to process the file. If Threads has not finished after about 4 minutes, the target fails with 504 platform.threads.container_timeout. If Threads rejects or expires the media, the target fails with 422 platform.threads.ERROR or 422 platform.threads.EXPIRED. A text post has no delay.

No post editing

A published Threads post cannot be edited. PATCH /v1/posts/{pid} returns 409 post.state_invalid. Delete the post and publish a new one: see 4. Update post.

Text-only posts

Omit media to publish a post with a text body only.

Reply chains are not published

segments on a post are ignored for Threads targets. Only the first post publishes.

Who can reply

Everyone can reply to a post unless reply_control sets otherwise. reply_control applies only on an account that holds threads_manage_replies: see “Platform data fields”.

Token expiry

A Threads access token lasts about 60 days. SocialAPI refreshes it. When a call returns 401 platform.threads.auth, reconnect the account through the OAuth flow.

Posting caps

SocialAPI refuses a publish that would pass 25 posts in an hour or 250 posts in 24 hours for one account, with 429 publishing.velocity_limit. A scheduled post is held and published when the window clears. When Threads refuses first, the target fails with 429 platform.threads.rate_limit. See Posting velocity caps.

Errors on a failed target

A publish that fails after the request returned puts a structured error on the target, in targets[].error:
  • 401 platform.threads.auth: the access token expired or was revoked. Reconnect the account.
  • 429 platform.threads.rate_limit: Threads’ own limit. Wait, then retry.
  • 422 platform.threads.THREADS_API__LINK_LIMIT_EXCEEDED: the post holds more than 5 unique links.
  • 422 platform.threads.ERROR, 422 platform.threads.EXPIRED: Threads rejected or expired the media.
  • 504 platform.threads.container_timeout: Threads did not finish processing the media after about 4 minutes.
  • platform.threads.<code>: Threads refused the request with its own error code and message. The HTTP status is 502 unless the code has its own mapping, such as 422 platform.threads.801. Read message.
  • 502 platform.threads.api_error: a failure reaching Threads, or a response with no usable error.
Every code is in Errors.

Recovery

  • Auth error. Reconnect the Threads account through the OAuth flow to get a fresh token.
  • Media timeout. A large video or a slow media URL causes it. Upload the media again and retry.
  • API error. Read message, fix the cause, and send POST /v1/posts/{pid}/retry. See Delivery.

8. Full worked example

The following example publishes a video post with a topic tag, then checks its status. Step 1: Upload media
Response:
Upload the file directly to the presigned URL, then verify:
Step 2: Publish the post
Response (publishing continues in the background):
Step 3: Check status
Response once published:

9. Required OAuth scopes

SocialAPI’s Meta Threads app requests these scopes during the OAuth flow. You configure nothing. The beta scopes are in Threads beta scopes. The scopes a scoped API key needs, the credit cost of a post, and the MCP tools that publish are on Publishing.
Last modified on October 17, 2026