Multi-platform search
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.
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. |
<platform>.<param> | 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. |
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
{
"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.<platform> | 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.<platform>.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.<platform>.endpoint) with the same query and send sources.<platform>.next_cursor as cursor:
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.
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 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 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.
