> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mallary.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Browse Post Analytics

> Search, filter, sort, and page through analytics for all posts in a Mallary profile.

This endpoint lists post groups across the full history of one connection profile. Omit `profile_id` to use the default profile. It requires Starter, Pro, or Business.

Use `start_date` and `end_date` to select posts **created** on those UTC dates. Each metric is the latest saved total for that post. The date filter does not turn lifetime totals into activity earned during the selected dates. `metric_window` tells you when a provider supplied a rolling 30-day or 90-day total instead.

The response returns up to 25 groups by default. Set `limit` to 1–100. For numbered pages, set `page` to 1–10000. The response includes `data.page`, `data.total_pages`, `data.limit`, and `data.total`, the count of matching groups across all pages. If no groups match, `data.total_pages` is `0`. Pass the returned `data.snapshot_at` with later page requests, keeping the same filters, sort, and limit. The timestamp is in UTC `YYYY-MM-DDTHH:mm:ssZ` form and can be used only with `page`. It keeps metric ranking at the same saved point in time. A post's status can still change while you browse.

You can also page forward with a cursor: pass `data.next_cursor` back as `cursor`, keeping the same filters and sort. A null cursor means the last page. Do not send `page` and `cursor` together. In numbered page mode, `data.next_cursor` is null.

Use `platform`, `status`, `media_type`, `search`, and `sort` to narrow the list. Sort by `display_views`, `likes`, `comments`, or `engagement_rate` for the highest values first. Add `_asc` to any of those values for the lowest first. `display_views` uses views when a platform supplies them, otherwise impressions. Posts without the selected metric appear last in either direction. Other existing sort values remain available. A cross-platform group matches a platform filter when any of its posts use that platform. Its `platform_metrics` still show each platform separately.

Metrics that the provider did not supply are `null`. A reported zero is `0`. For each group total, check `*_available` and `*_partial` before comparing posts: a partial value covers only some platforms in that group. `captured_at` tells you when the latest snapshot was saved.

The group `engagement_rate` combines the available platform-post rates into one percentage. Mallary weights each rate by its positive base count, such as views, impressions, or reach. A platform post without a usable rate or base is left out, not counted as zero. `engagement_rate_sample_count` tells you how many platform posts contributed; `engagement_rate_partial` is `true` when a rate is available but some platform posts did not contribute. `engagement_rate_denominator` is `mixed` when the contributing rates use different bases. Check each `platform_metrics` row for its own rate and base. If the platform posts cover different reporting periods, `metric_window` is `mixed`.

For a compact recent snapshot or a single post by Mallary job ID, use [Get Analytics](/api-reference/endpoint/analytics). For follower and subscriber history, use [Get Audience Counts](/api-reference/endpoint/audience).


## OpenAPI

````yaml GET /api/v1/analytics/posts
openapi: 3.0.3
info:
  title: Mallary API
  version: 1.5.0
  description: >
    Public API for multi-platform publishing, analytics, media upload, and
    webhooks.


    Authentication:

    - Use header `Authorization: Bearer {api_key}`.

    - API key identity is authoritative. Do not use `user_id` to identify a
    caller.


    Connection profiles:

    - Omit `profile_id` to use the authenticated user's default profile.

    - Send the profile's random public `profile_id` when you want to publish,
    list posts, read post analytics or audience counts, list platforms, update
    settings, or disconnect a platform for a non-default profile.

    - Use `GET /api/v1/profiles` to list profile IDs.

    - Per-platform account caps by plan: Free 1, Starter 4, Pro 10, Business 50.


    Rate limits (per user, per minute) depend on subscription plan:

    - plan_id 1: 75 req/min

    - plan_id 2: 150 req/min

    - plan_id 3: 750 req/min

    - plan_id 4: 1500 req/min
servers:
  - url: https://mallary.ai
    description: Production
security:
  - bearerAuth: []
externalDocs:
  description: Full product docs
  url: https://docs.mallary.ai/
