# Search X posts

Returns the X posts that match a search, from the top, latest or media tab, with author and engagement counts. Use it to follow the conversation on a topic.

Tool `x.search.posts` on X (Twitter). Contract version 1, released 2026-10-27.

## Example call

Over REST, send the input in the body. Over MCP, pass the same input to `call_tool`.

cURL:

```bash
curl https://api.voxoria.ai/v1/tools/x.search.posts/calls \
  -H "Authorization: Bearer $VOXORIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"query":"from:OpenAI","tab":"latest"}}'
```

Python:

```python
import os

import httpx

response = httpx.post(
    "https://api.voxoria.ai/v1/tools/x.search.posts/calls",
    headers={"Authorization": f"Bearer {os.environ['VOXORIA_API_KEY']}"},
    json={"input": {"query": "from:OpenAI", "tab": "latest"}},
    timeout=60,
)
print(response.json())
```

TypeScript:

```ts
const response = await fetch("https://api.voxoria.ai/v1/tools/x.search.posts/calls", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.VOXORIA_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"input": {"query": "from:OpenAI", "tab": "latest"}}),
});
console.log(await response.json());
```

MCP (`tools/call` params):

```json
{
  "name": "call_tool",
  "arguments": {
    "tool": "x.search.posts",
    "input": {
      "query": "from:OpenAI",
      "tab": "latest"
    }
  }
}
```

Both return [the full response](/docs/call-response.md): the call's ID, status and cost, with this tool's result in `output`.

## Input

| Input | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `query` | string | Yes |  | The search query. X matches more than a post's text, such as the post it quotes, a linked article or its media, so a post may not contain the query's words. |
| `tab` | string | No | `top` | Which tab of X's search results to read: top (X's ranking), latest or media (posts with photos or videos). One of `top`, `latest`, `media`. |
| `next_page_token` | string | No |  | Fetches the next page. Take it from pagination.next_page_token of the previous page, and send the same query and tab. |

## Output

A successful call returns these blocks in its `output`. A field not marked required can be `null`.

### posts

A list of rows. Always present, possibly empty.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | X's identifier of the post. The post is at https://x.com/i/status/ followed by it. |
| `url` | string | No | Address of the post on x.com. Format `uri`. |
| `text` | string | No | What the post says, links written as X's t.co short links. |
| `published_at` | string | No | When the post was published, in ISO 8601. |
| `author_id` | string | No | X's numeric identifier of the author, as a string. |
| `author_username` | string | No | The author's handle, without the @. |
| `author_name` | string | No | The author's display name. |
| `author_image_url` | string | No | Address of the author's profile picture. |
| `author_follower_count` | integer | No |  |
| `reply_count` | integer | No |  |
| `repost_count` | integer | No |  |
| `quote_count` | integer | No |  |
| `like_count` | integer | No |  |
| `bookmark_count` | integer | No |  |
| `view_count` | integer | No | Number of times the post was seen. |
| `conversation_id` | string | No | Identifier of the post that opened the thread; the post's own id when it opened it. |
| `in_reply_to_post_id` | string | No | Identifier of the post this one replies to. |
| `in_reply_to_username` | string | No | Handle of the author this post replies to, without the @. |
| `sensitive` | boolean | No | Whether X marks the post as possibly sensitive. |
| `quoted_post_id` | string | No | Identifier of the post this one quotes. |
| `quoted_post_text` | string | No |  |
| `quoted_post_author_username` | string | No |  |
| `hashtags` | array of string | No | Each hashtag in the text, without the |
| `mentioned_usernames` | array of string | No | Handle of each account the text mentions, without the @. |
| `link_urls` | array of string | No | Full address of each link in the text. |
| `image_urls` | array of string | No | Address of each photo attached to the post. |
| `videos` | array of object | No | Each video attached to the post. |
| `videos.preview_image_url` | string | Yes | Address of the video's still image. |
| `videos.duration_ms` | integer | No | Length of the video, in milliseconds. |
| `videos.width` | integer | No | Width of the original video, in pixels. |
| `videos.height` | integer | No | Height of the original video, in pixels. |

### pagination

One object. Can be `null`. How to fetch the next page. Null on the last page.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `next_page_token` | string | Yes | Send as next_page_token to fetch the next page. |

## Example output

The `output` of a real call, each list cut to 3 items.

