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

# Get Template Metrics

> Per-template delivery, read, click, and cost analytics with a daily time series and gap-filled buckets.

## What it does

Returns Meta's template analytics for up to 10 templates of a single application: an overall `summary`, a per-template `summary`, and a daily `series`.

* **Gap-filled buckets** — days Meta returns no data for are emitted as zero points, so the series is always continuous across the requested range.
* **Pending days** — zero points beyond Meta's `dataAvailableUntil` watermark are flagged `isPending: true`, telling you the day is not yet aggregated rather than genuinely empty.
* **Derived rates** — `deliveredRate`, `readRate`, `clickRate`, and `costPerDelivered` are computed for you and rounded to 4 decimals.

<Note>
  This endpoint is per-application and per-template. For organization-wide message volume, use [Get Messages](/public-api-reference/analytics/get-messages) instead.
</Note>

***

## Endpoint

```text theme={null}
GET /api/v1/wa/{app_id}/templates/metrics
```

There are no body parameters.

### Headers

<ParamField header="Authorization" type="string" required>
  Secret key in `Bearer sk_...` format. See [Secret Key authentication](/essentials/authentication#secret-key).
</ParamField>

### Path parameters

<ParamField path="app_id" type="string" required>
  Application ID. Must belong to the organization (otherwise `404`).
</ParamField>

### Query parameters

<ParamField query="templateId" type="string[]" required>
  Repeatable: `?templateId=a&templateId=b`. Between 1 and 10 IDs per request. Blank values are discarded and duplicates are collapsed before the request reaches Meta; more than 10 distinct IDs returns `422`.
</ParamField>

<ParamField query="startDate" default="30 days before today 00:00:00 (UTC)" type="string">
  ISO-8601 datetime. Start of the range.
</ParamField>

<ParamField query="endDate" default="today 23:59:59 (UTC)" type="string">
  ISO-8601 datetime. End of the range. Must be greater than `startDate`, and the total span cannot exceed 90 days.
</ParamField>

<ParamField query="granularity" default="DAILY" type="string">
  Bucket size of the `series`. `DAILY` is the only value Meta exposes for template analytics, so this is effectively fixed.
</ParamField>

<ParamField query="metricType" default="core set" type="string[]">
  Repeatable. Omit for the full core set (`SENT`, `DELIVERED`, `READ`, `CLICKED`, `COST`). Conversion metrics can be requested explicitly. See [Template Metrics Metric Type](/public-api-reference/template/reference/enums#template-metrics-metric-type).
</ParamField>

<ParamField query="productType" type="string">
  Restricts the result to one messaging product: `CLOUD_API` or `MARKETING_MESSAGES_LITE_API`. Omit for all products.
</ParamField>

<ParamField query="useWabaTimezone" default="false" type="boolean">
  When `true`, Meta buckets the days in the WABA's own timezone instead of UTC. The applied choice is echoed back as `usesWabaTimezone`.
</ParamField>

<Tip>
  **Limits:** at most 10 `templateId` values and at most a 90-day range per request. Split larger reports into several calls.
</Tip>

***

## Response

The envelope is `{ "data": {...}, "isSuccess": true }`, where `data` carries the range metadata, an overall `summary`, and one entry per requested template.

<ResponseField name="isSuccess" type="boolean">
  `true` when the request completed successfully.
</ResponseField>

<ResponseField name="data" type="object">
  <Expandable title="data">
    <ResponseField name="granularity" type="string">
      The granularity Meta applied (echoed from Meta, falling back to the requested value).
    </ResponseField>

    <ResponseField name="productType" type="string">
      The messaging product the numbers belong to. Dropped when Meta does not report one.
    </ResponseField>

    <ResponseField name="periodStart" type="string">
      ISO-8601 start of the requested range.
    </ResponseField>

    <ResponseField name="periodEnd" type="string">
      ISO-8601 end of the requested range.
    </ResponseField>

    <ResponseField name="dataAvailableUntil" type="string">
      ISO-8601 watermark: the latest moment Meta has aggregated data for. Buckets after it are returned with `isPending: true`. Dropped when Meta returned no data at all.
    </ResponseField>

    <ResponseField name="usesWabaTimezone" type="boolean">
      Whether the buckets follow the WABA timezone (`useWabaTimezone`) instead of UTC.
    </ResponseField>

    <ResponseField name="summary" type="object">
      Totals across every requested template. Same shape as a template summary (see below).
    </ResponseField>

    <ResponseField name="templates" type="object[]">
      One entry per requested `templateId`, in the order you sent them. A template with no data is still returned, with a zeroed summary and a fully gap-filled series.

      <Expandable title="template">
        <ResponseField name="templateId" type="string">
          The template's Meta ID.
        </ResponseField>

        <ResponseField name="summary" type="object">
          Totals for this template across the range.

          <Expandable title="summary">
            <ResponseField name="sent" type="integer">
              Messages sent.
            </ResponseField>

            <ResponseField name="delivered" type="integer">
              Messages delivered.
            </ResponseField>

            <ResponseField name="read" type="integer">
              Messages read.
            </ResponseField>

            <ResponseField name="clicked" type="integer">
              Button clicks. Counts `url_button` and `quick_reply_button` only — `unique_url_button` is excluded so clicks are not double-counted.
            </ResponseField>

            <ResponseField name="deliveredRate" type="number">
              `delivered / sent`, rounded to 4 decimals. `0` when `sent` is `0`.
            </ResponseField>

            <ResponseField name="readRate" type="number">
              `read / delivered`, rounded to 4 decimals.
            </ResponseField>

            <ResponseField name="clickRate" type="number">
              `clicked / delivered`, rounded to 4 decimals.
            </ResponseField>

            <ResponseField name="amountSpent" type="number">
              Total spend for the range, rounded to 6 decimals.
            </ResponseField>

            <ResponseField name="costPerDelivered" type="number">
              `amountSpent / delivered`, rounded to 4 decimals.
            </ResponseField>

            <ResponseField name="clicksBreakdown" type="object[]">
              Clicks grouped by `type` + `buttonContent`. Each item has `type` (see [Template Metrics Click Type](/public-api-reference/template/reference/enums#template-metrics-click-type)), `buttonContent` (the button label or URL; dropped when Meta does not report one), and `count`.
            </ResponseField>

            <ResponseField name="costBreakdown" type="object[]">
              Cost lines with `type` (see [Template Metrics Cost Type](/public-api-reference/template/reference/enums#template-metrics-cost-type)) and `value`. Empty when the range contains no cost data.
            </ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="series" type="object[]">
          One point per day in the range, including days Meta returned nothing for.

          <Expandable title="series item">
            <ResponseField name="periodStart" type="string">
              ISO-8601 start of the bucket.
            </ResponseField>

            <ResponseField name="periodEnd" type="string">
              ISO-8601 end of the bucket.
            </ResponseField>

            <ResponseField name="sent" type="integer">
              Messages sent in this bucket.
            </ResponseField>

            <ResponseField name="delivered" type="integer">
              Messages delivered in this bucket.
            </ResponseField>

            <ResponseField name="read" type="integer">
              Messages read in this bucket.
            </ResponseField>

            <ResponseField name="clicked" type="integer">
              Button clicks in this bucket (same counting rule as the summary).
            </ResponseField>

            <ResponseField name="deliveredRate" type="number">
              `delivered / sent` for this bucket.
            </ResponseField>

            <ResponseField name="readRate" type="number">
              `read / delivered` for this bucket.
            </ResponseField>

            <ResponseField name="clickRate" type="number">
              `clicked / delivered` for this bucket.
            </ResponseField>

            <ResponseField name="amountSpent" type="number">
              Spend in this bucket.
            </ResponseField>

            <ResponseField name="isPending" type="boolean">
              `true` for a zero-filled bucket that Meta has not aggregated yet (it falls after `dataAvailableUntil`). `false` for a real data point or for a day that is genuinely empty.
            </ResponseField>

            <ResponseField name="additionalMetrics" type="object">
              Any extra metric Meta returns for this bucket that is not part of the core set — for example the conversion metrics you requested via `metricType`. Dropped when there are none.
            </ResponseField>

            <ResponseField name="clicksBreakdown" type="object[]">
              Per-bucket click breakdown, same shape as in the summary.
            </ResponseField>

            <ResponseField name="costBreakdown" type="object[]">
              Per-bucket cost breakdown, same shape as in the summary.
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  **Invariants:** `Σ series[].sent == summary.sent` for each template (the same holds for `delivered`, `read`, `clicked`, and `amountSpent`), and the top-level `summary` is the sum of every template summary. Rates are always recomputed from the totals, never averaged from the buckets.
</Note>

***

## Examples

<AccordionGroup>
  <Accordion title="Demo 1 — single template (defaults: last 30 days, daily)">
    ```text theme={null}
    GET /api/v1/wa/app_7poyXj8GXuv76e/templates/metrics?templateId=842802041844912
    Authorization: Bearer sk_...
    ```

    ```json theme={null}
    {
      "data": {
        "granularity": "DAILY",
        "productType": "CLOUD_API",
        "periodStart": "2026-07-14T00:00:00+00:00",
        "periodEnd": "2026-08-13T23:59:59+00:00",
        "dataAvailableUntil": "2026-08-13T00:00:00+00:00",
        "usesWabaTimezone": false,
        "summary": {
          "sent": 1200, "delivered": 1140, "read": 860, "clicked": 210,
          "deliveredRate": 0.95, "readRate": 0.7544, "clickRate": 0.1842,
          "amountSpent": 18.42, "costPerDelivered": 0.0162,
          "clicksBreakdown": [ { "type": "url_button", "buttonContent": "Track Order", "count": 210 } ],
          "costBreakdown": [
            { "type": "amount_spent", "value": 18.42 },
            { "type": "cost_per_delivered", "value": 0.0162 }
          ]
        },
        "templates": [
          {
            "templateId": "842802041844912",
            "summary": {
              "sent": 1200, "delivered": 1140, "read": 860, "clicked": 210,
              "deliveredRate": 0.95, "readRate": 0.7544, "clickRate": 0.1842,
              "amountSpent": 18.42, "costPerDelivered": 0.0162,
              "clicksBreakdown": [ { "type": "url_button", "buttonContent": "Track Order", "count": 210 } ],
              "costBreakdown": [
                { "type": "amount_spent", "value": 18.42 },
                { "type": "cost_per_delivered", "value": 0.0162 }
              ]
            },
            "series": [
              {
                "periodStart": "2026-08-12T00:00:00+00:00",
                "periodEnd": "2026-08-13T00:00:00+00:00",
                "sent": 400, "delivered": 380, "read": 290, "clicked": 70,
                "deliveredRate": 0.95, "readRate": 0.7632, "clickRate": 0.1842,
                "amountSpent": 6.14, "isPending": false,
                "clicksBreakdown": [ { "type": "url_button", "buttonContent": "Track Order", "count": 70 } ],
                "costBreakdown": [ { "type": "amount_spent", "value": 6.14 } ]
              }
            ]
          }
        ]
      },
      "isSuccess": true
    }
    ```
  </Accordion>

  <Accordion title="Demo 2 — multiple templates (repeatable templateId)">
    ```text theme={null}
    GET /api/v1/wa/app_7poyXj8GXuv76e/templates/metrics?templateId=842802041844912&templateId=1560534655590931&startDate=2026-08-01T00:00:00&endDate=2026-08-08T00:00:00
    Authorization: Bearer sk_...
    ```

    The top-level `summary` aggregates both templates, while `templates[]` keeps them separate and in the order you sent them:

    ```json theme={null}
    {
      "data": {
        "granularity": "DAILY",
        "periodStart": "2026-08-01T00:00:00+00:00",
        "periodEnd": "2026-08-08T00:00:00+00:00",
        "dataAvailableUntil": "2026-08-08T00:00:00+00:00",
        "usesWabaTimezone": false,
        "summary": { "sent": 1700, "delivered": 1605, "read": 1180, "clicked": 265, "deliveredRate": 0.9441, "readRate": 0.7352, "clickRate": 0.1651, "amountSpent": 26.1, "costPerDelivered": 0.0163, "clicksBreakdown": [], "costBreakdown": [ { "type": "amount_spent", "value": 26.1 }, { "type": "cost_per_delivered", "value": 0.0163 } ] },
        "templates": [
          { "templateId": "842802041844912", "summary": { "sent": 1200, "delivered": 1140, "read": 860, "clicked": 210, "deliveredRate": 0.95, "readRate": 0.7544, "clickRate": 0.1842, "amountSpent": 18.42, "costPerDelivered": 0.0162, "clicksBreakdown": [], "costBreakdown": [] }, "series": [] },
          { "templateId": "1560534655590931", "summary": { "sent": 500, "delivered": 465, "read": 320, "clicked": 55, "deliveredRate": 0.93, "readRate": 0.6882, "clickRate": 0.1183, "amountSpent": 7.68, "costPerDelivered": 0.0165, "clicksBreakdown": [], "costBreakdown": [] }, "series": [] }
        ]
      },
      "isSuccess": true
    }
    ```
  </Accordion>

  <Accordion title="Demo 3 — pending days (today is not aggregated yet)">
    ```text theme={null}
    GET /api/v1/wa/app_7poyXj8GXuv76e/templates/metrics?templateId=842802041844912&startDate=2026-08-11T00:00:00&endDate=2026-08-13T23:59:59
    Authorization: Bearer sk_...
    ```

    Meta has aggregated up to `2026-08-12T00:00:00`, so the following bucket is emitted as a zero point flagged `isPending: true` — the day is not empty, it is simply not ready.

    ```json theme={null}
    {
      "data": {
        "granularity": "DAILY",
        "periodStart": "2026-08-11T00:00:00+00:00",
        "periodEnd": "2026-08-13T23:59:59+00:00",
        "dataAvailableUntil": "2026-08-12T00:00:00+00:00",
        "usesWabaTimezone": false,
        "summary": { "sent": 400, "delivered": 380, "read": 290, "clicked": 70, "deliveredRate": 0.95, "readRate": 0.7632, "clickRate": 0.1842, "amountSpent": 6.14, "costPerDelivered": 0.0162, "clicksBreakdown": [], "costBreakdown": [ { "type": "amount_spent", "value": 6.14 }, { "type": "cost_per_delivered", "value": 0.0162 } ] },
        "templates": [
          {
            "templateId": "842802041844912",
            "summary": { "sent": 400, "delivered": 380, "read": 290, "clicked": 70, "deliveredRate": 0.95, "readRate": 0.7632, "clickRate": 0.1842, "amountSpent": 6.14, "costPerDelivered": 0.0162, "clicksBreakdown": [], "costBreakdown": [] },
            "series": [
              { "periodStart": "2026-08-11T00:00:00+00:00", "periodEnd": "2026-08-12T00:00:00+00:00", "sent": 400, "delivered": 380, "read": 290, "clicked": 70, "deliveredRate": 0.95, "readRate": 0.7632, "clickRate": 0.1842, "amountSpent": 6.14, "isPending": false, "clicksBreakdown": [], "costBreakdown": [] },
              { "periodStart": "2026-08-12T00:00:00+00:00", "periodEnd": "2026-08-13T00:00:00+00:00", "sent": 0, "delivered": 0, "read": 0, "clicked": 0, "deliveredRate": 0, "readRate": 0, "clickRate": 0, "amountSpent": 0, "isPending": true, "clicksBreakdown": [], "costBreakdown": [] }
            ]
          }
        ]
      },
      "isSuccess": true
    }
    ```
  </Accordion>

  <Accordion title="Demo 4 — conversion metrics (metricType) → additionalMetrics">
    ```text theme={null}
    GET /api/v1/wa/app_7poyXj8GXuv76e/templates/metrics?templateId=1560534655590931&metricType=SENT&metricType=DELIVERED&metricType=WEBSITE_PURCHASES&productType=MARKETING_MESSAGES_LITE_API
    Authorization: Bearer sk_...
    ```

    Metrics outside the core set are surfaced per bucket under `additionalMetrics`:

    ```json theme={null}
    {
      "data": {
        "granularity": "DAILY",
        "productType": "MARKETING_MESSAGES_LITE_API",
        "periodStart": "2026-07-14T00:00:00+00:00",
        "periodEnd": "2026-08-13T23:59:59+00:00",
        "usesWabaTimezone": false,
        "summary": { "sent": 500, "delivered": 465, "read": 0, "clicked": 0, "deliveredRate": 0.93, "readRate": 0, "clickRate": 0, "amountSpent": 0, "costPerDelivered": 0, "clicksBreakdown": [], "costBreakdown": [] },
        "templates": [
          {
            "templateId": "1560534655590931",
            "summary": { "sent": 500, "delivered": 465, "read": 0, "clicked": 0, "deliveredRate": 0.93, "readRate": 0, "clickRate": 0, "amountSpent": 0, "costPerDelivered": 0, "clicksBreakdown": [], "costBreakdown": [] },
            "series": [
              { "periodStart": "2026-08-12T00:00:00+00:00", "periodEnd": "2026-08-13T00:00:00+00:00", "sent": 500, "delivered": 465, "read": 0, "clicked": 0, "deliveredRate": 0.93, "readRate": 0, "clickRate": 0, "amountSpent": 0, "isPending": false, "additionalMetrics": { "website_purchases": 34 }, "clicksBreakdown": [], "costBreakdown": [] }
            ]
          }
        ]
      },
      "isSuccess": true
    }
    ```
  </Accordion>

  <Accordion title="Demo 5 — WABA timezone buckets">
    ```text theme={null}
    GET /api/v1/wa/app_7poyXj8GXuv76e/templates/metrics?templateId=842802041844912&useWabaTimezone=true
    Authorization: Bearer sk_...
    ```

    The response echoes the applied choice so you can label your charts correctly:

    ```json theme={null}
    { "data": { "granularity": "DAILY", "usesWabaTimezone": true, "periodStart": "2026-07-14T00:00:00+00:00", "periodEnd": "2026-08-13T23:59:59+00:00", "summary": { "sent": 1200, "delivered": 1140, "read": 860, "clicked": 210, "deliveredRate": 0.95, "readRate": 0.7544, "clickRate": 0.1842, "amountSpent": 18.42, "costPerDelivered": 0.0162, "clicksBreakdown": [], "costBreakdown": [] }, "templates": [] }, "isSuccess": true }
    ```
  </Accordion>

  <Accordion title="Demo 6 — error: more than 10 template IDs → 422">
    ```text theme={null}
    GET /api/v1/wa/app_7poyXj8GXuv76e/templates/metrics?templateId=1&templateId=2&templateId=3&templateId=4&templateId=5&templateId=6&templateId=7&templateId=8&templateId=9&templateId=10&templateId=11
    Authorization: Bearer sk_...
    ```

    ```json theme={null}
    { "errors": { "code": "META_104", "group": "LIMIT_EXCEEDED", "description": "Too many templates requested. A maximum of 10 template IDs can be queried per request." }, "isSuccess": false }
    ```
  </Accordion>

  <Accordion title="Demo 7 — error: range wider than 90 days → 422">
    ```text theme={null}
    GET /api/v1/wa/app_7poyXj8GXuv76e/templates/metrics?templateId=842802041844912&startDate=2026-01-01T00:00:00&endDate=2026-08-13T00:00:00
    Authorization: Bearer sk_...
    ```

    ```json theme={null}
    { "errors": { "code": "META_105", "group": "VALIDATION", "description": "The requested date range is too large. The maximum allowed range is 90 days." }, "isSuccess": false }
    ```
  </Accordion>
</AccordionGroup>

***

## Errors

<ResponseField name="errors" type="object">
  Error details with `code`, `group`, and `description`; `isSuccess` is `false`.
</ResponseField>

### Auth / tenant

| HTTP | Code                      | When                                          |
| ---- | ------------------------- | --------------------------------------------- |
| 401  | `ORGANIZATION_SECRET_010` | Secret key is missing.                        |
| 401  | `ORGANIZATION_SECRET_011` | Secret key is invalid.                        |
| 404  | `APPLICATION_004`         | `app_id` does not belong to the organization. |

### Request validation

| HTTP | Code                         | Group            | When                                                                                                                                 |
| ---- | ---------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| 422  | `VAL_019`                    | `VALIDATION`     | `endDate <= startDate` (invalid date range).                                                                                         |
| 422  | `META_104`                   | `LIMIT_EXCEEDED` | More than 10 distinct `templateId` values.                                                                                           |
| 422  | `META_105`                   | `VALIDATION`     | The range exceeds 90 days.                                                                                                           |
| 400  | `META_102`                   | `VALIDATION`     | No usable `templateId` (all values blank).                                                                                           |
| 422  | `VAL_*` (FastAPI validation) | `VALIDATION`     | `templateId` missing entirely, invalid `granularity` / `metricType` / `productType` enum value, unparseable `startDate` / `endDate`. |

### Meta-side

| HTTP | Code       | When                                                                         |
| ---- | ---------- | ---------------------------------------------------------------------------- |
| 401  | `META_099` | Token invalid/expired (190).                                                 |
| 403  | `META_100` | Permission denied (10 / 200–299).                                            |
| 429  | `META_101` | Rate limit (4 / 80007).                                                      |
| 400  | `META_102` | Invalid parameter (100).                                                     |
| 409  | `META_103` | Template analytics is not enabled for this WABA — enable insights and retry. |
| 409  | `META_106` | Template analytics is not available for this WABA yet.                       |
| 422  | `META_107` | None of the given template IDs is valid for this WABA.                       |
| 502  | `META_098` | General/fallback analytics error.                                            |

Example error responses:

```json theme={null}
{ "errors": { "code": "VAL_019", "group": "VALIDATION", "description": "Invalid date range." }, "isSuccess": false }
```

```json theme={null}
{ "errors": { "code": "META_103", "group": "CONFLICT", "description": "Template analytics is not enabled for this WhatsApp Business Account. Enable insights and try again." }, "isSuccess": false }
```

```json theme={null}
{ "errors": { "code": "META_107", "group": "VALIDATION", "description": "None of the specified template IDs is valid for this WhatsApp Business Account." }, "isSuccess": false }
```
