Blog

Threads API: Publishing Posts via the API — a Developer Guide (2026)

Erwan Prost

Erwan Prost

· 12 min read

On this page

Publishing to Threads takes two API calls, not one. First you create a media container with POST https://graph.threads.net/v1.0/{threads-user-id}/threads, passing media_type as TEXT, IMAGE, VIDEO, or CAROUSEL. Meta returns a container ID. Then you publish that ID as creation_id to POST /{threads-user-id}/threads_publish, and the post goes live (Meta, Threads posts).

Auth is Threads-specific OAuth, not Instagram Login and not Facebook Login. Users authorize at https://threads.net/oauth/authorize, you exchange the code at graph.threads.net/oauth/access_token for a 1-hour token, then upgrade it to a 60-day long-lived token. Publishing needs the threads_basic and threads_content_publish scopes, and every threads_* scope requires Meta App Review before it works on real accounts.

How do you publish posts with the Threads API?

The Threads API borrows the container model from Instagram's Content Publishing API: you stage the content server-side, Meta downloads and processes any media, and a second call commits it. That indirection exists because Meta fetches your image_url and video_url itself, so the media has to sit on a publicly reachable server before the first call (Meta, Get started).

  1. 1.Authorize the account. Redirect the user to https://threads.net/oauth/authorize with scope=threads_basic,threads_content_publish. Authorization codes are single-use and valid for one hour.
  2. 2.Upgrade the token. Exchange the code at POST graph.threads.net/oauth/access_token for a short-lived token (1 hour), then call GET graph.threads.net/access_token?grant_type=th_exchange_token for a 60-day long-lived token. Refresh it with th_refresh_token once it is at least 24 hours old, or it expires permanently after 60 idle days (Meta, long-lived tokens).
  3. 3.Create the media container. POST /{threads-user-id}/threads. TEXT requires text, IMAGE requires image_url, VIDEO requires video_url, and CAROUSEL requires children (a comma-separated list of item container IDs built with is_carousel_item=true).
  4. 4.Wait, then check status. Meta says to "wait on average 30 seconds before publishing." Poll GET /{container-id}?fields=status,error_message at most once a minute for no more than five minutes; statuses are IN_PROGRESS, FINISHED, PUBLISHED, ERROR, EXPIRED.
  5. 5.Publish. POST /{threads-user-id}/threads_publish with creation_id. A container that is never published flips to EXPIRED after 24 hours and cannot be recovered.

Below is the same image post two ways: the raw Meta Graph flow, and the equivalent through the SocialAPI.ai unified publishing endpoint, which performs the container creation, the status polling, and the publish call on your behalf.

# 1. Create the media container
CONTAINER=$(curl -s -X POST \
  "https://graph.threads.net/v1.0/$THREADS_USER_ID/threads" \
  -d "media_type=IMAGE" \
  -d "image_url=https://cdn.example.com/launch.jpg" \
  -d "text=Shipped the Threads connector today." \
  -d "alt_text=Dashboard showing a new Threads connection" \
  -d "reply_control=accounts_you_follow" \
  -d "access_token=$THREADS_TOKEN" | jq -r .id)

# 2. Poll until processing finishes (Meta suggests ~30s on average,
#    once per minute for no more than 5 minutes)
curl -s "https://graph.threads.net/v1.0/$CONTAINER\
?fields=status,error_message&access_token=$THREADS_TOKEN"
# { "status": "FINISHED", "id": "17899..." }

# 3. Publish the container
curl -s -X POST \
  "https://graph.threads.net/v1.0/$THREADS_USER_ID/threads_publish" \
  -d "creation_id=$CONTAINER" \
  -d "access_token=$THREADS_TOKEN"
# { "id": "17900..." }

Three details are worth knowing if you build the Meta path yourself. Text-only posts need no container polling at all, so a naive "always poll" implementation wastes 30 seconds on every plain-text post. Video containers genuinely do need the wait, and a large file can still be IN_PROGRESS after five minutes. And error_message values such as INVALID_ASPEC_RATIO and FAILED_PROCESSING_VIDEO only surface on the status call, never on the create call.

That asymmetry is exactly what SocialAPI.ai's Threads connector encodes: text posts take a single atomic path, image containers publish straight after creation, and video containers get polled once a minute for up to five attempts before the target is marked failed with a structured error. The full behaviour is documented in the Threads publishing reference.

What media can a Threads post contain?

Content typeOfficial limits (Meta, 2026)
Text500 characters max. Emoji count toward the limit by UTF-8 byte count, not visual characters.
LinksMaximum 5 unique URLs per post. More returns THREADS_API__LINK_LIMIT_EXCEEDED. link_attachment applies to text-only posts.
ImageJPEG or PNG, max 8 MB, aspect ratio up to 10:1, width 320–1440 px, sRGB color space.
VideoMOV or MP4, H264 or HEVC, AAC audio ≤128 kbps, 23–60 FPS, max 300 seconds, max 1 GB, bitrate ≤100 Mbps.
Carousel2 to 20 items, images or videos. A carousel counts as one post against the publishing quota.
Alt textSupported on images, videos, and carousels. Not applicable to text-only posts.

