reddit.search. The transport rules that apply to every API a seller serves - signed requests, the response envelope, timeouts, and body limits - are on the operator endpoint contract.
The price you compete with
AnyAPI publishes this API from $0.35 per 1,000 requests. That is the price a buyer sees today, so it is the price your endpoint has to come in under to win traffic.The request your endpoint receives
| Field | Type | Required | What it means |
|---|---|---|---|
cursor | string | no | Opaque pagination cursor from a previous response’s nextCursor. Omit for the first page; pass it to fetch the next page of results. Include nextCursor in requireFields on the first request to make sure a source that supports pagination serves it. |
query | string | yes | Free-text search across all of Reddit. Reddit’s field operators are supported inside the string: subreddit:<name> to scope to one subreddit, author:<user>, title:<text>, selftext:<text>, self:yes|no, nsfw:yes|no, and boolean AND/OR/NOT. To restrict to a single subreddit you can use subreddit:<name> here, or use the reddit.subreddit_posts SKU for a plain subreddit listing. |
requireFields | array | no | Optional; omit it and routing is unchanged, with the cheapest source serving. Name the output fields this request must be able to return, for example nextCursor or media, and it is served only by a source that returns every one of them. Fields you do not name are still returned whenever the serving source has them. This can raise your price: when the cheapest source cannot return a named field, a dearer source serves, and you are quoted and charged its price. Name nextCursor only if you will fetch more than the first page: when you leave it out, a cheaper source that cannot paginate may serve the request, and its nextCursor is null, so there is no next page to ask for. A named field can still be absent on a post that genuinely lacks it. Naming a combination that no single source returns together is refused as invalid input, with no charge. On a paginated walk it applies to the first page only; later pages stay with the source that page chose, at the price it was quoted. |
sort | string | no | Result sort order. One of: relevance, hot, top, new, comments. |
timeframe | string | no | Time window for results. One of: hour, day, week, month, year, all. |
Full input JSON Schema
Full input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://getanyapi.com/schemas/reddit.search.input.json",
"example": {
"query": "mechanical keyboard"
},
"title": "Reddit search input",
"type": "object",
"additionalProperties": false,
"x-aliases": {
"time": "timeframe",
"time_filter": "timeframe",
"q": "query"
},
"required": [
"query"
],
"properties": {
"query": {
"type": "string",
"description": "Free-text search across all of Reddit. Reddit's field operators are supported inside the string: subreddit:<name> to scope to one subreddit, author:<user>, title:<text>, selftext:<text>, self:yes|no, nsfw:yes|no, and boolean AND/OR/NOT. To restrict to a single subreddit you can use subreddit:<name> here, or use the reddit.subreddit_posts SKU for a plain subreddit listing."
},
"sort": {
"type": "string",
"enum": [
"relevance",
"hot",
"top",
"new",
"comments"
],
"description": "Result sort order."
},
"timeframe": {
"type": "string",
"enum": [
"hour",
"day",
"week",
"month",
"year",
"all"
],
"description": "Time window for results."
},
"cursor": {
"type": "string",
"description": "Opaque pagination cursor from a previous response's nextCursor. Omit for the first page; pass it to fetch the next page of results. Include `nextCursor` in requireFields on the first request to make sure a source that supports pagination serves it."
},
"requireFields": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string",
"enum": [
"isArchived",
"isLocked",
"media",
"nextCursor"
]
},
"description": "Optional; omit it and routing is unchanged, with the cheapest source serving. Name the output fields this request must be able to return, for example `nextCursor` or `media`, and it is served only by a source that returns every one of them. Fields you do not name are still returned whenever the serving source has them. This can raise your price: when the cheapest source cannot return a named field, a dearer source serves, and you are quoted and charged its price. Name `nextCursor` only if you will fetch more than the first page: when you leave it out, a cheaper source that cannot paginate may serve the request, and its nextCursor is null, so there is no next page to ask for. A named field can still be absent on a post that genuinely lacks it. Naming a combination that no single source returns together is refused as invalid input, with no charge. On a paginated walk it applies to the first page only; later pages stay with the source that page chose, at the price it was quoted."
}
}
}
The response your endpoint must return
| Field | Type | Always present | What it means |
|---|---|---|---|
data | null or object | yes | |
data.nextCursor | string or null | yes | Opaque cursor for the next page of posts, or null when this lane has no more. Pass it back as cursor to continue. |
data.posts | array | yes | |
data.posts[].author | string | yes | Author username, without the u/ prefix. Empty when the upstream omits it. |
data.posts[].authorId | string | no | Reddit account ID of the author, without the t2_ prefix. |
data.posts[].createdUtc | number | yes | UTC epoch timestamp in seconds (Unix time). Multiply by 1000 for a JS Date in milliseconds. |
data.posts[].id | string | yes | Reddit post ID (base-36, without the t3_ prefix). |
data.posts[].isArchived | boolean | no | True when Reddit has archived the thread, which blocks new comments and votes. Archiving is a per-community setting, so an old thread is not necessarily archived. Absent when the source that served this request does not report it, which means unknown rather than false. |
data.posts[].isLocked | boolean | no | True when a moderator has locked the thread, which blocks new comments. Absent when the source that served this request does not report it, which means unknown rather than false. |
data.posts[].media | array | no | Photo, video, and GIF attachments on the post. Empty when the post has none. |
data.posts[].media[].height | integer | no | |
data.posts[].media[].type | string | yes | One of photo, video, or gif. |
data.posts[].media[].url | string | yes | Image URL. For a video or GIF this is the poster/thumbnail frame. |
data.posts[].media[].videoUrl | string | no | Playable video file URL. Present only for video and gif items. |
data.posts[].media[].width | integer | no | |
data.posts[].nsfw | boolean | no | Whether the post is marked not-safe-for-work. |
data.posts[].numComments | integer | yes | Total number of comments on the post. |
data.posts[].permalink | string | yes | Canonical reddit.com thread path for the post (e.g. “/r/golang/comments/abc123/…”). Differs from url, which is the destination link. Empty if the upstream omits it. |
data.posts[].score | integer | yes | Net score (upvotes minus downvotes) at fetch time. |
data.posts[].selftext | string | no | Body text of a self post, as Markdown. Empty on a link post, which has no body. |
data.posts[].subreddit | string | yes | Subreddit name, without the r/ prefix. |
data.posts[].title | string | yes | Post title. |
data.posts[].url | string | yes | The post’s destination link (the external URL for link posts, or the thread URL for self posts). |
found | boolean | yes |
Full output JSON Schema
Full output JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://getanyapi.com/schemas/reddit.search.output.json",
"title": "Reddit search output",
"type": "object",
"additionalProperties": false,
"required": [
"found",
"data"
],
"properties": {
"found": {
"type": "boolean"
},
"data": {
"oneOf": [
{
"type": "null"
},
{
"type": "object",
"additionalProperties": false,
"required": [
"posts",
"nextCursor"
],
"properties": {
"posts": {
"x-anyapi-must-populate": true,
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"title",
"author",
"score",
"numComments",
"url",
"permalink",
"createdUtc",
"subreddit"
],
"properties": {
"id": {
"x-anyapi-must-populate": true,
"type": "string",
"description": "Reddit post ID (base-36, without the t3_ prefix)."
},
"title": {
"x-anyapi-must-populate": true,
"type": "string",
"description": "Post title."
},
"author": {
"type": "string",
"description": "Author username, without the u/ prefix. Empty when the upstream omits it."
},
"score": {
"type": "integer",
"description": "Net score (upvotes minus downvotes) at fetch time."
},
"numComments": {
"type": "integer",
"description": "Total number of comments on the post."
},
"url": {
"x-anyapi-must-populate": true,
"type": "string",
"description": "The post's destination link (the external URL for link posts, or the thread URL for self posts)."
},
"permalink": {
"x-anyapi-must-populate": true,
"type": "string",
"description": "Canonical reddit.com thread path for the post (e.g. \"/r/golang/comments/abc123/...\"). Differs from url, which is the destination link. Empty if the upstream omits it."
},
"createdUtc": {
"type": "number",
"description": "UTC epoch timestamp in seconds (Unix time). Multiply by 1000 for a JS Date in milliseconds."
},
"subreddit": {
"x-anyapi-must-populate": true,
"type": "string",
"description": "Subreddit name, without the r/ prefix."
},
"isArchived": {
"type": "boolean",
"description": "True when Reddit has archived the thread, which blocks new comments and votes. Archiving is a per-community setting, so an old thread is not necessarily archived. Absent when the source that served this request does not report it, which means unknown rather than false."
},
"isLocked": {
"type": "boolean",
"description": "True when a moderator has locked the thread, which blocks new comments. Absent when the source that served this request does not report it, which means unknown rather than false."
},
"selftext": {
"type": "string",
"description": "Body text of a self post, as Markdown. Empty on a link post, which has no body."
},
"media": {
"type": "array",
"description": "Photo, video, and GIF attachments on the post. Empty when the post has none.",
"items": {
"type": "object",
"required": [
"type",
"url"
],
"properties": {
"type": {
"type": "string",
"description": "One of photo, video, or gif."
},
"url": {
"type": "string",
"format": "uri",
"description": "Image URL. For a video or GIF this is the poster/thumbnail frame."
},
"videoUrl": {
"type": "string",
"format": "uri",
"description": "Playable video file URL. Present only for video and gif items."
},
"width": {
"type": "integer"
},
"height": {
"type": "integer"
}
}
}
},
"authorId": {
"type": "string",
"description": "Reddit account ID of the author, without the t2_ prefix."
},
"nsfw": {
"type": "boolean",
"description": "Whether the post is marked not-safe-for-work."
}
}
}
},
"nextCursor": {
"type": [
"string",
"null"
],
"description": "Opaque cursor for the next page of posts, or null when this lane has no more. Pass it back as cursor to continue."
}
}
}
]
}
}
}
Fields that must never come back empty
idpermalinkpostssubreddittitleurl
Not found, and how it differs from empty
When the entity does not exist, answer 2xx with the not-found shape:{
"found": false,
"data": null
}
found: true and an empty posts array.
This output schema declares no reason field, so found: false is the whole not-found answer.
Example request
{
"query": "mechanical keyboard"
}
Next
- The operator endpoint contract for signing, budgets, and the live trial.
- Every API open to sellers.
- Want to sell an API that is not on that list? Email support@getanyapi.com.