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

> ## Agent Instructions
> Install the Courier skill before writing code: `npx skills add trycourier/courier-skills`. It carries the verified SDK shapes and the rules you cannot get wrong.
> Authenticate every request with `Authorization: Bearer <API_KEY>`. A workspace has multiple environments and each environment has its own API keys; start with Test.
> Templates and journeys can be built in the Courier app or created through the API; either way they live in the workspace and are referenced by ID when you send.
> The hosted MCP server is https://mcp.courier.com. For a briefing on what Courier is and when to use it, read https://www.courier.com/llms.txt.

# Get Notification Template Metrics

> Fetch the delivery funnel for one Notification Template as a time series — sent, delivered, opened, clicked, errors, and undeliverable — broken out per provider and channel inside each bucket. Sum the entries in a bucket for its totals; there is no bucket-level total.

Choose the window absolutely with `start` and `end`, or relatively with `lookback` (an ISO 8601 duration). `start` and `end` take precedence when both are supplied, and a request carrying neither defaults to `lookback=P30D`. The window is snapped outwards onto the `granularity` grid so every bucket it overlaps is returned whole, and the snapped boundaries come back as `start` and `end` — align a chart on those rather than on what was requested. Every boundary is UTC; there is no timezone support.

Every bucket in the window is returned, including the quiet ones, whose `data` array is empty, so a series is directly plottable with no gap filling client-side. An unknown template id returns `200` with an all-empty series rather than `404`, and messages sent without a Notification Template never appear here.

Available in the US region only.



## OpenAPI

````yaml /openapi-specs/openapi.documented.yml get /notifications/{id}/metrics
openapi: 3.0.1
info:
  title: Courier
  description: The Courier REST API for sending and managing notifications across channels.
  version: 0.0.1
servers:
  - url: https://api.courier.com
    description: Production
security: []
tags:
  - name: Send
    description: >-
      Send a message to one or more recipients — users, lists, audiences, or
      tenants — across every channel you have configured.
  - name: Templates
    description: >-
      Create, update, version, publish, and localize notification templates and
      their content.
  - name: Brands
    description: >-
      Manage the logos, colors, and layout that give the templates you send a
      consistent look.
  - name: Routing Strategies
    description: >-
      Define reusable channel routing and failover strategies, and see which
      templates use them.
  - name: Journeys
    description: >-
      Build, version, publish, invoke, and cancel multi-step notification
      workflows, along with the templates scoped to them.
  - name: Broadcasts
    description: >-
      Create a one-off send to a list or audience, author its content, then send
      it immediately or schedule it for later.
  - name: User Profiles
    description: >-
      Store the contact information Courier delivers to for each user — email,
      phone number, push tokens, and any custom data you send to.
  - name: Tenants
    description: >-
      Manage tenants — the organizations, teams, or accounts your users belong
      to — along with their users and default preferences.
  - name: Audiences
    description: >-
      Define filter-based groups whose membership Courier recalculates as user
      profiles change.
  - name: Lists
    description: >-
      Manage static groups of users that you subscribe explicitly, and send to
      them by list id or list pattern.
  - name: Providers
    description: >-
      Configure the channel providers Courier delivers through, and browse the
      provider types it supports.
  - name: Preference Topics
    description: >-
      Manage the workspace catalog of subscription topics, the sections that
      group them, and publishing the preference page.
  - name: User Preferences
    description: >-
      Read and write a single user's notification preferences, per topic and per
      channel.
  - name: Messages
    description: >-
      Look up the messages Courier has accepted, inspect their delivery history
      and rendered output, and cancel, resend, or archive them.
  - name: Device Tokens
    description: >-
      Register and manage the APNS and FCM device tokens Courier delivers push
      notifications to.
  - name: Tenant Memberships
    description: >-
      Associate a user with one or more tenants, and read or remove those
      associations.
  - name: Tenant Templates
    description: >-
      Manage the templates and template versions scoped to a single tenant,
      including the ones authored in the embedded designer.
  - name: Automations
    description: >-
      Invoke a stored automation template or an ad hoc automation defined in the
      request.
  - name: Digests
    description: >-
      Inspect what has accumulated in a digest schedule and release a digest
      ahead of its next scheduled delivery.
  - name: Translations
    description: >-
      Store and retrieve the translation strings Courier uses to render
      localized template content.
  - name: Track Events
    description: >-
      Record an inbound event that triggers the journeys and automations mapped
      to it.
  - name: Audit Events
    description: >-
      Read the audit trail of configuration and access changes in your
      workspace.
  - name: Authentication
    description: >-
      Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences,
      and the embedded designer — can call Courier as a single user. Server-side
      requests authenticate with your workspace API key instead.
