X Thread API
How to publish a connected thread of posts to X via API.
X has no dedicated thread endpoint. A thread is a chain of ordinary posts: publish the first with POST /2/tweets, then set each following post’s in_reply_to_tweet_id to the ID the previous call returned. Every post in the chain is billed and rate-limited separately. PostGate’s post.thread field currently supports Meta Threads only — X returns a 422.
A thread on X is not a single object — it's a chain of ordinary posts, each one a reply to the last, published in order by the same account. There is no dedicated “thread” endpoint on X's API; the chaining is entirely a client-side pattern built on top of the normal post-creation call. This page covers how that chain actually works, what it costs, and where PostGate stands on automating it today.
How does the chain actually work?
in_reply_to_tweet_id to the ID returned by the previous call. X links them into a thread in the UI because each one replies to the one before it — the same mechanic used for any reply, not something thread-specific.# Post 1
curl -X POST https://api.x.com/2/tweets \
-H "Authorization: OAuth oauth_consumer_key=...,oauth_token=...,..." \
-H "Content-Type: application/json" \
-d '{ "text": "1/ Here is what shipped this week." }'
# -> { "data": { "id": "1987650001", "text": "1/ Here is what shipped this week." } }
# Post 2, replying to post 1
curl -X POST https://api.x.com/2/tweets \
-H "Authorization: OAuth oauth_consumer_key=...,oauth_token=...,..." \
-H "Content-Type: application/json" \
-d '{
"text": "2/ First, the new chunked upload path.",
"reply": { "in_reply_to_tweet_id": "1987650001" }
}'What does each reply cost and consume?
Where does PostGate stand on X threads today?
post.thread field is built for exactly this pattern — an array of connected posts published as a self-reply chain through one request. As of this writing, that field is wired up for Meta Threads profiles only. Sending thread items against an X profile returns a 422 with the message "Thread replies are only supported on: threads." — an honest current limitation, not a documentation gap.curl -X POST "https://postgate.studio/api/posts?profile_group_id=grp_acme123" \
-H "Authorization: Bearer $POSTGATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"post": {
"body": "1/ Here is what shipped this week.",
"thread": [
{ "body": "2/ First, the new chunked upload path." },
{ "body": "3/ Second, per-target delivery status." }
]
},
"profiles": ["pro_threads123"]
}'What is the workaround for X today?
in_reply_to_tweet_id on your own follow-up call directly against X's API. It costs the same either way — the only difference is who issues each write call.Frequently asked questions
Is there a thread endpoint in the X API?
No. A thread on X is not a single object — it’s a chain of ordinary posts, each one a reply to the last, published in order by the same account. The chaining is entirely a client-side pattern built on the normal post-creation call, using the same reply mechanic as any other reply.
How much does posting an X thread cost?
Every post in a thread is a separate write call, billed and rate-limited independently — a five-post thread is five write charges, not one. It also consumes five units of whatever posting cap applies to the account.
Why does PostGate return a 422 for X threads?
PostGate’s unified post.thread field is built for exactly this pattern, but as of this writing it is wired up for Meta Threads profiles only. Sending thread items against an X profile returns a 422 with the message "Thread replies are only supported on: threads." — an honest current limitation, not a documentation gap.
How can I post an X thread through PostGate today?
Publish each post in the thread as its own single PostGate post, read the returned platform post ID off the target, and pass it as in_reply_to_tweet_id on your own follow-up call directly against X’s API. It costs the same either way — the only difference is who issues each write call.
