Developer

Call the same live data from your own code or your own agent: keys, what they’ve requested, skills and the API reference.

API reference

One REST API and one data shape for TikTok, Instagram, RedNote, Lemon8, LinkedIn, YouTube and Facebook, at https://api.soradar.app. The same live data the chat uses, for your own code and agents.
On this page: Quickstart

Quickstart

Every platform answers in the same shape, so the first request below works for all seven: swap tiktok for instagram, youtube or any other platform and the response keeps its fields.

  1. Create an API key

    Keys start with sk_live_. Every new account starts with 300 free credits, enough to try each platform.

    Create an API key
  2. Make your first request

    Fetch a public TikTok profile with your key in the Authorization header.

    Requestbash
    curl "https://api.soradar.app/v2/tiktok/users/khaby.lame" \
      -H "Authorization: Bearer $SORADAR_API_KEY"
  3. Read the response

    Every record has stable identity fields at the top level, then three blocks that are the same on every platform:

    content
    What the platform says about the record: bio, display name, verified status, location.
    metrics
    A time-stamped snapshot of the counters (followers, likes, views), taken at observedAt.
    provenance
    How complete the record is (summary or detail), when it was fetched, and an opaque source token.
    Responsejson
    {
      "platform": "tiktok",
      "id": "khaby.lame",
      "handle": "khaby.lame",
      "displayName": "Khabane Lame",
      "url": "https://www.tiktok.com/@khaby.lame",
      "content": {
        "bio": "If you wanna laugh you are in the right place😎",
        "avatar": "https://p16-sign.tiktokcdn.com/tos-maliva-avt-0068/...",
        "verified": true,
        "location": "Italy"
      },
      "metrics": {
        "observedAt": 1740000000000,
        "followers": 162800000,
        "following": 78,
        "posts": 1240,
        "likes": 2400000000
      },
      "provenance": {
        "source": "tiktok:user:811c9d",
        "fetchedAt": 1740000000000,
        "fidelity": "detail"
      }
    }

Authentication

Every endpoint under /v2/ except GET /v2/health needs an API key, sent as a Bearer token. Keys start with sk_live_.

Send your key

Put the key in the standard Authorization header with the Bearer scheme.

Headerhttp
Authorization: Bearer sk_live_your_api_key_here

A key works until you revoke it, and it only ever reads and bills your own account. We show the full key once, when you create it, and store only a SHA-256 hash of it — copy it somewhere safe then, as it cannot be shown again.

When a key is rejected

A request with no key gets 401 Unauthorized. A key that is revoked or malformed gets 403 Forbidden.

401 responsejson
{
  "error": "auth_required",
  "message": "Authorization header required: Bearer <api_key>",
  "hint": "Authorization header required: Bearer <api_key>"
}

Core concepts

Five ideas explain every response: one shape for all platforms, records that say how complete they are, metrics kept apart from content, a compact format for AI agents, and credits.

One shape across seven platforms

Each platform describes creators, posts, comments and counters its own way: TikTok uses 64-bit numeric ids, Instagram uses shortcodes, RedNote uses 24-character hex strings. Soradar maps all of them onto one normalized model, so field names, types and structure are identical on every platform. The platform is the first segment of the path.

PlatformPath segment
TikTok/v2/tiktok/…
Instagram/v2/instagram/…
RedNote/v2/xiaohongshu/…
Lemon8/v2/lemon8/…
LinkedIn/v2/linkedin/…
YouTube/v2/youtube/…
Facebook/v2/facebook/…

Summary and detail records

Every record declares its fidelity in provenance.fidelity: summary or detail. A summary record also lists the fields that were cut short in partialFields, so you never mistake a truncated value for the whole thing.

For example, RedNote search (GET /v2/xiaohongshu/search/posts) returns note text cut to 60 characters and no tags. Those records come back with fidelity: "summary" and partialFields: ["text", "tags"]. To get the full text and every tag, fetch the note by id with GET /v2/xiaohongshu/posts/:id.