paths:
  /notifications/{id}/metrics:
    get:
      tags:
        - Templates
      summary: Get Notification Template Metrics
      description: >-
        Fetch the delivery funnel for one Notification Template as a time series
        — sent, delivered, opened, clicked, errors, and undeliverable — broken
        out per provider and channel inside each bucket. Sum the entries in a
        bucket for its totals; there is no bucket-level total.


        Choose the window absolutely with `start` and `end`, or relatively with
        `lookback` (an ISO 8601 duration). `start` and `end` take precedence
        when both are supplied, and a request carrying neither defaults to
        `lookback=P30D`. The window is snapped outwards onto the `granularity`
        grid so every bucket it overlaps is returned whole, and the snapped
        boundaries come back as `start` and `end` — align a chart on those
        rather than on what was requested. Every boundary is UTC; there is no
        timezone support.


        Every bucket in the window is returned, including the quiet ones, whose
        `data` array is empty, so a series is directly plottable with no gap
        filling client-side. An unknown template id returns `200` with an
        all-empty series rather than `404`, and messages sent without a
        Notification Template never appear here.


        Available in the US region only.
      operationId: notifications_get_metrics
      parameters:
        - name: id
          in: path
          description: >-
            The Notification Template to report on — its ID (`nt_` prefix) or an
            alias. Must not contain commas or whitespace.
          required: true
          schema:
            type: string
            minLength: 1
        - name: granularity
          in: query
          description: >-
            The size of each bucket in the series. Defaults to `DAY`. `WEEK`
            buckets start on Sunday. A fine granularity caps the window it can
            cover: `HOUR` spans at most 7 days and `DAY` at most 90 days, and a
            wider window returns `400` — request a coarser granularity instead.
            `WEEK` and `MONTH` are uncapped, subject to the 1000-bucket limit on
            a single response.
          required: false
          schema:
            type: string
            enum:
              - HOUR
              - DAY
              - WEEK
              - MONTH
            default: DAY
        - name: lookback
          in: query
          description: >-
            The length of the window, counted back from now, as an ISO 8601
            duration (`P30D`, `P12W`, `PT12H`). Defaults to `P30D`, and is
            ignored when `start` and `end` are supplied. A malformed or
            non-positive duration returns `400`.
          required: false
          schema:
            type: string
            default: P30D
        - name: start
          in: query
          description: >-
            The inclusive start of the window, as an ISO 8601 timestamp with an
            offset (`2026-04-01T00:00:00Z`). Must be supplied together with
            `end` and be earlier than it; either one alone returns `400`.
          required: false
          schema:
            type: string
            format: date-time
        - name: end
          in: query
          description: >-
            The end of the window, as an ISO 8601 timestamp with an offset. Must
            be supplied together with `start`. An `end` in the future is
            accepted and not clamped — the trailing buckets come back empty.
          required: false
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: >-
            The delivery funnel for the Notification Template, bucketed over the
            resolved window.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotificationMetricsResponse'
              examples:
                Example1:
                  value:
                    notificationId: nt_01kx4h2jdafq8bk9aftxak4b40
                    granularity: DAY
                    start: '2026-08-17T00:00:00Z'
                    end: '2026-08-20T00:00:00Z'
                    series:
                      - period: '2026-08-17T00:00:00Z'
                        data: []
                      - period: '2026-08-18T00:00:00Z'
                        data:
                          - provider: sendgrid
                            channel: email
                            sent: 412
                            delivered: 408
                            opened: 173
                            clicked: 41
                            errors: 0
                            undeliverable: 4
                          - provider: twilio
                            channel: sms
                            sent: 96
                            delivered: 95
                            opened: 0
                            clicked: 12
                            errors: 1
                            undeliverable: 0
                      - period: '2026-08-19T00:00:00Z'
                        data:
                          - provider: sendgrid
                            channel: email
                            sent: 388
                            delivered: 385
                            opened: 151
                            clicked: 37
                            errors: 3
                            undeliverable: 0
        '400':
          description: >-
            The window or granularity could not be satisfied — a malformed
            duration or timestamp, only one of `start`/`end`, a `start` that is
            not earlier than `end`, a granularity too fine for the window, or a
            window covering more than 1000 buckets.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MetricsInvalidParams'
              examples:
                InvalidLookback:
                  value:
                    message: >-
                      lookback must be a valid ISO 8601 duration (e.g. P30D,
                      PT12H), got "30d".
                    type: invalid_params
                UnpairedStartEnd:
                  value:
                    message: start and end must be supplied together
                    type: invalid_params
                GranularityTooFine:
                  value:
                    message: >-
                      Granularity HOUR is too fine for the requested 90 day
                      range.
                    type: invalid_params
                TooManyBuckets:
                  value:
                    message: >-
                      Requested range covers 1200 WEEK buckets, exceeding the
                      1000 bucket limit for a single response. Narrow the range
                      or use a coarser granularity.
                    type: invalid_params
        '402':
          description: >-
            The window reaches further back than the workspace's plan allows.
            Lookback is capped at 30 days on Developer and 90 days on Business;
            Enterprise is uncapped. Exceeding the cap is an error, not an empty
            result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MetricsPaymentRequired'
              examples:
                LookbackExceeded:
                  value:
                    message: >-
                      Requested date range exceeds your plan's maximum lookback
                      of 30 days.
                    type: payment_required
        '429':
          description: >-
            Too many requests. Metrics reads are limited per second and per
            workspace — 1/s on Developer, 2/s on Business, 5/s on Enterprise.
            The response carries `Retry-After` alongside the `RateLimit-*`
            headers every response gets.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MetricsRateLimitExceeded'
              examples:
                RateLimited:
                  value:
                    message: Rate limit exceeded
                    type: rate_limit_exceeded
        '503':
          description: >-
            The metrics store is temporarily unavailable. Retry after the number
            of seconds in `Retry-After`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MetricsServiceUnavailable'
              examples:
                Unavailable:
                  value:
                    message: Metrics are temporarily unavailable.
                    type: service_unavailable
      security:
        - BearerAuth: []
      x-codeSamples:
        - lang: JavaScript
          source: >-
            import Courier from '@trycourier/courier';


            const client = new Courier({
              apiKey: process.env['COURIER_API_KEY'], // This is the default and can be omitted
            });


            const notificationMetricsResponse = await
            client.notifications.getMetrics('x');


            console.log(notificationMetricsResponse.end);
        - lang: Python
          source: |-
            import os
            from courier import Courier

            client = Courier(
                api_key=os.environ.get("COURIER_API_KEY"),  # This is the default and can be omitted
            )
            notification_metrics_response = client.notifications.get_metrics(
                id="x",
            )
            print(notification_metrics_response.end)
        - lang: Go
          source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/trycourier/courier-go/v4\"\n\t\"github.com/trycourier/courier-go/v4/option\"\n)\n\nfunc main() {\n\tclient := courier.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tnotificationMetricsResponse, err := client.Notifications.GetMetrics(\n\t\tcontext.TODO(),\n\t\t\"x\",\n\t\tcourier.NotificationGetMetricsParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", notificationMetricsResponse.End)\n}\n"
        - lang: Java
          source: >-
            package com.courier.example;


            import com.courier.client.CourierClient;

            import com.courier.client.okhttp.CourierOkHttpClient;

            import
            com.courier.models.notifications.NotificationGetMetricsParams;

            import com.courier.models.notifications.NotificationMetricsResponse;


            public final class Main {
                private Main() {}

                public static void main(String[] args) {
                    CourierClient client = CourierOkHttpClient.fromEnv();

                    NotificationMetricsResponse notificationMetricsResponse = client.notifications().getMetrics("x");
                }
            }
        - lang: Ruby
          source: >-
            require "courier"


            courier = Courier::Client.new(api_key: "My API Key")


            notification_metrics_response =
            courier.notifications.get_metrics("x")


            puts(notification_metrics_response)
        - lang: PHP
          source: >-
            <?php


            require_once dirname(__DIR__) . '/vendor/autoload.php';


            use Courier\Client;

            use Courier\Core\Exceptions\APIException;


            $client = new Client(apiKey: getenv('COURIER_API_KEY') ?: 'My API
            Key');


            try {
              $notificationMetricsResponse = $client->notifications->getMetrics(
                'x',
                end: new \DateTimeImmutable('2019-12-27T18:11:19.117Z'),
                granularity: 'HOUR',
                lookback: 'lookback',
                start: new \DateTimeImmutable('2019-12-27T18:11:19.117Z'),
              );

              var_dump($notificationMetricsResponse);
            } catch (APIException $e) {
              echo $e->getMessage();
            }
        - lang: C#
          source: >-
            using System;

            using TryCourier;

            using TryCourier.Models.Notifications;


            CourierClient client = new();


            NotificationGetMetricsParams parameters = new() { ID = "x" };


            var notificationMetricsResponse = await
            client.Notifications.GetMetrics(parameters);


            Console.WriteLine(notificationMetricsResponse);
        - lang: CLI
          source: |-
            courier notifications get-metrics \
              --api-key 'My API Key' \
              --id x
components:
  schemas:
    NotificationMetricsResponse:
      title: NotificationMetricsResponse
      type: object
      properties:
        notificationId:
          type: string
          description: The template the series describes, echoed from the request.
        granularity:
          type: string
          enum:
            - HOUR
            - DAY
            - WEEK
            - MONTH
          description: Bucket size the series was built at.
        start:
          type: string
          format: date-time
          description: >-
            Inclusive start of the window actually queried, floored onto the
            granularity grid. Second-precision UTC.
        end:
          type: string
          format: date-time
          description: >-
            End of the window actually queried, ceiled onto the granularity
            grid. Second-precision UTC.
        series:
          type: array
          description: >-
            One entry per bucket between `start` and `end`, oldest first,
            including buckets with no activity.
          items:
            $ref: '#/components/schemas/NotificationMetricsBucket'
      required:
        - notificationId
        - granularity
        - start
        - end
        - series
    MetricsInvalidParams:
      title: MetricsInvalidParams
      type: object
      properties:
        type:
          type: string
          enum:
            - invalid_params
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/BaseError'
    MetricsPaymentRequired:
      title: MetricsPaymentRequired
      type: object
      properties:
        type:
          type: string
          enum:
            - payment_required
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/BaseError'
    MetricsRateLimitExceeded:
      title: MetricsRateLimitExceeded
      type: object
      properties:
        type:
          type: string
          enum:
            - rate_limit_exceeded
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/BaseError'
    MetricsServiceUnavailable:
      title: MetricsServiceUnavailable
      type: object
      properties:
        type:
          type: string
          enum:
            - service_unavailable
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/BaseError'
    NotificationMetricsBucket:
      title: NotificationMetricsBucket
      type: object
      properties:
        period:
          type: string
          format: date-time
          description: Start of the bucket, second-precision UTC.
        data:
          type: array
          description: >-
            One entry per provider and channel that handled a message in this
            bucket. Empty when nothing was sent.
          items:
            $ref: '#/components/schemas/NotificationMetricsProvider'
      required:
        - period
        - data
    BaseError:
      title: BaseError
      type: object
      properties:
        message:
          type: string
          description: A message describing the error that occurred.
      required:
        - message
    NotificationMetricsProvider:
      title: NotificationMetricsProvider
      type: object
      properties:
        provider:
          type: string
          description: Provider that handled the messages, e.g. `sendgrid`.
        channel:
          type: string
          description: Channel the provider delivered on, e.g. `email`.
        sent:
          type: integer
          description: Messages handed to the provider.
        delivered:
          type: integer
          description: Messages the provider confirmed as delivered.
        opened:
          type: integer
          description: >-
            Messages opened at least once. Always `0` on channels with no open
            tracking.
        clicked:
          type: integer
          description: Messages with at least one tracked link click.
        errors:
          type: integer
          description: >-
            Messages the provider rejected or failed on, including ones a later
            provider then delivered.
        undeliverable:
          type: integer
          description: Messages Courier could not deliver on any provider for the channel.
      required:
        - provider
        - channel
        - sent
        - delivered
        - opened
        - clicked
        - errors
        - undeliverable
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

````