URL: /code/data/social/find-posts · Id: `page:/code/data/social/find-posts`

# Post.find

> Read the public posts on one Venue that use a term, newest or top first, with each author, community and how far it spread.

POST https://api.sb/&#123;your-domain&#125;/posts/find

Read the public posts on one Venue that use a term, newest or top first, with each author, community and how far it spread.

- **Price:** 19¢ per 100 searches
- **Success rate:** 99.4% of 147,547 calls
- **Freshness:** Fresh for 1 day
- **Emits:** `Post.found`

```text title="Run it · Ask"
Who on Reddit is asking how to track rent without a spreadsheet this month? Spend up to 1¢.
```

```ts title="Run it · SDK"
import { $ } from 'startup-builder'

const result = await $.try.Post.find({ term: 'track rent spreadsheet', venue: 'reddit', within: '30d', sort: 'new', maxCost: 0.01 })
```

```json title="Run it · Response"
{
  "term": "track rent spreadsheet",
  "venue": "reddit",
  "posts": [
    {
      "venue": "reddit",
      "url": "https://www.reddit.com/r/Landlord/comments/1kq9",
      "kind": "post",
      "title": "What do you use to track rent for 40 units?",
      "text": "Spreadsheet is falling apart and renewal notices keep slipping. What do you all use?",
      "author": {
        "handle": "u/fourplexfred",
        "url": "https://www.reddit.com/user/fourplexfred"
      },
      "community": "r/Landlord",
      "publishedAt": "2026-10-25T16:40:00Z",
      "engagement": {
        "score": 48,
        "comments": 31
      },
      "observedAt": "2026-10-27T14:02:11Z",
      "method": "sampled"
    }
  ],
  "after": "post_t3_1kq9",
  "total": null,
  "cost": {
    "usd": 0,
    "maxUsd": 0.0019,
    "units": 1,
    "misses": 0
  }
}
```

