Source: https://developers.tokportal.com/analytics/
Markdown: https://developers.tokportal.com/analytics.md

# Analytics

TokPortal Analytics v2 exposes account, portfolio, post-level, time-series, comment, export, and raw provider analytics for delivered accounts.

Data is owner-scoped by API key and can come from multiple sources:

- connected account analytics when the account is connected through TokPortal's supported social integrations
- public fallback analytics when connected analytics are unavailable
- TokPortal historical cache and post metadata

All examples use the public API base URL:

```text
https://app.tokportal.com/api/ext
```

## Access Levels

Analytics responses are plan-aware:

| Level            | Access                                                                                                         |
| ---------------- | -------------------------------------------------------------------------------------------------------------- |
| Starter          | Basic totals and limited post/account visibility.                                                              |
| Creator          | Core performance, time series, CSV export, and web reports.                                                    |
| Marketer/Farmer+ | Full analytics, raw provider payloads, demographics, comments, and advanced post intelligence where available. |

Every Analytics v2 response includes contract metadata or the `X-TokPortal-Analytics-Contract` header.

***

## Portfolio Dashboard

```http
GET /analytics
```

Returns the Analytics v2 dashboard for the API key owner: totals, accounts, top posts, audience summary, facets, access metadata, and the current data contract.

Optional filters:

| Query       | Description                                                            |
| ----------- | ---------------------------------------------------------------------- |
| `workspace` | Workspace ID.                                                          |
| `platform`  | Repeatable platform filter, e.g. `platform=tiktok&platform=instagram`. |
| `country`   | Repeatable country filter.                                             |
| `account`   | Repeatable saved account ID filter.                                    |
| `from`      | Start date or ISO timestamp.                                           |
| `to`        | End date or ISO timestamp.                                             |

```bash
curl -X GET "https://app.tokportal.com/api/ext/analytics?platform=tiktok" \
  -H "X-API-Key: sk_xxx"
```

Response shape:

```json
{
  "tier": "full",
  "access": {
    "level": "full",
    "planTier": "farmer",
    "reason": "full_access"
  },
  "totals": {
    "account_count": 99,
    "views": 648356,
    "impressions": 619676,
    "tracked_posts": 4876,
    "post_views": 2181245,
    "avg_fyp_pct": null
  },
  "accounts": [],
  "top_posts": [],
  "audience": {
    "age": [],
    "gender": [],
    "country": [],
    "city": [],
    "unit": "unknown"
  },
  "contract": {
    "name": "tokportal.analytics.v2",
    "version": "2026-09-22.1",
    "accessLevel": "full"
  }
}
```

***

## Account Drilldown

```http
GET /analytics/accounts/:id
```

Returns one account's Analytics v2 drilldown: account header, latest account snapshot, posts, daily series, demographics, derived stats, intelligence, and contract metadata.

```bash
curl -X GET https://app.tokportal.com/api/ext/analytics/accounts/9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c \
  -H "X-API-Key: sk_xxx"
```

Important fields:

| Field           | Description                                                  |
| --------------- | ------------------------------------------------------------ |
| `latest`        | Latest account-level metrics.                                |
| `posts`         | Tracked post list with latest post snapshot metrics.         |
| `daily_series`  | Stored daily points for charts.                              |
| `demographics`  | Parsed account or post audience demographics when available. |
| `derived_stats` | Derived lifetime stats from tracked posts.                   |
| `intelligence`  | Cached content/account intelligence when available.          |

***

## Time Series

```http
GET /analytics/series
```

Returns stored chart points. This endpoint does not live-refresh data.

Query parameters:

| Query         | Description                                                               |
| ------------- | ------------------------------------------------------------------------- |
| `metric`      | `views`, `likes`, `comments`, `shares`, or `followers`. Default: `views`. |
| `granularity` | `day` or `week`. Default: `day`.                                          |
| `mode`        | `cumulative`, `gained`, or `snapshot`. Default: `cumulative`.             |
| `account`     | Repeatable saved account ID.                                              |
| `from`        | Start date or ISO timestamp.                                              |
| `to`          | End date or ISO timestamp.                                                |

```bash
curl -X GET "https://app.tokportal.com/api/ext/analytics/series?metric=views&granularity=day&mode=cumulative&account=9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c&from=2026-05-01&to=2026-05-10" \
  -H "X-API-Key: sk_xxx"
```

***

## Account Compatibility Endpoint

