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.