---
title: "Best publications of the range"
method: GET
path: "/organizations/{id_organization}/publications/top"
tags: ["dashboard"]
---

# Best publications of the range

`GET /organizations/{id_organization}/publications/top`

## Request

- Base URL: `https://api.planvortex.com/v1.0.0`
- URL: `https://api.planvortex.com/v1.0.0/organizations/{id_organization}/publications/top`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (client credentials, token URL `https://api.planvortex.com/v1.0.0/oauth/token`)

The publications with the highest value of one metric.

**A publication whose network does not report that metric does not compete**, it is left out of the ranking rather than ranked as a zero. That is why asking for `saves` can return fewer rows than asking for `engagement`.

## Path parameters

- `id_organization` string, required

## Query parameters

- `from_date` string, date-time
- `to_date` string, date-time
- `metric` 'impressions' | 'reach' | 'engagement' | 'likes' | 'comments' | 'shares' | 'saves' | 'clicks' | 'video_views' | 'profile_views' | 'followers' | 'followers_gained': A metric in PlanVortex's common vocabulary. Each network reports what it reports and PlanVortex translates it; a metric a network does not publish is absent, never zero.
- `limit` integer

## Response `200`

Top publications

- object
  - `range` DashboardDashboardRange, required: The range that was actually used, plus the previous period of exactly the same length. The previous one is not "last month": comparing 30 days against a calendar month would move the delta with the calendar.
    - `from_date` string, date-time, required
    - `to_date` string, date-time, required
    - `previous_from_date` string, date-time, required
    - `previous_to_date` string, date-time, required
  - `metric` 'impressions' | 'reach' | 'engagement' | 'likes' | 'comments' | 'shares' | 'saves' | 'clicks' | 'video_views' | 'profile_views' | 'followers' | 'followers_gained', required: A metric in PlanVortex's common vocabulary. Each network reports what it reports and PlanVortex translates it; a metric a network does not publish is absent, never zero.
  - `publications` DashboardTopPublication[], required
    - `id_publication` string, required
    - `social_network` 'facebook' | 'instagram' | 'linkedin' | 'tiktok' | 'twitter' | 'whatsapp' | 'youtube' | 'google_business' | 'bluesky' | 'discord' | 'telegram' | 'threads' | 'slack' | 'pinterest', required: A social network supported by PlanVortex. **This list grows.** Treat it as an open enumeration: a client that rejects an unknown value breaks the day a network is added, which happens several times a year. Not every network does everything — ask `GET /social_capabilities`.
    - `publish_date` string, date-time
    - `collected_date` string, date-time: When this measurement was taken.
    - `metrics` NormalizedMetrics, required: Metrics translated to a **common vocabulary** shared by every network, which is what makes two networks comparable and summable (each network names them differently: `page_post_engagements`, `total_interactions`, `views`…). **A missing key means the network does not publish that metric** — it is never an implicit zero. A key present with value `0` means it was measured and came out zero. Never default a missing key to 0 when displaying it. `engagement` is the network's own total when it provides one, and otherwise the sum of likes, comments, shares, saves and clicks. Video views are deliberately excluded from it: a view is not an interaction.
      - `impressions` integer: Times the content was shown (not unique)
      - `reach` integer: Unique users reached
      - `engagement` integer: Total interactions
      - `likes` integer
      - `comments` integer
      - `shares` integer
      - `saves` integer
      - `clicks` integer
      - `video_views` integer
      - `profile_views` integer
      - `followers` integer: Followers accumulated at that date, not the day's gain.
      - `followers_gained` integer: Followers gained that day.
    - `engagement_base` 'reach' | 'impressions' | 'followers': What this row's engagement rate is divided by. **Two rows with different bases are not comparable**, so say which one it is when you put them in the same table.
    - `publication` object, required: The bit of the publication needed to render the row. Nothing else is projected.
      - `text` string
      - `title` string
      - `files` Upload[]
        - `_id` string, required
        - `id_organization` string, required
        - `name` string, required
        - `file_type` 'video' | 'image', required
        - `file_format` 'mp4' | 'jpeg' | 'gif' | 'png' | 'jpg', required: The format of the stored bytes. `heic`/`heif` are accepted at the door — that is what an iPhone produces — but never stored: they are converted to JPEG while being ingested, so an upload never comes back with one.
        - `file_properties` FileProperties, required: Measurements taken when the file was ingested. Always present on an upload.
          - `width` integer, required: `0` on a file whose dimensions could not be read.
          - `height` integer, required
          - `duration` integer, required: Seconds. `0` on an image.
          - `size_in_bytes` integer, required
          - `aspect_ratio` object, required: Width divided by height, as a number and as a person writes it.
            - `value` number, required
            - `text` string, required
          - `allowed_social_networks` string[], required: The networks whose accepted crops this file's ratio matches, with a 0.1 margin. It is about the RATIO only: a network listed here can still reject the file for its duration or its weight (see `GET /social_limits`).
        - `file_externals` object[], required: Where this file ended up on each network it has been published to. Some networks keep their own copy and give it an identifier that is reused instead of uploading the bytes again.
          - `social_network` 'facebook' | 'instagram' | 'linkedin' | 'tiktok' | 'twitter' | 'whatsapp' | 'youtube' | 'google_business' | 'bluesky' | 'discord' | 'telegram' | 'threads' | 'slack' | 'pinterest', required: A social network supported by PlanVortex. **This list grows.** Treat it as an open enumeration: a client that rejects an unknown value breaks the day a network is added, which happens several times a year. Not every network does everything — ask `GET /social_capabilities`.
          - `external_identifier` string, required
          - `external_url` string, required
        - `cover_image` Upload (recursive)
        - `cover_offset` integer: Point of the video, in milliseconds, used as the cover frame.
        - `ai_generated` AiImageOrigin: Where an AI-generated image came from. **Only images a model generated carry it**: a photo the organization uploaded, a product photo pulled from a connected shop or an image imported from an integration never does. It is set when the image is generated and cannot be edited. Use it to show your own AI label: under article 50(4) of the EU AI Act, telling the audience that an image is AI-generated is the job of whoever publishes it. Images made with the default model also carry a signed C2PA manifest, IPTC metadata and a SynthID watermark in the file itself. PlanVortex keeps the IPTC marker when it crops or recompresses an image for a network; the C2PA signature does not survive a change of pixels.
          - `provider` string, required: The AI provider that answered: `openrouter` unless the client brought its own key.
          - `model` string, required: The model, as it was requested, for instance `google/gemini-3.1-flash-image`.
          - `generated_at` string, date-time, required
          - `id_ai_plan` string: The AI plan that generated it.
        - `is_temporal` boolean, required: `true` on a file the platform created for itself — a crop made to fit a network's aspect ratio. Temporary files are not part of the library listing.
        - `public_path` string, uri, required: Download URL. IMPORTANT: it is a TEMPORARY, signed URL, not a permanent link. It expires (24 hours by default) and must not be stored or shared: ask for the upload again to get a valid one. The URL stays byte-identical within the same hour, so it can be cached for that long.
        - `creation_date` string, date-time, required
      - `publication_type` string
      - `url` string
      - `external_identifier` string

## Other responses

- `400`: Error. Classify by `code` in the body, never by the HTTP status.

---

[API](https://skmtc.dev/planvortex/apis/planvortex-api.md) · [All operations](https://skmtc.dev/planvortex/apis/planvortex-api/llms.txt) · [OpenAPI document](https://skmtc.dev/planvortex/apis/planvortex-api/revisions/abedbbc1cd52?raw)
