Get per-post analytics
Returns LinkedIn's own "Post analytics" screen for one of the connected account's posts: Discovery (impressions, members reached, in/out-of-network split), Profile activity (profile viewers and followers gained from the post), Engagement (reactions, comments, reposts, saves and sends), Link engagements (Premium custom button clicks and visits to links in the post), and viewer demographics by job title, location, seniority, company, industry and company size. Name the post any way you have it — an activity id, a share or ugcPost id/urn, a `/feed/update/` URL, a `/posts/` slug or an `lnkd.in` short link. Analytics itself only answers to the ACTIVITY id and a post's three ids are different numbers, so the route translates first and reports which step answered in `resolvedFrom`. Only the connected account's own posts have analytics; another member's post returns no numbers. Counts are LinkedIn's own estimates. Nulls are expected, and they are not errors. Every count is nullable and resolves independently. `linkEngagements` is populated only for Premium accounts on posts that carry a link. The Profile activity, Engagement and Link engagement cards are read off LinkedIn's rendered page by their English labels, so an account whose LinkedIn interface is in another language receives null for those fields while impressions, reach, the split and demographics still populate.
/analytics/post/summaryCode Examples
curl -X POST 'https://api.connectsafely.ai/linkedin/analytics/post/summary' \ -H 'Authorization: Bearer <your_api_key>' \ -H 'Content-Type: application/json' \ -d '{"postUrl":"https://www.linkedin.com/feed/update/urn:li:activity:7514941668970831872/"}'Returns LinkedIn's own "Post analytics" screen for one of the connected account's posts: Discovery (impressions, members reached, in/out-of-network split), Profile activity (profile viewers and followers gained from the post), Engagement (reactions, comments, reposts, saves and sends), Link engagements (Premium custom button clicks and visits to links in the post), and viewer demographics by job title, location, seniority, company, industry and company size.
Name the post any way you have it — an activity id, a share or ugcPost id/urn, a /feed/update/ URL, a /posts/ slug or an lnkd.in short link. Analytics itself only answers to the ACTIVITY id and a post's three ids are different numbers, so the route translates first and reports which step answered in resolvedFrom.
Only the connected account's own posts have analytics; another member's post returns no numbers. Counts are LinkedIn's own estimates.
Nulls are expected, and they are not errors. Every count is nullable and resolves independently. linkEngagements is populated only for Premium accounts on posts that carry a link. The Profile activity, Engagement and Link engagement cards are read off LinkedIn's rendered page by their English labels, so an account whose LinkedIn interface is in another language receives null for those fields while impressions, reach, the split and demographics still populate.
Parameters
No parameters.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
postUrl | string | Yes | The post, named any way you have it: an activity id, a share or ugcPost id/urn, a /feed/update/ URL, a /posts/ slug, or an lnkd.in short link. |
accountId | string | No | LinkedIn account ID to use. If omitted, uses the default account. |
Example
{
"postUrl": "https://www.linkedin.com/feed/update/urn:li:activity:7514941668970831872/"
}Responses
| Status | Description |
|---|---|
| 200 | Post analytics retrieved successfully |
| 400 | The post reference could not be resolved to an activity id (code: UNRESOLVABLE_POST_ID) |
| 401 | Unauthorized - invalid or missing API key |
| 500 | Internal Server Error - could not resolve credentials, or the analytics fetch failed (the exact upstream error is returned) |
200 Response Parameters
| Name | Type | Description |
|---|---|---|
success | boolean | |
accountId | string | LinkedIn account ID used |
activityId | string | The activity id the input resolved to |
resolvedFrom | string | Which step produced the activity id: the input already was one, a previously scraped row paired it (no LinkedIn call), or the post was scraped to find it. |
data | object |
200 Example
{
"success": true,
"accountId": "696ce9e780e0483585e4e553",
"activityId": "7514941668970831872",
"resolvedFrom": "input",
"data": {
"impressions": 18837,
"membersReached": 11850,
"impressionsBreakdown": [
{
"label": "In-network (followers and connections)",
"percentage": 1
},
{
"label": "Out-of-network",
"percentage": 99
}
],
"profileActivity": {
"profileViewers": 18,
"followersGained": 0
},
"engagement": {
"socialEngagements": 33,
"reactions": 27,
"comments": 2,
"reposts": 0,
"saves": 1,
"sends": 3
},
"linkEngagements": {
"total": 1,
"premiumCustomButton": 1,
"linkVisits": 0
},
"demographics": {
"overview": [
{
"label": "Senior",
"percentage": 29,
"category": "Seniority"
},
{
"label": "Software Development",
"percentage": 23,
"category": "Industry"
}
],
"categories": [
{
"category": "Seniority",
"entries": [
{
"label": "Senior",
"percentage": 29
},
{
"label": "Entry",
"percentage": 24
}
],
"hasData": true
},
{
"category": "Location",
"entries": [],
"hasData": false
}
]
}
}
}