---
title: "Get post analytics"
method: GET
path: "/v1/analytics"
tags: ["Analytics"]
---

# Get post analytics

`GET /v1/analytics`

Returns analytics for posts. With postId, returns a single post. Without it, returns a paginated list with overview stats.
Accepts both Zernio Post IDs and External Post IDs (auto-resolved). fromDate defaults to 90 days ago if omitted, max range 366 days.
Single post lookups may return 202 (sync pending) or 424 (all platforms failed). For follower stats, use /v1/accounts/follower-stats.

LinkedIn personal accounts: Analytics are only available for posts published through Zernio. LinkedIn's API only returns metrics for posts authored by the authenticated user. Organization/company page analytics work for all posts.

## Query parameters

- `postId` string
- `platform` string
- `profileId` string
- `accountId` string
- `source` 'all' | 'late' | 'external'
- `fromDate` string, date
- `toDate` string, date
- `limit` integer
- `page` integer
- `sortBy` 'date' | 'engagement' | 'impressions' | 'reach' | 'likes' | 'comments' | 'shares' | 'saves' | 'clicks' | 'views' | 'follows'
- `order` 'asc' | 'desc'

## Response `200`

Analytics result

- union
  - AnalyticsSinglePostResponse
    - `postId` string
    - `latePostId` string, nullable — Original Zernio post ID if scheduled via Zernio
    - `status` 'published' | 'failed' | 'partial' — Overall post status. "partial" when some platforms published and others failed.
    - `content` string
    - `scheduledFor` string, date-time
    - `publishedAt` string, date-time, nullable
    - `analytics` PostAnalytics
      - `impressions` integer
      - `reach` integer
      - `likes` integer
      - `comments` integer
      - `shares` integer
      - `saves` integer — Number of saves/bookmarks (Instagram, Pinterest, X/Twitter)
      - `clicks` integer
      - `views` integer
      - `follows` integer — Instagram feed posts and stories only: organic accounts that started following from this post. 0 for reels and other platforms.
      - `igReelsAvgWatchTime` integer — Instagram Reels only: average watch time per play, in milliseconds. 0 for non-Reels media and other platforms.
      - `igReelsVideoViewTotalTime` integer — Instagram Reels only: total watch time including replays, in milliseconds. 0 for non-Reels media and other platforms.
      - `videoDurationSeconds` integer, nullable — Video length in seconds. Currently Instagram Reels only; combine with igReelsAvgWatchTime (ms) to estimate retention. Null when unknown (other platforms, non-video media, or when Instagram does not expose the media URL, e.g. reels with copyrighted audio).
      - `engagementRate` number
      - `lastUpdated` string, date-time
    - `platformAnalytics` PlatformAnalytics[]
      - `platform` string
      - `status` 'published' | 'failed'
      - `platformPostId` string, nullable — The native post ID on the platform (e.g. Instagram media ID, tweet ID)
      - `accountId` string
      - `accountUsername` string, nullable
      - `analytics` PostAnalytics
        - `impressions` integer
        - `reach` integer
        - `likes` integer
        - `comments` integer
        - `shares` integer
        - `saves` integer — Number of saves/bookmarks (Instagram, Pinterest, X/Twitter)
        - `clicks` integer
        - `views` integer
        - `follows` integer — Instagram feed posts and stories only: organic accounts that started following from this post. 0 for reels and other platforms.
        - `igReelsAvgWatchTime` integer — Instagram Reels only: average watch time per play, in milliseconds. 0 for non-Reels media and other platforms.
        - `igReelsVideoViewTotalTime` integer — Instagram Reels only: total watch time including replays, in milliseconds. 0 for non-Reels media and other platforms.
        - `videoDurationSeconds` integer, nullable — Video length in seconds. Currently Instagram Reels only; combine with igReelsAvgWatchTime (ms) to estimate retention. Null when unknown (other platforms, non-video media, or when Instagram does not expose the media URL, e.g. reels with copyrighted audio).
        - `engagementRate` number
        - `lastUpdated` string, date-time
      - `syncStatus` 'synced' | 'pending' | 'unavailable' — Sync state of analytics for this platform
      - `platformPostUrl` string, uri, nullable
      - `errorMessage` string, nullable — Error details when status is failed
    - `platform` string
    - `platformPostUrl` string, uri, nullable
    - `isExternal` boolean
    - `syncStatus` 'synced' | 'pending' | 'partial' | 'unavailable' — Overall sync state across all platforms
    - `message` string, nullable — Human-readable status message for pending, partial, or failed states
    - `thumbnailUrl` string, uri, nullable
    - `mediaType` 'image' | 'video' | 'carousel' | 'text', nullable
    - `mediaItems` object[] — All media items for this post. Carousel posts contain one entry per slide.
      - `type` 'image' | 'video'
      - `url` string, uri, nullable — 'Direct URL to the media file. Null when the platform withholds it: check mediaStatus before downloading. Instagram omits the video file for Reels it flags as containing copyrighted material (its docs name audio as the usual cause), so type stays "video" while the file is permanently unreachable.'
      - `thumbnail` string, uri, nullable — Thumbnail URL (same as url for images). Still present when url is null.
      - `altText` string — Accessibility alt text set on the media, when present.
      - `mediaStatus` 'unavailable' — Present only when the media file could not be retrieved. Absent means the file is available at url.
      - `unavailableReason` 'platform_withheld' — Why the file is missing. platform_withheld means the platform declined to return it and retrying will not help.
  - AnalyticsListResponse
    - `overview` AnalyticsOverview
      - `totalPosts` integer
      - `publishedPosts` integer
      - `scheduledPosts` integer
      - `lastSync` string, date-time, nullable
      - `dataStaleness` object
        - `staleAccountCount` integer — Number of accounts with stale analytics data
        - `syncTriggered` boolean — Whether a background sync was triggered for stale accounts
    - `posts` object[]
      - `_id` string
      - `latePostId` string, nullable — Original Zernio post ID if scheduled via Zernio
      - `content` string
      - `scheduledFor` string, date-time
      - `publishedAt` string, date-time
      - `status` string
      - `analytics` PostAnalytics
        - `impressions` integer
        - `reach` integer
        - `likes` integer
        - `comments` integer
        - `shares` integer
        - `saves` integer — Number of saves/bookmarks (Instagram, Pinterest, X/Twitter)
        - `clicks` integer
        - `views` integer
        - `follows` integer — Instagram feed posts and stories only: organic accounts that started following from this post. 0 for reels and other platforms.
        - `igReelsAvgWatchTime` integer — Instagram Reels only: average watch time per play, in milliseconds. 0 for non-Reels media and other platforms.
        - `igReelsVideoViewTotalTime` integer — Instagram Reels only: total watch time including replays, in milliseconds. 0 for non-Reels media and other platforms.
        - `videoDurationSeconds` integer, nullable — Video length in seconds. Currently Instagram Reels only; combine with igReelsAvgWatchTime (ms) to estimate retention. Null when unknown (other platforms, non-video media, or when Instagram does not expose the media URL, e.g. reels with copyrighted audio).
        - `engagementRate` number
        - `lastUpdated` string, date-time
      - `platforms` PlatformAnalytics[]
        - `platform` string
        - `status` 'published' | 'failed'
        - `platformPostId` string, nullable — The native post ID on the platform (e.g. Instagram media ID, tweet ID)
        - `accountId` string
        - `accountUsername` string, nullable
        - `analytics` PostAnalytics
          - `impressions` integer
          - `reach` integer
          - `likes` integer
          - `comments` integer
          - `shares` integer
          - `saves` integer — Number of saves/bookmarks (Instagram, Pinterest, X/Twitter)
          - `clicks` integer
          - `views` integer
          - `follows` integer — Instagram feed posts and stories only: organic accounts that started following from this post. 0 for reels and other platforms.
          - `igReelsAvgWatchTime` integer — Instagram Reels only: average watch time per play, in milliseconds. 0 for non-Reels media and other platforms.
          - `igReelsVideoViewTotalTime` integer — Instagram Reels only: total watch time including replays, in milliseconds. 0 for non-Reels media and other platforms.
          - `videoDurationSeconds` integer, nullable — Video length in seconds. Currently Instagram Reels only; combine with igReelsAvgWatchTime (ms) to estimate retention. Null when unknown (other platforms, non-video media, or when Instagram does not expose the media URL, e.g. reels with copyrighted audio).
          - `engagementRate` number
          - `lastUpdated` string, date-time
        - `syncStatus` 'synced' | 'pending' | 'unavailable' — Sync state of analytics for this platform
        - `platformPostUrl` string, uri, nullable
        - `errorMessage` string, nullable — Error details when status is failed
      - `platform` string
      - `platformPostUrl` string, uri
      - `isExternal` boolean
      - `profileId` string, nullable
      - `thumbnailUrl` string, uri
      - `mediaType` 'image' | 'video' | 'gif' | 'document' | 'carousel' | 'text'
      - `mediaItems` object[] — All media items for this post. Carousel posts contain one entry per slide.
        - `type` 'image' | 'video'
        - `url` string, uri — Direct URL to the media
        - `thumbnail` string, uri — Thumbnail URL (same as url for images)
        - `altText` string — Accessibility alt text set on the media, when present.
    - `pagination` Pagination
      - `page` integer
      - `limit` integer
      - `total` integer
      - `pages` integer
    - `accounts` SocialAccount[] — Connected social accounts (followerCount and followersLastUpdated only included if user has analytics add-on)
      - `_id` string, required
      - `platform` 'tiktok' | 'instagram' | 'facebook' | 'youtube' | 'linkedin' | 'twitter' | 'threads' | 'pinterest' | 'reddit' | 'bluesky' | 'googlebusiness' | 'telegram' | 'snapchat' | 'discord' | 'slack' | 'whatsapp' | 'linkedinads' | 'metaads' | 'pinterestads' | 'tiktokads' | 'xads' | 'googleads' | 'openaiads' | 'sms' | 'phone' | 'rcs', required
      - `profileId` union, required
        - string
        - Profile
          - `_id` string
          - `userId` string
          - `name` string
          - `description` string
          - `color` string
          - `isDefault` boolean
          - `isOverLimit` boolean — Only present when includeOverLimit=true. Indicates if this profile exceeds the plan limit.
          - `createdAt` string, date-time
      - `username` string
      - `displayName` string
      - `profilePicture` string, nullable — URL to the account's profile picture on the platform. May be null if the platform does not provide one.
      - `profileUrl` string — Full profile URL for the connected account on its platform.
      - `isActive` boolean, required
      - `needsReconnection` boolean — The platform definitively reported the stored OAuth token as dead. While true, GET /v1/connect/{platform}/ads returns a fresh authUrl (implicit force=true) instead of alreadyConnected, so re-running the connect flow recovers the account. Cleared automatically when the account is re-authorized.
      - `followersCount` number — Follower count (only included if user has analytics add-on)
      - `followersLastUpdated` string, date-time — Last time follower count was updated (only included if user has analytics add-on)
      - `parentAccountId` string, nullable — Reference to the parent posting SocialAccount. Set for ads accounts that share or derive from a posting account's OAuth token. null for standalone ads (Google Ads) and all posting accounts.
      - `enabled` boolean — Whether the user explicitly activated this account. false means the account was created as a side effect (e.g., posting account auto-created when user connected ads first). Posting UI and scheduler ignore accounts with enabled: false.
      - `metadata` object — Platform-specific metadata. Fields vary by platform. For WhatsApp accounts, includes: - qualityRating: Phone number quality rating from Meta (GREEN, YELLOW, RED, or UNKNOWN) - nameStatus: Display name review status (APPROVED, PENDING_REVIEW, DECLINED, or NONE). A declined or pending display name does not by itself block sending; sendability is reported separately via health_status (can_send_message). - messagingLimitTier: Maximum unique business-initiated conversations per 24h rolling window (TIER_250, TIER_1K, TIER_10K, TIER_100K, or TIER_UNLIMITED). Scales automatically as quality rating improves. - verifiedName: Meta-verified business display name - displayPhoneNumber: Formatted phone number (e.g., "+1 555-123-4567") - wabaId: WhatsApp Business Account ID - phoneNumberId: Meta phone number ID For LinkedIn accounts, profileData carries the profile details refreshed on each daily snapshot: - profileData.bio: The member's headline for personal accounts, or the organization description for organization accounts. null when the member has not set one. - profileData.extraData.vanityName: The member's profile slug, i.e. the /in/{vanityName} segment of profileUrl. Personal accounts only; an organization's own slug is in metadata.organizationInfo.vanityName.
    - `hasAnalyticsAccess` boolean — Whether user has analytics add-on access

## Other responses

- `202` — Analytics are being synced from the platform (single post lookup only). The response body matches AnalyticsSinglePostResponse with syncStatus "pending" and a message.
- `400` — Validation error
- `401` — Unauthorized
- `402` — Analytics access required. Legacy plans need the Analytics add-on; included by default on usage-based plans.
- `404` — Resource not found
- `424` — Post failed to publish on all platforms. Analytics are unavailable. (single post lookup only)
- `500` — Internal server error

---

[API](https://skmtc.net/zernio/apis/zernio-api.md) · [All operations](https://skmtc.net/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/zernio/zernio-api/revisions/0942091eaa8c/schema)
