# GET /v1/projects/:projectId/metrics (/docs/api/reference/metrics/unified-metrics)



<Endpoint method="GET" path="/v1/projects/{projectId}/metrics" auth="Bearer" scope="metrics:read" phase="1" />

Organic metrics for anything you can identify — a single platform post, a social account, a project layer, a whole project, or your organization. `scope` controls what kind of thing you are asking about; `id` is the specific one; `metrics`, `since`, `until`, and `granularity` control what you get back.

Metrics always come back as `(series, totals)`. `series` is the bucketed time series at your requested granularity; `totals` is the aggregate over the full window. You get both so your UI can render the chart and the big number without a second call.

For ranked creatives rather than raw time series, use [`GET /v1/projects/:projectId/top-performers`](/docs/api/reference/metrics/top-performers).

<Parameters
  title="Query"
  rows="[
  { name: 'scope', type: 'string', required: true, description: 'What you are asking about.', enum: ['platform_post', 'social_account', 'project', 'project_layer', 'organization'] },
  { name: 'id', type: 'string', required: true, description: 'Id of the scoped entity. platform_post takes a platform_post_id; social_account takes a social_account_id; project takes a project_id; project_layer takes a project_layer_id; organization takes the org id from /v1/whoami.' },
  { name: 'metrics', type: 'string[]', description: 'Which metrics to return. Omit for the default bundle for the scope.', enum: ['views', 'reach', 'impressions', 'likes', 'comments', 'shares', 'saves', 'watch_time_ms', 'engagement_rate', 'followers', 'follower_delta', 'posts_published'] },
  { name: 'since', type: 'string (ISO-8601)', description: 'Window start. Inclusive.', default: '30 days ago' },
  { name: 'until', type: 'string (ISO-8601)', description: 'Window end. Exclusive.', default: 'now' },
  { name: 'granularity', type: 'string', description: 'Series bucket size.', enum: ['hour', 'day', 'week'], default: 'day' },
]"
/>

## Example request [#example-request]

<Tabs items="['curl', 'TypeScript', 'Python']">
  <Tab value="curl">
    ```bash
    curl "https://api.layers.com/v1/projects/prj_01HX9Y7K8M2P4RSTUV56789AB/metrics?scope=project&id=prj_01HX9Y7K8M2P4RSTUV56789AB&metrics=views&metrics=engagement_rate&since=2026-04-01T00:00:00Z&until=2026-04-18T00:00:00Z&granularity=day" \
      -H "Authorization: Bearer lp_live_01HX9Y6K7EJ4T2_4QZpN..."
    ```
  </Tab>

  <Tab value="TypeScript">
    ```ts
    const params = new URLSearchParams({
      scope: "project",
      id: "prj_01HX9Y7K8M2P4RSTUV56789AB",
      since: "2026-04-01T00:00:00Z",
      until: "2026-04-18T00:00:00Z",
      granularity: "day",
    });
    params.append("metrics", "views");
    params.append("metrics", "engagement_rate");

    const res = await fetch(
      `https://api.layers.com/v1/projects/prj_01HX9Y7K8M2P4RSTUV56789AB/metrics?${params}`,
      { headers: { Authorization: `Bearer ${apiKey}` } },
    );
    const { series, totals } = await res.json();
    ```
  </Tab>

  <Tab value="Python">
    ```python
    import httpx

    params = [
        ("scope", "project"),
        ("id", "prj_01HX9Y7K8M2P4RSTUV56789AB"),
        ("since", "2026-04-01T00:00:00Z"),
        ("until", "2026-04-18T00:00:00Z"),
        ("granularity", "day"),
        ("metrics", "views"),
        ("metrics", "engagement_rate"),
    ]
    r = httpx.get(
        "https://api.layers.com/v1/projects/prj_01HX9Y7K8M2P4RSTUV56789AB/metrics",
        params=params,
        headers={"Authorization": f"Bearer {api_key}"},
    )
    payload = r.json()
    ```
  </Tab>
</Tabs>

## Response [#response]

<Response status="200" description="OK">
  ```json
  {
    "scope": "project",
    "id": "prj_01HX9Y7K8M2P4RSTUV56789AB",
    "window": {
      "since": "2026-04-01T00:00:00Z",
      "until": "2026-04-18T00:00:00Z",
      "granularity": "day"
    },
    "series": [
      { "bucket": "2026-04-01", "views": 12840, "engagement_rate": 0.041 },
      { "bucket": "2026-04-02", "views": 17220, "engagement_rate": 0.052 },
      { "bucket": "2026-04-03", "views": 9880,  "engagement_rate": 0.037 }
    ],
    "totals": {
      "views": 240911,
      "engagement_rate": 0.047,
      "post_count": 23
    }
  }
  ```
</Response>

<Response status="422" description="scope/id mismatch or unknown metric.">
  ```json
  { "error": { "code": "VALIDATION", "message": "Unknown metric: conversions. Use /v1/projects/:projectId/ads-metrics for paid metrics." } }
  ```
</Response>

<Response status="404" description="Scoped entity not found or not in your organization." />

## Defaults by scope [#defaults-by-scope]

| Scope            | Default metrics                                                    | Notes                                                                    |
| ---------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------ |
| `platform_post`  | `views`, `likes`, `comments`, `shares`, `saves`, `engagement_rate` | Single post; `granularity=day` or `hour`.                                |
| `social_account` | `followers`, `follower_delta`, `posts_published`, `views`          | Account-level roll-up.                                                   |
| `project_layer`  | `views`, `engagement_rate`, `posts_published`                      | Per-layer so you can compare Social Content vs Managed UGC side by side. |
| `project`        | Same as `project_layer`, summed across layers.                     |                                                                          |
| `organization`   | `views`, `posts_published` across all projects.                    | Coarse — use for an overview pane.                                       |

## Notes [#notes]

* Engagement rate is `(likes + comments + shares + saves) / max(views, 1)`. Platforms report each differently; we normalize before computing.
* `watch_time_ms` is only populated for platforms that expose it (TikTok, Instagram Reels). Zero on static formats.
* Paid metrics (spend, CPA, ROAS) live on [`GET /v1/projects/:projectId/ads-metrics`](/docs/api/reference/ads/ads-metrics). Asking for `spend` here returns `VALIDATION`.
* Windows longer than 90 days with `granularity=hour` get clamped. Either narrow the window or step up to `day`.

## See also [#see-also]

* [`GET /v1/projects/:projectId/ads-metrics`](/docs/api/reference/ads/ads-metrics) — paid metrics
* [`GET /v1/projects/:projectId/top-performers`](/docs/api/reference/metrics/top-performers) — ranked creatives
* [Publish to learn](/docs/api/guides/publish-to-learn) — the read-side feedback loop
