Post
The schema-2 post object. Every field, its type, and which platforms fill it.
Any endpoint that returns a post returns it in this shape, whichever platform it came from. Write one parser and it reads posts from every platform the API serves. This page describes schema 2, which every key gets from October 4, 2026. What changed from the previous shape is on Schema 2.
Where posts sit in data
| Endpoint returns | Path |
|---|---|
One post (/v1/instagram/post, /v1/youtube/video, …) | data.post |
A list of posts (/v1/instagram/profile/posts, /v1/tiktok/search, …) | data.items[].post |
A list also carries data.total, the total the platform states (not the size of this page), and data.truncated, true when the platform cut the list short. Both are null when the platform does not say. The next page is in pagination.next_cursor; see Pagination.
Example
One row from /v1/instagram/profile/posts?handle=nasa, shortened:
{
"success": true,
"platform": "instagram",
"endpoint": "/v1/instagram/profile/posts",
"schema_version": "2",
"data": {
"items": [
{
"post": {
"id": "3983374110243288826",
"url": "https://www.instagram.com/nasa/p/DdHyaYAifb6/",
"kind": "carousel",
"content": {
"text": "Cementing their names in history. …",
"media_urls": ["https://scontent-lga3-2.cdninstagram.com/v/…", "https://scontent-lga3-3.cdninstagram.com/v/…"],
"thumbnail_url": null,
"duration_seconds": null
},
"author": {
"id": "528817151",
"username": "nasa",
"display_name": "NASA",
"avatar_url": "https://scontent-lga3-1.cdninstagram.com/v/…",
"verified": true
},
"engagement": { "views": null, "likes": 120041, "comments": 978, "shares": null, "saves": null },
"flags": {
"nsfw": null, "spoiler": null, "pinned": true, "deleted": false,
"likes_hidden": null, "comments_hidden": null, "shares_hidden": null,
"views_hidden": null, "saves_hidden": null
},
"published_at": "2026-09-10T21:20:24.000Z",
"language": null,
"ext": { "media_type": "carousel", "carousel_count": 4 }
}
}
],
"total": null,
"truncated": null
},
"pagination": { "next_cursor": "v2c.ZIyWbi3x…", "has_more": true, "page_size": 12 },
"unavailable": [],
"credits_used": 10,
"credits_remaining": 9990,
"request_id": "req_bc4ed40ba570",
"cached": false,
"idempotent_replay": false,
"charge_reason": "miss",
"free_call": false
}Fields
Every field below is always present. A value the platform does not give is null, never left out and never a placeholder.
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string | No | The platform's ID for the post. Always a string. Never parse it as a number: Instagram and X IDs are larger than 2^53. |
url | string | Yes | Link to the post on the platform. |
kind | string | Yes | The post's format: text, image, carousel, video, short, live, article or link. short is short-form vertical video (a reel, a TikTok, a YouTube Short). null when the platform does not say and it cannot be read without guessing. More values may be added, so keep a default branch when you switch on it. |
content.text | string | Yes | Caption, description or body text. |
content.media_urls | string[] | Yes | Main media, always an array, one URL per item, even for a single photo. null when the platform gives none. |
content.thumbnail_url | string | Yes | Thumbnail image. |
content.duration_seconds | number | Yes | Length of a video or clip in seconds. null when the post is not a video. |
author.id | string | Yes | The author's platform ID. On Reddit it is the account's t2_… ID, prefix kept. On LinkedIn a person's member URN (ACoAA…), as on their profile, with the numeric member id in ext.author_member_id; a company's numeric id. null where the source gives none; see Which platforms fill which fields. |
author.username | string | Yes | The author's handle. |
author.display_name | string | Yes | The author's display name. On Reddit usually null: Reddit shows a username, and the t2_… ID that arrives in this place goes to author.id. |
author.avatar_url | string | Yes | The author's profile picture. |
author.verified | boolean | Yes | Whether the author is verified. |
engagement.views | integer | Yes | Views where the platform shows them. On Instagram videos and reels this is the play count shown in the app, and it counts Instagram plays only, not views of a copy cross-posted to Facebook. Fetch the Facebook copy with /v1/facebook/post if you need both. |
engagement.likes | integer | Yes | Likes or reactions. On Reddit a score below zero is not a like count: likes is null and the score is in ext.score. |
engagement.comments | integer | Yes | Comment count. On /v1/instagram/post it counts top-level comments; the Instagram list endpoints count all comments including replies. Both use this field. |
engagement.shares | integer | Yes | Shares, reposts or retweets. On Instagram this is the Send count, available only from /v1/instagram/post/stats, /v1/instagram/profile/reels/full and /v1/instagram/profile/posts/full; other Instagram endpoints return null. |
engagement.saves | integer | Yes | Saves or bookmarks. |
flags.nsfw | boolean | Yes | Marked as adult content. null when the platform does not say. |
flags.spoiler | boolean | Yes | Marked as a spoiler. null when the platform does not say. |
flags.pinned | boolean | Yes | Pinned to the profile. null when the platform does not say. |
flags.deleted | boolean | No | The post has been deleted or removed. Always true or false. |
flags.likes_hidden | boolean | Yes | true when the creator hides the like count; engagement.likes is then null. null on ordinary posts. |
flags.comments_hidden | boolean | Yes | true when the comment count is hidden; engagement.comments is then null. |
flags.shares_hidden | boolean | Yes | true when the share count is hidden; engagement.shares is then null. |
flags.views_hidden | boolean | Yes | true when the view count is hidden; engagement.views is then null. |
flags.saves_hidden | boolean | Yes | true when the save count is hidden; engagement.saves is then null. |
published_at | string | Yes | When the post was published, as ISO 8601 in UTC, ending in Z. Platforms that send Unix timestamps are converted. |
language | string | Yes | The post's language as the platform itself states it, such as en or pt-BR. null when the platform gives no tag. We do not detect languages. |
ext | object | Yes | Platform-specific fields. See below. |
Counts: null is not 0
A count is a whole number of zero or more, or null. null means the platform does not show it, or hides it on this post. 0 means it really is zero. Do not add a null into a total as if it were zero.
Extension fields (ext)
Platform-specific extras. Each one appears only on platforms that provide it and is left out elsewhere, so treat all of them as optional. They hold detail the unified fields cannot, and the IDs that let you pass a result from one endpoint into the next. ext is null when a post has no extras.
Keys are always snake_case, on every platform, YouTube included (made_for_kids, category_id). An ext value whose key ends in _id is a string, and one whose key ends in _at is an ISO 8601 UTC time. ext never carries our cursors or tokens; page with pagination.next_cursor.
| Field | Type | Nullable | Description |
|---|---|---|---|
ext.music_id | string | Yes | TikTok sound ID. Pass it to /v1/tiktok/song/videos?clipId= to find other videos using the same sound. |
ext.author_followers | integer | Yes | The author's follower count as carried on the row: X and TikTok post rows, and searches that include it. A snapshot, not live. Always null on Instagram rows; call /v1/instagram/profile?handle= for the exact current count. |
ext.author_following | integer | Yes | Following count included in the row, when present. |
ext.author_posts_count | integer | Yes | The author's post count included in the row, when present. |
ext.download_count | integer | Yes | TikTok only. How many times the video was downloaded to a device. Separate from engagement.saves, which counts saves to an in-app collection. |
ext.region | string | Yes | TikTok only. The ISO 3166-1 alpha-2 country the video is registered to, usually the creator's account country. It is not the viewer's country or a language. On /v1/tiktok/trending, /v1/tiktok/search and /v1/tiktok/search/top, filter on it to keep rows from one country. |
ext.subreddit | string | Yes | Reddit subreddit name on search and list rows. Pass it to /v1/reddit/subreddit/details?subreddit=. |
ext.title | string | Yes | Post title, where the platform separates title from body. |
ext.selftext | string | Yes | Reddit text-post body. |
ext.upvote_ratio | integer | Yes | Reddit only. Share of votes that are upvotes, from 0 to 1. The value is a fraction even though the type says integer. Filled on /v1/reddit/search rows where available, null elsewhere. |
ext.flair | string | Yes | Reddit post flair. |
ext.type | string | Yes | Platform's own post type. |
ext.content_type | string | Yes | Platform's own content type. kind is read from it where it is present. |
ext.video_view_count | integer | Yes | Instagram's old 3-second view count. No longer served, so new lookups do not carry it. Use engagement.views. |
ext.ig_play_count | integer | Yes | Instagram's own play count, shown separately so you can tell it apart from any combined figure. Present on /v1/instagram/post/stats, and on /v1/instagram/post for videos. |
ext.repost_count | integer | Yes | Repost count, where it is separate from shares. |
ext.media_type | string | Yes | Platform's media type (photo, video, carousel and so on). kind is read from it where it is present. |
ext.text_truncated | boolean | Yes | true when the text was cut short on this surface. |
ext.ip_location | string | Yes | Location the platform displays for the poster, where shown. |
ext.carousel_count | integer | Yes | Number of items in a carousel. |
ext.remix_count | integer | Yes | Number of remixes. |
ext.facebook_likes | integer | Yes | Instagram only. Facebook likes from a cross-post that were removed from engagement.likes, so that field matches what instagram.com shows. Add them back for a combined figure. Absent when nothing was removed or the like count is hidden. |
ext.facebook_comments | integer | Yes | Instagram only. The comment equivalent of ext.facebook_likes. Each of the two appears only for the count it changed. |
ext.usertags | string[] | Yes | Accounts tagged in the post. |
ext.coauthors | string[] | Yes | Instagram Collab posts. Every co-author as { id, username, full_name, is_verified, profile_pic_url }. A Collab post has one creator but shows on every co-author's grid, so post.author may not be the profile you asked for. All accounts on the post are post.author.username plus each username here. An empty array means not a Collab. Absent where there is no signal, including on /v1/instagram/post; use /v1/instagram/post/stats for a single post. |
ext.music | string | Yes | Music or sound attached to the post. |
ext.sponsor_tags | string[] | Yes | Sponsor or paid-partnership tags. |
ext.location | string | Yes | Location tagged on the post. |
ext.quoted_post | string | Yes | Threads quote posts. The quoted post as { id, url, author: { id, username }, text, media_urls, thumbnail_url }. A quote post often has no text or media of its own, and what you see on its page belongs to the quoted post by another author. It stays here so content.* always describes the outer post. Absent on posts that are not quotes. |
ext.retweeted_post | string | Yes | Twitter/X: the original post behind a retweet. |
ext.quote_count | integer | Yes | Number of quote posts. |
ext.all_media_urls | string[] | Yes | Every media URL on the post. |
ext.reaction_counts | string[] | Yes | Counts broken down by reaction type. |
ext.share_urn | string | Yes | LinkedIn share URN. |
ext.post_type | string | Yes | Platform's post type. |
ext.activity_id | string | Yes | LinkedIn activity ID. |
ext.published_at_precision | string | Yes | How precise published_at is when the platform shows only a relative or rounded time. |
ext.author_urn | string | Yes | LinkedIn URN of the author. |
ext.author_headline | string | Yes | LinkedIn headline of the author. |
ext.author_type | string | Yes | Whether the LinkedIn author is a person or a company. |
ext.is_repost_quote | boolean | Yes | true when a repost adds its own commentary. |
ext.article | string | Yes | LinkedIn article attached to the post. |
ext.reaction_type | string | Yes | The reaction a member left, on reaction lists. |
ext.download_media_urls | string[] | Yes | Downloadable media URLs, when requested. |
ext.tags | string[] | Yes | Tags attached to the post. |
ext.category_id | string | Yes | YouTube category ID. |
ext.category_title | string | Yes | YouTube category name. |
ext.topic_categories | string[] | Yes | YouTube topic categories. |
ext.duration | string | Yes | YouTube duration in its original format. |
ext.license | string | Yes | YouTube license. |
ext.made_for_kids | boolean | Yes | YouTube made-for-kids flag. |
ext.default_audio_language | string | Yes | YouTube default audio language. |
ext.has_paid_product_placement | boolean | Yes | YouTube paid product placement flag. |
ext.caption | string | Yes | YouTube caption status. |
ext.position | integer | Yes | Position in a YouTube playlist. |
ext.playlist_id | string | Yes | YouTube playlist ID. |
ext.video_owner_channel_id | string | Yes | Channel that owns a video in a playlist. |
ext.video_published_at | string | Yes | When a playlist video was published. |
ext.description | string | Yes | Full description, where separate from content.text. |
ext.playlist_item_id | string | Yes | YouTube playlist item ID. |
ext.playlist_owner_channel_id | string | Yes | Channel that owns the playlist. |
ext.playlist_owner_title | string | Yes | Name of the playlist owner. |
ext.published_label | string | Yes | The relative time label the platform shows, such as "3 days ago". |
ext.published_precision | string | Yes | How precise the published time is. |
ext.video_count | integer | Yes | Number of videos, on playlist or collection rows. |
ext.commerce | string | Yes | Shopping or commerce details attached to the post. |
ext.on_screen_texts | string[] | Yes | Text shown on screen in the video. |
ext.topic_tag | string | Yes | Threads topic tag. |
ext.topic_tag_id | string | Yes | Threads topic tag ID. |
ext.reshare_count | integer | Yes | Reshare count, where reported separately. |
ext.ad | string | Yes | Facebook Ad Library details, on /v1/facebook/adlibrary/ad and /v1/facebook/adlibrary/company/ads rows: page_id, currency, spend, reach_estimate, publisher_platforms, categories, targeted_or_reached_countries, cta_text, cta_type, link_url, is_active, end_date_iso, display_format, title, video_hd_url, video_sd_url. Absent elsewhere. |
ext.feedback_id | string | Yes | Facebook feedback ID, used to fetch comments and replies. |
ext.event | string | Yes | Facebook event details, including interested_count, going_count, end_timestamp and ticket_url. |
ext.trend | string | Yes | TikTok trend-board data. On /v1/tiktok/hashtags/popular: rank, country_code, period_days, posts and views for the period (not lifetime), industry, industry_id, industry_label for the first board read (null for the overall board), boards listing every board the hashtag ranks on as { industry, industry_id, industry_label, rank }, popularity_curve as { date, value } with value 0 to 100 relative to the period's peak, and top_creators. On /v1/tiktok/videos/popular: rank, country_code, period_days, order_by, period_views, organic_views, engagement_rate, six_second_view_through_rate, content_tags. Absent elsewhere. |
ext.updated_at | string | Yes | When the post was last edited, where shown. |
ext.score | integer | Yes | Reddit only. A post score below zero. A negative score is not a like count, so engagement.likes is null and the score is kept here. Absent when the score is zero or above. |
Which platforms fill which fields
Every platform returns this shape. id and flags.deleted are never null. The table covers the nine platforms the API launched with. The others return the same shape, and each response's unavailable list names the fields it could not fill. How to read the table: yes marks a field the platform is able to supply, though any single row can still have it null. An empty cell marks a field that platform never supplies, so expect null every time.
| Platform | author.verified | engagement.saves | engagement.shares | content.duration_seconds | engagement.views | author.avatar_url | engagement.comments | content.media_urls | url | engagement.likes | content.thumbnail_url | flags.pinned |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | |||
| yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | ||
| yes | yes | yes | yes | yes | yes | yes | yes | |||||
| yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | |||
| yes | yes | yes | yes | yes | yes | yes | yes | |||||
| Threads | yes | yes | yes | yes | yes | yes | yes | yes | yes | |||
| TikTok | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes |
| Twitter/X | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | |
| YouTube | yes | yes | yes | yes | yes | yes | yes | yes |
Instagram saves come only from /v1/instagram/post/stats with include=saves. See Metric substitutions for the full list of per-platform nulls.
The three fields schema 2 added are filled where the platform gives them:
author.id: Facebook, Instagram list endpoints, LinkedIn, TikTok, YouTube (the channel ID) and Reddit, where it is the account'st2_…ID with the prefix kept, the same value comments and profiles carry. On Threads, Twitter/X and Pinterest the source usually gives none, so it isnulland the response lists it inunavailable.kind: read from the platform's own media or content type where it sends one (Instagram, YouTube), and otherwise only where the format is certain: a reel or Shorts URL, a TikTok video, a LinkedIn article.nullotherwise.language: only where the platform tags it, such as YouTube, Reddit and Twitter/X.
unavailable
When a field the platform normally fills is null on every post in a response, the response lists its path in unavailable, for example "items[].post.author.id". One filled row is enough to keep a field off the list. Fields a platform never shows publicly are never listed, so you are not told on every call:
| Platform | Never listed in unavailable |
|---|---|
engagement.shares, engagement.saves | |
author.username, engagement.saves | |
| Threads | engagement.saves |
| YouTube | engagement.shares, engagement.saves |
engagement.views, engagement.shares, engagement.saves, author.display_name | |
engagement.views, engagement.saves | |
engagement.views |
Instagram shares and saves are on the list because only the endpoints named above fill them; a plain Instagram post leaves them null without that being a gap. TikTok and Twitter/X have nothing on the list. kind, content.* and language are never listed on any platform, because null there usually describes the post (a photo has no duration) rather than a missing field.
More on this in Data availability.
Returned by
Endpoints that return a post or a list of posts use this shape on:
Facebook · Instagram · LinkedIn · Pinterest · Reddit · Threads · TikTok · Twitter/X · YouTube
To see which native platform field feeds each unified field, read Field equivalence.