> **For coding agents and LLMs:** This is one page from the Social Fetch docs (markdown export). For curated orientation and workflow guidance, start with [`/llms.txt`](https://www.socialfetch.dev/llms.txt); for agent onboarding and crawl rules, use [`/agents.txt`](https://www.socialfetch.dev/agents.txt); for the full endpoint list with links to pages like this one, use [`/llms-endpoints.txt`](https://www.socialfetch.dev/llms-endpoints.txt); for one platform's parameters and curls, use [`/llms-{platform}.txt`](https://www.socialfetch.dev/llms-tiktok.txt); use [`/llms.json`](https://www.socialfetch.dev/llms.json) when you need structured JSON for tool registration.

## This page

- **On-site (HTML):** <https://www.socialfetch.dev/docs/api/v1/query/search/post>
- **Markdown (.mdx) URL:** <https://www.socialfetch.dev/docs/api/v1/query/search/post.mdx>

## API base URL and authentication

- **API origin (from OpenAPI `servers`):** `https://api.socialfetch.dev`
- **Authentication:** send `x-api-key: sfk_...` on `/v1/**` and `/v2/**` routes unless the operation is explicitly anonymous (check OpenAPI `security`, the [API reference hub](https://www.socialfetch.dev/docs/api.mdx), [`/llms.txt`](https://www.socialfetch.dev/llms.txt), or [`/llms.json`](https://www.socialfetch.dev/llms.json) for each route).
- **OpenAPI JSON:** <https://www.socialfetch.dev/openapi.json>

## Recommended docs entrypoints (this site)

- [Documentation overview](https://www.socialfetch.dev/docs.mdx) — top-level orientation (markdown).
- [Quickstart](https://www.socialfetch.dev/docs/quickstart.mdx) — authenticate with `x-api-key`, validate auth with `whoami`, and understand the JSON envelope.
- [SDK](https://www.socialfetch.dev/docs/sdk.mdx) — official TypeScript SDK guide, including `SocialFetchClient`, `Result`, and `unwrap()`.
- [Capability matrix](https://www.socialfetch.dev/docs/capability-matrix.mdx) — every operation with identifiers, pagination, outcomes, media download, credits, and its SDK method. Generated from OpenAPI, so use it for route selection instead of scanning individual pages.
- [Recipes](https://www.socialfetch.dev/docs/recipes.mdx) — copyable workflows (brand monitoring, transcripts, Ad Library, creator scoring, Reddit research) with credit callouts and SDK examples.
- [Integrations](https://www.socialfetch.dev/docs/integrations.mdx) — MCP for AI clients, n8n verified node, Apify Store Actors, Make custom app, SDK, and REST API connection paths.
- [MCP product page](https://www.socialfetch.dev/mcp) — hosted MCP overview, OAuth, Skills install.
- [MCP integration](https://www.socialfetch.dev/docs/integrations/mcp.mdx) — hosted `/mcp` server, OAuth, Cursor/VS Code/Claude install snippets, 910 endpoint tools, plus docs_search/docs_read for implementation help.
- [n8n integration](https://www.socialfetch.dev/docs/integrations/n8n.mdx) — install `n8n-nodes-socialfetch`, credentials, and workflow examples.
- [Apify integration](https://www.socialfetch.dev/docs/integrations/apify.mdx) — Store Actors under @social-fetch, PPE billing, dataset export, and quick start.
- [Make integration](https://www.socialfetch.dev/docs/integrations/make.mdx) — custom app modules for Make scenarios, API key credentials, and module catalog.
- [`/llms-endpoints.txt`](https://www.socialfetch.dev/llms-endpoints.txt) — every documented operation with a direct link to that route's agent-readable markdown page (prefer this over parsing OpenAPI).
- [`/llms-{platform}.txt`](https://www.socialfetch.dev/llms-tiktok.txt) — per-platform endpoint files generated from OpenAPI (parameters, credits, curls).
- [`/agents.txt`](https://www.socialfetch.dev/agents.txt) — agent crawl/onboarding file with capabilities, auth rules, and allowlist.
- [`/llms.json`](https://www.socialfetch.dev/llms.json) — structured machine-readable operation inventory with parameter names, pagination, outcomes, credits, and SDK mapping.
- [API reference hub](https://www.socialfetch.dev/docs/api.mdx) — human-friendly index of operations with links into generated pages.
- [Errors](https://www.socialfetch.dev/docs/errors.mdx) — shared error envelope and HTTP status guidance.
- [Credits](https://www.socialfetch.dev/docs/credits.mdx) — metering, `402`, and planning batch jobs.
- Outcome semantics such as `found`, `not_found`, and `private` are documented in [Errors](https://www.socialfetch.dev/docs/errors.mdx) and on operation pages when present in the OpenAPI contract.

## Markdown docs convention

- Every docs page has a markdown twin: append **`.mdx`** to the docs pathname (for example `/docs/quickstart` → `/docs/quickstart.mdx`).
- Agents that send `Accept: text/markdown` on `/docs/**` HTML URLs may receive markdown directly (same URL, `Vary: Accept`).
- Published blog posts use the same convention: `/blog/{slug}` → `/blog/{slug}.mdx`, or `Accept: text/markdown` on the HTML URL (`Vary: Accept`).

---
# Search with a Boolean query (https://www.socialfetch.dev/docs/api/v1/query/search/post)

## Summary

Search X, Reddit, YouTube, TikTok, LinkedIn, Instagram, Threads and Hacker News live with one Boolean query: each platform is searched in its own syntax,…

**Tags:** `System`

## HTTP

- **Method:** POST
- **Path:** `/v1/query/search`
- **Base URL:** `https://api.socialfetch.dev`

## Capability summary

- **SDK mapping:** HTTP only today
- **Pagination:** none

## Credits

- The searches it runs bill at their normal credit rates
- The searches never spend more than maxCredits; what isn't used isn't charged
- With sentiment, 1 credit per 10 posts given one, on top of maxCredits
- With insights, 1 credit per 10 posts given them, on top of maxCredits
- See meta.creditsCharged for the total

## Authentication

- **`x-api-key`**: API key (`sfk_...`)

## Parameters

### `idempotency-key` (header)

- **Required:** yes
- **Constraints:** type `string`; pattern: `^[\x21-\x7e]{1,255}$`
- **Description:** A key you choose for this search, such as a UUID. A retry with the same key and body returns the first response without charging again, for 24 hours.

## Request body

- **Required:** yes; content type `application/json`

**Shape:**

- **query** (required) — type `string`; minLength: 1; maxLength: 8192. The Boolean query. Check it for free first with POST /v1/query/validate.
- **syntax** (optional) — type `string`; enum: native, x, onclusive, talkwalker, brandwatch, meltwater. Syntax the query is written in: `native` (Social Fetch's Boolean language), or another tool's to import: `x` (X search), `onclusive`, `talkwalker`, `brandwatch` (also Cision Social Listening) or `meltwater`.
- **platforms** (optional) — type `array`. Platforms to search. Every platform when omitted.
  - _items:_
    - type `string`; enum: twitter, reddit, youtube, tiktok, linkedin, instagram, threads, hackernews
- **since** (optional) — type `string`. Earliest post time, between 2000 and 2100. Overrides a date in an imported query.
- **until** (optional) — type `string`. Latest post time, between 2000 and 2100, not before `since`. Overrides a date in an imported query.
- **maxCredits** (required) — type `integer`; minimum: 1; maximum: 10000. The most this search may charge, shared evenly between the platforms with something to search. Held from your balance while it runs; what isn't used is given back.
- **strict** (optional) — type `boolean`. Leave out posts whose match depends on something the platform didn't return (`outcome: unknown`). Default false.
- **sentiment** (optional) — type `boolean`. Estimate each post's sentiment (positive, neutral or negative), for 1 credit per 10 posts given one, on top of maxCredits: the searches still get all of maxCredits, and every post they find with text is given one. Only posts given one are charged. If your balance or the key's monthly limit can't cover it, the posts come back without one and nothing is charged for it, said in warnings. Default false.
- **insights** (optional) — type `object`. Judge each post found: is it about what the topic is about, what is it (a complaint, question, praise, buying, promotion or news), does it need a reply, is it a risk, and up to 3 yes/no questions of your own. 1 credit per 10 posts given them, on top of maxCredits, as sentiment: only posts given insights are charged; if your balance or the key's monthly limit can't cover it, posts come back without them and nothing is charged, said in warnings. Every post is still returned, whatever its relevance. Not available with zero data retention.
  - **about** (required) — type `string`; minLength: 2; maxLength: 200. What the topic is about, in a few words: the name and what it is, so posts using the word another way can be told apart. For example "Notion, the note-taking app" or "Jaguar, the car brand".
  - **questions** (optional) — type `array`. Up to 3 yes/no questions of your own, asked of every post, such as "Does the post mention sizing or fit?". Each post's answers come back in `insights.answers`, in this order.
    - _items:_
      - type `string`; minLength: 5; maxLength: 200
- **noise** (optional) — type `array`. Kinds of post to leave out of the matches, such as job ads. Checked on each post after it's found, so the search itself isn't narrowed and the credits are the same. How many each left out is in `filtered`. None by default.
  - _items:_
    - type `string`; enum: jobs, giveaways, crypto-spam
- **platformSearches** (optional) — type `object`. Searches to run on a platform instead of those planned from the query, by platform. A platform left out is searched as planned. Only changes what's searched: every post is still checked against the whole query.
  - **twitter** (optional) — type `array`. Searches to run on this platform instead of those planned from the query, in its own syntax (Instagram: hashtags, with or without `#`). Posts found are still checked against the whole query.
    - _items:_
      - type `string`; minLength: 1; maxLength: 200
  - **reddit** (optional) — type `array`. Searches to run on this platform instead of those planned from the query, in its own syntax (Instagram: hashtags, with or without `#`). Posts found are still checked against the whole query.
    - _items:_
      - type `string`; minLength: 1; maxLength: 200
  - **youtube** (optional) — type `array`. Searches to run on this platform instead of those planned from the query, in its own syntax (Instagram: hashtags, with or without `#`). Posts found are still checked against the whole query.
    - _items:_
      - type `string`; minLength: 1; maxLength: 200
  - **tiktok** (optional) — type `array`. Searches to run on this platform instead of those planned from the query, in its own syntax (Instagram: hashtags, with or without `#`). Posts found are still checked against the whole query.
    - _items:_
      - type `string`; minLength: 1; maxLength: 200
  - **linkedin** (optional) — type `array`. Searches to run on this platform instead of those planned from the query, in its own syntax (Instagram: hashtags, with or without `#`). Posts found are still checked against the whole query.
    - _items:_
      - type `string`; minLength: 1; maxLength: 200
  - **instagram** (optional) — type `array`. Searches to run on this platform instead of those planned from the query, in its own syntax (Instagram: hashtags, with or without `#`). Posts found are still checked against the whole query.
    - _items:_
      - type `string`; minLength: 1; maxLength: 200
  - **threads** (optional) — type `array`. Searches to run on this platform instead of those planned from the query, in its own syntax (Instagram: hashtags, with or without `#`). Posts found are still checked against the whole query.
    - _items:_
      - type `string`; minLength: 1; maxLength: 200
  - **hackernews** (optional) — type `array`. Searches to run on this platform instead of those planned from the query, in its own syntax (Instagram: hashtags, with or without `#`). Posts found are still checked against the whole query.
    - _items:_
      - type `string`; minLength: 1; maxLength: 200

**Example:**

```json
{
  "query": "string",
  "maxCredits": 0
}
```

## Responses (status codes)

- **200**: What the query matched, and how far the search got on each platform. A search that ran out of time returns what finished, with status 200. A retry with the same Idempotency-Key and body returns this response again, with `Idempotent-Replayed: true`, and charges nothing.
- **400**: Malformed request, a missing or malformed Idempotency-Key, a query that can't be read (validate it first), or a time window a search can't use.
- **401**: Missing or invalid API key
- **402**: The balance can't cover `maxCredits`, or the API key's monthly limit can't. Nothing was charged.
- **409**: The Idempotency-Key's first search is still running (`reason: in_progress`), or it ran and its response wasn't kept to return (`reason: not_kept`, such as under zero retention). Nothing was charged.
- **422**: The Idempotency-Key was used with a different request. Nothing was charged.
- **500**: Unexpected error
- **503**: Too many requests in progress for this account, or a stored first response couldn't be read just now. Retry with the same Idempotency-Key.

## Response body (200)

What the query matched, and how far the search got on each platform. A search that ran out of time returns what finished, with status 200. A retry with the same Idempotency-Key and body returns this response again, with `Idempotent-Replayed: true`, and charges nothing.

### Field outline

- **data** (required) — type `object`. Endpoint-specific response payload.
  - **normalizedQuery** (required) — type `string`. The query searched, in Social Fetch's syntax.
  - **mentions** (required) — type `array`. What the query matched, across platforms. A post found twice is listed once; a repost or near-copy of another post is listed too, naming it in `duplicateOf`.
    - _items:_
      - **key** (required) — type `string`. `platform:id`, unique across platforms, such as `twitter:123`.
      - **platform** (required) — type `string`; enum: twitter, reddit, youtube, tiktok, linkedin, instagram, threads, hackernews. A platform a search runs on: `twitter` (X), `reddit`, `youtube`, `tiktok`, `linkedin`, `instagram` (searched by hashtag, so only posts that use the hashtag are found), `threads` (searched by plain words, one short page a search, so it can miss posts) or `hackernews` (stories and comments). More platforms follow.
      - **id** (required) — type `string`. The post's id on its platform.
      - **url** (required) — type `string`; nullable. The post's link.
      - **title** (required) — type `string`; nullable. A separate title (a Reddit post's); null when the platform has none.
      - **texts** (required) — type `array`. Each text field, the main one first. Fields are matched one at a time, so a phrase never runs from one into the next.
        - _items:_
      - **text** (required) — type `string`. The main text, for display.
      - **evaluatedFields** (required) — type `array`. The fields the query was checked against.
        - _items:_
          - type `string`
      - **createdAt** (required) — type `string`; nullable. When it was posted, ISO 8601 in UTC.
      - **createdAtIsEstimate** (required) — type `boolean`. True when the platform gave the time only roughly ("3 days ago"), so a date window can be off.
      - **author** (required) — type `object`; nullable
      - **community** (required) — type `object`; nullable. The subreddit, channel or group it was posted in.
      - **language** (required) — type `string`; nullable. Lower case, such as `en` or `es-mx`.
      - **languageIsDetected** (required) — type `boolean`. True when the language was detected from the text, because the platform didn't give one.
      - **country** (required) — type `string`; nullable
      - **types** (required) — type `array`; nullable. Every type the post is (a reply can also quote); null when the platform doesn't say.
        - _items:_
          - type `string`
      - **thread** (required) — type `object`. Where it sits in a conversation, by the platform's own ids.
      - **metrics** (required) — type `object`
      - **reach** (required) — type `object`; nullable. How many people it could reach, and what that's based on.
      - **hashtags** (required) — type `array`. Without #.
        - _items:_
          - type `string`
      - **mentions** (required) — type `array`. Accounts mentioned, without @.
        - _items:_
          - type `string`
      - **links** (required) — type `array`. Links in the post, beyond its own.
        - _items:_
          - type `string`
      - **matchedFrom** (required) — type `array`. Which of our operations found it, such as `twitter.search.list`.
        - _items:_
          - type `string`
      - **outcome** (required) — type `string`; enum: match, unknown. `unknown` when the match depends on something the platform didn't return (see `unevaluableFields`).
      - **matchedTerms** (required) — type `array`. The query's terms found in it.
        - _items:_
          - type `string`
      - **unevaluableFields** (required) — type `array`. The fields its match depends on that couldn't be checked.
        - _items:_
          - type `string`
      - **categories** (required) — type `array`. The query's categories it falls in.
        - _items:_
          - type `string`
      - **uncertainCategories** (required) — type `array`. Categories that depend on something the platform didn't return.
        - _items:_
          - type `string`
      - **duplicateOf** (required) — type `object`; nullable. The post this one repeats, and why; null for a story's first or only post. Nothing is left out: group a post under the one it names to show each story once. Worked out over one search's posts: in a search's response the named post is in the same list. A saved query's matches keep what the run that first found them worked out, so the named post may be on another page, outside a filter, itself a repeat of an earlier post, or past its retention.
      - **sentiment** (optional) — type `object`. The feeling the post expresses, when sentiment was asked for and the post got one.
      - **insights** (optional) — type `object`. How the post was judged, when insights were asked for and the post got them.
  - **filtered** (required) — type `object`. How many matches each requested `noise` preset left out, each post once (zero when it left out none). Empty when none were requested.
    - **jobs** (optional) — type `integer`; minimum: 0
    - **giveaways** (optional) — type `integer`; minimum: 0
    - **crypto-spam** (optional) — type `integer`; minimum: 0
  - **platforms** (required) — type `array`
    - _items:_
      - **platform** (required) — type `string`; enum: twitter, reddit, youtube, tiktok, linkedin, instagram, threads, hackernews. A platform a search runs on: `twitter` (X), `reddit`, `youtube`, `tiktok`, `linkedin`, `instagram` (searched by hashtag, so only posts that use the hashtag are found), `threads` (searched by plain words, one short page a search, so it can miss posts) or `hackernews` (stories and comments). More platforms follow.
      - **status** (required) — type `string`; enum: exhausted, capped, budget, deadline, unsearchable, failed. How far it got: `exhausted`, every search ran to its last page; `capped`, the platform's own limit on pages stopped it; `budget`, `maxCredits` did; `deadline`, the search ran out of time (what finished is returned); `unsearchable`, nothing in the query can be searched there; `failed`, every call failed.
      - **coverage** (required) — type `string`; enum: full, partial, none. `full`: every part of the query was searched; `partial`: some can't be (see notes); `none`: nothing could.
      - **notes** (required) — type `array`. What wasn't covered, and why.
        - _items:_
          - type `string`
      - **searchTerms** (required) — type `array`. What was searched, in the platform's own syntax.
        - _items:_
          - type `string`
      - **fetched** (required) — type `integer`; minimum: 0. Posts read.
      - **matched** (required) — type `integer`; minimum: 0. Posts the query matched, not counting those `filtered` left out.
      - **filtered** (required) — type `integer`; minimum: 0. Posts the query matched that the request's `noise` presets left out.
      - **creditsCharged** (required) — type `integer`; minimum: 0
      - **errors** (required) — type `object`. Error codes of calls that failed, with how many.
      - **unevaluableFields** (required) — type `array`. Fields the query uses that this platform doesn't return.
        - _items:_
          - type `string`
  - **warnings** (required) — type `array`. Plain-language cautions, most important first.
    - _items:_
      - type `string`
- **meta** (required) — type `object`. Metadata describing the request and billing outcome.
  - **requestId** (required) — type `string`; minLength: 1. Unique request identifier for tracing this API call.
  - **creditsCharged** (required) — type `integer`; minimum: 0. Credits charged for this request.
  - **version** (required) — type `string`; enum: v1. Public API version that served the response.

### Example JSON (OpenAPI example)

```json
{
  "data": {
    "normalizedQuery": "(\"social fetch\" OR socialfetch) AND (api OR scraping) AND NOT hiring",
    "mentions": [
      {
        "key": "twitter:1985402761553920115",
        "platform": "twitter",
        "id": "1985402761553920115",
        "url": "https://x.com/devnotes/status/1985402761553920115",
        "title": null,
        "texts": [
          {
            "field": "text",
            "text": "Switched our listening pipeline to the Social Fetch API this week. One Boolean query across X and Reddit, scraping handled for us."
          }
        ],
        "text": "Switched our listening pipeline to the Social Fetch API this week. One Boolean query across X and Reddit, scraping handled for us.",
        "evaluatedFields": [
          "text"
        ],
        "createdAt": "2026-11-05T14:21:07.000Z",
        "createdAtIsEstimate": false,
        "author": {
          "id": null,
          "handle": "devnotes",
          "name": "Dev Notes",
          "followers": null,
          "verified": false
        },
        "community": null,
        "language": "en",
        "languageIsDetected": false,
        "country": null,
        "types": [
          "post"
        ],
        "thread": {
          "parentId": null,
          "conversationId": "1985402761553920115",
          "quotedId": null,
          "repostedId": null
        },
        "metrics": {
          "likes": 42,
          "views": 3120,
          "comments": 5,
          "shares": 7
        },
        "reach": {
          "estimate": 3120,
          "basis": "views"
        },
        "hashtags": [],
        "mentions": [],
        "links": [],
        "matchedFrom": [
          "twitter.search.list"
        ],
        "outcome": "match",
        "matchedTerms": [
          "social fetch"
        ],
        "unevaluableFields": [],
        "categories": [],
        "uncertainCategories": [],
        "duplicateOf": null
      }
    ],
    "filtered": {
      "jobs": 1,
      "giveaways": 0
    },
    "platforms": [
      {
        "platform": "twitter",
        "status": "exhausted",
        "coverage": "full",
        "notes": [],
        "searchTerms": [
          "(\"social fetch\" OR socialfetch) (api OR scraping) -hiring"
        ],
        "fetched": 14,
        "matched": 1,
        "filtered": 1,
        "creditsCharged": 2,
        "errors": {},
        "unevaluableFields": []
      }
    ],
    "warnings": []
  },
  "meta": {
    "requestId": "req_01JBX0Q9Z6Y0V2Q5Q2E0Y5K8H4",
    "creditsCharged": 4,
    "version": "v1"
  }
}
```

### Machine-readable error codes

When an error JSON body is returned, it may include one of these `error.code` values (derived from the OpenAPI schemas for this operation; additional codes may exist at runtime):

- `bad_request`

## Error handling & retries

Interpret HTTP status codes using the descriptions below. Do not assume a JSON body unless the OpenAPI schema defines one for that status.

- **400**: Malformed request, a missing or malformed Idempotency-Key, a query that can't be read (validate it first), or a time window a search can't use. **Retry:** Fix the request; retrying the same invalid payload will not help.
- **401**: Missing or invalid API key **Retry:** Fix the API key first; retrying without changes will not help.
- **402**: The balance can't cover `maxCredits`, or the API key's monthly limit can't. Nothing was charged. **Retry:** Do not retry without resolving billing/credits (retrying the same request will not help).
- **409**: The Idempotency-Key's first search is still running (`reason: in_progress`), or it ran and its response wasn't kept to return (`reason: not_kept`, such as under zero retention). Nothing was charged.
- **422**: The Idempotency-Key was used with a different request. Nothing was charged.
- **500**: Unexpected error
- **503**: Too many requests in progress for this account, or a stored first response couldn't be read just now. Retry with the same Idempotency-Key. **Retry:** Usually safe to retry with exponential backoff and jitter.

### Suggested client defaults

- Send the API key using the `x-api-key` header on every request.
- On `503` (and sometimes `502`), retry with backoff; cap retries and surface a clear error to the user.
- On `402`, surface an actionable billing message rather than blind retries.