Threads API rate limits (official, 2026)

There is no single official "Threads API rate limits" page — the numbers are split across two Meta documents. Per-action quotas live on the Threads API overview, while the general API-call budget lives on the Graph API rate limiting page. If a search result points you at /docs/threads/get-started/rate-limits, that URL is a 404.

QuotaOfficial limitWindowHow to read usage
API-published posts25024-hour moving periodquota_usage / config
Replies1,00024-hour moving periodreply_quota_usage / reply_config
Deletions10024-hour moving perioddelete_quota_usage / delete_config
Location searches50024-hour moving periodlocation_search_quota_usage
Keyword search queries2,200rolling 24 hoursNot exposed on the limits endpoint
Total API calls4800 × impressions24-hour moving periodX-Business-Use-Case-Usage header
Threads API per-action quotas in a 24-hour moving window
Posts250Replies1,000Deletions100Location search500Keyword search2,200

Source: Meta, Threads API overview

Per-profile quotas documented by Meta as of July 2026. A carousel counts as a single post. Keyword-search queries that return no results do not consume quota.

The call-budget formula catches teams off guard: Calls within 24 hours = 4800 × Number of Impressions, where impressions counts how often the profile's content entered someone's screen in the last 24 hours. Meta floors the impression value at 10, so a brand-new profile with no reach still gets 48,000 calls a day. A profile that goes quiet, however, sees its ceiling shrink with its reach.

Do not guess your remaining headroom. Threads exposes a quota introspection endpoint that returns live usage for every action type, and the X-Business-Use-Case-Usage response header reports call_count, total_cputime, and total_time as percentages where 100 means throttled. Read both before you retry, rather than backing off blindly. For the general retry strategy across platforms, see the social API rate limits guide.

bash
curl "https://graph.threads.net/v1.0/$THREADS_USER_ID/threads_publishing_limit\
?fields=quota_usage,config,reply_quota_usage,reply_config\
&access_token=$THREADS_TOKEN"

# {
#   "data": [{
#     "quota_usage": 12,
#     "config": { "quota_total": 250, "quota_duration": 86400 },
#     "reply_quota_usage": 3,
#     "reply_config": { "quota_total": 1000, "quota_duration": 86400 }
#   }]
# }

Is the Threads API free?

Meta documents no price, tier, or billing model for the Threads API. We checked the docs index, the API overview, the get-started guide, and the Threads social-technologies page in July 2026: none of them mention cost, fees, or paid tiers. That is a meaningful difference from the X/Twitter API, where DM and posting access sit behind a paid Pro tier.

What gates access instead is Meta App Review. Every threads_* permission — threads_basic, threads_content_publish, threads_manage_replies, threads_read_replies, threads_manage_insights, threads_delete, and the rest — requires review before it works on accounts outside your own developer org (Meta permissions reference). The price of the Threads API is measured in submission rounds and screencasts, not dollars.

The Threads API has no price tag. It has an App Review queue, which for most teams is the more expensive of the two.

That is the same tax described in our guide to using the Instagram and Facebook API without your own Meta App Review, and the workaround is identical. SocialAPI.ai operates a managed Meta Threads app whose scopes are already approved, so connecting an account is an OAuth redirect rather than a review submission. The free tier covers 2 brands, 10 posts/mo, and 50 interactions/mo, on infrastructure running at >99.9% uptime.

What can't the Threads API do?

Threads shipped fast and the API still has real gaps. These are the ones that most often change an implementation plan, all confirmed against Meta's own documentation and against what our Threads connector can actually expose:

  • No DM API. Threads has in-app direct messages, but no messaging endpoints exist in the developer docs. If your product needs social DMs, Instagram, Messenger, LinkedIn, and X are the platforms that offer them.
  • No native scheduling. There is no scheduled_publish_time parameter. Meta's overview instead tells developers that if their app offers scheduling, the app must enforce the publishing limits itself. Scheduling is your queue's problem, or your provider's.
  • No post editing. Threads has no endpoint to change a published post's text or media. Correcting a typo means DELETE and republish — which also spends one of your 100 daily deletions.
  • Mentions are webhook-only. There is no polling endpoint for mentions. You subscribe to the mentions webhook field with threads_manage_mentions and Advanced Access, or you do not get mention data at all.
  • Insights are scoped and time-boxed. Metrics need threads_manage_insights, follower_demographics requires at least 100 followers, and since/until cannot reach before 13 April 2024.
  • Liking replies is not exposed. You can reply, hide, unhide, and delete. Programmatically liking a reply is not part of the API surface.

Threads vs Instagram API: what's the difference?

Both are Meta products, both use the container-then-publish pattern, and there the similarity stops. They are separate API surfaces with separate hosts, separate OAuth windows, separate app credentials, and separate quotas. A Meta app that wants Threads access enables a dedicated "Access the Threads API" use case and gets its own Threads app ID and secret.