```http
GET /accounts/:id/analytics
```

This older public path now uses Analytics v2. It keeps legacy-shaped fields for existing integrations and also exposes the full v2 payload under `data.analytics_v2`.

```bash
curl -X GET https://app.tokportal.com/api/ext/accounts/9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c/analytics \
  -H "X-API-Key: sk_xxx"
```

Response:

```json
{
  "data": {
    "account_id": "9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c",
    "followers_count": 12400,
    "total_videos_tracked": 48,
    "total_views": 580000,
    "total_likes": 42000,
    "average_engagement_rate": 7.24,
    "analytics_version": "v2",
    "analytics_v2": {
      "account": {},
      "latest": {},
      "posts": []
    }
  }
}
```

***

## Post Analytics by Account

```http
GET /accounts/:id/analytics/videos
```

Returns Analytics v2 tracked posts in the older paginated list shape.

Query parameters:

| Parameter    | Type    | Default       | Description                                            |
| ------------ | ------- | ------------- | ------------------------------------------------------ |
| `sort_by`    | string  | `upload_date` | `views`, `likes`, `engagement_rate`, or `upload_date`. |
| `sort_order` | string  | `desc`        | `asc` or `desc`.                                       |
| `page`       | integer | `1`           | Page number.                                           |
| `per_page`   | integer | `50`          | Results per page, max `100`.                           |

```bash
curl -X GET "https://app.tokportal.com/api/ext/accounts/9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c/analytics/videos?sort_by=views&sort_order=desc" \
  -H "X-API-Key: sk_xxx"
```

Rows include `tracked_post_id`, `analytics_version: "v2"`, and the full v2 row under `analytics_v2`.

***

## Single Post Analytics

```http
GET /videos/:id/analytics
```

Pass an Analytics v2 `tracked_post_id` when available. For older integrations, this endpoint can still fall back to a legacy `video_analytics.id`.

```bash
curl -X GET https://app.tokportal.com/api/ext/videos/8c2d0f2e-.../analytics \
  -H "X-API-Key: sk_xxx"
```

