One envelope, every endpoint
Standard routed /v1 JSON responses share an envelope. Batch uses a separate wrapper containing per-item envelopes; SSE carries the envelope in its final result event. The fields inside data still depend on the endpoint. Success looks like this:
{
"success": true,
"platform": "tiktok",
"endpoint": "/v1/tiktok/profile",
"data": { … }, // the normalized payload — shapes below
"credits_used": 1,
"credits_remaining": 4230,
"request_id": "req_bd41f9027ac3e6518f",
"cached": false
}Standard envelopes carry credits_used. Successful calls includecredits_remaining; errors may omit it if the balance was not read. Use credits/balance for a current balance rather than assuming a missing value is zero. request_id is the correlation id to quote in support. cached is true only when the response was re-served from the short-lived response cache (see Pagination & caching). Errors use one envelope too, documented with every type on the Errors page — failures never cost credits.
Sandbox responses identify themselves
The same envelope serves /sandbox, with two deliberate differences: endpoint echoes a /sandbox/… path (a saved sample can never masquerade as production data) and synthetic payloads carry "synthetic": true plus a warning inside data. Production /v1 never serves synthetic data — an endpoint that cannot reach a real upstream answers an honest error instead.
List responses and the cursor key
Many list endpoints use these three keys. Check the endpoint reference for named collections, extra metadata and single-page limits:
{
"items": [ … ], // fields depend on this endpoint
"count": 30,
"cursor": "eyJwYWdlIjoy…" // null when no usable next cursor was supplied
}cursor is how you page — pass it back as the cursor query parameter when that endpoint supports it. A supplied cursor is an opaque string, even where the upstream pages by number or timestamp underneath. null means no usable next cursor was supplied; it is not proof that all history was retrieved. Check has_more and warnings when present: has_more: null means continuation is unknown. Details are on Pagination & caching.
Common field families, endpoint-specific payloads
Normalization preserves source fields in readable families, but it does not make every platform or fallback payload identical. These are recurring keys, not a required schema for every response. Use the endpoint's documented fields and handle unavailable data:
| Family | Where | Recurring keys |
|---|---|---|
author | profiles, and nested inside posts/comments | id · handle · name · url · followers · verified · avatar_url |
| post / video | many social feeds, searches and single-post reads | id · url · caption/text · created_at · stats · author; availability varies |
| YouTube video | official-API video and channel-upload reads | id · title · description · published_at · channel · views · likes · comments_count |
| comment | comment lists and reply threads | id · text · created_at/published_at · likes · reply_count · author; reply previews may be incomplete |
| transcript | supported transcript endpoints | platform · url · transcript · has_transcript |
| ad | meta_ads, tiktok_ads, linkedin_ads, google_ads | identity + creative + run dates + disclosed reach/spend, per network |
| product | tiktokshop, ebay, marketplace | id · title · url · image · price.{amount,formatted,currency} · rating |
A typical author:
{
"id": "6659752019493208069",
"handle": "stoolpresidente",
"name": "Dave Portnoy",
"url": "https://www.tiktok.com/@stoolpresidente",
"followers": 4400000,
"verified": true,
"avatar_url": "https://…"
}Full-profile bundles are bounded pages
Supported social full-profile bundles return profile, a source-defined page of posts, and posts_pagination. The requested posts value is a desired page size, not a promise of that many records. A successful page may be shorter or longer. Follow posts_pagination.next_params with all its returned parameters; do not assume a data.cursor field. YouTube's channel bundle instead returns recent_videos, cursor and recent_videos_pagination.
Inspect complete, partial and legs where supplied. HTTP 200 can contain a partial bundle. complete: true means the requested components and bounded page succeeded, not that the account's entire history was collected. Missing continuation can mean unsupported or unknown pagination, not an empty history.
Computed fields and honest nulls
Source fields and arithmetic are distinct from model-generated interpretations. Where supported, formulas, sample sizes, receipts and warnings describe how derived figures were produced. Full-profile computed fields are arithmetic over the returned page, not an AI analysis. Some Panorama endpoints accept optional topics, themes or tone model passes; those outputs are labelled and are interpretations, not source facts. youtube/video-sponsors is also inferential; absence of a detected sponsor does not prove there was none.
Missing fields may be absent or null, depending on the endpoint; neither means zero or false. Source-reported zero remains zero. A transcript endpoint can return transcript: null, has_transcript: false after checking for captions; that successful check may still be billed. Inspect warnings and completeness metadata. A fallback can provide fewer fields or support different filters and pagination; unsupported controls may return an error instead of silently running a different query.
Versioning
How /v1 evolves — additive fields only, breaking changes on a new version path, and the deprecation notice with its headers — is on Versioning & deprecation.