Metric substitutions
Which unified fields stay null on which platform, how to fill the ones a join can recover, and the one place a field carries a different metric.
All 9 platforms map onto one unified schema, but no platform publishes every field in it. When a platform does not provide a value, the response carries null.
No invented values, no borrowed metrics
A unified field never holds a made-up number, and never holds a different metric under its name. When a platform has a related metric worth keeping, it goes under ext.*, so the unified field keeps its exact meaning.
This page lists those cases. If a field is listed here as always null on a platform, that is how the platform works, not a bug. For how the computed block is derived, see Computed fields.
The one substitution
Facebook events are the only place a unified field carries a different metric. An event has no views or likes, so on /v1/facebook/profile/events and /v1/facebook/events the RSVP counts use those two fields:
post.engagement.viewsholds the interested count.post.engagement.likesholds the going count.
The same numbers are also under their own names in post.ext.event.interested_count and post.ext.event.going_count. The mapping is identical whether the value came with the row or was filled by include=details.
Instagram's nulls depend on the type of media.
post.engagement.savesisnulleverywhere except/v1/instagram/post/statswithinclude=saves, which reads save and repost counts for one post. List rows have no save count and staynull.post.engagement.likesandpost.engagement.commentsare Instagram's own counts. Some reads of a post that was also shared to Facebook include the Facebook likes and comments; those are subtracted so the number matches what instagram.com shows. Accounts that hide their like count returnnullrather than Instagram's placeholder figure.- When something was subtracted, the response tells you.
post.ext.facebook_likesandpost.ext.facebook_commentshold the Facebook part that was removed, and a note indata._warningsnames the affected rows. Add the two together for the combined figure. Both fields are absent on posts with no Facebook share, and each one is absent on its own when nothing was removed from that count. post.engagement.sharesisnullon the basic endpoints. Share counts come only from/v1/instagram/post/stats,/v1/instagram/profile/reels/fulland/v1/instagram/profile/posts/full.post.engagement.viewsand the share count exist only on video: reels, videos, and carousels that contain a video. Photos and photo-only carousels have neither, on any endpoint, so theircomputed.engagement_rateandcomputed.estimated_reacharenulltoo. Likes and comments are filled on every media type.- Stories have no engagement numbers. Story views, replies, likes and reach are private analytics for the account owner.
/v1/instagram/storiesreturns each live story's media, timestamps and IDs, with the engagement fieldsnull. No API can return story metrics for an account you do not own.
Pinterest spreads its counts between the list endpoints and the pin itself.
- Search rows have no counts:
post.engagement.saves,likes(reactions),commentsandsharesarenullon a plain/v1/pinterest/searchcall. Addinclude=engagementand each row is filled from the pin's own record in the same call, at 20 extra credits per row filled./v1/pinterest/pinreturns the same counts for a single pin for 20 credits. post.engagement.viewsisnullon search rows. Pinterest publishes no view count there.- Board rows have saves, comments and shares but no date:
post.published_atisnullon a plain/v1/pinterest/boardcall because the board data has no date.include=engagementfills the date from the pin, along with any missing reaction count. post.content.textis the pin's title, or its description when there is no title. Many pins have neither, sonullmeans the pin really has no text. Pinterest's auto-generated image caption is never used here.
Threads
Threads puts some numbers only on single posts, and the lists can fill them on request.
post.engagement.viewsisnullon/v1/threads/user/postsand/v1/threads/search, because Threads shows a view count only on a post's own page./v1/threads/postreturns it for one post for 20 credits, andinclude=engagementfills it on each row of either list in the same call, at 20 extra credits per row filled. Onsearchthis covers the first 20 rows.- Brand-new posts have no view count anywhere yet; Threads adds one later. On
search, such a row adds no credits, because the join only charges when it fills a view count or display name, and it still gets its pinned flag. A direct/v1/threads/postcall on such a post will not have a view count either. post.flags.pinnedisnullonsearchrows, where Threads leaves the field out instead of sendingfalse.include=engagementfills it.author.followersandauthor.bioarenullon/v1/threads/search/users, which returns identity only.include=profilefills both, plus the private flag and the bio link, at 20 extra credits per account filled.post.author.display_nameisnullonuser/postsby default.include=engagementfills it, and so does asking for more than 15 posts.- A join charges only for rows it fills, adds nothing for a row it serves from a recent fetch, and reports what it did in
data.hydration. See Threads.
Two author fields are weaker on people-list rows than on the member's own profile, and a join recovers both in the same call.
author.followerson/v1/linkedin/search/people,/v1/linkedin/company/peopleand/v1/linkedin/post/reactionsrows is LinkedIn's rounded display figure, not an exact count: 39,000 for a member with 39,278, or 2,000 for one with 2,344. Those rows setauthor.ext.followers_approximatetotrue. Many rows show no figure at all, and thereauthor.followersisnull, not a guess.author.followingisnullon every plain people-list row.- Send
include=profileto join each row to that member's profile in the same call.author.followersbecomes the exact count,author.followinggets the member's connection count (on LinkedIn, following means connections), andauthor.location,author.joined_at, plus country, website, cover image and profile flags underauthor.ext, are filled where the row lacked them. Every row the join fills setsauthor.ext.followers_approximatetofalse, including rows that had no count before, so the flag always tells you whether the figure is exact. Rows the join could not fill keep their original flag. - The list costs 200 credits, and the join adds 80 credits per row it fills, up to 1,000 credits in total. Rows served from a recent fetch and rows the join cannot fill add nothing.
limit(1 to 10) caps both the rows and the extra credits. See LinkedIn.
Facebook shows several per-post numbers only on the post's own page, so list rows have null there until you ask for the join.
- Rows from
/v1/facebook/profile/postsnever carrypost.engagement.shares, and reels in that feed also lackpost.engagement.viewsandpost.content.duration_seconds. Facebook publishes those numbers on the post page itself, not in the feed. Sendinclude=engagementto fill each row from its own post in the same call, at 20 extra credits per row filled. A post with no public share count staysnullrather than0, and that row adds nothing. post.engagement.savesis alwaysnull. Facebook shows no save count anywhere.- A
/v1/facebook/profile/photosrow is the image, its caption and its link.post.author.display_name,post.author.avatar_url,post.engagement.likes,comments,sharesandpost.published_atare allnullon a plain call.include=detailsfills them from the photo's own post, at 20 extra credits per photo filled. A photo posted alone carries that post's counts; a photo inside a multi-photo post carries its own, usually much lower. Photos have no view count, sopost.engagement.viewsstaysnulleither way. post.ext.event.end_timestampandpost.ext.event.ticket_urlarenullon both event lists, with or without the join. Facebook did not publish either on any event checked, so the join cannot promise them.- A Facebook join charges only for rows it fills, adds nothing for rows served from a recent fetch, and reports what it did in
data.hydration. See Facebook.
Always-null fields by platform
These fields are null on every surface of a platform because the platform never shows them. No parameter will fill them.
| Platform | Always null | Why |
|---|---|---|
| YouTube | post.engagement.shares, post.engagement.saves | Both are private to the channel owner |
post.engagement.views, .shares, .saves | Reddit shows no view or share counts, and "saved" is a per-user flag, not a count | |
author.verified | Not shown | |
post.engagement.saves | Not shown | |
| Facebook, list endpoints | author.avatar_url, post.media_urls | List rows are slimmer; on photos, include=details fills the author |
| Threads | author.following, author.posts_count, author.likes_count, author.joined_at | None of the four appear on a public Threads profile |
| Threads | comment.parent_id | Threads does not say which reply a nested reply answers |
| TikTok | post.parent_id on top-level comments | Only replies have a parent |
One field has a default instead of a null: a single tweet from Twitter/X has no pinned flag, so post.pinned is false.
Defaults we set
/v1/instagram/search/hashtag uses type=top when you leave type out, so results are predictable. Send type=recent or type=clips to change it.
Testing your integration
Test against the live API without surprises. What is free, what is billed, and which paths to check before launch.
Which endpoint should I use?
Side-by-side decision tables for the endpoints that look alike, with the credit price of each so you pick the one that returns what you need for the least.