# Multi-platform search (/docs/search/multi) One query sent to several platforms' own search endpoints in one call, returning each platform's rows at that platform's own page price. Send one query to `GET /v1/search/multi` and it runs on each platform's own search endpoint at once. Every row is the row that platform's search endpoint returns, with `platform` added, and each platform costs its own page price, charged only when it came back with rows. ```bash title="cURL" curl "https://www.socialcrawl.dev/v1/search/multi?query=matcha+latte&platforms=tiktok,instagram,youtube" \ -H "x-api-key: YOUR_API_KEY" ``` This call searched three platforms. Their rows arrive together in `data.items`, grouped by platform in the order you listed them, and a post URL that already appeared is left out. `data.sources` reports what each platform returned and cost, and gives you its cursor for the next page. ## Which platforms `platforms` is a comma-separated list. Without it the call searches TikTok, Instagram, YouTube, Reddit and Threads. | `platforms` value | Runs | Page price | | ----------------- | ----------------------------- | ---------- | | `tiktok` | `GET /v1/tiktok/search` | 1 credit | | `instagram` | `GET /v1/instagram/search/reels` | 1 credit | | `youtube` | `GET /v1/youtube/search` | 1 credit | | `reddit` | `GET /v1/reddit/search` | 1 credit | | `threads` | `GET /v1/threads/search` | 1 credit | | `twitter` | `GET /v1/twitter/search/tweets` | 1 credit | | `facebook` | `GET /v1/facebook/search/posts` | 1 credit | | `linkedin` | `GET /v1/linkedin/search/posts` | 5 credits | A name outside this list is a `400 INVALID_REQUEST` that names the accepted values and costs nothing. ## Request parameters | Param | Required | Type | Default | Description | | --------------------- | -------- | ------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `query` | yes | string (1 to 500 chars) | none | Keyword or phrase, sent unchanged to every platform. | | `platforms` | no | CSV | `tiktok,instagram,youtube,reddit,threads` | The platforms to search, from the table above. | | `since` | no | `YYYY-MM-DD` or ISO 8601 timestamp | none | Keeps only posts published on or after this date, on every platform. A row with no date is kept. A value that is not a date is a free `400`. | | `.` | no | as on that platform's endpoint | none | A platform's own search filter, passed through to that platform only. See the next table. | | `relevance`, `label` | no | as on the single search endpoints | none | Judged relevance and labels across every platform's rows. See [Relevance and labels](#relevance-and-labels). | `since` is sent to the platform as its own date filter where one exists (Threads and Facebook `start_date`, the X `since:` search operator), and is applied to each row's `post.published_at` on every platform. ### Per-platform filters Put the platform in front of the filter name, for example `tiktok.region=US` or `reddit.sort=new`. Each one is sent to that platform's endpoint exactly as that endpoint takes it, and a filter for a platform you did not request is not used. A value outside a filter's list is a free `400`. | Filter | Values | | ----------------------- | -------------------------------------------------------------------------------------------- | | `tiktok.date_posted` | `yesterday`, `this-week`, `this-month`, `last-3-months`, `last-6-months`, `all-time` | | `tiktok.sort_by` | `relevance`, `most-liked`, `date-posted` | | `tiktok.region` | A country code, for example `US` | | `instagram.date_posted` | `last-week`, `last-month`, `last-year` | | `youtube.uploadDate` | `today`, `this_week`, `this_month`, `this_year` | | `youtube.sortBy` | `relevance`, `popular` | | `youtube.type` | `videos`, `shorts` | | `youtube.duration` | `under_3_min`, `between_3_and_20_min`, `over_20_min` | | `youtube.region` | A country code | | `reddit.sort` | `relevance`, `new`, `top`, `comment_count` | | `reddit.timeframe` | `all`, `day`, `week`, `month`, `year` | | `threads.start_date` | A date, as on `/v1/threads/search` | | `threads.end_date` | A date, as on `/v1/threads/search` | | `twitter.sort` | `latest`, `top` | | `facebook.start_date` | A date, as on `/v1/facebook/search/posts` | | `facebook.end_date` | A date, as on `/v1/facebook/search/posts` | | `facebook.recent_posts` | `true` or `false` | | `facebook.location_uid` | A location id, as on `/v1/facebook/search/posts` | | `linkedin.sort_by` | `date_posted`, `relevance` | | `linkedin.date_posted` | `past_24h`, `past_week`, `past_month` | | `linkedin.content_type` | `videos`, `photos`, `jobs`, `live_videos`, `documents`, `collaborative_articles` | ## What you get back ```json title="Response" { "success": true, "platform": "search", "endpoint": "/v1/search/multi", "data": { "query": "matcha latte", "platforms": ["tiktok", "instagram", "youtube"], "since": null, "sources": { "tiktok": { "endpoint": "/v1/tiktok/search", "status": "ok", "http_status": 200, "rows": 20, "rows_kept": 20, "credits": 1, "next_cursor": "sc.eyJ2IjoyLCJjIjoiMjAifQ", "has_more": true }, "instagram": { "endpoint": "/v1/instagram/search/reels", "status": "empty", "http_status": 200, "rows": 0, "rows_kept": 0, "credits": 0, "next_cursor": null, "has_more": false }, "youtube": { "endpoint": "/v1/youtube/search", "status": "ok", "http_status": 200, "rows": 19, "rows_kept": 18, "credits": 1, "next_cursor": "sc.eyJ2IjoyLCJjIjoiRWdJUUFR…", "has_more": true } }, "methodology_version": "search-multi/1.0", "search_status": "complete", "items": [ { "platform": "tiktok", "post": { "id": "…", "url": "…" }, "computed": { } } ], "total": 38, "duplicates_removed": 1, "credits_charged": 2 }, "credits_used": 2, "credits_remaining": 4998, "request_id": "req-XXXXX", "cached": false } ``` | Field | Description | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `items` | Every platform's rows, each exactly as that platform's own search endpoint returns it (`post` and `computed`), plus `platform`. Grouped in request order, each group in the platform's own order. | | `sources.` | One report per requested platform: `endpoint`, `status` (`ok`, `empty` or `failed`), `http_status`, `rows` returned, `rows_kept` after `since` and deduplication, `credits`, `next_cursor` and `has_more`. | | `duplicates_removed` | Rows left out because the same post URL had already appeared, the first one kept. | | `search_status` | `complete` when no platform failed, `partial` when at least one failed and at least one answered. | | `credits_charged` | The sum of `sources..credits`. Matches the envelope's `credits_used`. | | `total` | `items.length`. | | `query`, `platforms`, `since` | Your request as parsed. | A platform whose search found nothing reports `empty`, not `failed`, and costs nothing. ## How do I get the next page? This endpoint returns one page per platform and does not page itself, so sending it `cursor` is a `400`. To go deeper on one platform, call that platform's own endpoint (`sources..endpoint`) with the same `query` and send `sources..next_cursor` as `cursor`: ```bash title="cURL" curl "https://www.socialcrawl.dev/v1/tiktok/search?query=matcha+latte&cursor=sc.eyJ2IjoyLCJjIjoiMjAifQ" \ -H "x-api-key: YOUR_API_KEY" ``` From there the walk is the ordinary one described in [Pagination](/docs/pagination.md). ## Billing Metered, **1-12 credits**. Each platform costs its own endpoint's page price, and only when its page came back with rows. The call holds the sum of the requested platforms' prices up front and refunds every platform that failed or found nothing. The default five platforms hold 5 credits. | Scenario | Charge | | ------------------------------------------------- | ------------------------------------------------ | | Default five platforms, all return rows | 5 | | TikTok, Instagram and YouTube, Instagram finds nothing | 2 | | TikTok and LinkedIn, both return rows | 6 | | A page `since` trimmed to no rows | Still that platform's page price, as on its own endpoint | | Every platform failed | 0 (full refund), `502` | | Cache hit (within 5 minutes) | 0 | ## Relevance and labels Rows carry the same judged fields as the single search endpoints, and they are judged across all platforms at once, so a TikTok row and a Reddit row can be compared on one scale. Every row carries `computed.relevance` against your query and the default labels at no extra credit. `relevance=score`, `relevance=filter`, `relevant_to=` and `label=` work as they do on the single search endpoints, and their extras are priced the same way. See [Labels](/docs/labels.md#post-search-relevance) for the field shapes and prices. ## Multi or everywhere? `search/multi` returns each platform's native rows at native prices, with no planning and no reranking. Use it when you would otherwise call three or four search endpoints yourself. [Universal social search](/docs/search/everywhere.md) is a different product at a flat 20 credits: it plans your query, searches more sources, reads top comments, and ranks and clusters the merged results into one answer. ## Next steps - [Universal social search](/docs/search/everywhere.md): Planned, reranked and comment-enriched results across more sources. - [Pagination](/docs/pagination.md): Continue one platform - [Labels](/docs/labels.md): Relevance and labels on every row, and what the extras cost.