Threads API publishing: access, permissions, limits, steps
Threads API publishing from Meta's sample code: the app and permissions, the container then publish flow, the 250-post daily quota and what's known on price.
The Threads API publishes a post in two calls: create a media container with POST /me/threads, then publish it with POST /me/threads_publish. You need a Meta app with the Threads use case and a Threads user token with threads_basic and threads_content_publish, and Meta's sample collection shows a quota of 250 posts and 1,000 replies per 24 hours.
This guide is part of Meta API use cases: which one your app needs. It is built only from Meta's official GitHub repositories (the Threads sample app, its Postman collection and the webhooks sample) and the Threads entries in our API changelog. If you want to schedule Threads posts with a tool rather than build one, read Can you schedule posts on Threads? instead.
What this means for you
Tools that post to Threads for you use this API. It can post text, images, videos, carousels, replies and quotes, but it has no "publish later" setting, so the tool keeps your post and sends it at the time you picked.
Each Threads profile also has a daily quota. Meta's example shows 250 posts a day, so a tool that posts a lot for one profile can run into it.
The details: how Threads API publishing works
Access: an app with the Threads use case
Step 1 in Meta's Postman collection is to "create a Meta app with the Threads use case". The API opened to all developers on June 18, 2024, and since September 23, 2025 it also works for profiles without a linked Instagram account.
The Threads part of the app has its own credentials. Meta's sample app README says to use the app ID and secret "defined for the Threads API of your app", which "ARE not the same as the regular app ID and app secret". The collection says where they are: App Dashboard > App settings > Basic > Threads App ID and Threads App secret.
Two rules from the same README apply to redirect URIs:
- Add your redirect URL to the app's redirect callback URLs in the app dashboard.
- Threads apps "do not support redirect URLs with using
localhost", and "OAuth redirects are only supported over HTTPS". The sample maps a local domain in/etc/hostsand creates a certificate for it.
Meta's Threads sources on GitHub don't describe testers or App Review for Threads permissions. The only access level they mention is for embeds: with standard access, the oEmbed request can embed posts from the @meta, @threads, @instagram and @facebook accounts. Meta App Review requirements covers what Meta's samples say about roles and Advanced Access in general. Check each Threads permission's status in the App Dashboard before people outside your team connect.
Threads API permissions
Meta's sample app asks for ten permissions at login, and the collection's scope variable lists the same ten:
| Permission | In the collection's list of permissions to check on a token |
|---|---|
threads_basic | Yes |
threads_content_publish | Yes |
threads_read_replies | Yes |
threads_manage_replies | Yes |
threads_manage_insights | Yes |
threads_keyword_search | No |
threads_manage_mentions | No |
threads_delete | No |
threads_location_tagging | No |
threads_profile_discovery | No |
The collection also notes that threads_basic is enough to exchange or refresh a token. One permission from our changelog isn't in the sample's list: sharing a post to an Instagram Story needs threads_share_to_instagram.
Tokens: code, short-lived, long-lived
The sample app and the collection follow the same sequence:
- Send the user to
{authorization_host}/oauth/authorizewithclient_id,redirect_uri,scope(comma-separated) andresponse_type=code. - Exchange the code with
POST {api_host}/oauth/access_token, sendingclient_id,client_secret,grant_type=authorization_code,redirect_uriandcode. The redirect URI "must be the same URI or the request will be rejected". This returns a short-lived token. - Swap it for a long-lived token with
GET {api_host}/access_token?grant_type=th_exchange_token&client_secret=.... - Refresh a long-lived token before it expires with
GET {api_host}/refresh_access_token?grant_type=th_refresh_token.
The collection's example response for the long-lived token shows expires_in of 5,184,000 seconds, which is 60 days. That is an example, not a stated lifetime, so store the expires_in your app receives. Meta access tokens compares the Threads token with Meta's other token types.
The host: graph.threads.net or graph.threads.com
Meta's own sources disagree here. Our changelog entry records graph.threads.net with v1.0 from June 7, 2024. On March 23, 2026, commit 583bfaa, titled "threads.net -> threads.com", moved the sample app to graph.threads.com for API calls and www.threads.com for authorization. The Postman collection, updated the same day, still sets api_host to graph.threads.net and authorization_host to www.threads.net.
The examples below use {api_host} for that reason. Keep the host in config so you can change it without a release. The sample app adds an optional version segment, with v1.0 as the commented-out example, and otherwise uses the app's default version.
Publish a Threads post: container, then publish
# 1. Create a container
POST {api_host}/me/threads?media_type=TEXT&text=Hello&access_token={token}
→ { "id": "{container_id}" }
# 2. Check its status (repeat until FINISHED)
GET {api_host}/{container_id}?fields=id,status,error_message&access_token={token}
# 3. Publish it
POST {api_host}/me/threads_publish?creation_id={container_id}&access_token={token}
→ { "id": "{threads_media_id}" }
media_type is TEXT, IMAGE (with image_url), VIDEO (with video_url) or CAROUSEL. Images and videos are fetched from the URL you pass ("We will cURL your image using the URL provided"), so they must be on a public server. Both take alt_text.
The status check returns one of five values, as Meta's collection defines them:
| Status | Meaning |
|---|---|
IN_PROGRESS | The container is still in the publishing process |
FINISHED | The container and its media are ready to publish |
PUBLISHED | The container's media has been published |
ERROR | The container failed to complete the publishing process |
EXPIRED | The container was not published within 24 hours |
Meta's sample app checks the status every 5 seconds while it reads IN_PROGRESS, enables publishing at FINISHED, and shows error_message on ERROR.
Text posts in one call: auto_publish_text
A text post can skip step 3. With auto_publish_text=true, the collection says, the post "is published automatically when a Threads media container is created". The sample app sends the flag only for TEXT posts and treats the returned ID as the published post's ID, not a container ID.
Other options on the create call, from the collection:
link_attachment: text posts only, and not together with a poll. Without it, the first URL in the text becomes the link preview. Posts with more than five links fail since December 22, 2025.poll_attachment: up to four options (option_atooption_d), text posts only, and not together with a link.topic_tag,location_id,text_entities(spoilers) andis_spoiler_media.reply_control:everyone,accounts_you_follow,mentioned_only,parent_post_author_onlyorfollowers_only.enable_reply_approvals, added with reply approvals.is_ghost_post: a ghost post "will expire after 24 hours".gif_attachment. The collection's example still namesTENORas the provider, but our changelog records that Tenor was sunset by March 31, 2026 in favour of GIPHY.
Carousels
A carousel takes three calls:
- Create an item container for each image or video with
is_carousel_item=true. - Create the carousel container with
media_type=CAROUSELandchildrenset to a comma-separated list of the item IDs. Text is optional. - Publish it with
threads_publish, as above.
The collection's request says a carousel holds "at least 2 and up to 20" items, which matches our September 19, 2024 entry. The saved example response under the same request still says "up to 10", so the 10 is an older figure that wasn't updated. CAROUSEL can't be used for a single post.
Replies, quotes and reposts
- Reply: create a container with
reply_to_idset to the post or reply you're answering, then publish it. - Quote: create a
TEXTcontainer withquote_post_id, then publish it. - Repost:
POST {api_host}/{thread_id}/repost, one call.
Replies count against their own quota, below.
Threads API limits
GET {api_host}/me/threads_publishing_limit reports a profile's usage and limits. The fields Meta's collection asks for are quota_usage, config, reply_quota_usage, reply_config, delete_quota_usage, delete_config, location_search_quota_usage and location_search_config. Each config holds quota_total and quota_duration.
| Limit | What Meta's GitHub shows |
|---|---|
| Posts | quota_total 250, quota_duration 86,400 seconds (example response) |
| Replies | quota_total 1,000, quota_duration 86,400 seconds (example response) |
| Deletions | A quota exists; no figure in the example (added July 14, 2025) |
| Location search | A quota exists; no figure in the example (same entry) |
| Unpublished container | Expires after 24 hours |
| Carousel | 2 to 20 items |
| Links per post | Up to 5 (our changelog) |
The 250 and 1,000 come from the collection's example response, not from a written rule, so read the live values before a bulk job and plan around quota_usage. For the Graph API's app-level rate limits, see Meta Graph API rate limits.
Scheduling posts with the Threads API
None of the requests in Meta's Postman collection takes a publish time, and the sample app has no scheduling code. A Threads scheduler therefore stores the post itself and runs the create and publish calls at the chosen time. Because a container expires after 24 hours, create it near the publish time, not when the user saves the post.
Webhooks
Meta's webhooks sample sets up Threads webhooks "as a sub use case under the Threads API main use case", with a callback URL that answers the hub.mode, hub.verify_token and hub.challenge check. Threads webhooks launched on August 13, 2024, and the changelog later added mention, delete and publish webhooks. Meta webhooks covers verification and signatures for all three Meta networks.
Threads API pricing: what Meta's sources show
No price, paid tier or usage charge appears in Meta's Threads sample app, its Postman collection or the Threads entries in our changelog. We don't call the API free, because none of those sources says so either. What they do show is the quota system above: limits per profile, reported by threads_publishing_limit.
What changed in the Threads API, by date
| Date | Change |
|---|---|
| 2024-06-18 | Opens to all developers |
| 2024-08-13 | Webhooks |
| 2024-09-19 | Carousels up to 20 items |
| 2025-03-06 | Post deletion, then polls on April 14 |
| 2025-07-14 | Quotas for deletions and location search |
| 2025-09-23 | Profiles without Instagram |
| 2025-11-20 | Profile discovery from 100 followers |
| 2025-12-22 | More than five links rejected |
| 2026-03-23 | Meta's sample app moves to graph.threads.com (commit 583bfaa) |
| 2026-03-25 | Reply approvals and sharing to an Instagram Story |
| 2026-03-31 | Tenor GIFs sunset; GIPHY instead |
What to do next
- Business owners: You don't need to build anything. If a tool posts to Threads for you, it works within a daily quota per profile, and the Threads hub lists the tools that publish there.
- Marketers and agencies: If one profile gets a lot of posts and replies through a tool, ask how the tool handles the quota and what happens to a post that fails at its scheduled time.
- Developers: Create the app with the Threads use case, request only the permissions you use, keep the API host in config, poll the container until
FINISHEDbefore publishing, and readthreads_publishing_limitbefore bulk jobs.
Questions people ask
How much does the Threads API cost?
We can't state a price. No price, paid tier or usage charge appears in Meta's Threads sample app or Postman collection on GitHub, or in the Threads entries in our API changelog. What those sources do show are quotas: a profile's posts, replies, deletions and location searches are counted against limits that the threads_publishing_limit request reports.
How many posts can the Threads API publish per day?
The example response in Meta's Postman collection shows a quota of 250 posts and 1,000 replies, each with a duration of 86,400 seconds (24 hours). That is an example response, so read the real figures for each profile from GET /me/threads_publishing_limit before a bulk run.
Can you schedule a post with the Threads API?
Not with a publish time. None of the requests in Meta's Postman collection take a scheduled time, so your app stores the post and makes the create and publish calls when the time comes. An unpublished container expires after 24 hours, so create it close to the publish time.
Which permissions does the Threads API need to publish?
Meta's collection names threads_basic and threads_content_publish among the permissions to check on a token, and its sample app requests both at login, along with eight more for replies, insights, search, mentions, deletion, location tagging and profile discovery. Ask for the ones your features use.
Do I need an Instagram account to use the Threads API?
No. Since September 23, 2025 the Threads API works for Threads profiles without a linked Instagram account. Two metrics, followers_count and follower_demographics, were left out at first and became available to those profiles on January 30, 2026.
Sources
- Meta on GitHub: Threads API Postman collection (fbsamples/threads_api)
- Meta on GitHub: Threads API sample app (fbsamples/threads_api, src/index.js)
- Meta on GitHub: Threads sample app, container status check (public/scripts/publish.js)
- Meta on GitHub: Threads API sample app README (fbsamples/threads_api)
- Meta on GitHub: Threads sample commit "threads.net -> threads.com" (fbsamples/threads_api 583bfaa, 23 Mar 2026)
- Meta on GitHub: Graph API webhooks sample, Threads setup (fbsamples/graph-api-webhooks-samples)
- Our changelog: Threads API opens to all developers
- Our changelog: Threads publishing limit adds quotas for deletions and location search
Related
- API
LinkedIn Posts API: what you can schedule and how
LinkedIn's Posts API publishes text, images, video, documents, polls and multi-image posts but has no schedule field. How tools schedule, permissions, limits.
- API
Instagram Content Publishing API: posts, reels, carousels
How the Instagram Content Publishing API works on both logins: containers, reels, carousels of up to 10, stories, and why Meta gives 100, 50 or 25 posts a day.
- API
Meta access tokens: Instagram, Facebook Page and Threads
Meta access tokens for Instagram, Facebook Pages and Threads: what Meta's own code and Postman collections show, and the token lifetimes they leave unstated.
- API
Instagram API rate limit: Meta's quotas and usage headers
The Instagram API rate limit from Meta's own sample code: the daily publishing quota, the Threads quotas, the X-App-Usage headers and the error codes to watch.