API REFERENCE

Get Post Stats

On this page
GET/api/posts/{id}/stats

The platform's own analytics for one post published with Create Post, read live through the same connection that published it. Currently LinkedIn company-page posts only; other platforms and LinkedIn personal (member) posts return 422. Each call is a fresh read and as_of records when it happened. Each successful read costs $0.001 (1,000 credits), charged to the caller after LinkedIn returns the numbers. Credits are checked first; a request that fails (4xx/5xx) is not charged.

Authentication

x-api-key in header

bearerAuth bearer

Request

cURL
curl --request GET \
  --url 'https://api.recoupable.dev/api/posts/YOUR_ID/stats' \
  --header 'x-api-key: YOUR_API_KEY'

Replace the YOUR_ placeholders with your values. Required query parameters are included; optional parameters are listed below.

Try it

Fill in the fields, send the request from your browser, and read the live response. The curl below updates as you type.

Kept in this browser tab only and cleared when it closes.

cURL for this request
curl --request GET \
  --url 'https://recoup-api.vercel.app/api/posts/{id}/stats'

Parameters

Path parameters

idstringrequired

The post's id, from Create Post.

Responses

200The post's current stats.

application/json

statusstring · enumrequired

Status of the request

Values: "success"

statsobjectrequired
Properties for stats
post_idstringrequired

The post's id.

Example: "3f8e2c1a-5b7d-4e9f-a1c2-6d4b8e0f2a91"

format: uuid

platformstringrequired

The platform the post was published to.

Example: "linkedin"

post_urlstringrequired

The live post's URL.

Example: "https://www.linkedin.com/feed/update/urn:li:share:7389012345678901248"

impressionsinteger | nullrequired

Times the post was shown. null when the platform does not report it.

Example: 412

unique_impressionsinteger | nullrequired

Distinct members the post was shown to. null when the platform does not report it.

Example: 287

clicksinteger | nullrequired

Clicks on the post's content, company name or logo. null when the platform does not report it.

Example: 19

likesinteger | nullrequired

Likes (reactions). null when the platform does not report it.

Example: 14

commentsinteger | nullrequired

Comments. null when the platform does not report it.

Example: 3

sharesinteger | nullrequired

Reposts. null when the platform does not report it.

Example: 2

engagementnumber | nullrequired

LinkedIn's engagement rate for the post, from 0 to 1. null when the platform does not report it.

Example: 0.0922

video_viewsinteger | nullrequired

Times the post's video was viewed; LinkedIn counts a view at 3 or more seconds. null for non-video posts or when LinkedIn returns none.

Example: 356

viewersinteger | nullrequired

Distinct members who viewed the post's video. null for non-video posts or when LinkedIn returns none.

Example: 241

watch_time_msinteger | nullrequired

Total time the post's video was watched, in milliseconds. null for non-video posts or when LinkedIn returns none.

Example: 2847000

as_ofstringrequired

Server time of the read.

Example: "2026-10-25T18:04:12Z"

format: date-time

400id is not a valid uuid.

application/json

statusstring · enumrequired

Always error

Values: "error"

missing_fieldsarray<one of>

JSON path segments to the first field that failed validation, e.g. ["description"]

Item properties for missing_fields
oneOf · string 1

string

oneOf · integer 2

integer

errorstringrequired

Human-readable error message

401Unauthorized.

application/json

statusstring · enumrequired

Always error

Values: "error"

missing_fieldsarray<one of>

JSON path segments to the first field that failed validation, e.g. ["description"]

Item properties for missing_fields
oneOf · string 1

string

oneOf · integer 2

integer

errorstringrequired

Human-readable error message

402Insufficient credits: the account has less than the $0.001 a read costs. Returned after the 400/401/403/404/409/422 checks and before LinkedIn is called, so nothing is read and nothing is charged.

application/json

errorstring · enumrequired

Values: "insufficient_credits"

remaining_creditsintegerrequired

Example: 0

required_creditsintegerrequired

Example: 250000

billingUrlstringrequired

Static link to the Recoup app, where a human can save a card and buy credits. It is a constant, not a freshly minted Stripe Checkout Session, so a credit-gated endpoint that keeps returning 402 creates nothing. To buy credits programmatically, call POST /api/credits/sessions.

Example: "https://app.recoupable.dev"

403Access denied to this post's account.

application/json

statusstring · enumrequired

Always error

Values: "error"

missing_fieldsarray<one of>

JSON path segments to the first field that failed validation, e.g. ["description"]

Item properties for missing_fields
oneOf · string 1

string

oneOf · integer 2

integer

errorstringrequired

Human-readable error message

404No post with that id.

application/json

statusstring · enumrequired

Always error

Values: "error"

missing_fieldsarray<one of>

JSON path segments to the first field that failed validation, e.g. ["description"]

