---
title: "The whole home screen in one call"
method: GET
path: "/organizations/{id_organization}/dashboard"
tags: ["dashboard"]
---

# The whole home screen in one call

`GET /organizations/{id_organization}/dashboard`

## Request

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

Composes every block of the home screen in a single round trip: operational health, publications, publication metrics, account metrics, plan use, AI plans, the best AI plans and unread messages.

**A block the caller cannot read is omitted, not refused.** The endpoint only demands the minimum permission — reading the organization — and then checks each block on its own: somebody who can only see publications still gets their home instead of a 403. `available_blocks` says which blocks were allowed, so an absent block for lack of permission and an absent block for lack of data can be drawn differently.

The messages block is also omitted when the client's plan has no messaging.

## Path parameters

- `id_organization` string, required

## Query parameters

- `from_date` string, date-time
- `to_date` string, date-time

## Response `200`

The dashboard

- DashboardDashboard: Everything the home screen needs, in ONE round trip. **A missing block is not an error.** Each one is checked against its own permission and omitted when the caller cannot read it, instead of failing the whole request; `available_blocks` says which ones were allowed. A block that is `true` in `available_blocks` and absent from the body means there was no data — except `messages`, which also turns to `false` when the plan does not include chat.
  - `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
  - `available_blocks` object, required: Which blocks the caller was allowed to see. A `false` here is a permission (or plan) answer; a block that is `true` but empty means there is no data.
    - `health` boolean, required
    - `publications` boolean, required
    - `publication_metrics` boolean, required
    - `account_metrics` boolean, required
    - `plan_use` boolean, required
    - `ai_plans` boolean, required
    - `messages` boolean, required
    - `ai_plan_results` boolean, required: Needs both `ai_plans:read` and `publication_stats:read`: the block shows plans and their publications' metrics.
  - `health` object: What needs fixing today. Each half has its own permission: somebody who cannot read accounts still sees the failed publications.
    - `accounts_with_errors` DashboardAccountWithError[]
      - `_id` string, required
      - `name` string, required
      - `username` string
      - `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`.
      - `image` string
      - `error_code` integer, required: PlanVortex error code that broke it. `0` means healthy, so anything here is non-zero.
    - `publications_with_errors` DashboardDashboardPublicationRef[]: Up to ten publications in state `with_errors`, newest first.
      - `_id` string, required
      - `name` string
      - `text` string
      - `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
      - `creation_date` string, date-time
      - `publication_errors` object[]: Only on the failed ones. Same shape as in a full `Publication`.
        - `code` integer, required
        - `message` string, required
        - `data` object
      - `publication_warnings` object[]: What still has to be done **by hand on the network** for a publication that DID go out. Same shape as `publication_errors`, and an empty array when there is nothing to do. It is a separate field because these are not failures: the publication stays in state `sended` and must **not** be retried, because retrying would publish it twice. Like `publication_errors`, it belongs to the last attempt. Today there is one code. **2400** (YouTube): YouTube accepted the upload but did not make the video public, so YouTube Studio shows it as a draft or private until someone sets its audience and visibility there. The upload does not fail when this happens; PlanVortex reads the video back right after uploading it to find out. `data` carries `requested_privacy_status`, `privacy_status` (what YouTube actually left), `upload_status`, `made_for_kids` and `studio_url`, the YouTube Studio page where it is finished.
        - `code` integer, required
        - `message` string, required
        - `data` object
    - `upcoming_publications` DashboardDashboardPublicationRef[]: Up to ten publications due in the next 48 hours.
      - `_id` string, required
      - `name` string
      - `text` string
      - `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
      - `creation_date` string, date-time
      - `publication_errors` object[]: Only on the failed ones. Same shape as in a full `Publication`.
        - `code` integer, required
        - `message` string, required
        - `data` object
      - `publication_warnings` object[]: What still has to be done **by hand on the network** for a publication that DID go out. Same shape as `publication_errors`, and an empty array when there is nothing to do. It is a separate field because these are not failures: the publication stays in state `sended` and must **not** be retried, because retrying would publish it twice. Like `publication_errors`, it belongs to the last attempt. Today there is one code. **2400** (YouTube): YouTube accepted the upload but did not make the video public, so YouTube Studio shows it as a draft or private until someone sets its audience and visibility there. The upload does not fail when this happens; PlanVortex reads the video back right after uploading it to find out. `data` carries `requested_privacy_status`, `privacy_status` (what YouTube actually left), `upload_status`, `made_for_kids` and `studio_url`, the YouTube Studio page where it is finished.
        - `code` integer, required
        - `message` string, required
        - `data` object
    - `total_drafts` integer
  - `publications` object
    - `total` integer, required: Publications created in the range.
    - `by_state` object[], required
      - `state` string
      - `total` integer
    - `by_network` object[], required
      - `social_network` 'facebook' | 'instagram' | 'linkedin' | 'tiktok' | 'twitter' | 'whatsapp' | 'youtube' | 'google_business' | 'bluesky' | 'discord' | 'telegram' | 'threads' | 'slack' | 'pinterest': 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`.
      - `total` integer
    - `by_day` object[], required: Publications **created** each day, split by state.
      - `day` string: `YYYY-MM-DD`, in UTC.
      - `state` string
      - `total` integer
    - `published_by_day` object[], required: Publications that actually **went out** each day, split by network. Only the ones in state `sended`.
      - `day` string: `YYYY-MM-DD`, in UTC.
      - `social_network` 'facebook' | 'instagram' | 'linkedin' | 'tiktok' | 'twitter' | 'whatsapp' | 'youtube' | 'google_business' | 'bluesky' | 'discord' | 'telegram' | 'threads' | 'slack' | 'pinterest': 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`.
      - `total` integer
    - `previous_total` integer: The same count for the previous period, for the delta.
  - `publication_metrics` object
    - `total` 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.
    - `previous_total` 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.
    - `by_network` object[], required
      - `social_network` 'facebook' | 'instagram' | 'linkedin' | 'tiktok' | 'twitter' | 'whatsapp' | 'youtube' | 'google_business' | 'bluesky' | 'discord' | 'telegram' | 'threads' | 'slack' | 'pinterest': 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`.
      - `publications` integer
      - `metrics` NormalizedMetrics: 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.
    - `top` 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.
              - …
            - `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
  - `account_metrics` object
    - `total` 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.
    - `previous_total` 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.
    - `by_day` DashboardMetricRow[], required
      - `group` string, nullable, required: The value of the axis: the day, the network or the account identifier. **`null` when `group_by` was `total`** — the field is always there, the value is not always a string.
      - `name` '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.
      - `value` number, required
    - `by_network` DashboardMetricRow[], required
      - `group` string, nullable, required: The value of the axis: the day, the network or the account identifier. **`null` when `group_by` was `total`** — the field is always there, the value is not always a string.
      - `name` '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.
      - `value` number, required
  - `plan_use` DashboardPlanUse
    - `actual_use` PlanUseData, required: The resources a plan grants. On a client it is what was contracted; on an organization, the slice of it that was assigned. The sum across all the organizations of a client can never exceed what the client has contracted. Users are NOT here: every plan has unlimited users, so they are neither charged nor split between organizations. They are still counted, in `PlanUseData.users`. There are no `artificial_inteligence`, `whatsapp` or `stats` flags either: statistics and WhatsApp are on every plan, and what gates AI is `ai_credits` — a plan with credits has AI, and Free has zero.
      - `accounts` integer, required: Social accounts that may be connected.
      - `space` number, required: Storage, in GB.
      - `integrations` integer, required: Connections to a third-party tool material is pulled from (Google Drive, an RSS feed). Not the same thing as an app: an app is API access, and it has its own allowance in `apps`.
      - `apps` integer: Apps this plan allows: 1 on Free, 2 on Basic, 5 on Pro, 10 on Custom. Each one is a `client_id` with a secret, so each one is a key to the whole public API — which every plan has, Free included. Unlike accounts or storage this is NOT split between organizations: an app belongs to the client. On a use payload it is how many exist right now.
      - `twitter_credits` integer: Monthly X (Twitter) credits. X bills per use: 15 per post, 200 if the text contains a link, 15 per deletion, 1 per stat read, 1 per timeline item. The pool resets on the 1st of each calendar month and does not roll over.
      - `ai_credits` integer: Monthly AI credits (1 credit = $0.001 of provider cost): 15 per plan orchestration pass, 2 per generated text, 70 per generated image. Resets monthly and does not roll over. A client using its own provider key (BYOK) does not consume them in that scope.
    - `actual_asigned` PlanData, required: The resources a plan grants. On a client it is what was contracted; on an organization, the slice of it that was assigned. The sum across all the organizations of a client can never exceed what the client has contracted. Users are NOT here: every plan has unlimited users, so they are neither charged nor split between organizations. They are still counted, in `PlanUseData.users`. There are no `artificial_inteligence`, `whatsapp` or `stats` flags either: statistics and WhatsApp are on every plan, and what gates AI is `ai_credits` — a plan with credits has AI, and Free has zero.
      - `accounts` integer, required: Social accounts that may be connected.
      - `space` number, required: Storage, in GB.
      - `integrations` integer, required: Connections to a third-party tool material is pulled from (Google Drive, an RSS feed). Not the same thing as an app: an app is API access, and it has its own allowance in `apps`.
      - `apps` integer: Apps this plan allows: 1 on Free, 2 on Basic, 5 on Pro, 10 on Custom. Each one is a `client_id` with a secret, so each one is a key to the whole public API — which every plan has, Free included. Unlike accounts or storage this is NOT split between organizations: an app belongs to the client. On a use payload it is how many exist right now.
      - `twitter_credits` integer: Monthly X (Twitter) credits. X bills per use: 15 per post, 200 if the text contains a link, 15 per deletion, 1 per stat read, 1 per timeline item. The pool resets on the 1st of each calendar month and does not roll over.
      - `ai_credits` integer: Monthly AI credits (1 credit = $0.001 of provider cost): 15 per plan orchestration pass, 2 per generated text, 70 per generated image. Resets monthly and does not roll over. A client using its own provider key (BYOK) does not consume them in that scope.
    - `limits` PlanData, required: The resources a plan grants. On a client it is what was contracted; on an organization, the slice of it that was assigned. The sum across all the organizations of a client can never exceed what the client has contracted. Users are NOT here: every plan has unlimited users, so they are neither charged nor split between organizations. They are still counted, in `PlanUseData.users`. There are no `artificial_inteligence`, `whatsapp` or `stats` flags either: statistics and WhatsApp are on every plan, and what gates AI is `ai_credits` — a plan with credits has AI, and Free has zero.
      - `accounts` integer, required: Social accounts that may be connected.
      - `space` number, required: Storage, in GB.
      - `integrations` integer, required: Connections to a third-party tool material is pulled from (Google Drive, an RSS feed). Not the same thing as an app: an app is API access, and it has its own allowance in `apps`.
      - `apps` integer: Apps this plan allows: 1 on Free, 2 on Basic, 5 on Pro, 10 on Custom. Each one is a `client_id` with a secret, so each one is a key to the whole public API — which every plan has, Free included. Unlike accounts or storage this is NOT split between organizations: an app belongs to the client. On a use payload it is how many exist right now.
      - `twitter_credits` integer: Monthly X (Twitter) credits. X bills per use: 15 per post, 200 if the text contains a link, 15 per deletion, 1 per stat read, 1 per timeline item. The pool resets on the 1st of each calendar month and does not roll over.
      - `ai_credits` integer: Monthly AI credits (1 credit = $0.001 of provider cost): 15 per plan orchestration pass, 2 per generated text, 70 per generated image. Resets monthly and does not roll over. A client using its own provider key (BYOK) does not consume them in that scope.
  - `ai_plans` object
    - `total` integer, required
    - `credits_spent` integer, required
    - `by_state` object[], required
      - `state` string
      - `total` integer
    - `last_plan` DashboardDashboardAiPlanRef: The most recent AI plan, projected: enough to tell at a glance whether one is still generating, failed, or is waiting to be validated. `publications` are identifiers here.
      - `_id` string, required
      - `state` 'pending' | 'generating' | 'generated' | 'validated' | 'failed' | 'cancelled', required
      - `prompt` string
      - `credits_spent` integer
      - `publications` string[]
      - `creation_date` string, date-time, required
      - `generation_end_date` string, date-time
      - `error` object
        - `code` integer, required
        - `message` string, required
        - `data` object
    - `generated_publications` integer, required: Publications generated by the plans of the range.
    - `pending_validation` integer, required: Plans already generated and **waiting for someone to validate them**: work paid for that is not publishing anything yet.
  - `ai_plan_results` object: The best AI plans of the range, by interactions per measured publication — the short version of `GET /clients/{id}/organizations/{id}/ai_plans/results`, with the same rules: the range filters on the plan's **week**, and only plans with at least 3 measured publications compete. Unlike that endpoint it covers the organization **and its children**, like the rest of this screen, so each plan carries its `id_organization`.
    - `top` AiPlanResult[], required: Up to three plans, best first. Only ranked ones.
      - `id_ai_plan` string, required
      - `id_organization` string, required: The organization the plan belongs to. In the dashboard block it can be a **child** of the organization you asked about, and a plan is only reachable by id through its own organization.
      - `prompt` string, required
      - `template` 'standard' | 'from_images' | 'from_text' | 'from_catalog' | 'campaign', required: What the plan was generated from. A plan created before templates existed reads `standard`.
      - `state` 'generated' | 'validated', required: Only these two can have results. A `generated` plan was never validated, but someone may have published some of its drafts by hand.
      - `week_start` string, date-time, required: The week the plan publishes in. **This is what the range filters on**, not the creation date.
      - `creation_date` string, date-time, required
      - `archived_date` string, date-time: Archived plans are included: archiving is visibility only, and what they published is still published.
      - `accounts` integer, required: Accounts the plan was generated for.
      - `social_networks` SocialNetwork[], required: Networks the plan published on. With the `social_network` filter, only the filtered ones.
      - `credits_spent` integer, required: AI credits the plan cost, for the whole plan.
      - `publications` object, required
        - `total` integer, required: Publications of the plan that still exist. Deleted ones do not count.
        - `published` integer, required: Went out to the network.
        - `measured` integer, required: Published **and** with metrics collected: the only ones the averages use.
        - `scheduled` integer, required: Scheduled, or being published right now.
        - `failed` integer, required: Failed to publish.
      - `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_per_publication` number: Interactions per measured publication — **the number plans are ranked by**. The total rewards size (seven accounts for seven days beat one account even if each post does half as well), and the engagement rate divides by reach on some networks and by followers on others, which makes two plans on different networks incomparable. Absent when nothing is measured yet.
      - `expected_engagement_per_publication` number: What **your usual posts** would get with the same mix of networks: the organization's average interactions per measured post on each network, weighted by how many measured posts the plan has there. Two measured posts on Instagram (average 5) and two on LinkedIn (average 1) expect (2·5 + 2·1) / 4 = 3. The average covers **every** measured post of the organization in the range, AI ones included, on the same networks. Weighting by network is what keeps a LinkedIn-only plan from always reading as below average just because LinkedIn moves less than Instagram.
      - `engagement_vs_average` number: `engagement_per_publication` divided by `expected_engagement_per_publication`: **1 means like your average, 2 twice as much, 0.5 half**. This is the number that says whether a plan is *good*, not just first — the ranking still orders by `engagement_per_publication`, so the first plan can be below 1. Absent with nothing measured or no average to compare with.
      - `credits_per_engagement` number: AI credits per interaction: what each interaction cost. Lower is better. Absent with no interactions, with no credits spent (your own AI key) and **whenever `social_network` is filtered** — the cost belongs to the whole plan, and dividing it by one network's interactions would overprice every one of them.
      - `last_publish_date` string, date-time
      - `ranked` boolean, required: Whether the plan competes in the ranking: it needs at least **3 measured publications**, or all of them if it published fewer. With a single measurement, one lucky post would put its plan first.
      - `maturing` boolean, required: Its numbers are still moving: something is still scheduled, or its last publication is less than 7 days old. Comparing it with a plan from last month is unfair to the new one — say so rather than hiding it.
    - `plans` integer, required: Plans with results in the range.
    - `ranked_plans` integer, required: How many of those compete in the ranking. `plans > 0` with `ranked_plans: 0` means there are results, just not enough measured yet.
    - `engagement_per_publication` number: Interactions per measured publication across every plan of the range.
    - `engagement_vs_average` number: Interactions per post of every plan of the range over what your usual posts would get on the same networks. 1 means like your average.
  - `messages` object
    - `unread` integer, required

## 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)