A summary recordjson
{
  "platform": "xiaohongshu",
  "id": "64b8e1920000000012345",
  "content": {
    "title": "Top Shanghai Boutique Cafes",
    "text": "Exploring the best artisanal coffee roasters in the French Concession area..."
  },
  "provenance": {
    "source": "xiaohongshu:post:7a81df",
    "fidelity": "summary",
    "partialFields": ["text", "tags"]
  }
}

Entities and observations

Content barely changes; engagement changes all the time. Soradar keeps the two apart: the entity (handle, publish date, post text) is stable, and metrics is an observation taken at a moment.

Every metrics object carries observedAt, in epoch milliseconds. Asking again on later days appends a new observation instead of overwriting the old one, so your own request history becomes a time series. That history is what powers growth, velocity and the creator medians in the /stats endpoint.

A format for AI agents: ?x-format=llm

Plain JSON from social platforms is full of signed media URLs, often ten or more per video for mirrors and covers. A model without network access cannot open them, they expire in about 48 hours, and they can take up to 65% of the tokens in a response.

Add ?x-format=llm to any request to get compact Markdown instead.

Left out

  • Signed, expiring media and video URLs
  • Raw avatar URLs and duplicate renditions
  • Unstructured platform-specific extras

Kept

  • Normalized metrics with explicit units
  • Inline warnings on truncated fields
  • Engagement rates with their denominator stated
  • Media summarized by count and type, such as "1 video"
Response with ?x-format=llmmarkdown
# @charlidamelio (TikTok)
Followers: 151,800,000 | Following: 1,440 | Posts: 2,940 | Likes: 11,500,000,000
Verified: yes | Bio: hey :)

## Recent Posts
### Post 7315712989011242267
Published: 2026-01-01
Text: feeling grateful for all the love ✨
Media: 1 video (CDN media URLs omitted for model attention budget)
Metrics: 2.34M likes | 45.6M views | 156K comments | 89K shares | 42K collects
Engagement basis: 45,600,000 views (5.63% engagement rate)
Fidelity: detail

Credits

Requests are paid for in credits. How many a request uses depends on the platform and the endpoint: a profile lookup uses fewer than a deep comment thread. Every new account starts with 300 free credits, and GET /v2/account/credits returns your balance at any time. How credits work →

Endpoints

Every endpoint lives on https://api.soradar.app, returns JSON, and reports freshness and fidelity in its response headers. Paths take the platform as their first segment, so one endpoint covers all seven platforms.

Health and capabilities

GET/v2/health

No authentication

Liveness check. Returns 200 and the service version while the API is up.

Requestbash
curl -X GET "https://api.soradar.app/v2/health"
Responsejson
{
  "status": "healthy",
  "version": "2.0.0"
}

GET/v2/capabilitiesGET/v2/capabilities/:platform

Requires a Bearer key

Lists what each platform supports: its endpoints, their query parameters and the sort options they accept. Read it at runtime instead of hard-coding what a platform can do.

Path parameters
platformstring
tiktok, instagram, xiaohongshu (RedNote), lemon8, linkedin, youtube or facebook.
Omit it to list every platform.
Requestbash
curl -X GET "https://api.soradar.app/v2/capabilities/tiktok" \
  -H "Authorization: Bearer $SORADAR_API_KEY"
Responsejson
{
  "platform": "tiktok",
  "capabilities": [
    {
      "platform": "tiktok",
      "dataType": "user",
      "providers": ["tiktok:user:811c9d"],
      "params": {
        "id": { "type": "string", "required": true }
      }
    },
    {
      "platform": "tiktok",
      "dataType": "search_post",
      "providers": ["tiktok:search_post:2b4d9e"],
      "params": {
        "q": { "type": "string", "required": true },
        "limit": { "type": "number", "default": 20, "max": 50 },
        "sort": { "type": "string", "enum": ["relevance", "popular", "recent"] }
      }
    }
  ]
}

Users

GET/v2/:platform/users/:id

Requires a Bearer key

A creator’s profile: bio, verification and current follower counts.

