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.
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/:idnow returns alatest_statsarray (one entry per placement) and, for placement networks, asummary_statsrollup summed across every placement.GET /api/profiles/:id/statsreturns the full timeseries — every snapshot recorded for a profile, ordered byrecorded_at, withfrom/tofilters.
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.
| Network | Placement-scoped? | Typical fields |
|---|---|---|
facebook | Yes (per page) | fan_count, followers_count, page_impressions, page_views_total, page_fan_adds, page_fan_removes |
linkedin | Yes (per organization) | followerCount, shareCount, likeCount, commentCount, clickCount, engagement, allPageViews, overviewPageViews, aboutPageViews, careersPageViews, peoplePageViews, insightsPageViews |
telegram | Yes (per channel) | followers_count, channel_title, channel_username |
instagram | No | followers_count, follows_count, media_count, reach, profile_views, accounts_engaged, total_interactions, website_clicks |
threads | No | followers_count, views, likes, replies, reposts, quotes |
youtube | No | subscriberCount, viewCount, videoCount |
twitter | No | followers_count, following_count, tweet_count, listed_count, like_count |
tiktok | No | follower_count, following_count, likes_count, video_count |
pinterest | No | follower_count, following_count, pin_count, board_count, monthly_views, analytics_30d |
bluesky | No | followersCount, 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 inlatest_stats[].statsbut are excluded fromsummary_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.
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?
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 Stats — records[].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:
- Call
GET /api/profilesto find the profile id. - Call
GET /api/profiles/:idfor the latest snapshot. - Call
GET /api/profiles/:id/statsfor the full timeseries. Passplacement_idfor Facebook, LinkedIn, and Telegram profiles.
No new scopes, no separate billing, no opt-in. Profile stats are recorded on every connected profile starting today.
Postproxy
One API for every social platform
Publish to Instagram, X, LinkedIn, TikTok, YouTube and more with a single request. Free plan, no credit card required.