read:post
Reads one post by X's own numeric id: the lookup you make when you already hold one, out of a mentions page, a search, a reply, or the answer to a post you published. If you hold a link rather than an id, the id is the number at the end of it.
Fields
id |
Required. X's own numeric id, as a string. Never a handle |
profile |
the account to read as. Optional when the agent has one |
reason |
Required over MCP. One short sentence, in the agent's own words, for the person |
What comes back
data is X's own answer, verbatim, so X's data sits inside ours.
{ "status": "done",
"ref": "4J4CDMA2",
"message": "",
"data": {
"data": {
"id": "1832000000000000007",
"text": "We rebuilt the pipeline this week.",
"created_at": "2026-09-15T09:12:44.000Z",
"author_id": "1400000000000000001",
"conversation_id": "1832000000000000007",
"edit_history_post_ids": ["1832000000000000007"],
"lang": "en",
"reply_settings": "everyone",
"possibly_sensitive": false,
"public_metrics": {
"repost_count": 2, "reply_count": 1, "like_count": 14,
"quote_count": 0, "bookmark_count": 3, "impression_count": 812
}
}
} }
id, text and edit_history_post_ids are always there. in_reply_to_user_id,
referenced_posts and entities appear only when the post has them.
A post X does not hold is not an error
It answers 200 with an errors array and no data, rather than a 404. Check for data before
reading it.
The author is an id, not a name
Okaybot asks for every field of the post and no expansions: fields are free, but an expansion is
another charged resource at X and would make the quoted price a lie. To put a face to the id,
read:user it, which is a call of its own.