SocialCrawl

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
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 valueRunsPage price
tiktokGET /v1/tiktok/search1 credit
instagramGET /v1/instagram/search/reels1 credit
youtubeGET /v1/youtube/search1 credit
redditGET /v1/reddit/search1 credit
threadsGET /v1/threads/search1 credit
twitterGET /v1/twitter/search/tweets1 credit
facebookGET /v1/facebook/search/posts1 credit
linkedinGET /v1/linkedin/search/posts5 credits

A name outside this list is a 400 INVALID_REQUEST that names the accepted values and costs nothing.

Request parameters

ParamRequiredTypeDefaultDescription
queryyesstring (1 to 500 chars)noneKeyword or phrase, sent unchanged to every platform.
platformsnoCSVtiktok,instagram,youtube,reddit,threadsThe platforms to search, from the table above.
sincenoYYYY-MM-DD or ISO 8601 timestampnoneKeeps 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>noas on that platform's endpointnoneA platform's own search filter, passed through to that platform only. See the next table.
relevance, labelnoas on the single search endpointsnoneJudged 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.

FilterValues
tiktok.date_postedyesterday, this-week, this-month, last-3-months, last-6-months, all-time
tiktok.sort_byrelevance, most-liked, date-posted
tiktok.regionA country code, for example US
instagram.date_postedlast-week, last-month, last-year
youtube.uploadDatetoday, this_week, this_month, this_year
youtube.sortByrelevance, popular
youtube.typevideos, shorts
youtube.durationunder_3_min, between_3_and_20_min, over_20_min
youtube.regionA country code
reddit.sortrelevance, new, top, comment_count
reddit.timeframeall, day, week, month, year
threads.start_dateA date, as on /v1/threads/search
threads.end_dateA date, as on /v1/threads/search
twitter.sortlatest, top
facebook.start_dateA date, as on /v1/facebook/search/posts
facebook.end_dateA date, as on /v1/facebook/search/posts
facebook.recent_poststrue or false
facebook.location_uidA location id, as on /v1/facebook/search/posts
linkedin.sort_bydate_posted, relevance
linkedin.date_postedpast_24h, past_week, past_month
linkedin.content_typevideos, photos, jobs, live_videos, documents, collaborative_articles

What you get back

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
}
FieldDescription
itemsEvery 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_removedRows left out because the same post URL had already appeared, the first one kept.
search_statuscomplete when no platform failed, partial when at least one failed and at least one answered.
credits_chargedThe sum of sources.<platform>.credits. Matches the envelope's credits_used.
totalitems.length.
query, platforms, sinceYour 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
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.

ScenarioCharge
Default five platforms, all return rows5
TikTok, Instagram and YouTube, Instagram finds nothing2
TikTok and LinkedIn, both return rows6
A page since trimmed to no rowsStill that platform's page price, as on its own endpoint
Every platform failed0 (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.

Next steps