TikTok · Instagram · YouTube · X

One API for
social post data.

Paste any post or profile URL, get the same normalized JSON back — every engagement number each platform exposes, deleted content as a real 404, and the cost attributed to the key that asked. Your bots just ask for numbers.

8
stats, one schema
500
URLs per batch
404
not zeroes, for deleted
request
curl "https://tikdata.io/v1/post?url=https://www.tiktok.com/@tiktok/video/7680721699171601694" \
  -H "Authorization: Bearer thr_live_xxx"
response · 200
{
  "platform": "tiktok",
  "id": "7680721699171601694",
  "caption": "this summer was all about the classic hits…",
  "createdAt": "2026-09-02T00:03:08.000Z",
  "author": {
    "handle": "tiktok",
    "name": "TikTok",
    "followers": 95663434
  },
  "stats": {
    "views": 202473,
    "likes": 8267,
    "comments": 1261,
    "shares": 631,
    "saves": 922,
    "reposts": 0,
    "quotes": 0,
    "downloads": 40
  }
}

Coverage

Every stat a platform will admit to.

Eight engagement numbers under one set of names. Where a platform doesn't expose one, the field is present and 0 — never missing, never an exception. Each cell is the upstream field it was read from, verified against a live response.

On X a repost is the share mechanism, so shares and reposts carry the same number there by design — summing shares across platforms gives you a comparable figure instead of a zero.

statTikTokInstagramYouTubeX
viewsplay_countplay_countview_countviews
likesdigg_countlike_countlike_countlikes
commentscomment_countcomment_countcomment_countreplies
sharesshare_countshare_count—retweets
savescollect_countsave_count—bookmarks
repostsrepost_countrepost_count—retweets
quotes———quotes
downloadsdownload_count———
followersfollower_countvia /v1/profilesubscriber_countsub_count

Why route through it

Every bot holding its own provider key is four problems.

A leaked credential, no attribution, no shared pacing, and the same normalization code copied into each project. One gateway retires all four.

01

One shape, four platforms

The same JSON whether the URL is a TikTok video, a Reel, a Short or a post on X. Field archaeology — X's sub_count, Instagram's edge_* wrappers, YouTube's “4.54M subscribers” strings — happens here, once.

02

The provider key never leaves the server

Consumers hold a thr_live_ key that only this gateway understands. Revoke one without rotating anything else, and never ship the upstream account key to a bot again.

03

Per-key cost, priced live

Every call is counted against the key that made it, then priced at read time against the provider's progressive account-wide discount tiers — so the number matches the bill, not a snapshot.

04

Pacing lives here

Outbound calls are held under the plan's 100 req/s by a sliding window. Batch 500 URLs in one request and the fan-out is paced for you; one dead id never sinks the rest.

Detail that matters

A deleted post returns 404, not zeroes.

Upstream answers HTTP 200 for a dead video id and simply omits the post object. Read that naively and a removed post looks like a real crash to 0 views — which, if the numbers feed view tracking, is a payout dispute waiting to happen.

TikData checks for the post explicitly and answers 404. Same for creators: X and Instagram return 200 with an invented "not found" body for accounts that don't exist, and both become 404 here — so a renamed creator never reads as one who lost their whole audience.

upstream, raw
HTTP/1.1 200 OK
{ "code": 200, "data": {} }

→ looks like: 0 views, 0 likes
through tikdata
HTTP/1.1 404 Not Found
{ "error": "post not found",
  "platform": "tiktok",
  "id": "9999999999999999999" }

Endpoints

Ten, documented to the field.

Full reference →
GET/v1/postOne post, every stat, platform detected from the URL.
POST/v1/postsUp to 500 URLs, fanned out server-side, per-item ok.
POST/v1/videos/bulk_statsUp to 100 videos by id or url, one flat row each, typed errors.
GET/v1/profileThe creator — followers, bio, verified, post count.
GET/v1/creator/statsFollowers plus everything published in the last N days.
ANY/v1/raw/{path}Verbatim pass-through; a two-line migration for existing bots.
GET/v1/whoamiWhich key and project am I.
GET/v1/usageThis key's calls and cost today, priced live.
GET/v1/accountThe provider's live account meter (admin).
ADMIN/v1/keysMint, list, disable, delete.

Already calling the provider directly? Point your base URL at /v1/raw and swap the key. Existing call sites keep working unchanged.

Three steps

01

Mint a key

One per consumer, so spend is attributable and any one project can be cut off on its own.

curl -X POST "https://tikdata.io/v1/keys" \
  -H "x-admin-token: $INGEST_TOKEN" \
  -H "content-type: application/json" \
  -d '{"label":"my bot","project":"my-bot"}'
02

Confirm it

whoami echoes the key and project — the health check when wiring a new consumer.

curl "https://tikdata.io/v1/whoami" \
  -H "Authorization: Bearer thr_live_xxx"
03

Ask for numbers

One URL or five hundred. Every result carries its own ok, so one bad URL never sinks the request.

curl -X POST "https://tikdata.io/v1/posts" \
  -H "Authorization: Bearer thr_live_xxx" \
  -H "content-type: application/json" \
  -d '{"urls":["https://…","https://…"]}'

For agents

Readable by models, too.

/llms.txt indexes the whole reference in the llmstxt.org format, and every docs page is also served as raw Markdown at its .md URL. Same files — one source of truth for people and agents.