Item properties for missing_fields
oneOf · string 1

string

oneOf · integer 2

integer

errorstringrequired

Human-readable error message

409The post cannot be read yet. Either it is not published (its status is not posted or it has no post_url; error Post is not published yet, so it has no stats), or the platform is not connected for the post's account (error linkedin is not connected for this account). This is checked before 422, so an unpublished post on any platform returns 409.

application/json

statusstring · enumrequired

Always error

Values: "error"

missing_fieldsarray<one of>

JSON path segments to the first field that failed validation, e.g. ["description"]

Item properties for missing_fields
oneOf · string 1

string

oneOf · integer 2

integer

errorstringrequired

Human-readable error message

422Stats are not supported for this post. Only LinkedIn company-page posts are supported today. Errors: Stats are not available for <platform> posts yet (any other platform), Stats are available for LinkedIn company-page posts only (a LinkedIn personal post), post_url does not name a LinkedIn post.

application/json

statusstring · enumrequired

Always error

Values: "error"

missing_fieldsarray<one of>

JSON path segments to the first field that failed validation, e.g. ["description"]

Item properties for missing_fields
oneOf · string 1

string

oneOf · integer 2

integer

errorstringrequired

Human-readable error message

500Internal server error.

application/json

statusstring · enumrequired

Always error

Values: "error"

missing_fieldsarray<one of>

JSON path segments to the first field that failed validation, e.g. ["description"]

Item properties for missing_fields
oneOf · string 1

string

oneOf · integer 2

integer

errorstringrequired

Human-readable error message

502The platform rejected the stats read, for example because the connection lacks analytics access (error LinkedIn rejected the stats read for this post).

application/json

statusstring · enumrequired

Always error

Values: "error"

missing_fieldsarray<one of>

JSON path segments to the first field that failed validation, e.g. ["description"]

Item properties for missing_fields
oneOf · string 1

string

oneOf · integer 2

integer

errorstringrequired

Human-readable error message

Full specification

Download the OpenAPI file for complete schemas, constraints, and examples.

Download social.json
View operation source
json
{
  "operationId": "getPostsByIdStats",
  "summary": "Get post stats",
  "description": "The platform's own analytics for one post published with [Create Post](/api-reference/publishing/create), read live through the same connection that published it. Currently LinkedIn company-page posts only; other platforms and LinkedIn personal (member) posts return 422. Each call is a fresh read and `as_of` records when it happened. Each successful read costs $0.001 (1,000 credits), charged to the caller after LinkedIn returns the numbers. Credits are checked first; a request that fails (4xx/5xx) is not charged.",
  "security": [
    {
      "apiKeyAuth": []
    },
    {
      "bearerAuth": []
    }
  ],
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The post's id, from [Create Post](/api-reference/publishing/create)."
    }
  ],
  "responses": {
    "200": {
      "description": "The post's current stats.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PostStatsResponse"
          }
        }
      }
    },
    "400": {
      "description": "`id` is not a valid uuid.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PostErrorResponse"
          }
        }
      }
    },
    "401": {
      "description": "Unauthorized.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PostErrorResponse"
          }
        }
      }
    },
    "402": {
      "description": "Insufficient credits: the account has less than the $0.001 a read costs. Returned after the 400/401/403/404/409/422 checks and before LinkedIn is called, so nothing is read and nothing is charged.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SocialInsufficientCreditsResponse"
          }
        }
      }
    },
    "403": {
      "description": "Access denied to this post's account.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PostErrorResponse"
          }
        }
      }
    },
    "404": {
      "description": "No post with that id.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PostErrorResponse"
          }
        }
      }
    },
    "409": {
      "description": "The post cannot be read yet. Either it is not published (its status is not `posted` or it has no `post_url`; error `Post is not published yet, so it has no stats`), or the platform is not connected for the post's account (error `linkedin is not connected for this account`). This is checked before 422, so an unpublished post on any platform returns 409.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PostErrorResponse"
          }
        }
      }
    },
    "422": {
      "description": "Stats are not supported for this post. Only LinkedIn company-page posts are supported today. Errors: `Stats are not available for <platform> posts yet` (any other platform), `Stats are available for LinkedIn company-page posts only` (a LinkedIn personal post), `post_url does not name a LinkedIn post`.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PostErrorResponse"
          }
        }
      }
    },
    "500": {
      "description": "Internal server error.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PostErrorResponse"
          }
        }
      }
    },
    "502": {
      "description": "The platform rejected the stats read, for example because the connection lacks analytics access (error `LinkedIn rejected the stats read for this post`).",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PostErrorResponse"
          }
        }
      }
    }
  }
}

Data coverage

LinkedIn reports organic activity only, within a rolling 12-month window; a post older than 12 months returns what LinkedIn still holds.

Get started with Recoup.