Metrics
One endpoint gives you the numbers that matter for a sending project: totals over a window, a per-day series to chart, and the raw counts you need to compute delivery, bounce, and complaint rates.
The metrics endpoint aggregates the same events that drive webhooks — delivery, bounce, complaint, open, click — into totals and a daily breakdown for a project. It returns counts; you compute rates from them, so you stay in control of exactly how each rate is defined.
01 Get metrics
/v1/metricsOptional from and to ISO-8601 timestamps bound the window; omit them for a sensible recent default. The response echoes the resolved range so you always know which window the numbers describe.
# Last 7 days (default range)
curl https://api.drin.run/v1/metrics \
-H "Authorization: Bearer $DRIN_API_KEY"
# An explicit window
curl "https://api.drin.run/v1/metrics?from=2026-05-01T00:00:00Z&to=2026-05-31T23:59:59Z" \
-H "Authorization: Bearer $DRIN_API_KEY"02 The response
Three fields: the resolved range, a totals map keyed by event type, and a daily array of { date, counts } — one bucket per day, each with its own counts map.
{
"range": { "from": "2026-05-26T00:00:00Z", "to": "2026-06-02T00:00:00Z" },
"totals": {
"sent": 12480,
"delivery": 12190,
"bounce": 142,
"complaint": 9,
"open": 8204,
"click": 1903
},
"daily": [
{ "date": "2026-05-26", "counts": { "sent": 1780, "delivery": 1740, "bounce": 22, "complaint": 1 } },
{ "date": "2026-05-27", "counts": { "sent": 1810, "delivery": 1772, "bounce": 18, "complaint": 2 } }
]
}totals and each day's counts are event types — sent, delivery, bounce, complaint, open, click, and the rest. A type with no events in the window is simply absent, so read defensively (treat a missing key as 0).03 Computing rates
Rates are ratios over sent. Compute them yourself from totals so the denominator is unambiguous:
const t = metrics.totals;
const sent = t.sent ?? 0;
const deliveryRate = sent ? (t.delivery ?? 0) / sent : 0; // want: high
const bounceRate = sent ? (t.bounce ?? 0) / sent : 0; // want: < 4%
const complaintRate = sent ? (t.complaint ?? 0) / sent : 0; // want: < 0.1%
const openRate = sent ? (t.open ?? 0) / sent : 0;
const clickRate = sent ? (t.click ?? 0) / sent : 0;
console.log((bounceRate * 100).toFixed(2) + "% bounce");- Delivery rate —
delivery / sent. The share that reached the mailbox provider. Higher is better. - Bounce rate —
bounce / sent. The single most important number to watch. Keep it well under 4%. - Complaint rate —
complaint / sent. Spam-button presses. Keep it under 0.1%. - Open / click rate — engagement signals. Useful trends, but treat the absolutes with care (privacy proxies inflate opens; not every client loads tracking).
04 Charting over time
The daily series is built for time-series charts. Map each bucket the same way you mapped the totals to get a rate-over-time line:
// Plot a bounce-rate-over-time line from the daily series.
const points = metrics.daily.map((d) => {
const sent = d.counts.sent ?? 0;
return { date: d.date, bounceRate: sent ? (d.counts.bounce ?? 0) / sent : 0 };
});05 Reading the numbers
High bounce usually means a stale or unverified recipient list — clean it and lean on suppressions. High complaints usually mean unwanted mail — tighten consent and make unsubscribing easy. The metrics endpoint is your early-warning system; check it before a provider does it for you.