> ## Documentation Index
> Fetch the complete documentation index at: https://getanyapi.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# TikTok Top Search

> Sell tiktok.search_top on AnyAPI: the request your endpoint receives, the response it must return, and what the live trial grades.

Search TikTok's top results for a keyword (caption, views, likes, comments, shares) with cursor pagination.

This page is the seller-facing summary of one catalog API, `tiktok.search_top`. 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](https://getanyapi.com/docs/sell/operator-endpoint-contract.md).

## The price you compete with

AnyAPI publishes this API from **\$0.60 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 | Pagination cursor from a previous response. |
| `publishTime` | string | no | Time-frame filter: yesterday, this-week, this-month, last-3-months, last-6-months, all-time. One of: `yesterday`, `this-week`, `this-month`, `last-3-months`, `last-6-months`, `all-time`. |
| `query` | string | yes | Keyword to search for (e.g. "funny"). |
| `region` | string | no | 2-letter country code for the proxy location (e.g. US, GB, FR). |
| `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 `soundClipId` or `nextCursor`, 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. A named field can still be absent on a record that genuinely lacks it. Naming a combination that no single source returns together is refused as invalid input, with no charge. |
| `sortBy` | string | no | Sort order: relevance, most-liked, date-posted. One of: `relevance`, `most-liked`, `date-posted`. |

> **Full input JSON Schema**
>
> ```json theme={"dark"}
> {
>   "$schema": "https://json-schema.org/draft/2020-12/schema",
>   "$id": "https://getanyapi.com/schemas/tiktok.search_top.input.json",
>   "example": {
>     "query": "funny"
>   },
>   "title": "TikTok Top Search input",
>   "type": "object",
>   "additionalProperties": false,
>   "x-anyapi-compat-values": {
>     "sortBy": {
>       "latest": "date-posted"
>     },
>     "publishTime": {
>       "last-week": "this-week",
>       "last-month": "this-month"
>     }
>   },
>   "required": [
>     "query"
>   ],
>   "properties": {
>     "query": {
>       "type": "string",
>       "description": "Keyword to search for (e.g. \"funny\")."
>     },
>     "publishTime": {
>       "type": "string",
>       "enum": [
>         "yesterday",
>         "this-week",
>         "this-month",
>         "last-3-months",
>         "last-6-months",
>         "all-time"
>       ],
>       "description": "Time-frame filter: yesterday, this-week, this-month, last-3-months, last-6-months, all-time."
>     },
>     "sortBy": {
>       "type": "string",
>       "enum": [
>         "relevance",
>         "most-liked",
>         "date-posted"
>       ],
>       "description": "Sort order: relevance, most-liked, date-posted."
>     },
>     "region": {
>       "type": "string",
>       "description": "2-letter country code for the proxy location (e.g. US, GB, FR)."
>     },
>     "cursor": {
>       "type": "string",
>       "description": "Pagination cursor from a previous response."
>     },
>     "requireFields": {
>       "type": "array",
>       "uniqueItems": true,
>       "items": {
>         "type": "string",
>         "enum": [
>           "authorFollowers",
>           "contentType",
>           "nextCursor",
>           "soundAuthor",
>           "soundClipId",
>           "soundTitle"
>         ]
>       },
>       "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 `soundClipId` or `nextCursor`, 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. A named field can still be absent on a record that genuinely lacks it. Naming a combination that no single source returns together is refused as invalid input, with no charge."
>     }
>   }
> }
> ```

## The response your endpoint must return

| Field | Type | Always present | What it means |
| - | - | - | - |
| `data` | null or object | yes | |
| `data.items` | array | yes | |
| `data.items[].author` | string | yes | |
| `data.items[].authorFollowers` | integer or null | no | The author's follower count at the time of the request. Null when the serving source does not report it. |
| `data.items[].authorImage` | string | no | Author's avatar image URL. Signed and short-lived, so the query string is load-bearing and kept intact. |
| `data.items[].authorName` | string | no | Author's display name. |
| `data.items[].authorUserId` | string | no | Author's numeric TikTok user id. |
| `data.items[].caption` | string | yes | |
| `data.items[].comments` | integer | yes | |
| `data.items[].contentType` | string or null | yes | TikTok's own label for the post format, such as video, or null when the serving source does not report it. |
| `data.items[].createdUtc` | number | no | UTC epoch timestamp in seconds (Unix time). Multiply by 1000 for a JS Date in milliseconds. |
| `data.items[].durationSeconds` | number | no | Media duration in seconds. |
| `data.items[].hashtags` | array | no | Hashtags carried in the caption, without the leading #. Empty when the post uses none; @-mentions are excluded. |
| `data.items[].id` | string | yes | |
| `data.items[].image` | string | no | URL of the item's cover image. Signed and short-lived, so the query string is load-bearing and kept intact. |
| `data.items[].likes` | integer | yes | |
| `data.items[].saves` | integer | no | |
| `data.items[].shares` | integer | yes | |
| `data.items[].soundAuthor` | string or null | no | Credited author of the sound. Null when the serving source does not report it. |
| `data.items[].soundClipId` | string or null | no | Id of the sound the video uses. Pass it to tiktok.song or tiktok.song\_videos as clipId. Null when the serving source does not report it. |
| `data.items[].soundTitle` | string or null | no | Name of the sound. "original sound" means the creator's own audio rather than a licensed track. Null when the serving source does not report it. |
| `data.items[].url` | string | yes | |
| `data.items[].videoUrl` | string | no | Playable video URL. Signed and short-lived, so the query string is load-bearing and kept intact. |
| `data.items[].views` | integer | yes | |
| `data.nextCursor` | string or null | yes | Opaque cursor for the next page of results, or null when this lane has no more. Pass it back as cursor to continue. |
| `found` | boolean | yes | |

Extra fields are kept, missing declared fields fail.

> **Full output JSON Schema**
>
> ```json theme={"dark"}
> {
>   "$schema": "https://json-schema.org/draft/2020-12/schema",
>   "$id": "https://getanyapi.com/schemas/tiktok.search_top.output.json",
>   "title": "TikTok Top Search output",
>   "type": "object",
>   "additionalProperties": false,
>   "required": [
>     "found",
>     "data"
>   ],
>   "properties": {
>     "found": {
>       "type": "boolean"
>     },
>     "data": {
>       "oneOf": [
>         {
>           "type": "null"
>         },
>         {
>           "type": "object",
>           "additionalProperties": false,
>           "required": [
>             "items",
>             "nextCursor"
>           ],
>           "properties": {
>             "nextCursor": {
>               "type": [
>                 "string",
>                 "null"
>               ],
>               "description": "Opaque cursor for the next page of results, or null when this lane has no more. Pass it back as cursor to continue."
>             },
>             "items": {
>               "x-anyapi-must-populate": true,
>               "type": "array",
>               "items": {
>                 "type": "object",
>                 "required": [
>                   "id",
>                   "caption",
>                   "contentType",
>                   "url",
>                   "author",
>                   "views",
>                   "likes",
>                   "comments",
>                   "shares"
>                 ],
>                 "properties": {
>                   "id": {
>                     "x-anyapi-must-populate": true,
>                     "type": "string"
>                   },
>                   "caption": {
>                     "x-anyapi-must-populate": true,
>                     "type": "string"
>                   },
>                   "contentType": {
>                     "type": [
>                       "string",
>                       "null"
>                     ],
>                     "description": "TikTok's own label for the post format, such as video, or null when the serving source does not report it."
>                   },
>                   "url": {
>                     "x-anyapi-must-populate": true,
>                     "type": "string"
>                   },
>                   "author": {
>                     "x-anyapi-must-populate": true,
>                     "type": "string"
>                   },
>                   "views": {
>                     "type": "integer"
>                   },
>                   "likes": {
>                     "type": "integer"
>                   },
>                   "comments": {
>                     "type": "integer"
>                   },
>                   "shares": {
>                     "type": "integer"
>                   },
>                   "saves": {
>                     "type": "integer"
>                   },
>                   "createdUtc": {
>                     "x-anyapi-must-populate": true,
>                     "type": "number",
>                     "description": "UTC epoch timestamp in seconds (Unix time). Multiply by 1000 for a JS Date in milliseconds."
>                   },
>                   "image": {
>                     "type": "string",
>                     "description": "URL of the item's cover image. Signed and short-lived, so the query string is load-bearing and kept intact."
>                   },
>                   "videoUrl": {
>                     "type": "string",
>                     "description": "Playable video URL. Signed and short-lived, so the query string is load-bearing and kept intact."
>                   },
>                   "durationSeconds": {
>                     "type": "number",
>                     "description": "Media duration in seconds."
>                   },
>                   "authorName": {
>                     "type": "string",
>                     "description": "Author's display name."
>                   },
>                   "authorUserId": {
>                     "type": "string",
>                     "description": "Author's numeric TikTok user id."
>                   },
>                   "authorImage": {
>                     "type": "string",
>                     "description": "Author's avatar image URL. Signed and short-lived, so the query string is load-bearing and kept intact."
>                   },
>                   "hashtags": {
>                     "x-anyapi-must-populate": true,
>                     "type": "array",
>                     "description": "Hashtags carried in the caption, without the leading #. Empty when the post uses none; @-mentions are excluded.",
>                     "items": {
>                       "type": "string"
>                     }
>                   },
>                   "soundTitle": {
>                     "type": [
>                       "string",
>                       "null"
>                     ],
>                     "description": "Name of the sound. \"original sound\" means the creator's own audio rather than a licensed track. Null when the serving source does not report it."
>                   },
>                   "soundAuthor": {
>                     "type": [
>                       "string",
>                       "null"
>                     ],
>                     "description": "Credited author of the sound. Null when the serving source does not report it."
>                   },
>                   "soundClipId": {
>                     "type": [
>                       "string",
>                       "null"
>                     ],
>                     "description": "Id of the sound the video uses. Pass it to tiktok.song or tiktok.song_videos as clipId. Null when the serving source does not report it."
>                   },
>                   "authorFollowers": {
>                     "type": [
>                       "integer",
>                       "null"
>                     ],
>                     "description": "The author's follower count at the time of the request. Null when the serving source does not report it."
>                   }
>                 }
>               }
>             }
>           }
>         }
>       ]
>     }
>   }
> }
> ```

## Fields that must never come back empty

* `author`
* `caption`
* `createdUtc`
* `hashtags`
* `id`
* `items`
* `url`

The repository marks these fields as ones every source must be able to fill. An empty value is only correct when the entity itself genuinely has nothing there.

## Not found, and how it differs from empty

When the entity does not exist, answer 2xx with the not-found shape:

```json theme={"dark"}
{
  "found": false,
  "data": null
}
```

An empty list is not a not-found: when the entity exists and has nothing to return, answer 2xx with `found: true` and an empty `items` array.

This output schema declares no `reason` field, so `found: false` is the whole not-found answer.

## Example request

```json theme={"dark"}
{
  "query": "funny"
}
```

The compatibility checks fire the schema's example at your endpoint. After that, your answers are graded against what the currently serving source returned for the same real customer inputs.

## Next

* [The operator endpoint contract](https://getanyapi.com/docs/sell/operator-endpoint-contract.md) for signing, budgets, and the live trial.
* [Every API open to sellers](https://getanyapi.com/docs/sell/apis/index.md).
* Want to sell an API that is not on that list? Email [support@getanyapi.com](mailto:support@getanyapi.com).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.