# Search Reddit posts

Returns the Reddit posts that match a search, with subreddit, author, score and comment count, a page at a time. Use it to find what communities say about a topic.

Tool `reddit.search.posts` on Reddit. Contract version 1, released 2026-10-30.

## 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/reddit.search.posts/calls \
  -H "Authorization: Bearer $VOXORIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"query":"litellm","time_range":"month"}}'
```

Python:

```python
import os

import httpx

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

TypeScript:

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

MCP (`tools/call` params):

```json
{
  "name": "call_tool",
  "arguments": {
    "tool": "reddit.search.posts",
    "input": {
      "query": "litellm",
      "time_range": "month"
    }
  }
}
```

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. Reddit's search operators work, such as subreddit:python, author:spez, title:"exact phrase" or AND, OR and NOT in capitals. |
| `sort` | string | No | `relevance` | Order of the results: relevance (Reddit's ranking), hot, top (highest score), new or comments (most commented). Only relevance weighs how well a post matches the query. One of `relevance`, `hot`, `top`, `new`, `comments`. |
| `time_range` | string | No |  | Only posts published in the last hour, day, week, month or year. One of `hour`, `day`, `week`, `month`, `year`. |
| `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, sort and time_range. |

## 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 | Reddit's full name of the post, t3_ followed by the post id in its address. |
| `url` | string | Yes | Address of the post on www.reddit.com, as reddit.post.detail and reddit.post.comments take it. Format `uri`. |
| `title` | string | No |  |
| `text` | string | No | The body of a text post, in Markdown. Null for a link post. |
| `link_url` | string | No | Address a link post points at, such as an article or an image. Null for a text post. |
| `subreddit` | string | Yes | Name of the subreddit the post is in, without r/. |
| `flair` | string | No | Text of the post's flair, the label its subreddit gives it. |
| `published_at` | string | No | When the post was published, in ISO 8601. |
| `author_id` | string | No | Reddit's full name of the author's account, t2_ followed by its id. |
| `author_username` | string | No | The author's username, without u/. |
| `score` | integer | No | Upvotes minus downvotes, as Reddit shows it. Reddit fuzzes it slightly. |
| `upvote_ratio` | number | No | Share of the votes that are upvotes, from 0 to 1. Reddit fuzzes it slightly. |
| `comment_count` | integer | No |  |
| `nsfw` | boolean | No | Whether the post is marked NSFW (not safe for work). |
| `spoiler` | boolean | No | Whether the post is marked as a spoiler. |
| `locked` | boolean | No | Whether the post is locked to new comments. |
| `stickied` | boolean | No | Whether the post is pinned to the top of its subreddit. |

### 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": "t3_1xbnrhi",
      "url": "https://www.reddit.com/r/Python/comments/1xbnrhi/litellm_11070_on_pypi_is_compromised/",
      "title": "litellm 1.107.0 on PyPI is compromised",
      "text": "the payloads run on every python start on the machine and not just when you import litellm. Your IDE, pip, CI jobs everything python on that host is affected.\n\nIt steals ssh keys, aws credentials, browser passwords, shell history and AI coding tool configs. The backdoor runs as a daemon and executes whatever code the attacker’s server returns every hour.\n\nPin to 1.106.2.\n\ncomplete breakdown: [safedep.io/litellm-pypi-compromise-credential-stealer-backdoor](http://safedep.io/litellm-pypi-compromise-credential-stealer-backdoor)",
      "link_url": null,
      "subreddit": "Python",
      "flair": null,
      "published_at": "2026-10-21T13:52:24Z",
      "author_id": null,
      "author_username": "BattleRemote3157",
      "score": null,
      "upvote_ratio": null,
      "comment_count": null,
      "nsfw": null,
      "spoiler": null,
      "locked": null,
      "stickied": null
    },
    {
      "id": "t3_1xbpoye",
      "url": "https://www.reddit.com/r/LocalLLM/comments/1xbpoye/alert_litellm_11070_was_compromised_today/",
      "title": "Alert! LiteLLM 1.107.0 was compromised today",
      "text": "#Alert\n\nSo it's not only PHP that was vulnerable today (patch yours NOW!) but also, one of the prominent and widely used LLM Gateway - **LiteLLM AI Gateway** was (again) backdoored.\n\nNot sure who discovered the backdoor, but it's serious.\n\nHere's the information:\n\nVersion: LiteLLM 1.107.0 (PyPI and the official Docker images).\n\nOne line was added to the build config: `data = \"cook\"` under [tool.maturin].\n\nThat directive makes maturin bundle a directory named cook/ into the wheel's data section, and pip installs it as top-level site files.\n\nThree files land next to site-packages, not inside the litellm package: a 12 byte cook.pth containing `import cook`, a one-line cook.py that unpacks a 61,000 byte credential stealer, and a sitecustomize.py that runs an hourly remote code loader.\n\nBecause Python processes .pth files and imports sitecustomize during interpreter startup, the payload runs on any Python start. An environment that never imports litellm is still affected, and using pip from that environment to investigate re-triggers it.\n\nThe collector is broad. It takes browser password stores, SSH, GPG and TLS private keys, AWS, Azure, GCP and Kubernetes credentials, instance and ECS metadata roles, CI tokens, .env files, and the auth files for Claude, Codex, Gemini, Cursor and Copilot.\n\nIt also queries your proxy's own database, pulling every saved provider credential and model configuration out of LiteLLM_CredentialsTable and LiteLLM_ProxyModelTable.\n\nEverything is encrypted with an embedded RSA-4096 key and POSTed to [www.litellm.dev/healthcheck](http://www.litellm.dev/healthcheck), a domain the attacker controls.\n\nThe second component is the part that should worry platform teams. [sitecustomize.py](http://sitecustomize.py) polls a domain list from a GitHub repository every hour and executes whatever Python it downloads from that domain, with no signature or checksum. The attacker never needs to ship a new package version to change what runs on your hosts.What makes this hard to audit: the malicious commits were never merged to main, and the official v1.107.0 tag points at a clean, signed commit.\n\nThe published artifacts came from a repository recorded as Berri-AI, one hyphen from BerriAI. Reviewing the tag, or the main branch, would have told you nothing was wrong.\n\nCurrent state as of this afternoon: PyPI has quarantined 1.107.0 and rolled latest back to 1.106.2, the compromised image tags are gone from GHCR and Docker Hub, the attacker's GitHub account and C2 pointer repository have both been taken down, and the exfil server is still listening.\n\nIf you deployed 1.107.0, check for /tmp/.pc_once_72129118c59f5636c0bb and /tmp/remote_code_loader.lock. If either exists, rebuild rather than patch, and rotate every credential the process could read, including the keys stored in your proxy database.\n\nTwo controls would have blocked most of this: lockfiles with hashes, and OIDC trusted publishing so a long-lived publish token never reaches a compromised CI machine. The longer term fix is pinning source revisions rather than version tags, since in this incident the tag was never the source of the bad build.\n\n#SupplyChainSecurity #AppSec #Python #LLMOps #LiteLLM",
      "link_url": null,
      "subreddit": "LocalLLM",
      "flair": null,
      "published_at": "2026-10-21T15:07:04Z",
      "author_id": null,
      "author_username": "AdamLangePL",
      "score": null,
      "upvote_ratio": null,
      "comment_count": null,
      "nsfw": null,
      "spoiler": null,
      "locked": null,
      "stickied": null
    },
    {
      "id": "t3_1xbnui2",
      "url": "https://www.reddit.com/r/cybersecurity/comments/1xbnui2/litellm_11070_compromised_on_pypi_and_installs_a/",
      "title": "LiteLLM 1.107.0 compromised on PyPI and installs a credential stealer and backdoor",
      "text": "the payloads run on every python start on the machine and not just when you import litellm. Your IDE, pip, CI jobs everything python on that host is affected.\n\nIt steals ssh keys, aws credentials, browser passwords, shell history and AI coding tool configs. The backdoor runs as a daemon and executes whatever code the attacker’s server returns every hour.\n\nPin to 1.106.2.",
      "link_url": null,
      "subreddit": "cybersecurity",
      "flair": null,
      "published_at": "2026-10-21T13:55:53Z",
      "author_id": null,
      "author_username": "BattleRemote3157",
      "score": null,
      "upvote_ratio": null,
      "comment_count": null,
      "nsfw": null,
      "spoiler": null,
      "locked": null,
      "stickied": null
    }
  ],
  "pagination": {
    "next_page_token": "pt1.bGl0ZXNjcmFwZTp0M18xeGdvdjV0"
  }
}
```