Path parameters
platformstringrequired
tiktok, instagram, xiaohongshu (RedNote), lemon8, linkedin, youtube or facebook.
idstringrequired
The user’s handle or platform id.
Requestbash
curl -X GET "https://api.soradar.app/v2/tiktok/users/khaby.lame" \
  -H "Authorization: Bearer $SORADAR_API_KEY"
Responsejson
{
  "platform": "tiktok",
  "id": "khaby.lame",
  "handle": "khaby.lame",
  "displayName": "Khabane Lame",
  "url": "https://www.tiktok.com/@khaby.lame",
  "content": {
    "bio": "If you wanna laugh you are in the right place😎",
    "avatar": "https://p16-sign.tiktokcdn.com/tos-maliva-avt-0068/...",
    "verified": true,
    "location": "Italy"
  },
  "metrics": {
    "observedAt": 1740000000000,
    "followers": 162800000,
    "following": 78,
    "posts": 1240,
    "likes": 2400000000
  },
  "provenance": {
    "source": "tiktok:user:811c9d",
    "fetchedAt": 1740000000000,
    "fidelity": "detail"
  }
}

GET/v2/:platform/users/:id/posts

Requires a Bearer key

The posts a creator has published, one page at a time.

Path parameters
platformstringrequired
tiktok, instagram, xiaohongshu (RedNote), lemon8, linkedin, youtube or facebook.
idstringrequired
The user’s handle or platform id.
Query parameters
limitinteger
How many items to return.
cursorstring
The nextCursor from the previous page.
sinceinteger
Only items published after this time, in epoch milliseconds.
Requestbash
curl -X GET "https://api.soradar.app/v2/tiktok/users/khaby.lame/posts?limit=2" \
  -H "Authorization: Bearer $SORADAR_API_KEY"
Responsejson
{
  "items": [
    {
      "platform": "tiktok",
      "id": "7315712989011242267",
      "author": {
        "id": "khaby.lame",
        "handle": "khaby.lame",
        "displayName": "Khabane Lame"
      },
      "publishedAt": 1735730000000,
      "content": {
        "title": "When you try to open a door...",
        "text": "Life is simple, why complicate it? 😂 #comedy #lifehack",
        "tags": ["comedy", "lifehack"]
      },
      "metrics": {
        "observedAt": 1740000000000,
        "likes": 2340000,
        "views": 45600000,
        "shares": 89000,
        "comments": 156000
      },
      "provenance": {
        "source": "tiktok:user_posts:5d2a71",
        "fetchedAt": 1740000000000,
        "fidelity": "detail"
      }
    }
  ],
  "nextCursor": "cursor_eyJwYWdlIjoyfQ=="
}

GET/v2/:platform/users/:id/stats

Requires a Bearer key

A creator’s performance over a window: median views, likes and comments, the median engagement rate, and the historical observations recorded so far.

Path parameters
platformstringrequired
tiktok, instagram, xiaohongshu (RedNote), lemon8, linkedin, youtube or facebook.
idstringrequired
The user’s handle or platform id.
Query parameters
windowstring
The period to summarize.
7d, 30d or 90d. Default 30d.
Requestbash
curl -X GET "https://api.soradar.app/v2/tiktok/users/khaby.lame/stats?window=30d" \
  -H "Authorization: Bearer $SORADAR_API_KEY"
Responsejson
{
  "platform": "tiktok",
  "userId": "khaby.lame",
  "window": "30d",
  "summary": {
    "followers": 162800000,
    "totalPostsInWindow": 24,
    "medianLikes": 1850000,
    "medianViews": 32000000,
    "medianComments": 94000,
    "engagementRateMedian": 0.058
  },
  "observations": [
    {
      "observedAt": 1737400000000,
      "followers": 162400000,
      "likes": 2390000000
    },
    {
      "observedAt": 1740000000000,
      "followers": 162800000,
      "likes": 2400000000
    }
  ],
  "limitations": []
}

Posts and comments

GET/v2/:platform/posts/:id

Requires a Bearer key

One post in full: caption text, media, tags and engagement counts.