## Inputs
| Name | Type | Meaning | Price |
| --- | --- | --- | --- |
| `term` | `string` | The words to look for, as a buyer writes them: `track rent spreadsheet`, not `rent tracking software`. Quote a phrase to match it exactly. Required. | Included |
| `venue` | `'reddit' \| 'x' \| 'hacker-news' \| 'linkedin' \| 'youtube' \| 'tiktok' \| 'instagram' \| 'facebook' \| 'stack-overflow' \| 'github'` | Where to read. Every Venue returns the same row; On each Venue says which fields each one fills. Default `'reddit'`. | Included |
| `venue: 'reddit'` | Option | Posts on Reddit | About 19¢ per 100 searches; works 99.4% of 147,547 calls |
| `venue: 'x'` | Option | Posts on X | About 8¢ per 100 searches; works 85.8% of 164,875 calls |
| `venue: 'hacker-news'` | Option | Posts on Hacker News | About 1.5¢ per 100 searches; works 100% of 1,661 calls |
| `venue: 'linkedin'` | Option | Posts on LinkedIn | About 20¢ per 100 searches; works 99.5% of 68,307 calls |
| `venue: 'youtube'` | Option | Posts on YouTube | About 10¢ per 100 searches; works 96.6% of 23,942 calls |
| `venue: 'tiktok'` | Option | Posts on TikTok | About 10¢ per 100 searches; works 99.8% of 37,404 calls |
| `venue: 'instagram'` | Option | Posts on Instagram | About 15¢ per 100 searches; works 99.93% of 21,215 calls |
| `venue: 'facebook'` | Option | Posts on Facebook | About $2.95 per 100 searches; works 99.7% of 8,361 calls |
| `venue: 'stack-overflow'` | Option | Posts on Stack Overflow | About 1.5¢ per 100 searches; works 100% of 9 calls |
| `venue: 'github'` | Option | Issues on one GitHub repository | About 1.5¢ per 100 searches; works 100% of 82 calls |
| `community` | `string` | One subreddit (`r/Landlord`), Stack Overflow tag, Instagram hashtag or GitHub repository (`owner/name`). Required on GitHub. | Included |
| `kinds` | `('post' \| 'comment')[]` | Add `comment` to read replies that use the term too, on Reddit, X and Hacker News. Default `['post']`. | Included |
| `within` | `string` | How far back to read: `24h`, `7d`, `30d`, `90d`, `1y`. Default `'30d'`. | Included |
| `sort` | `'relevance' \| 'new' \| 'top'` | `new` for a daily listening run, `top` to find the threads buyers already trust. Default `'relevance'`. | Included |
| `exclude` | `string[]` | Authors to leave out: your own accounts, so a mention you wrote never counts. Default `your Handles`. | Included |
| `limit` | `number` | Rows a page, at most 100. You pay for rows returned, never rows asked for. Default `25`. | Included |
| `after` | [`Cursor`](/code/data/types#cursor) | The cursor from the last page. | Included |
| `maxAge` | `string` | A stored reading younger than this returns at $0 instead of reading again. Default `'1d'`. | Included |
| `maxCost` | `number` | The most this call may spend, in USD. Over it, the call is refused before it spends, or stops early with what it has. Default `0.05`. | Included |

## Outputs
| Field | Type | What `null` means | What it means |
| --- | --- | --- | --- |
| `term` | `string` | Never null: the term as sent. | None. |
| `venue` | [`VenueId`](/code/data/types#venueid) | Never null: the Venue read. | None. |
| `posts` | `FoundPost[]` | Never null: empty when no post used the term in `within`, at $0. | `post` with 10 or more comments in 30 days: Buyers are asking about the problem in public right now. Answer the thread with a sourced reply, not a pitch, and read its commenters with `Post.findEngagers`. *Planning estimate.*<br />`score` under 5 after 24 hours: The thread did not travel; a reply there reaches the asker and few others. Answer it if the asker fits your customer; otherwise wait for a thread that did. *Planning estimate.*<br />One community holds a third of the rows: That is where your buyers talk. Read its rules before posting, and run `Post.find` with `community` set daily. *Planning estimate.* |
| `posts[].url` | `string` | Never null: the post’s own link. | None. |
| `posts[].kind` | `'post' \| 'comment' \| 'video' \| 'question' \| 'issue'` | Never null: `video` on YouTube, TikTok and Instagram, `question` on Stack Overflow, `issue` on GitHub. | None. |
| `posts[].title` | `string \| null` | The Venue gives posts no title: X, LinkedIn, TikTok, Instagram and comments. | None. |
| `posts[].text` | `string \| null` | A link post or a video with no caption. | None. |
| `posts[].author` | `{ handle: string; url: string \| null } \| null` | The account was deleted or is hidden. | None. |
| `posts[].community` | `string \| null` | The Venue has no communities, or the post sits in none. | None. |
| `posts[].publishedAt` | `string \| null`, in ISO 8601 | The Venue shows no date. | None. |
| `posts[].engagement` | `{ score?: number; reactions?: number; comments?: number; shares?: number; views?: number }` | Never null. A count is absent where the Venue does not show it, never zero: LinkedIn shows no views. | None. |
| `posts[]` | [`Observed`](/code/data/types#observed) | Each row also carries `observedAt`, `method` and `venue`. | None. |
| `after` | [`Cursor`](/code/data/types#cursor) | The last page: there are no more rows. | None. |
| `total` | `number \| null`, in posts | The Venue reports no total; most do not. | None. |
| `cost` | [`Cost`](/code/data/types#cost), in USD | Never null. In try mode `usd` is 0 and `maxUsd` is what the call would have cost. | None. |

### On each Venue
| Venue | What comes back | Limits | Price |
| --- | --- | --- | --- |
| Reddit | Posts and, with `kinds`, comments; `community` is the subreddit; `score` and `comments`, no views. | Newest 1,000 posts a term; `community` narrows to one subreddit. | About 19¢ per 100 searches |
| X | Posts and replies; `reactions` (likes), `shares` (reposts), `comments` and `views`. | The last 7 days on the first route; older posts come back only from the second route. | About 8¢ per 100 searches |
| Hacker News | Stories and comments; `score` and `comments`; `community` is null. | Full history; `sort: top` reads by points. | About 1.5¢ per 100 searches |
| LinkedIn | Member and company posts; `reactions`, `comments` and `shares`; no views. | Posts only, never comments; `within` up to 90 days. | About 20¢ per 100 searches |
| YouTube | Videos, `kind: video`; `title` and description, `views`, `reactions` and `comments`. | Search order is the Venue’s own; `sort: new` reads upload date. | About 10¢ per 100 searches |
| TikTok | Videos, `kind: video`; caption as `text`, `views`, `reactions`, `comments` and `shares`. | Captions only: what is said in the video is not searched. | About 10¢ per 100 searches |
| Instagram | Reels, `kind: video`; caption as `text`, `views`, `reactions` and `comments`. | Reels only: photo posts are reached by hashtag, through `community`. | About 15¢ per 100 searches |
| Facebook | Public posts from pages and public groups; `reactions`, `comments` and `shares`. | Public posts only, never private groups; the dearest Venue at about 3¢ a search. | About $2.95 per 100 searches |
| Stack Overflow | Questions, `kind: question`; `score`, `comments` (answers) and `views`; `community` is the tag. | Questions by tag and term. | About 1.5¢ per 100 searches |
| GitHub | Issues on one repository, `kind: issue`; `comments` and `reactions`. | One repository a call, named in `community` as `owner/name`. | About 1.5¢ per 100 searches |

## Effects
**Action class**

None: it reads, so no approval rule names it

**Modes**

- `try`: Runs the read and returns real rows; nothing is saved and nothing is billed.
- `send`: Returns a pending Action at once; its Event carries the rows when the read finishes.
- `do`: Waits for the read and returns the rows, billed per result.

**Idempotency**

The same `Idempotency-Key` with the same input replays the first answer at $0; with other input it returns 409.

**Saved or shared**

Nothing is written to your records. A search is shared across startups for the same term, Venue and window for a day; it reads public posts only.

**Emits**

`Post.found` with `{ term, venue, posts, total }`

**Performed by**

[Marketing lead](https://startupbuilder.dev/agents/marketing/marketing-lead)

**Price**

About 19¢ per 100 searches. At most $2.95 per 100 searches. Free: a search read younger than `maxAge`, a search that finds no posts. `maxCost` defaults to 5¢. A daily listening run on 3 Venues for a month: 90 × 0.19¢ a search is about 17¢.

**Reliability**

The first route succeeds 99.4% of 147,547 calls. If it fails, the call refuses with `sources-busy` and nothing is spent.

**Freshness**

A reading younger than 1 day returns at $0. Readings are shared across startups for the same subject and locale.

**Batch and pages**

Up to 100 posts a page. Pages of 25 rows by default, 100 at most; pass `after` for the next page. It answers in one response.

**Rate**

[The shared rate rules](/code/data#rate): 10 calls a second per key, and an array input counts as one call.

**Capability**

[Market data](https://startupbuilder.dev/systems/marketing/market-data)

## Refuses when
| Check | Error | Fix | Then call |
| --- | --- | --- | --- |
| A search engine, answer engine or network the call does not read, such as ChatGPT sent to `Keyword.measure` | [`venue-unsupported`](/code/refusals#venue-unsupported) | Pick one the call’s `venue` input lists; AI answers are `Keyword.ask`, posts are `Keyword.search`. | [`Keyword.ask`](/code/data/keywords/ask) |

Every data call can also meet [the shared data-call refusals](/code/refusals#data-calls): [`filter-unsupported`](/code/refusals#filter-unsupported), [`input-missing`](/code/refusals#input-missing), [`limit-exceeded`](/code/refusals#limit-exceeded), [`max-cost`](/code/refusals#max-cost), [`rate-limited`](/code/refusals#rate-limited), [`sources-busy`](/code/refusals#sources-busy).

```json
{
  "type": "https://startupbuilder.dev/errors/venue-unsupported",
  "title": "The call does not read that search engine or network",
  "status": 422,
  "detail": "A search engine, answer engine or network the call does not read, such as ChatGPT sent to `Keyword.measure`.",
  "fix": "Pick one the call’s `venue` input lists; AI answers are `Keyword.ask`, posts are `Keyword.search`.",
  "next": {
    "verb": "Keyword.ask",
    "input": {
      "keyword": "best rent tracking software for a 40-unit property manager",
      "venues": [
        "chatgpt"
      ]
    }
  },
  "instance": "https://api.sb/leaseline.app/actions/action_1"
}
```

## When it waits
Returns in one response; nothing waits.

## Example
The same term on Hacker News: one row shape on every Venue, so the code that reads Reddit reads this too. Hacker News fills `score` and `comments` and leaves `community` null.

**Ask**

```text
Has anyone on Hacker News asked how to track rent for a small portfolio
in the last year? Spend up to 1¢.
```

**API**

```bash
curl -X POST "https://api.sb/leaseline.app/posts/find?mode=try" \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "term": "rent tracking landlord",
  "venue": "hacker-news",
  "within": "1y",
  "sort": "top",
  "limit": 1,
  "maxCost": 0.01
}'
```

**CLI**

```bash
npx startup-builder do Post.find --data '{
  "term": "rent tracking landlord",
  "venue": "hacker-news",
  "within": "1y",
  "sort": "top",
  "limit": 1,
  "maxCost": 0.01
}'
```

The CLI runs in try mode unless you pass `--do`.

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "mode": "try",
    "code": "return await $.Post.find({ term: 'rent tracking landlord', venue: 'hacker-news', within: '1y', sort: 'top', limit: 1, maxCost: 0.01 })"
  }
}
```

**SDK**

```ts
import { $ } from 'startup-builder'

const result = await $.try.Post.find({
  term: 'rent tracking landlord',
  venue: 'hacker-news',
  within: '1y',
  sort: 'top',
  limit: 1,
  maxCost: 0.01,
})
```


```json title="Response, in try mode"
{
  "term": "rent tracking landlord",
  "venue": "hacker-news",
  "posts": [
    {
      "venue": "hacker-news",
      "url": "https://news.ycombinator.com/item?id=41022817",
      "kind": "post",
      "title": "Ask HN: How do small landlords track rent and renewals?",
      "text": null,
      "author": {
        "handle": "brickandledger",
        "url": "https://news.ycombinator.com/user?id=brickandledger"
      },
      "community": null,
      "publishedAt": "2026-03-11T14:22:00Z",
      "engagement": {
        "score": 112,
        "comments": 87
      },
      "observedAt": "2026-10-27T14:02:11Z",
      "method": "sampled"
    }
  ],
  "after": "post_hn_41022817",
  "total": null,
  "cost": {
    "usd": 0,
    "maxUsd": 0.00015,
    "units": 1,
    "misses": 0
  }
}
```

To retry, send the same `Idempotency-Key`: the retry returns the first answer for $0. A new key reads again.

A `sk_test_` key answers these the same way every time, at $0 ([every test value](/code/checks#test-values)).

| Test value | Always returns | What it is for |
| --- | --- | --- |
| `term: 'track rent spreadsheet', venue: 'reddit'` | `{"posts":[{"url":"https://www.reddit.com/r/Landlord/comments/1kq9","community":"r/Landlord","engagement":{"score":48,"comments":31}}]}` | Returns the same r/Landlord thread every time, so a listening Workflow’s next step runs on a known row. |
| `maxCost: 0.0001` | Refuses with [`max-cost`](/code/refusals#max-cost) | Any priced call with a maxCost of 0.0001 is refused before it spends: the price is above the cap. |
| `rate-limited.test` | Refuses with [`rate-limited`](/code/refusals#rate-limited) | Any call naming this hostname answers 429 with Retry-After, so your retry logic runs. |
| `sources-busy.test` | Refuses with [`sources-busy`](/code/refusals#sources-busy) | Any call naming this hostname answers 503 as if every route were busy, and nothing is spent. |

Watch it on a schedule: a Monitor runs this call and records an Event only when the reading changes.

```ts
await $.Monitor.create({
  verb: 'Post.find',
  input: { term: 'track rent spreadsheet', venue: 'reddit', sort: 'new' },
  change: 'new-post',
  every: '1d',
})
```

## Used by
- **Workflows:** [Post-engager harvest](/capabilities/find-customers/post-engagers)
- **Agent tasks:** [Answer threads](/capabilities/publish-and-post/answer-threads) · [Launch day](/capabilities/earn-first-links/launch-day) · [Account brief](/capabilities/reach-out/account-brief) · [Message test](/capabilities/run-ads/message-test)
- **Jobs:** [Publish and post](/capabilities/publish-and-post) · [Research demand](/capabilities/research-demand)

## Related
[`Post.findEngagers`](/code/data/social/find-engagers) · [`Handle.find`](/code/data/social/find-handles) · [`Handle.measure`](/code/data/social/measure-handles)