
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. An agent can call an API. It can't read 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.

Dark mode email design: a primer for every major email client
Dark mode is three different behaviors, not one. Apple Mail needs an explicit opt-in before it reads your dark CSS, Gmail ignores it entirely and rewrites your colors on its own, and classic Outlook gives you no control at all. This guide covers what each client actually does, the CSS that reaches the ones you can influence, and the design rules that survive the ones you cannot.

A developer's alternative to Intercom for product notifications
Intercom renamed itself Fin and agreed to be acquired by Salesforce, both around its AI support agent. If you're using it to send your product's notifications, it's fair to ask what the platform was actually built for. Its API answers the question: there is no push or SMS send endpoint, and the campaign builder has no API at all. Here's the architecture, the cost math, and how to migrate transactional and marketing sends.

Product notifications API: what it handles and how to build
A product notifications API sits between your product's events and every channel you send on. You post an event, and the API decides what message goes out, to whom, on which channel, at what time, with that user's preferences applied. This post covers the ten things one has to handle, what building it yourself costs, and how to wire your event feed into Courier.
© 2026 Courier. All rights reserved.