curl --request POST \
--url https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"organization_urn": "<string>",
"days": 45,
"include": [],
"workspace": "<string>"
}
'import requests
url = "https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics"
payload = {
"organization_urn": "<string>",
"days": 45,
"include": [],
"workspace": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({organization_urn: '<string>', days: 45, include: [], workspace: '<string>'})
};
fetch('https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'organization_urn' => '<string>',
'days' => 45,
'include' => [
],
'workspace' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics"
payload := strings.NewReader("{\n \"organization_urn\": \"<string>\",\n \"days\": 45,\n \"include\": [],\n \"workspace\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"organization_urn\": \"<string>\",\n \"days\": 45,\n \"include\": [],\n \"workspace\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"organization_urn\": \"<string>\",\n \"days\": 45,\n \"include\": [],\n \"workspace\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"source": "linkedin_cmapi",
"provenance": "platform_reported",
"source_note": "<string>",
"connect_path": "<string>",
"read_elsewhere": {
"metric_keys": [
"<string>"
],
"tool": "<string>",
"path": "<string>"
},
"organization_urn": "<string>",
"administered_organizations": [
"<string>"
],
"window": {
"kind": "lifetime",
"days": 123,
"granularity": "DAY",
"follower_window_ends_days_ago": 123,
"follower_start_ms": 123,
"follower_end_ms": 123
},
"total_followers": 123,
"follower_demographics": {
"by_association_type": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_country": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_function": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_industry": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_geo": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_seniority": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_staff_count_range": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
}
},
"follower_gains": [
{
"start_ms": 123,
"end_ms": 123,
"organic_follower_gain": 123,
"paid_follower_gain": 123
}
],
"page_views": [
{
"start_ms": 123,
"end_ms": 123,
"all_page_views": 123,
"all_desktop_page_views": 123,
"all_mobile_page_views": 123,
"overview_page_views": 123,
"custom_button_clicks": 123
}
],
"shares": [
{
"start_ms": 123,
"end_ms": 123,
"impression_count": 123,
"unique_impressions_count": 123,
"click_count": 123,
"like_count": 123,
"comment_count": 123,
"share_count": 123,
"engagement": 123
}
],
"unavailable": [
{
"section": "<string>",
"reason": "<string>"
}
],
"workspace": "<string>",
"working_in": {
"label": "<string>",
"note": "<string>",
"workspace": "<string>",
"source": "call-override"
}
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}Call analytics.linkedin_page_analytics
‘how is our LinkedIn page doing?’, ‘who follows us on LinkedIn?’ — read this workspace’s LinkedIn company-page statistics over the grant the workspace connected: followers and their demographics, page views and clicks, and organic post engagement, optionally over a window of days. The answer names the source it read; when LinkedIn is reached only through the workspace’s CRM connection it says so and returns no LinkedIn figures. It changes nothing. Not for the cross-platform social totals — that is analytics.query_metrics.
Every result names the workspace it ran in. Say which workspace the answer is about. When the account has more than one workspace and none is selected, this tool refuses with workspace_ambiguous and lists the choices — offer them, never pick one.
curl --request POST \
--url https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"organization_urn": "<string>",
"days": 45,
"include": [],
"workspace": "<string>"
}
'import requests
url = "https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics"
payload = {
"organization_urn": "<string>",
"days": 45,
"include": [],
"workspace": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({organization_urn: '<string>', days: 45, include: [], workspace: '<string>'})
};
fetch('https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'organization_urn' => '<string>',
'days' => 45,
'include' => [
],
'workspace' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics"
payload := strings.NewReader("{\n \"organization_urn\": \"<string>\",\n \"days\": 45,\n \"include\": [],\n \"workspace\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"organization_urn\": \"<string>\",\n \"days\": 45,\n \"include\": [],\n \"workspace\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.goosybear.ai/api/v1/tools/analytics.linkedin_page_analytics")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"organization_urn\": \"<string>\",\n \"days\": 45,\n \"include\": [],\n \"workspace\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"source": "linkedin_cmapi",
"provenance": "platform_reported",
"source_note": "<string>",
"connect_path": "<string>",
"read_elsewhere": {
"metric_keys": [
"<string>"
],
"tool": "<string>",
"path": "<string>"
},
"organization_urn": "<string>",
"administered_organizations": [
"<string>"
],
"window": {
"kind": "lifetime",
"days": 123,
"granularity": "DAY",
"follower_window_ends_days_ago": 123,
"follower_start_ms": 123,
"follower_end_ms": 123
},
"total_followers": 123,
"follower_demographics": {
"by_association_type": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_country": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_function": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_industry": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_geo": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_seniority": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
},
"by_staff_count_range": {
"buckets": [
{
"key": "<string>",
"follower_count": 123
}
],
"total_buckets": 123,
"truncated": true
}
},
"follower_gains": [
{
"start_ms": 123,
"end_ms": 123,
"organic_follower_gain": 123,
"paid_follower_gain": 123
}
],
"page_views": [
{
"start_ms": 123,
"end_ms": 123,
"all_page_views": 123,
"all_desktop_page_views": 123,
"all_mobile_page_views": 123,
"overview_page_views": 123,
"custom_button_clicks": 123
}
],
"shares": [
{
"start_ms": 123,
"end_ms": 123,
"impression_count": 123,
"unique_impressions_count": 123,
"click_count": 123,
"like_count": 123,
"comment_count": 123,
"share_count": 123,
"engagement": 123
}
],
"unavailable": [
{
"section": "<string>",
"reason": "<string>"
}
],
"workspace": "<string>",
"working_in": {
"label": "<string>",
"note": "<string>",
"workspace": "<string>",
"source": "call-override"
}
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}Authorizations
An API key minted at Settings › API & MCP. Send it as Authorization: Bearer <key>. A key carries its holder's own permissions, resolved on every call — revoking a membership closes the key's reach immediately. Keep it in an environment variable (GOOSY_API_KEY), never in a committed file.
Headers
Your own id for this request, echoed back and recorded on the audit trail. 1–128 characters from A–Z a–z 0–9 . _ : -, starting with a letter or digit; anything else is replaced by a generated id.
128Body
The company page to read, as its LinkedIn page URN — the urn:li:… identifier carried on the connected grant. Omit when the connection administers exactly one page — it is then chosen automatically. If several are administered, this is required and the answer lists them.
Read a trailing window of this many days instead of lifetime totals. OMIT for the lifetime read, which is the only one that carries follower DEMOGRAPHICS (industry, seniority, function, geography) — LinkedIn drops every demographic facet from a time-bound follower query, so a window and a breakdown are two different questions.
1 <= x <= 90Which sections to read: followers (count + demographics or gains), page_views (views and custom-button clicks), shares (organic impressions, clicks, reactions, comments, engagement rate). Omit for all three. Each section is a separate LinkedIn call, so narrowing this spends less of the page's rate budget.
1followers, page_views, shares Which workspace to run in — its slug. Omit to use your default. With more than one reachable workspace and no default, the call is refused and the choices are listed.
1Response
The call was admitted and dispatched. ok says whether the tool succeeded — a refusal the tool itself produced is still a 200, exactly as it is a successful JSON-RPC result over MCP.
- Option 1
- Option 2
The tool ran and answered.
Which rail these numbers came from. linkedin_cmapi = LinkedIn's own page analytics; ghl = the workspace posts through GoHighLevel, which reports no LinkedIn-specific numbers; none = neither is connected.
linkedin_cmapi, ghl, none The trust class, on the metric dictionary's own axis. Both connected rails are platform_reported — the platform's number, subject to the platform's methodology. Null when there is no number.
platform_reported The plain-language sentence to tell the operator about where these numbers come from. Say it — never paraphrase it into a stronger claim.
Where the operator connects LinkedIn page analytics directly, when that would change the answer. Null when already connected on the direct rail.
On the ghl source ONLY: the cross-platform social metric keys LinkedIn activity is counted inside, and the tool/page that reads them. There is no LinkedIn breakdown to give — offer these instead of guessing one.
Show child attributes
Show child attributes
The company page these numbers are for. Null on the ghl and none sources, which have no page-level read.
Every company page this connection may read. More than one and organization_urn is required.
What was ACTUALLY read — not what was asked for. The two differ whenever LinkedIn's follower publication lag applies.
Show child attributes
Show child attributes
The page's total follower count, from LinkedIn's networkSizes read. It is a SEPARATE call from the follower statistics and carries no publication lag. Null when the followers section was not read or its call failed.
Lifetime read only. Bucket keys are LinkedIn URNs or enums, and each count rolls organic AND paid followers together — LinkedIn's own instruction, not an approximation. Each facet reports its FULL bucket count alongside the top few it carries; see truncated.
Show child attributes
Show child attributes
Time-bound read only. GAINS per interval, not running totals.
Show child attributes
Show child attributes
all_page_views counts every page tab across desktop and mobile; overview_page_views counts the overview tab only, so all_* is legitimately the larger number.
Show child attributes
Show child attributes
ORGANIC only — sponsored activity is not counted here and lives on the ads rail. like_count can be negative when a member unlikes a sponsored share; that is LinkedIn's number, not a bug.
Show child attributes
Show child attributes
Sections that were asked for and could not be read, each with why. A section listed here has NO number — never report it as zero.
Show child attributes
Show child attributes
The slug of the workspace this call ran in.
Which workspace this call ran in, and how that was decided. Present on every workspace-scoped result.
Show child attributes
Show child attributes