
The Template Metrics API is live. GET /notifications/{id}/metrics returns the delivery funnel for a notification template as a time series: sends, deliveries, opens, clicks, errors, and undeliverable counts, bucketed by hour, day, week, or month, with every bucket broken out by provider and channel.
This is the part of Courier that doesn't change: if it's in the dashboard, it's on the API. Journeys, templates, brands, routing rules, preference topics, audiences, tenants, provider configuration. The dashboard is a client of the same public API you get, not a privileged surface sitting above it. Analytics was one of the last screens where the answer lived only on the screen.
That parity is the point. It means the numbers aren't stuck in our UI: they can go in your product, next to the rest of your customer's data, or straight to an agent that needs to know how last week's sends went. Handing an agent an API is far easier than handing it a chart.
One request per template, with the shape you'd want to chart already built in.
Every bucket carries one row per provider and channel pair that handled messages in that period. A template that sends email through SendGrid and SMS through Twilio returns both rows, with counts for sent, delivered, opened, clicked, errors, and undeliverable. You can see that email is carrying the volume while a single provider quietly racks up errors, without a second call.
Ask for a relative window with lookback as an ISO 8601 duration (P30D, P12W, PT12H), or an exact one with start and end timestamps. The default is the last 30 days.
Set granularity to HOUR, DAY, WEEK, or MONTH. Courier expands your window outward to whole buckets, so a 36-hour request at DAY granularity returns two complete days instead of one and a half, and the response echoes the adjusted start and end for your axis labels. Quiet periods come back too, as buckets with an empty data array, so there are no gaps to fill on your side before the data hits a chart.
The endpoint is in all seven server SDKs: Node, Python, Ruby, Go, Java, PHP, and C#. Same call, same parameters, typed the way the rest of your kit is:
// npm install @trycourier/courierimport Courier from "@trycourier/courier";const client = new Courier();const metrics = await client.notifications.getMetrics(templateId, {lookback: "P7D",granularity: "DAY",});console.log(metrics.start, metrics.end, metrics.series.length);
Or by curl, addressing the template by ID or alias:
curl "https://api.courier.com/notifications/$TEMPLATE_ID/metrics?lookback=P7D&granularity=DAY" \-H "Authorization: Bearer $COURIER_API_KEY"
GET /notifications, pull seven days at DAY granularity for each, and post the top senders and their delivery rates to Slack every Monday. Nobody has to remember to run it.HOUR granularity for your critical templates, compare delivered against sent, and page when the ratio drops with real volume behind it.Each of these used to mean screenshotting a dashboard or building your own event pipeline. Now it's one endpoint and a loop.
Finer buckets cap the window you can request, because the response would otherwise get enormous:
| Granularity | Maximum window |
|---|---|
HOUR | 7 days |
DAY | 90 days |
WEEK | Uncapped |
MONTH | Uncapped |
How far back you can look, and how fast you can ask, depend on your plan:
| Plan | Max lookback | Requests per second |
|---|---|---|
| Developer (free) | 30 days | 1 |
| Business | 90 days | 2 |
| Enterprise | 730 days | 5 |
A window past your plan's cap returns a 402 rather than a silently shortened result, so you find out in development instead of shipping a chart that shows less than it claims. Rate limits are per workspace, and every response carries RateLimit-* headers so you can pace a loop over many templates.
Three more things to design around. All windows and buckets are UTC, so a daily bucket is a UTC calendar day. The endpoint covers one template per call, so a workspace-wide view means listing templates and iterating. And it's available in the US region today.
The Template Metrics API is live on every plan, including the free Developer plan. Nothing to turn on: point it at a template you already send and the numbers come back.
The Analytics tab isn't going anywhere, and this doesn't replace it. Same data, different client: a chart when you're the one looking, JSON when your code or your agent is.
Get started: the Template Metrics API guide for window selection, granularity rules, error responses, and per-language examples, or the API reference for the full schema.

Know the moment users change notification preferences
Every preference change in Courier now reaches your systems two ways. A `preferences:user:updated` webhook fires the moment a user opts in, opts out, or changes a topic's channels, wherever they made the change. `GET /preferences/logs` returns the history, newest first, with the previous value where Courier knows it. Keep your CRM, warehouse, or marketing tools in step with what users chose.

Test Courier emails end to end with your AI agent
Give your coding agent an AgentMail inbox, and it can test your Courier emails the way a user would: send the change, check what arrives, review how it renders, and fix what it finds before the change reaches Production.

Let your agent check every email before it ships
Courier Device Preview gives your coding agent real screenshots from Outlook, Gmail, and Apple Mail. Here's the prompt and workflow to have it check every email, fix the draft, and check again before you publish.