paths:
  /api/v1/analytics/posts:
    get:
      summary: Browse analytics for all posts
      description: >-
        Returns paginated post groups across the selected profile's full
        history. Metric values are the latest saved totals for each post, not
        activity earned inside the selected date range. Date filters use the
        post group's creation date (UTC). Unavailable metrics are null; a
        reported zero remains zero. Use `page` for numbered navigation and pass
        the returned `snapshot_at` with later pages to keep metric ranking at
        the same saved point in time. Alternatively, pass `next_cursor` as
        `cursor` with the same filters and sort. Do not combine `page` and
        `cursor`. Post status can still change while browsing. Requires a paid
        plan with analytics access.
      operationId: listAnalyticsPosts
      parameters:
        - in: query
          name: profile_id
          schema:
            $ref: '#/components/schemas/ProfileId'
          description: Connection profile to inspect. Omit to use the default profile.
        - in: query
          name: start_date
          schema:
            type: string
            format: date
          description: Include post groups created on or after this UTC date.
        - in: query
          name: end_date
          schema:
            type: string
            format: date
          description: Include post groups created on or before this UTC date.
        - in: query
          name: platform
          schema:
            $ref: '#/components/schemas/Platform'
          description: Include groups with a post on this platform.
        - in: query
          name: status
          schema:
            type: string
            enum:
              - successful
              - scheduled
              - failed
              - processing
              - partial
          description: Filter by the post group's status.
        - in: query
          name: media_type
          schema:
            type: string
            enum:
              - video
              - photo
              - mixed_media
              - text_or_link
          description: Include groups with this media type.
        - in: query
          name: search
          schema:
            type: string
            maxLength: 200
          description: Search post text and batch IDs.
        - in: query
          name: sort
          schema:
            type: string
            enum:
              - newest
              - oldest
              - views
              - display_views
              - display_views_asc
              - likes
              - likes_asc
              - comments
              - comments_asc
              - engagement
              - engagement_rate
              - engagement_rate_asc
              - clicks
              - impressions
            default: newest
          description: >-
            Sort post groups. Metric sorts are highest first unless the value
            ends in `_asc`. `display_views` uses a platform's views when
            available, otherwise its impressions. Posts without the selected
            metric appear last in either direction.
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 25
          description: Maximum number of post groups in one page.
        - in: query
          name: cursor
          schema:
            type: string
          description: >-
            Opaque `next_cursor` from the previous page. Keep filters and sort
            the same. Cannot be combined with `page`.
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
            maximum: 10000
          description: >-
            One-based page number for numbered navigation. Cannot be combined
            with `cursor`. Omit for cursor navigation.
        - in: query
          name: snapshot_at
          schema:
            type: string
            format: date-time
          description: >-
            UTC server timestamp in `YYYY-MM-DDTHH:mm:ssZ` form returned with
            the first numbered page. Use it only with `page`; pass it with later
            page numbers and the same filters, sort, and limit so metric ranking
            stays fixed while browsing.
      responses:
        '200':
          description: Post analytics page retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AnalyticsPostsResponse'
        '400':
          description: Invalid filter, page, snapshot timestamp, or cursor
        '401':
          description: Missing or invalid API key
        '403':
          description: Analytics are not available for the current plan
        '429':
          description: Rate limit exceeded