Path parameters
platformstringrequired
tiktok, instagram, xiaohongshu (RedNote), lemon8, linkedin, youtube or facebook.
idstringrequired
The post’s platform id or shortcode.
Requestbash
curl -X GET "https://api.soradar.app/v2/instagram/posts/C8x9Kl10m" \
  -H "Authorization: Bearer $SORADAR_API_KEY"
Responsejson
{
  "platform": "instagram",
  "id": "C8x9Kl10m",
  "url": "https://www.instagram.com/p/C8x9Kl10m/",
  "author": {
    "id": "creativestudio",
    "handle": "creativestudio",
    "displayName": "Creative Studio"
  },
  "publishedAt": 1739800000000,
  "content": {
    "text": "Behind the scenes of our latest design sprint in Tokyo 🇯🇵 #design #architecture",
    "tags": ["design", "architecture"],
    "media": [
      {
        "type": "image",
        "url": "https://instagram.fsnc1-1.fna.fbcdn.net/v/..."
      }
    ]
  },
  "metrics": {
    "observedAt": 1740000000000,
    "likes": 48200,
    "comments": 612
  },
  "provenance": {
    "source": "instagram:post:9e120f",
    "fetchedAt": 1740000000000,
    "fidelity": "detail"
  }
}

GET/v2/:platform/posts/:id/comments

Requires a Bearer key

The comments on a post, one page at a time.

Path parameters
platformstringrequired
tiktok, instagram, xiaohongshu (RedNote), lemon8, linkedin, youtube or facebook.
idstringrequired
The post’s platform id or shortcode.
Query parameters
limitinteger
How many items to return.
cursorstring
The nextCursor from the previous page.
Requestbash
curl -X GET "https://api.soradar.app/v2/instagram/posts/C8x9Kl10m/comments?limit=1" \
  -H "Authorization: Bearer $SORADAR_API_KEY"
Responsejson
{
  "items": [
    {
      "platform": "instagram",
      "id": "17992019481029482",
      "postId": "C8x9Kl10m",
      "author": {
        "id": "tokyocamera",
        "handle": "tokyocamera",
        "displayName": "Tokyo Street Photo"
      },
      "text": "The lighting in the second slide is absolutely stunning!",
      "publishedAt": 1739805000000,
      "metrics": {
        "observedAt": 1740000000000,
        "likes": 84
      },
      "provenance": {
        "source": "instagram:comment:8412ef",
        "fetchedAt": 1740000000000,
        "fidelity": "detail"
      }
    }
  ],
  "nextCursor": "cursor_comment_2"
}

Batch

POST/v2/batch

Requires a Bearer key

Runs up to 25 requests concurrently in a single call. Each item gets its own status code and headers, so one failure (a private profile among twenty public ones) does not fail the rest.

Body
requestsarrayrequired
The requests to run. Each has an id you choose, echoed back on its result, and the path of a GET endpoint above.
Up to 25 items.
Requestbash
curl -X POST "https://api.soradar.app/v2/batch" \
  -H "Authorization: Bearer $SORADAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "requests": [
      { "id": "req-1", "path": "/v2/tiktok/users/khaby.lame" },
      { "id": "req-2", "path": "/v2/instagram/users/creativestudio" }
    ]
  }'
Responsejson
{
  "results": [
    {
      "id": "req-1",
      "status": 200,
      "headers": {
        "x-data-freshness": "fresh",
        "x-fidelity": "detail"
      },
      "body": {
        "platform": "tiktok",
        "id": "khaby.lame",
        "handle": "khaby.lame"
      }
    },
    {
      "id": "req-2",
      "status": 200,
      "headers": {
        "x-data-freshness": "cached",
        "x-fidelity": "detail"
      },
      "body": {
        "platform": "instagram",
        "id": "creativestudio",
        "handle": "creativestudio"
      }
    }
  ],
  "total": 2,
  "succeeded": 2,
  "failed": 0
}

Account

GET/v2/account/credits

Requires a Bearer key

Your credit balance right now, and the latest entries in your credit ledger.