Response fields include normalized post metrics, `analytics_version`, and for v2 records an `analytics_v2` object with the tracked post and latest snapshot, plus `platform_signals` and `signal_insights` (see [Platform Signals](https://developers.tokportal.com/analytics/#platform-signals)).

***

## Platform Signals

Every post row returned by the account drilldown, the dashboard top posts, `GET /videos/:id/analytics` and the videos endpoints carries a `signals` / `platform_signals` object describing what the platform did with the live post. Fields are `null` until the post has been checked (about 48 hours after posting, again at 7 days, and on every later scrape) — `null` means *not checked yet*, never *no*. Signals are health information and are visible on **every tier**.

| Field             | Meaning                                                                                                                                                                                                    |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `not_recommended` | TikTok **Not For Feed / Not Recommended**: the post stays online but is excluded from the For You feed and typically sits at 0 views. On a large sample this flag explains 86 % of posts stuck at 0 views. |
| `ai_label`        | `creator` (declared at posting) or `platform` (applied by TikTok moderation). Visible to viewers; can reduce distribution.                                                                                 |
| `sound`           | `ok`, `non_commercial` (cannot be promoted), `removed` (pulled for copyright, plays muted), `muted` (Instagram).                                                                                           |

Why TikTok does it, in its own words: content is "ineligible for the FYF if it includes unoriginal or reused material without anything new" ([For You feed eligibility standards](https://www.tiktok.com/community-guidelines/en/fyf-standards/)), and "if you repeatedly post content that is unsuitable for the For You feed, your account and posts won't appear in the For You feed" ([Why is my account not being recommended?](https://support.tiktok.com/en/safety-hc/account-and-user-safety/why-is-my-account-not-being-recommended)). AI labels follow TikTok's [AI-generated content](https://support.tiktok.com/en/using-tiktok/creating-videos/ai-generated-content) rules; sound restrictions follow the [commercial use of music](https://support.tiktok.com/en/business-and-creator/creator-and-business-accounts/commercial-use-of-music-on-tiktok) rules. A flag is a content decision of the platform: it is not a defect of the account, and it is not a ground for replacement or refund under TokPortal's [Ban & Replacement Policy](https://www.tokportal.com/ban-and-replacement-policy#low-performance).

From the **Creator** tier, post rows also carry connected-API depth (TikTok accounts connected through TokPortal):

| Field                | Meaning                                                                                                 |
| -------------------- | ------------------------------------------------------------------------------------------------------- |
| `new_followers`      | Followers gained from this post.                                                                        |
| `audience_types`     | `{ new_viewer, returning_viewer, follower, non_follower }`, shares 0..1.                                |
| `impression_sources` | Full breakdown: `for_you`, `follow`, `search`, `personal_profile`, `sound`, `direct_message`, `others`. |
| `retention_curve`    | `[{ second, percentage }]` — share of viewers still watching at each second.                            |
| `engagement_curve`   | `[{ second, percentage }]` — when likes were given.                                                     |

The account drilldown adds `account_signals`: private / business / "joined recently" flags, the share of the last 5 checked posts not recommended (`recent_not_recommended` / `recent_posts_checked`), sound issues and AI-labelled counts, and on Instagram the 30-day reach split `reach_followers_30d` / `reach_non_followers_30d`. Instagram `daily_series` points now carry `reach` from the official Meta `reach/day` insight.

### Flagged posts

```http
GET /analytics/signals
```

Owner-scoped list of every post carrying a signal, newest first.

| Query             | Description                                                           |
| ----------------- | --------------------------------------------------------------------- |
| `signal`          | `not_recommended`, `ai_label` or `sound_status`. Omit for any signal. |
| `account`         | Repeatable saved account ID filter.                                   |
| `from`, `to`      | Only signals updated inside the window (ISO timestamps).              |
| `limit`, `offset` | Pagination, `limit` 1..200 (default 50).                              |

```bash
curl -X GET "https://app.tokportal.com/api/ext/analytics/signals?signal=not_recommended&limit=20" \
  -H "X-API-Key: sk_xxx"
```

```json
{
  "data": [
    {
      "tracked_post_id": "31bbd0c0-4fd1-446f-9f19-d453536c9694",
      "video_listing_id": "2dd8a805-3a24-4e84-bbba-4b31f805b34d",
      "saved_account_id": "f92b2e59-7ec2-45d0-9a88-a8abaa6a8851",
      "username": "lena.huber_",
      "platform": "tiktok",
      "country": "DE",
      "platform_post_id": "7653808499427790102",
      "permalink": "https://www.tiktok.com/@lena.huber_/video/7653808499427790102",
      "published_at": "2026-06-21T00:00:00Z",
      "platform_signals": {
        "checked_at": "2026-09-19T05:28:00Z",
        "not_recommended": true,
        "not_recommended_since": "2026-07-06T15:27:30Z",
        "ai_label": null,
        "sound": "non_commercial",
        "sound_reason": "Can't promote due to audio copyright issue"
      },
      "signal_insights": null,
      "updated_at": "2026-09-22T05:47:52Z"
    }
  ],
  "pagination": { "limit": 20, "offset": 0, "total": 9 },
  "contract": { "name": "tokportal.analytics.v2", "version": "2026-09-22.1", "accessLevel": "starter" }
}
```

Webhooks push the same observations as they happen: [`video.not_recommended`, `video.ai_labeled`, `video.sound_restricted`, `account.distribution_warning`](https://developers.tokportal.com/webhooks#platform-signal-events). Clients also get a grouped in-app notification per order per day and an optional daily e-mail digest (Settings → Notifications).

***

## Comment Pulse

```http
GET /analytics/comments
```

Returns a dashboard-level comment pulse across top posts in the selected scope. Full-tier only. The endpoint serves cached comments and cached semantic analysis, hydrating comments only when the cache is empty or stale.

Query parameters:

| Parameter         | Description                                                      |
| ----------------- | ---------------------------------------------------------------- |
| `limit`           | Total comments to return, `1..40`. Default: `24`.                |
| `postLimit`       | Number of top posts to sample, `1..10`. Default: `6`.            |
| `commentsPerPost` | Comments to hydrate per post when needed, `1..12`. Default: `8`. |
| `post`            | Repeatable tracked post ID to force a specific sample.           |
| `workspace`       | Workspace ID.                                                    |
| `account`         | Repeatable saved account ID.                                     |
| `platform`        | Repeatable platform filter.                                      |
| `country`         | Repeatable country filter.                                       |
| `from`            | Start date or ISO timestamp.                                     |
| `to`              | End date or ISO timestamp.                                       |

```bash
curl -X GET "https://app.tokportal.com/api/ext/analytics/comments?platform=tiktok&limit=24" \
  -H "X-API-Key: sk_xxx"
```

The response echoes the scope it actually sampled under `applied_filters`. When you pass `post`, it forces that specific sample and overrides the dashboard filters (`workspace`, `account`, `platform`, `country`, `from`, `to`) — the response states when that happened, so read `applied_filters` instead of assuming your filter set was honoured.

***

## Post Comments

```http
GET /analytics/accounts/:id/comments
```

Returns cached comments for one tracked post. Full-tier only.

Query parameters:

| Parameter       | Description                          |
| --------------- | ------------------------------------ |
| `trackedPostId` | Analytics v2 tracked post ID.        |
| `postId`        | Connected provider post ID fallback. |
| `limit`         | Number of comments, max `50`.        |

```bash
curl -X GET "https://app.tokportal.com/api/ext/analytics/accounts/9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c/comments?trackedPostId=8c2d0f2e-..." \
  -H "X-API-Key: sk_xxx"
```

***

## CSV Export

```http
GET /analytics/export/videos
```

Returns `text/csv` for all videos in scope. The exported columns are plan-aware.

Optional filters:

| Query       | Description                                                  |
| ----------- | ------------------------------------------------------------ |
| `workspace` | Workspace ID.                                                |
| `account`   | Repeatable saved account ID.                                 |
| `platform`  | Repeatable platform filter.                                  |
| `country`   | Repeatable country filter.                                   |
| `q`         | Search text over account, post text, URLs, and platform IDs. |
| `from`      | Start date or ISO timestamp.                                 |
| `to`        | End date or ISO timestamp.                                   |

```bash
curl -X GET "https://app.tokportal.com/api/ext/analytics/export/videos?account=9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c" \
  -H "X-API-Key: sk_xxx"
```

***

## HTML Reports

```http
POST /analytics/export/reports
POST /analytics/export/reports/html
```

`POST /analytics/export/reports` creates a shareable Analytics v2 web report; the response includes a report `token` and public `url`. `POST /analytics/export/reports/html` takes the same body and returns a standalone downloadable HTML document. Creator and full-tier plans can generate reports. Custom branding is available for full/farmer plans.

Do not send `Idempotency-Key` to analytics report creation or HTML report export. These responses can contain a private report token or artifact, so TokPortal rejects the header before execution with `400 IDEMPOTENCY_KEY_NOT_ALLOWED_FOR_SENSITIVE_RESPONSE`. If the request outcome is uncertain, list or reconcile the workspace's reports before creating another one. Never include report tokens in support logs.

```bash
curl -X POST https://app.tokportal.com/api/ext/analytics/export/reports \
  -H "X-API-Key: sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "April performance report",
    "template": "executive",
    "accountIds": ["9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c"],
    "from": "2026-04-01",
    "to": "2026-04-30"
  }'
```

### Request Body

| Field         | Type           | Description                                                                                |
| ------------- | -------------- | ------------------------------------------------------------------------------------------ |
| `title`       | string \| null | Report title. Max **120** characters.                                                      |
| `template`    | string \| null | Layout: `executive`, `agency`, `creator`, `minimal`, `growth`, or `board`.                 |
| `brandName`   | string \| null | White-label brand name. Max **80** characters.                                             |
| `brandAccent` | string \| null | White-label accent colour, `#rrggbb`.                                                      |
| `accountIds`  | string\[]      | Saved account IDs to include.                                                              |
| `workspaceId` | string \| null | Workspace ID.                                                                              |
| `platforms`   | string\[]      | Repeatable platform filter: `tiktok`, `instagram`.                                         |
| `countries`   | string\[]      | Country codes.                                                                             |
| `query`       | string \| null | Free-text filter over accounts, post text, URLs, and platform IDs. Max **120** characters. |
| `from`        | string \| null | Inclusive start date, `YYYY-MM-DD`.                                                        |
| `to`          | string \| null | Inclusive end date, `YYYY-MM-DD`.                                                          |

### Validation

Both routes validate this body rather than coercing it.

- **`template`** — any value outside the six listed above is rejected with `INVALID_FIELD`. It is not replaced by `executive`.
- **`from` / `to`** — must be `YYYY-MM-DD`. A full ISO timestamp is accepted and truncated to its date; anything else is rejected with `INVALID_FIELD` rather than being treated as no filter at all, which used to widen the report to the account's entire history. `from` must not be after `to`.
- **`brandAccent`** — `#rrggbb`, or a `#rgb` short form which is expanded to six digits. Named colours (`red`), `rgb()` notation, and 8-digit hex are rejected with `INVALID_FIELD`.
- **Lengths** — `title` 120, `brandName` 80, `query` 120 characters.

### Reading back what was applied

The settings that actually took effect are echoed, so you never have to inspect the rendered report to find out what the server used.

On `POST /analytics/export/reports` they come back on the JSON response under `applied`:

| Field                  | Description                       |
| ---------------------- | --------------------------------- |
| `applied.template`     | The layout actually used.         |
| `applied.brand_name`   | The brand name actually rendered. |
| `applied.brand_accent` | The accent colour actually used.  |
| `applied.filters.from` | The start date actually applied.  |
| `applied.filters.to`   | The end date actually applied.    |

On `POST /analytics/export/reports/html` the same information comes back as `X-TokPortal-Report-*` response headers (for example `X-TokPortal-Report-Template`).

> **INFO: White-labelling is plan-gated**
> `brandName` and `brandAccent` are only applied on the full analytics tier with a Farmer plan. On every other plan the brand is reset to TokPortal, and `applied.brand_name` together with `canBrand` say so — read them before promising a client a white-labelled document.

***

## Raw Provider Payloads

Full-tier clients can retrieve stored raw provider payloads. These endpoints are useful when you need fields that TokPortal has stored but has not yet normalized into product UI fields.

### Account Raw Snapshots

```http
GET /analytics/accounts/:id/raw
```

Returns rows from `account_analytics_snapshots`, including normalized metrics and the stored `raw` JSON payload.

```bash
curl -X GET "https://app.tokportal.com/api/ext/analytics/accounts/9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c/raw?source=bundle_social&limit=3" \
  -H "X-API-Key: sk_xxx"
```

### Post Raw Snapshots

```http
GET /analytics/posts/:tracked_post_id/raw
```

Returns rows from `post_analytics_snapshots`, including normalized metrics, raw per-post analytics, and tracked post metadata.

```bash
curl -X GET "https://app.tokportal.com/api/ext/analytics/posts/8c2d0f2e-.../raw?source=bundle_social&limit=3" \
  -H "X-API-Key: sk_xxx"
```

Raw endpoint filters:

| Query    | Description                            |
| -------- | -------------------------------------- |
| `source` | `bundle_social`, `apify`, or `manual`. |
| `limit`  | `1..30`, default `5`.                  |
| `from`   | Start date or ISO timestamp.           |
| `to`     | End date or ISO timestamp.             |

***

## Refresh Analytics

```http
POST /accounts/:id/analytics/refresh
```

Triggers a targeted Analytics v2 refresh for one account. Background sync is the primary refresh path; use this endpoint for targeted repair or bootstrap flows.

Body:

```json
{
  "includePosts": true,
  "includeComments": true,
  "postLimit": 20,
  "force": true,
  "forcePosts": false,
  "bootstrapPosts": false
}
```

> **WARNING: `includeComments` requires `force`**
> Comment hydration only takes effect when `force` is `true`, `includePosts` is not `false`, and the workspace holds the full analytics tier. Sending `includeComments: true` without `force` is refused for strict callers (MCP by default) and reported back in `applied` for the rest — it is no longer dropped without a word.

The server dedupes repeated requests:

| Source                    | Dedupe window |
| ------------------------- | ------------- |
| Connected analytics       | 6 hours       |
| Public fallback analytics | 24 hours      |

Response:

```json
{
  "data": {
    "account_id": "9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c",
    "platform": "tiktok",
    "status": "refreshed",
    "analytics_version": "v2"
  }
}
```

***

## Check Refresh Availability

```http
GET /accounts/:id/analytics/can-refresh
```

Returns whether targeted refresh is currently available for an account under the Analytics v2 dedupe policy.

```bash
curl -X GET https://app.tokportal.com/api/ext/accounts/9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c/analytics/can-refresh \
  -H "X-API-Key: sk_xxx"
```

Response:

```json
{
  "data": {
    "account_id": "9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c",
    "can_refresh": true,
    "next_refresh_at": null,
    "hours_remaining": 0,
    "source": "connected",
    "analytics_version": "v2"
  }
}
```

***

## Contract

```http
GET /analytics/contract
```

Returns the global Analytics v2 contract, the current API key's access payload, metric semantics, endpoint metadata, freshness targets, and redaction rules.

## Connected Instagram and TikTok insights

`GET /analytics/accounts/{id}/insights` returns the same `connected_analytics` block as the account drilldown. The MCP tool is `getAnalyticsAccountInsights` (remote MCP at `https://app.tokportal.com/api/ext/mcp`). All reads are scoped to the API key owner and read stored observations; opening a dashboard or calling this endpoint never starts a provider refresh.

Requires Creator or higher. Starter receives `403 plan_required` from the insights endpoint, and the block is omitted from the normal drilldown. Existing quotas and refresh policies are unchanged.

```bash
curl -H "X-API-Key: $API_KEY" \
  "https://api.tokportal.com/analytics/accounts/$ACCOUNT_ID/insights"
```

When no recently verified active Zernio connection exists, the endpoint returns:

```json
{"account_id":"saved-account-uuid","available":false,"connected_analytics":null}
```

The normal drilldown omits `connected_analytics` in this case. The dashboard also hides the new block, including after a recorded disconnection. A pinned provider ID alone, or an old analytics snapshot, is not proof of an active connection. Proof older than 24 hours is treated as unavailable until a server check succeeds. A delayed disconnection webhook with an older provider timestamp does not override a newer verified check. Legacy analytics and historical snapshots remain available through their existing contracts.

When available, `connected_analytics` contains:

| Field                                      | Meaning                                                                                                                                                                                                                        |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `platform`                                 | `instagram` or `tiktok`.                                                                                                                                                                                                       |
| `connection_checked_at`                    | Latest accepted server connection proof.                                                                                                                                                                                       |
| `captured_at`                              | Stored account observation time, not a claim of instant platform freshness.                                                                                                                                                    |
| `account.period.from`, `account.period.to` | Exact account insight window.                                                                                                                                                                                                  |
| `account.metrics`                          | Available, tier-aware account counts. Instagram reach, views, engaged accounts and interactions cover the period. TikTok follower/following/video/like counters are lifetime counters; follower gains/losses cover the window. |
| `account.daily_followers`                  | Daily follower counts, when supplied.                                                                                                                                                                                          |
| `account.daily_reach`                      | Daily Instagram reach, when supplied. Never sum daily unique reach into period unique reach.                                                                                                                                   |
| `account.demographics`                     | Full-tier audience counts by age, gender, country and city; `null` until eligible/available. Instagram normally requires at least 100 followers.                                                                               |
| `posts[].tracked_post_id`                  | TokPortal tracked-post ID, matching the normal drilldown.                                                                                                                                                                      |
| `posts[].captured_at`                      | Actual metric observation timestamp.                                                                                                                                                                                           |
| `posts[].metrics`                          | Optional lifetime per-post metrics: saves, followers gained, reach, profile/website/link clicks, average/total watch seconds, completion, replays or reposts.                                                                  |
| `posts[].traffic_sources`                  | Available traffic-source shares as percentages from 0 to 100.                                                                                                                                                                  |
| `posts[].audience_types`                   | Available new/returning and follower/non-follower shares as percentages from 0 to 100. These are two independent distributions.                                                                                                |

`completion_rate` is a fraction from 0 to 1 (0.42 means 42%). `average_watch_seconds` and `total_watch_seconds` use seconds. Unknown or unsupported metrics are omitted, never manufactured as zero. Real observed zeros remain valid counts. Generic zero-filled TikTok depth responses are withheld until there is evidence that detailed insights are available.

Creator includes core account growth, daily histories, post saves/followers gained and traffic/audience shares. Marketer/Farmer/full adds account reach and engagement, watch time, completion, profile/website/link clicks and demographics. Lower-tier responses do not carry hidden full-tier values.

Instagram account views include feed, Reels, Stories and other surfaces and deliberately differ from post-level totals. TikTok detailed post metrics depend on the connection lane and platform availability, often arrive 24–48 hours after publication, and may be limited to recently active posts. This endpoint does not promise account-level TikTok impressions/reach or a second-by-second retention curve.

New correctly connected accounts enter the existing background sync automatically. Account data and optional Instagram follower/reach history and demographics refresh through the daily account lane; optional audience failures do not discard the core observation. Analytics webhooks wake ingestion of already-available changes, not a real-time platform update. Use `captured_at`, the explicit period and `GET /analytics/contract` when interpreting results.
