TikTok · Instagram · YouTube · X
Paste any post URL, get the same normalized JSON back. TikData handles platform detection, the per-platform field archaeology, rate limiting and per-project attribution — so your bots just ask for numbers.
curl "https://tikdata.io/v1/post?url=https://www.tiktok.com/@tiktok/video/7680721699171601694" \
-H "Authorization: Bearer thr_live_xxx"{
"platform": "tiktok",
"id": "7680721699171601694",
"url": "https://www.tiktok.com/@tiktok/video/...",
"caption": "this summer was all about the classic hits",
"cover": "https://...",
"createdAt": "2026-09-02T00:03:08.000Z",
"author": {
"handle": "tiktok",
"name": "TikTok",
"followers": 95629391
},
"stats": {
"views": 137591,
"likes": 6321,
"comments": 993,
"shares": 436,
"saves": 677
}
}Swap the URL for an Instagram Reel, a YouTube Short or a post on X. Same shape, same field names, every time.
Every consumer 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.
Stop writing per-platform field digging in every project. The same JSON comes back whether the URL is a TikTok video, a Reel, a Short or a post on X.
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 client again.
The key identifies the project, so every call is counted against it automatically. Nothing to install, forget, or lose when a file gets re-uploaded.
Outbound calls are held under the plan's rate limit by a sliding window. Batch up to 500 URLs in one request and the fan-out is paced for you.
Detail that matters
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. Missing individual stats still come back as 0 — platforms omit different fields, and a partial answer beats a failed refresh.
HTTP/1.1 200 OK
{ "code": 200, "data": {} }
→ looks like: 0 views, 0 likesHTTP/1.1 404 Not Found
{ "error": "post not found",
"platform": "tiktok",
"id": "9999999999999999999" }| GET | /v1/post?url= | One post, normalized. Platform detected from the URL. |
| POST | /v1/posts | Batch. Up to 500 URLs, fanned out under the rate gate. |
| ANY | /v1/raw/{path} | Verbatim pass-through for anything without a custom endpoint. |
| GET | /v1/whoami | Which key and project am I calling as. |
| ADMIN | /v1/keys | Mint, list, disable and delete keys. |
Already calling the provider directly? Point your base URL at /v1/raw and swap the key — it is a verbatim pass-through, so existing call sites keep working unchanged.
One per consumer, so spend is attributable and a single 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"}'whoami is the health check when wiring up a new consumer — it echoes the key and project.
curl "https://tikdata.io/v1/whoami" \
-H "Authorization: Bearer thr_live_xxx"One URL or five hundred. Each batch result carries its own ok flag, 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://..."]}'