Query parameters
limitinteger
How many ledger entries to return.
Max 50.
Requestbash
curl -X GET "https://api.soradar.app/v2/account/credits" \
  -H "Authorization: Bearer $SORADAR_API_KEY"
Responsejson
{
  "balanceCredits": 284,
  "balance_credits": 284,
  "recent": [
    {
      "id": "led_01jm9k...",
      "deltaCredits": -2,
      "delta_credits": -2,
      "reason": "usage:tiktok:user_posts",
      "createdAt": 1740000000000,
      "note": null
    },
    {
      "id": "led_01jm8a...",
      "deltaCredits": 300,
      "delta_credits": 300,
      "reason": "initial_grant",
      "createdAt": 1739900000000,
      "note": "Developer trial grant"
    }
  ]
}

GET/v2/account/usage

Requires a Bearer key

What your keys requested over a window: request counts per platform, cache hits, and the most recent requests.

Query parameters
windowHoursinteger
How far back to look, in hours.
Default 24, max 720 (30 days).
sinceTsinteger
Start of the window, in epoch milliseconds. Takes precedence over windowHours.
nowTsinteger
End of the window, in epoch milliseconds.
Default: now.
limitinteger
How many recent requests to return.
Max 50.
Requestbash
curl -X GET "https://api.soradar.app/v2/account/usage?windowHours=24&limit=2" \
  -H "Authorization: Bearer $SORADAR_API_KEY"
Responsejson
{
  "window": {
    "sinceTs": 1739913600000,
    "untilTs": 1740000000000,
    "windowMs": 86400000,
    "label": "24h"
  },
  "requestCount": 16,
  "byPlatform": [
    {
      "platform": "tiktok",
      "requestCount": 12,
      "requests": 12,
      "upstreamCalls": 8,
      "cacheHits": 4
    },
    {
      "platform": "instagram",
      "requestCount": 4,
      "requests": 4,
      "upstreamCalls": 4,
      "cacheHits": 0
    }
  ],
  "recent": [
    {
      "requestId": "550e8400-e29b-41d4-a716-446655440000",
      "ts": 1740000000000,
      "keyId": "key_01jh...",
      "platform": "tiktok",
      "dataType": "user",
      "outcome": "cache_hit",
      "upstreamCalls": 0,
      "latencyMs": 14,
      "itemsReturned": 1
    }
  ]
}

GET/v2/account/me

Requires a Bearer key

Your account profile: id, email, display_name and created_at.

GET/v2/account/keys

Requires a Bearer key

Your API keys, active and revoked, with each key’s prefix, creation date and request count.

Control parameters

Control parameters start with x- and go in the query string beside the data parameters. Data parameters such as q or limit decide what you get and form the cache key; control parameters decide how the request runs or is rendered, without splitting the cache.

x-cachestring
How to use the cache. bypass always fetches live; stale-ok accepts an older cached copy for the fastest answer; only answers from cache or returns 404, never fetching live.
bypass, stale-ok or only. Default: standard caching.
x-formatstring
Response format. json is the normalized data; markdown renders it as readable prose; llm drops expiring media URLs, adds inline truncation warnings and packs the result tightly for AI agents.
json, markdown or llm. Default json.
x-describe-mediastring
Set to 1 to have images attached to posts analyzed and given factual descriptive captions.
1 or 0. Default 0.
x-session-idstring
Your own task id, such as an agent run or CI job, used to group usage. You can send it as the X-Session-Id header instead.
Up to 128 characters. Default: none.
x-session-budget-microsinteger
A hard spending ceiling for the session named by x-session-id. Once it is reached, further calls in that session return 402 session_budget_exhausted.
A positive integer. Default: no limit.
Requestbash
curl "https://api.soradar.app/v2/tiktok/users/khaby.lame?x-format=llm&x-cache=stale-ok" \
  -H "Authorization: Bearer $SORADAR_API_KEY"

Response headers

Freshness, fidelity and tracing travel in headers, not in the body, so the payload stays the same whether it came from cache or a live fetch.