```json
{
  "posts": [
    {
      "id": "2090885187634905500",
      "url": null,
      "text": "As we continue to push the frontier of capabilities while improving efficiency, we're dropping API and credit pricing of GPT-5.6 Sol by over 20% for the next 3 months. https://t.co/UoTb3hcB2t",
      "published_at": "2026-08-21T19:34:10Z",
      "author_id": "4398626122",
      "author_username": "OpenAI",
      "author_name": "OpenAI",
      "author_image_url": "https://pbs.twimg.com/profile_images/1885410181409820672/ztsaR0JW_normal.jpg",
      "author_follower_count": 5471705,
      "reply_count": 718,
      "repost_count": 848,
      "quote_count": 610,
      "like_count": 13888,
      "bookmark_count": 1000,
      "view_count": 3898181,
      "conversation_id": "2090885187634905500",
      "in_reply_to_post_id": null,
      "in_reply_to_username": null,
      "sensitive": false,
      "quoted_post_id": null,
      "quoted_post_text": null,
      "quoted_post_author_username": null,
      "hashtags": null,
      "mentioned_usernames": null,
      "link_urls": null,
      "image_urls": null,
      "videos": [
        {
          "preview_image_url": "https://pbs.twimg.com/amplify_video_thumb/2090884941819285504/img/JpIf7VDQGLhawgzB.jpg",
          "duration_ms": 5000,
          "width": 1536,
          "height": 864
        }
      ]
    },
    {
      "id": "2104986129686741046",
      "url": null,
      "text": "GPT-6.1 Sol: near-Astra intelligence for a fifth of the price.\n\nIt’s the most cost-efficient model for its performance available today. https://t.co/hH8PnE2Oxk",
      "published_at": "2026-09-29T17:26:16Z",
      "author_id": "4398626122",
      "author_username": "OpenAI",
      "author_name": "OpenAI",
      "author_image_url": "https://pbs.twimg.com/profile_images/1885410181409820672/ztsaR0JW_normal.jpg",
      "author_follower_count": 5471705,
      "reply_count": 721,
      "repost_count": 1713,
      "quote_count": 1082,
      "like_count": 21116,
      "bookmark_count": 1936,
      "view_count": 3238371,
      "conversation_id": "2104986129686741046",
      "in_reply_to_post_id": null,
      "in_reply_to_username": null,
      "sensitive": false,
      "quoted_post_id": null,
      "quoted_post_text": null,
      "quoted_post_author_username": null,
      "hashtags": null,
      "mentioned_usernames": null,
      "link_urls": null,
      "image_urls": null,
      "videos": [
        {
          "preview_image_url": "https://pbs.twimg.com/amplify_video_thumb/2104984622191067137/img/6xK8vFcs_vBe4SKN.jpg",
          "duration_ms": 8366,
          "width": 1920,
          "height": 1080
        }
      ]
    },
    {
      "id": "2104984504133918973",
      "url": null,
      "text": "Introducing dots, powered by GPT-6 Astra.\n\nRemarkably capable, always-on agents built to handle everything. https://t.co/inY5BZj3Kz",
      "published_at": "2026-09-29T17:19:49Z",
      "author_id": "4398626122",
      "author_username": "OpenAI",
      "author_name": "OpenAI",
      "author_image_url": "https://pbs.twimg.com/profile_images/1885410181409820672/ztsaR0JW_normal.jpg",
      "author_follower_count": 5471705,
      "reply_count": 2348,
      "repost_count": 3367,
      "quote_count": 3324,
      "like_count": 38099,
      "bookmark_count": 10502,
      "view_count": 14831016,
      "conversation_id": "2104984504133918973",
      "in_reply_to_post_id": null,
      "in_reply_to_username": null,
      "sensitive": false,
      "quoted_post_id": null,
      "quoted_post_text": null,
      "quoted_post_author_username": null,
      "hashtags": null,
      "mentioned_usernames": null,
      "link_urls": null,
      "image_urls": null,
      "videos": [
        {
          "preview_image_url": "https://pbs.twimg.com/amplify_video_thumb/2104984413113393152/img/ww-kV51l6J5DwxZJ.jpg",
          "duration_ms": 147818,
          "width": 1920,
          "height": 1080
        }
      ]
    }
  ],
  "pagination": {
    "next_page_token": "pt1.dGlraHViOkRBQUNDZ0FDSFZaXzZnZ0FKeEFLQUFNZFZuX3FCX19ZOEFnQUJBQUFBQUlMQUFVQUFBRHdSVzFRUXpaM1FVRkJabEV2WjBkS1RqQjJSM0F2UVVGQlFVSlJZek4yZW5aU1NtRjRTMEowT0hwM0szUXlka0ZaUnpONWRTOVZjV0ZqUldOYVVFSmllV1pLZGtKbWVEQldSRlJzVjIxMlJsVklVRVI2TUcxVFlWRmxTVmh6VFVsb0x6RnZRak40TVZGaWVFWnpiV2xGTkVjdmMwUXdkWGhpUVZKblpGRk1PVlpEUW5SU2FrSXdZbU5hYlRGWGEwZGpTRlJhYjFGUWNXRnZVREJrVTNjNWVHUXhkbEoyUWpGV2JUQjZWRmQxU0hsSVV6RjRTR3RCV0c5VU5HTXJaVVpyUVRWd1VrZFNlV1ZzVGt4cFJtOUVWVWhSVWxKQlFYTmhkMXAzWkU1dGJUZGtVbkJCVG1nd1pVRXlSR2hIZVVKUUNBQUdBQUFBQUFnQUJ3QUFBQUFNQUFnS0FBRVhzTUloXzFvQjN3QUFBQQ"
  }
}
```
