InsightSocial API

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.views holds the interested count.
  • post.engagement.likes holds 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

Instagram's nulls depend on the type of media.

  • post.engagement.saves is null everywhere except /v1/instagram/post/stats with include=saves, which reads save and repost counts for one post. List rows have no save count and stay null.
  • post.engagement.likes and post.engagement.comments are 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 return null rather than Instagram's placeholder figure.
  • When something was subtracted, the response tells you. post.ext.facebook_likes and post.ext.facebook_comments hold the Facebook part that was removed, and a note in data._warnings names 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.shares is null on the basic endpoints. Share counts come only from /v1/instagram/post/stats, /v1/instagram/profile/reels/full and /v1/instagram/profile/posts/full.
  • post.engagement.views and 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 their computed.engagement_rate and computed.estimated_reach are null too. 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/stories returns each live story's media, timestamps and IDs, with the engagement fields null. No API can return story metrics for an account you do not own.

Pinterest

Pinterest spreads its counts between the list endpoints and the pin itself.

  • Search rows have no counts: post.engagement.saves, likes (reactions), comments and shares are null on a plain /v1/pinterest/search call. Add include=engagement and each row is filled from the pin's own record in the same call, at 20 extra credits per row filled. /v1/pinterest/pin returns the same counts for a single pin for 20 credits.
  • post.engagement.views is null on search rows. Pinterest publishes no view count there.
  • Board rows have saves, comments and shares but no date: post.published_at is null on a plain /v1/pinterest/board call because the board data has no date. include=engagement fills the date from the pin, along with any missing reaction count.
  • post.content.text is the pin's title, or its description when there is no title. Many pins have neither, so null means 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.views is null on /v1/threads/user/posts and /v1/threads/search, because Threads shows a view count only on a post's own page. /v1/threads/post returns it for one post for 20 credits, and include=engagement fills it on each row of either list in the same call, at 20 extra credits per row filled. On search this 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/post call on such a post will not have a view count either.
  • post.flags.pinned is null on search rows, where Threads leaves the field out instead of sending false. include=engagement fills it.
  • author.followers and author.bio are null on /v1/threads/search/users, which returns identity only. include=profile fills both, plus the private flag and the bio link, at 20 extra credits per account filled.
  • post.author.display_name is null on user/posts by default. include=engagement fills 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.

LinkedIn

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.followers on /v1/linkedin/search/people, /v1/linkedin/company/people and /v1/linkedin/post/reactions rows 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 set author.ext.followers_approximate to true. Many rows show no figure at all, and there author.followers is null, not a guess.
  • author.following is null on every plain people-list row.
  • Send include=profile to join each row to that member's profile in the same call. author.followers becomes the exact count, author.following gets the member's connection count (on LinkedIn, following means connections), and author.location, author.joined_at, plus country, website, cover image and profile flags under author.ext, are filled where the row lacked them. Every row the join fills sets author.ext.followers_approximate to false, 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

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/posts never carry post.engagement.shares, and reels in that feed also lack post.engagement.views and post.content.duration_seconds. Facebook publishes those numbers on the post page itself, not in the feed. Send include=engagement to 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 stays null rather than 0, and that row adds nothing.
  • post.engagement.saves is always null. Facebook shows no save count anywhere.
  • A /v1/facebook/profile/photos row is the image, its caption and its link. post.author.display_name, post.author.avatar_url, post.engagement.likes, comments, shares and post.published_at are all null on a plain call. include=details fills 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, so post.engagement.views stays null either way.
  • post.ext.event.end_timestamp and post.ext.event.ticket_url are null on 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.

PlatformAlways nullWhy
YouTubepost.engagement.shares, post.engagement.savesBoth are private to the channel owner
Redditpost.engagement.views, .shares, .savesReddit shows no view or share counts, and "saved" is a per-user flag, not a count
Redditauthor.verifiedNot shown
Facebookpost.engagement.savesNot shown
Facebook, list endpointsauthor.avatar_url, post.media_urlsList rows are slimmer; on photos, include=details fills the author
Threadsauthor.following, author.posts_count, author.likes_count, author.joined_atNone of the four appear on a public Threads profile
Threadscomment.parent_idThreads does not say which reply a nested reply answers
TikTokpost.parent_id on top-level commentsOnly 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.

On this page