An X thread looks simple after it is published. Under the hood, it is a sequence of connected Posts that must stay in the right order.
That order matters when a coding agent prepares the thread. The agent needs somewhere to save the copy, a way to keep every reply attached to the same job, and a clear checkpoint before anything reaches a public account.
You can build this directly on the X API. You can also put a smaller publishing layer between your agent and the provider. The tradeoff is how much OAuth, scheduling, retry, and receipt logic you want to own. This guide shows both paths and the contract OpenPMM provides through hosted MCP, its public API, and CLI.
For the broader multi-channel contract, see OpenPMM's social media API and CLI. This guide stays focused on the state and sequencing required for X threads.
The direct X API building block
X's official endpoint index lists POST /2/tweets as the create-Post operation. It accepts OAuth user context rather than an app-only read token.[4] The official Python sample uses OAuth 2.0 with PKCE, requests the tweet.write scope, and sends a text payload through the create-Post endpoint.[3]
A minimal direct request starts with one Post:
{
"text": "The opening Post in the thread"
}The next Post must be created as a reply. Your application captures the first Post ID, sends the second Post with reply metadata, captures that new ID, and continues until the thread is complete. X's official sample notes that the create endpoint also accepts reply settings.[3]
That is manageable for one script. Scheduling is where the bookkeeping starts.
Why thread scheduling needs state
A scheduler cannot send every reply at once and hope the provider connects them correctly. It needs to preserve:
- the ordered body items;
- the target X account;
- the intended publication time and time zone;
- the provider ID returned for each published item;
- the current attempt, so a retry does not duplicate the thread.
It also needs to distinguish preparation from publication. A coding agent should be able to draft and validate a thread without receiving silent permission to post it.
This is where a weekend script tends to become an integration project. You need OAuth, encrypted token storage, retry rules, scheduling, provider receipts, and enough persisted state to tell whether an interrupted run published nothing, part of a thread, or the complete sequence.
Represent the thread as one ordered package
OpenPMM's public API contract represents X, Bluesky, Mastodon, and Threads reply sequences as an ordered body array. Later items publish as replies to the opening item.[2]
A draft request for X looks like this:
{
"when": "draft",
"group": "x_thread_api_guide",
"posts": [
{
"channel": "x",
"body": [
"An X thread is an ordered publishing job, not one long string.",
"Save the complete sequence as a draft before choosing an account or time.",
"Publish only after a person confirms the exact copy."
]
}
]
}The group keeps related Posts together. For a draft, the request names the channel and omits the destination. The live OpenPMM schema requires at least one body item, allows up to 25, and rejects URLs inside X body items.[2]
Saving a draft does not publish it. That separation gives an agent room to prepare copy while a person keeps control of the public side effect.
Schedule the approved draft
Once the copy is approved, the publishing request names the exact draft ID, its version, and the connected destination. The current OpenPMM contract accepts now, the next queue slot, or an ISO 8601 timestamp with a UTC offset.[2]
{
"confirmed": true,
"when": "2026-08-26T09:00:00+02:00",
"time_zone": "Europe/Berlin",
"posts": [
{
"id": "post_example",
"version": 1,
"destination_id": "dest_x_example"
}
]
}The scheduling call needs an idempotency key. If the network times out, the client retries the same request with the same key instead of inventing a second publishing job.[2]
There are two useful checks after the request:
- Read the Post back and confirm its state, version, destination, body order, and scheduled time.
- Keep the returned Post IDs so later status checks refer to the exact remote objects.
A successful HTTP response is not enough. The application should mark the job scheduled only after the remote state matches the request.
A safer agent workflow
A workable flow is short:
- The agent writes channel-specific copy.
- Your validator checks body count, text limits, links, and protected facts.
- The agent creates a draft and reads it back.
- A person reviews the exact immutable revision.
- A separate confirmed request schedules that revision.
- The workflow stores the remote Post IDs and verifies the schedule.
The human checkpoint belongs between drafting and scheduling. It should not be buried inside a broad instruction such as "handle social for this release." A public send deserves its own visible action.
OpenPMM is designed around that split. Its product notes describe an agent-operated workflow that connects channels once, then prepares, schedules, or publishes through hosted MCP, the API, or the CLI while returning a clear result.[1] The API contract separately requires explicit confirmation for publishing and scheduling.[2]
What to validate before scheduling
Before your application sends the confirmed request, check the details that are expensive to fix later:
- Every reply has a job in the sequence. Cut repetition instead of splitting prose mechanically.
- Product names, prices, commands, links, and quotations still match their sources.
- The opening Post works on its own. Readers may see it without expanding the thread.
- The selected destination is the intended account.
- The timestamp includes a UTC offset, and the displayed time zone matches the operator's expectation.
- The content hash is the same hash that the reviewer approved.
- The retry path reuses the original idempotency key.
These checks are boring on purpose. Scheduling software should make the final action predictable, not surprising.
Build directly or use a publishing layer?
Use the X API directly when X is your only destination and you want to own the full integration. X publishes official samples for creating Posts with user-context authentication.[3][4]
A publishing layer makes more sense when the same agent will also prepare content for other channels, or when you do not want to maintain provider OAuth, scheduling, media processing, and receipt handling yourself. OpenPMM is intentionally narrower than a social dashboard. The live product gives a coding agent one publishing contract for the account owner's connected channels through hosted MCP, API, or CLI.[1]
OpenPMM is available now. Compatible agents can connect through the hosted MCP server with browser-based OAuth, while terminal and direct integration workflows can use the CLI or API. The public documentation and OpenAPI contract describe the same underlying publishing workflow.[1][2]
Keep the final send explicit
Speed is not the test here. Useful automation can show exactly what will be published, where it will go, when it will run, and what happened afterward.
For an X thread, that means storing the ordered copy as one job, approving an exact revision, scheduling it with an idempotent request, and reading the remote state back. The agent can do most of the work. The public send still gets a deliberate human confirmation.
Sources
[1] https://www.openpmm.com/docs — OpenPMM documentation [2] https://api.openpmm.com/v1/openapi.json — OpenPMM API OpenAPI contract [3] https://raw.githubusercontent.com/xdevplatform/samples/99992dd773dd77f23cb4236edbb66a1210e248d0/python/posts/create_post.py — X API v2 create Post sample [4] https://raw.githubusercontent.com/xdevplatform/samples/99992dd773dd77f23cb4236edbb66a1210e248d0/api-index.json — X API v2 endpoint index