X-Request-Iduuid
A unique id for this request. It also appears in error responses; quote it when you contact support.
550e8400-e29b-41d4-a716-446655440000
X-Credits-Chargedinteger
The number of credits this request deducted from your balance, as an integer. Cache hits are billed like fresh fetches; edge-cache hits, errors and refused requests report 0. On POST /v2/batch, each item’s headers carry its own value and the batch response carries the total.
For example 15.
X-Data-Freshnessstring
fresh: fetched live for this request. cached: served from cache. stale: served from cache after its freshness window had passed.
fresh, cached or stale.
X-Data-Ageinteger
Seconds since the record was fetched from the platform.
For example 142.
X-Fidelitystring
summary: a search or list result that may have truncated fields (see partialFields). detail: the complete record.
summary or detail.
X-Upstream-Callsinteger
How many live fetches this request made. 0 on a cache hit.
X-Data-Sourcestring
An opaque token naming where the data came from. It cannot be reversed into anything else.
tiktok:user:811c9d
X-Session-Idstring
Echoes the session id you sent, confirming the request counts toward that session’s usage and budget.
agent-run-2026-03-12

Errors

Every error says what went wrong and what to do next, in a hint written so that both a developer and an AI agent can recover without guessing.

Error shape

Every 4xx and 5xx response has the same JSON body: the error code, a message, a hint, and, where it helps, the supported values.

400 responsejson
{
  "error": "unsupported_parameter",
  "message": "Invalid value 'compact' for 'x-format'. Supported values: json, markdown, llm",
  "hint": "Use ?x-format=json (default), ?x-format=markdown, or ?x-format=llm",
  "supported": ["json", "markdown", "llm"]
}

Error codes

400unsupported_parameter

A query or control parameter is invalid, malformed or not recognized.

The supported array in the response lists the names and values that are allowed.

401auth_required

The Authorization header is missing or empty.

Send Authorization: Bearer sk_live_….

402quota_exhausted

Your balance has reached 0 credits.

Top up credits in the dashboard, or contact us.

402session_budget_exhausted

The session reached the ceiling you set with x-session-budget-micros.

This is your own cap. Report the partial results, or start a new session.

403auth_invalid

The API key is invalid, expired or revoked.

Create a new key under Developer → API keys.

404not_found

The user, post, shortcode or comment does not exist.

Check the handle or id, and that the resource is public.

404unsupported_platform

The platform in the path is not recognized.

Use tiktok, instagram, xiaohongshu, lemon8, linkedin, youtube or facebook.

429rate_limited

Too many requests in a short time.

Back off and retry with exponential backoff and jitter.

501capability_disabled

This platform capability is temporarily turned off.

GET /v2/capabilities shows what is available right now.

503upstream_unavailable

The platform’s data could not be reached right now.

Retry after a short delay. Honour the Retry-After header when it is present.

504timeout

The platform took too long to answer.

Retry with a smaller limit or a narrower since window.

Credits

Each request deducts credits from your account balance. How many depends on the platform and how deep the query goes.

How credits are counted

  • 300 free credits come with every new account, enough to try all seven platforms.
  • Priced per endpoint. A profile lookup uses fewer credits than a deep, paginated comment thread.
  • Capped per task if you want. Set x-session-budget-micros with a x-session-id to stop an agent’s run at a ceiling you choose (see control parameters).

Check your balance

Read your balance and recent ledger entries from the API:

Requestbash
curl "https://api.soradar.app/v2/account/credits" \
  -H "Authorization: Bearer $SORADAR_API_KEY"
Responsejson
{
  "balanceCredits": 284,
  "recent": [
    {
      "id": "led_01jm9k...",
      "deltaCredits": -2,
      "reason": "usage:tiktok:user_posts",
      "createdAt": 1740000000000,
      "note": null
    },
    {
      "id": "led_01jm8a...",
      "deltaCredits": 300,
      "reason": "initial_grant",
      "createdAt": 1739900000000,
      "note": "Developer trial grant"
    }
  ]
}

Your balance and credit history are also in the dashboard. View credits →