Meet the new Scripe, live on October 7.Register

OpenAPI reference · Analytics

Per-post analytics (library)

GET/analytics/posts

Offset-paginated per-post LinkedIn metrics (views, likes, comments, shares, engagement rate) for one or more projects, newest first.

If projectId is omitted, fetches posts across all projects available to the caller in the workspace.

Rows describe posts that are live on LinkedIn, which is not the same object as the Scripe draft they may have come from — see the three ids on PostAnalytics.

content is an excerpt by default (content=preview). A full page of 50 posts carries ~66 000 characters of post bodies, which is the wrong default for an endpoint whose job is ranking. Pass content=full when you need the whole body.

Required scope: analytics:read.

Authorization

  • Authorizationstringrequired

    Bearer token in the Authorization header.

    Pass Authorization: Bearer scripe_sk_live_<...> (or scripe_sk_test_<...> for test keys) on every request. Keys are scoped to a single workspace and can be revoked from the Scripe dashboard.

    The same header also accepts an OAuth 2.1 access token (scripe_oat_*); both credentials share one scope vocabulary and every operation below documents the scope it requires. An API key can hold every scope named on this surface except webhooks:manage, which is grantable to OAuth tokens only today — the webhook-endpoint operations answer 403 scope_missing to every API key. Operations that name no scope accept any valid token of the workspace.

Query parameters

  • projectIdstring

    One project id, or a comma-separated list. If omitted, defaults to all available projects.

  • postIdstring

    Report on specific Scripe posts: one post_… id or a comma-separated list of up to 50. This is how "how did THIS post do?" is answered — the response contains only those posts, with no date range to work out and no page to scan.

    A named post that has no metrics is reported in meta rather than silently absent, because an empty page reads as "no engagement" when the truth may be "never published". An id the reported-on project(s) do not contain is a 400, never an empty page.

  • dateFromstring <date-time>

    ISO 8601 or YYYY-MM-DD lower bound (inclusive).

  • dateTostring <date-time>

    ISO 8601 or YYYY-MM-DD upper bound (inclusive).

  • limitinteger

    Page size. Default 50, max 200. Values above the max are clamped silently; only a non-integer or a value below 1 is rejected with bad_pagination.

    Default: 50

  • offsetinteger

    Default: 0

  • sortstring

    Ordering. impressions ranks by views and engagement by total interactions — neither ranks by engagement rate.

    Allowed values: recent, impressions, engagement

    Default: "recent"

  • contentstring

    How much of each post body to return. preview returns the first ~280 characters cut on a word boundary and sets content_truncated; full returns the whole body; none omits it (content: null, content_truncated: true when a body exists).

    Allowed values: preview, full, none

    Default: "preview"

Header parameters

  • Scripe-Api-Versionstring

    Pin the API version. Format YYYY-MM-DD. Omit to receive the currently rolling default. Unknown versions return 400 version_unsupported.

Responses

  • 200

    Page of per-post analytics.

  • 400

    Malformed request (bad cursor, bad limit, etc.).

  • 401

    Missing, malformed, expired, or revoked API key.

  • 403

    Plan not eligible, scope missing, or workspace mismatch.

  • 404

    Resource not found in this workspace.

  • 429

    Sliding-window rate limit exceeded.

Example request

bash
curl --request GET \
  --url 'https://api.scripe.io/v1/analytics/posts' \
  --header 'Authorization: Bearer <token>'

Example response (200)

json
{
  "data": [
    {
      "id": "string",
      "post_id": "post_a1b2c3d4e5f6g7h8",
      "project_id": "string",
      "linkedin_post_id": "urn:li:activity:7302247578123788289",
      "permalink": "string",
      "content": "string",
      "content_truncated": true,
      "content_type": "string",
      "media_type": "string",
      "posted_at": "2026-08-10T09:00:00Z",
      "metrics": {
        "views": 0,
        "likes": 0,
        "comments": 0,
        "shares": 0,
        "total_engagement": 0,
        "engagement_rate": 0
      }
    }
  ],
  "pagination": {
    "total": 0,
    "limit": 0,
    "offset": 0,
    "has_more": true
  },
  "meta": {
    "requested_post_ids": [
      "string"
    ],
    "unmeasured": [
      {
        "post_id": "string",
        "reason": "not_published",
        "detail": "string"
      }
    ]
  }
}