AspectThreads APIInstagram API
Hostgraph.threads.net or graph.threads.comgraph.instagram.com / graph.facebook.com
OAuth windowthreads.net/oauth/authorizeInstagram Login or Facebook Login
Scope prefixthreads_*instagram_business_* / pages_*
Text-only postsYes (media_type=TEXT)No, media is required
Body length500 charactersLonger captions, no 500-char cap
Publishing quota250 posts / 24h100 posts / 24h
Direct messagesNo APIYes (Instagram Messaging API)
Instagram account requiredNo, since 23 Sep 2025Yes, a Business or Creator account

The last row is the one that changed most recently. Since 23 September 2025 the Threads API works for profiles with no linked Instagram account, and since 30 January 2026 those profiles can also read followers_count and follower_demographics (Threads changelog). Treating Threads as "Instagram with a different endpoint" was already wrong; it is now wrong in a way that breaks onboarding assumptions.

Practically, supporting both means two OAuth flows, two token-refresh schedules, two quota models, and two error vocabularies. That is the maintenance argument for one API across all social networks: a single POST /v1/posts with a targets array, where the Threads container flow and the Instagram publishing flow are implementation details you never see.

Frequently asked questions

How do you publish a post with the Threads API?
In two steps. Send POST https://graph.threads.net/v1.0/{threads-user-id}/threads with media_type set to TEXT, IMAGE, VIDEO, or CAROUSEL plus the matching field (text, image_url, video_url, or children). Meta returns a container ID. Wait about 30 seconds, optionally polling GET /{container-id}?fields=status,error_message until the status is FINISHED, then send POST /{threads-user-id}/threads_publish with creation_id set to that container ID. An unpublished container expires after 24 hours. SocialAPI.ai performs all three calls behind a single POST /v1/posts.
Is the Threads API free?
Meta does not document any cost, tier, or billing model for the Threads API. As of July 2026 there is no pricing page in the Threads developer documentation, and the docs index, overview, and get-started guides make no mention of fees. Access is gated by Meta App Review and by rate limits rather than by payment. That said, absence of a published price is not the same as Meta declaring the API free, so treat App Review time and engineering effort as the real cost of entry.
What are the Threads API rate limits?
Per profile, in a 24-hour moving period: 250 API-published posts, 1,000 replies, 100 deletions, and 500 location searches. Keyword search allows 2,200 queries per rolling 24 hours, and queries returning no results do not consume quota. On top of those, the general Graph API budget applies: calls within 24 hours = 4800 × number of impressions, with impressions floored at 10. Check live usage with GET /{threads-user-id}/threads_publishing_limit and the X-Business-Use-Case-Usage response header.
Do you need an Instagram account to use the Threads API?
No, not since 23 September 2025, when Meta opened the Threads API to profiles without a linked Instagram account. Follower metrics were initially excluded, and on 30 January 2026 Meta extended followers_count and follower_demographics to those profiles too. The Threads OAuth flow is entirely separate from Instagram Login regardless, running through threads.net with its own app ID, app secret, and threads_* scopes.
Can you schedule Threads posts through the API?
Not natively. The Threads API has no scheduling parameter or endpoint. Meta's own overview instructs developers that if their application offers scheduling, the application is responsible for enforcing the publishing limits itself. You either build the queue, the retry logic, and the quota accounting yourself, or use a provider that already has one. SocialAPI.ai accepts a scheduled_at ISO 8601 timestamp on POST /v1/posts and defers the Threads publish until then.
Can you read or send Threads DMs through the API?
No. Threads added in-app direct messages for users, but no DM endpoints exist in the Threads API documentation. The documented surface covers posts, carousels, media retrieval, profiles, reply moderation, mentions, insights, webhooks, keyword search, and oEmbed. If your product needs programmatic direct messages, Instagram, Facebook Messenger, LinkedIn, and X are the platforms that expose them.
What is the Threads character limit for API posts?
500 characters, the same as the Threads app. Emoji are counted by UTF-8 byte count rather than as single visual characters, so an emoji-heavy post hits the ceiling sooner than a character count in your UI would suggest. Posts also accept a maximum of five unique URLs; exceeding that returns THREADS_API__LINK_LIMIT_EXCEEDED.

To publish to Threads without building the container flow, see the Threads platform page, read the publishing reference, or sign up free and connect an account through the managed OAuth flow. The same POST /v1/posts call targets Instagram, Facebook, LinkedIn, TikTok, X, and YouTube.

Official Meta documentation cited in this guide: Threads API — Posts (container and publish flow) · Threads API — Overview (24-hour publishing quotas) · Graph API — Rate limiting (4800 × impressions formula) · Threads API — Troubleshooting (container status, publishing limit endpoint) · Threads API — Long-lived tokens · Threads API — Get access tokens and permissions · Meta permissions reference (threads_* scopes) · Threads API — Changelog · Threads API — Keyword search · Instagram Platform — Content publishing (100 posts / 24h)

Get started today

Ready to unify your social interactions?

Free tier available · No credit card required · Ships with MCP server

We use essential cookies for security, and analytics cookies with your consent. Privacy Policy.