Profile stats: follower and engagement timeseries via API

Postproxy now records follower counts and engagement metrics for every connected profile across all ten networks, exposed as a unified timeseries endpoint.

Profile stats: follower and engagement timeseries via API
Quick answer

Postproxy now captures stats snapshots for every connected profile across all ten networks. GET /api/profiles/:id returns the latest snapshot, and GET /api/profiles/:id/stats returns the full timeseries. Facebook pages, LinkedIn organizations, and Telegram channels are scoped per placement, with a summary_stats rollup summed across them.

What changed

Two endpoints joined the Profiles API:

  • GET /api/profiles/:id now returns a latest_stats array (one entry per placement) and, for placement networks, a summary_stats rollup summed across every placement.
  • GET /api/profiles/:id/stats returns the full timeseries — every snapshot recorded for a profile, ordered by recorded_at, with from / to filters.

Which networks are covered?

All ten. Facebook, Instagram, LinkedIn, TikTok, YouTube, X (Twitter), Threads, Pinterest, Bluesky, Telegram — every platform Postproxy publishes to is also polled for profile-level stats.

Three of them — Facebook, LinkedIn, and Telegram — are placement-scoped. A Facebook profile may have many pages, a LinkedIn profile may have many organizations, a Telegram bot may have many channels. Each placement gets its own timeseries; the summary_stats block sums numeric fields across them so a single number is still available without iterating.

What fields does each platform expose?

The stats object is a passthrough — keys come straight from each network’s API. They are not normalized into a shared schema, because the platforms do not agree on what “engagement” means and a forced common shape would either drop signal or invent fields that do not exist.

NetworkPlacement-scoped?Typical fields
facebookYes (per page)fan_count, followers_count, page_impressions, page_views_total, page_fan_adds, page_fan_removes
linkedinYes (per organization)followerCount, shareCount, likeCount, commentCount, clickCount, engagement, allPageViews, overviewPageViews, aboutPageViews, careersPageViews, peoplePageViews, insightsPageViews
telegramYes (per channel)followers_count, channel_title, channel_username
instagramNofollowers_count, follows_count, media_count, reach, profile_views, accounts_engaged, total_interactions, website_clicks
threadsNofollowers_count, views, likes, replies, reposts, quotes
youtubeNosubscriberCount, viewCount, videoCount
twitterNofollowers_count, following_count, tweet_count, listed_count, like_count
tiktokNofollower_count, following_count, likes_count, video_count
pinterestNofollower_count, following_count, pin_count, board_count, monthly_views, analytics_30d
blueskyNofollowersCount, followsCount, postsCount

Two filters Postproxy applies on top of the raw passthrough:

  • LinkedIn page-view metrics are collapsed to the rollups — redundant mobile/desktop splits and dead sections (productsPageViews, lifeAtPageViews) are dropped.
  • Non-numeric fields (e.g. Telegram’s channel_title) appear in latest_stats[].stats but are excluded from summary_stats.stats, which sums numeric values only.

A key only appears in a snapshot if the platform returned a value for it on that pull, so individual fields can come and go between records — code that reads stats should treat every key as optional.

How do you read the latest snapshot?

Already calling GET /api/profiles/:id? The new fields are additive — latest_stats and summary_stats show up alongside the existing profile attributes.

Terminal window
curl "https://api.postproxy.dev/api/profiles/prof_abc123" \
-H "Authorization: Bearer YOUR_API_KEY"

For a Facebook profile with two pages, the response shape is:

{
"id": "prof_abc123",
"platform": "facebook",
"name": "Acme Inc.",
"latest_stats": [
{
"placement_id": "111111111111",
"stats": { "fan_count": 12450, "page_impressions": 38210, "page_fan_adds": 42 },
"recorded_at": "2026-05-20T06:14:00Z"
},
{
"placement_id": "222222222222",
"stats": { "fan_count": 880, "page_impressions": 4120, "page_fan_adds": 6 },
"recorded_at": "2026-05-20T06:14:00Z"
}
],
"summary_stats": {
"stats": { "fan_count": 13330, "page_impressions": 42330, "page_fan_adds": 48 },
"recorded_at": "2026-05-20T06:14:00Z"
}
}

For non-placement networks (Bluesky, X, Threads, Instagram, TikTok, YouTube, Pinterest), latest_stats contains a single entry with placement_id: null and summary_stats is null.

If latest_stats is empty, the profile is connected but has not been polled yet.

How do you pull the full timeseries?

Terminal window
curl "https://api.postproxy.dev/api/profiles/prof_abc123/stats?placement_id=111111111111&from=2026-04-01T00:00:00Z" \
-H "Authorization: Bearer YOUR_API_KEY"

Response:

{
"data": {
"profile_id": "prof_abc123",
"platform": "facebook",
"placement_id": "111111111111",
"records": [
{ "stats": { "fan_count": 12380, "page_impressions": 35120 }, "recorded_at": "2026-04-01T06:12:00Z" },
{ "stats": { "fan_count": 12395, "page_impressions": 36040 }, "recorded_at": "2026-04-02T06:12:00Z" }
]
}
}

Records are ordered ascending by recorded_at. from and to accept ISO 8601 timestamps and apply inclusively.

placement_id is required for facebook, linkedin, and telegram — one timeseries per placement, so the endpoint must be scoped to one. Omit it (or pass it; it is ignored) for the other networks.

{ "error": "placement_id is required for linkedin profiles" }

The shape mirrors Post Statsrecords[].stats + recorded_at — so charting code written for post-level timeseries works for profile-level timeseries without modification.

Where this fits

For teams already wiring up Post Stats, Profile Stats slots into the same reporting pipeline:

  • Reporting dashboards. Two queries — profile-level for follower trends, post-level for per-piece performance — cover the whole picture.
  • Client portals. Agencies and white-label tools can surface follower growth charts for each connected account without standing up a separate analytics integration.
  • Internal benchmarking. Compare engagement rate (sum of likes/comments/shares ÷ followers) across networks in one query loop, since both numerator and denominator come from the same endpoint.
  • Multi-brand setups. One profile group per brand keeps each client’s stats isolated under the same API surface.

Getting started

If you already have a Postproxy account:

  1. Call GET /api/profiles to find the profile id.
  2. Call GET /api/profiles/:id for the latest snapshot.
  3. Call GET /api/profiles/:id/stats for the full timeseries. Pass placement_id for Facebook, LinkedIn, and Telegram profiles.

No new scopes, no separate billing, no opt-in. Profile stats are recorded on every connected profile starting today.

Ready to get started?

Start with our free plan and scale as your needs grow. No credit card required.