components:
  schemas:
    ProfileId:
      type: string
      pattern: ^[A-Za-z0-9]{6,32}$
      example: AbC123xYz90
      description: Random public connection profile ID returned by `GET /api/v1/profiles`.
    Platform:
      type: string
      description: Supported publishing platform identifier.
      enum:
        - twitter
        - x
        - facebook
        - instagram
        - linkedin
        - youtube
        - tiktok
        - pinterest
        - reddit
        - threads
        - bluesky
    AnalyticsPostsResponse:
      type: object
      properties:
        status:
          type: string
          enum:
            - ok
        data:
          type: object
          properties:
            profile_id:
              $ref: '#/components/schemas/ProfileId'
              nullable: true
            items:
              type: array
              items:
                $ref: '#/components/schemas/AnalyticsPostGroup'
            next_cursor:
              type: string
              nullable: true
              description: >-
                Cursor for the next page, or null on the last cursor page and in
                numbered page mode.
            page:
              type: integer
              minimum: 1
              description: >-
                One-based page number; present only when the request includes
                `page`.
            total_pages:
              type: integer
              minimum: 0
              description: >-
                Number of pages for the matching post groups at the requested
                limit; present only in numbered page mode.
            limit:
              type: integer
              minimum: 1
              maximum: 100
              description: >-
                Maximum number of post groups requested for this page; present
                only in numbered page mode.
            snapshot_at:
              type: string
              format: date-time
              description: >-
                Server timestamp used to keep metric ranking fixed across
                numbered pages; present only in numbered page mode.
            total:
              type: integer
              description: Count of matching post groups, independent of the current page.
            generated_at:
              type: string
              format: date-time
    AnalyticsPostGroup:
      type: object
      description: >-
        A post group and its latest saved per-platform metrics. Flat totals may
        cover only some platforms; check each `*_available` and `*_partial`
        flag. A null metric means unavailable, not zero. `display_views` uses
        one count per platform, preferring views and otherwise using
        impressions.
      properties:
        id:
          type: string
        batch_id:
          type: string
          nullable: true
        post_id:
          type: integer
          nullable: true
        job_ids:
          type: array
          items:
            type: integer
        title:
          type: string
        message:
          type: string
        thumbnail_url:
          type: string
          nullable: true
        media_type:
          type: string
        status:
          type: string
          enum:
            - successful
            - scheduled
            - failed
            - processing
            - partial
        created_at:
          type: string
          nullable: true
        posted_at:
          type: string
          nullable: true
        platforms:
          type: array
          items:
            type: string
        platform_count:
          type: integer
        platform_metrics:
          type: array
          items:
            $ref: '#/components/schemas/AnalyticsPostPlatformMetrics'
        views:
          type: integer
          nullable: true
        display_views:
          type: integer
          nullable: true
          description: >-
            Dashboard Views count. Uses views when reported, otherwise
            impressions, once per platform post.
        display_views_available:
          type: boolean
        display_views_partial:
          type: boolean
        display_view_sample_count:
          type: integer
          description: Number of platform posts with a reported view or impression count.
        average_display_views:
          type: number
          nullable: true
        impressions:
          type: integer
          nullable: true
        reach:
          type: integer
          nullable: true
        likes:
          type: integer
          nullable: true
        comments:
          type: integer
          nullable: true
        shares:
          type: integer
          nullable: true
        clicks:
          type: integer
          nullable: true
        saves:
          type: integer
          nullable: true
        bookmarks:
          type: integer
          nullable: true
        outbound_clicks:
          type: integer
          nullable: true
        pin_clicks:
          type: integer
          nullable: true
        url_clicks:
          type: integer
          nullable: true
        profile_clicks:
          type: integer
          nullable: true
        engaged_users:
          type: integer
          nullable: true
        engagement:
          type: integer
          nullable: true
        engagement_rate:
          type: number
          nullable: true
          description: >-
            Denominator-weighted average percentage of platform-post rates with
            a usable rate and positive base. Missing rates are excluded, not
            treated as zero. Check the sample count and partial flag for
            coverage.
        engagement_rate_denominator:
          type: string
          nullable: true
          enum:
            - views
            - impressions
            - reach
            - mixed
          description: Base shared by contributing rates, or mixed when their bases differ.
        engagement_rate_partial:
          type: boolean
          description: >-
            True when a combined rate is available but some platform posts did
            not contribute.
        engagement_rate_sample_count:
          type: integer
          description: >-
            Number of platform posts with a usable rate and positive base that
            contributed to the combined rate.
        outbound_click_rate:
          type: number
          nullable: true
          description: >-
            Pinterest outbound clicks divided by impressions, as a percentage,
            when available for one platform.
        outbound_click_rate_denominator:
          type: string
          nullable: true
          enum:
            - impressions
        url_click_rate:
          type: number
          nullable: true
          description: >-
            X URL clicks divided by impressions, as a percentage, when available
            for one platform.
        url_click_rate_denominator:
          type: string
          nullable: true
          enum:
            - impressions
        metric_window:
          type: string
          nullable: true
          enum:
            - lifetime
            - rolling_30d
            - rolling_90d
            - mixed
        captured_at:
          type: string
          format: date-time
          nullable: true
        analytics_available:
          type: boolean
        analytics_partial:
          type: boolean
        analytics_collecting:
          type: boolean
        analytics_reconnect_required:
          type: boolean
      additionalProperties: true
    AnalyticsPostPlatformMetrics:
      type: object
      description: >-
        One platform's latest saved metric snapshot. Each numeric metric has a
        matching `*_available` flag; unsupported or uncollected values are null.
        `display_views` uses views when reported, otherwise impressions, without
        adding the two.
      properties:
        job_id:
          type: integer
        platform:
          $ref: '#/components/schemas/Platform'
        label:
          type: string
        platform_post_url:
          type: string
          nullable: true
        status:
          type: string
        analytics_status:
          type: string
          enum:
            - available
            - collecting
            - reconnect_required
            - unavailable
        captured_at:
          type: string
          format: date-time
          nullable: true
        metric_window:
          type: string
          nullable: true
        metric_semantics_version:
          type: integer
          nullable: true
        display_views:
          type: integer
          nullable: true
        display_views_available:
          type: boolean
        engagement_rate:
          type: number
          nullable: true
          description: >-
            Percentage reported or derived for this platform post. Check the
            denominator field for its base.
        engagement_rate_denominator:
          type: string
          nullable: true
          enum:
            - views
            - impressions
            - reach
        outbound_click_rate:
          type: number
          nullable: true
        outbound_click_rate_denominator:
          type: string
          nullable: true
          enum:
            - impressions
        url_click_rate:
          type: number
          nullable: true
        url_click_rate_denominator:
          type: string
          nullable: true
          enum:
            - impressions
      additionalProperties: true
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'Use `Authorization: Bearer {api_key}`'

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.