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

# Metrics

> Sending totals and a daily series — delivery, bounce, and complaint rates over a time range, and how to read them.

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](/webhooks) 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.

## Get metrics

**`GET /v1/metrics`**

Optional `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.

<CodeGroup>
  ```bash cURL theme={null}
  # 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"
  ```

  ```typescript Node.js theme={null}
  const metrics = await drin.metrics.get({
    from: "2026-05-01T00:00:00Z",
    to: "2026-05-31T23:59:59Z",
  });
  ```
</CodeGroup>

## 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.

```json Response theme={null}
{
  "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 } }
  ]
}
```

<Info>
  **Counts are keyed by event type.** Keys in `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`).
</Info>

## Computing rates

Rates are ratios over `sent`. Compute them yourself from `totals` so the denominator is unambiguous:

```typescript theme={null}
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).

## 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:

```typescript theme={null}
// 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 };
});
```

<Tip>
  **Watch the trend, not a single day.** A one-day spike on low volume is noise; a rising multi-day trend is a signal. Plot the bounce and complaint lines against your thresholds and act on sustained movement.
</Tip>

## Reading the numbers

<Warning>
  **The lines that matter.** Drin watches the same limits the mailbox providers enforce. Sustained bounce above **4%** or complaints above **0.1%** put your sending — and eventually the whole platform's — reputation at risk, and can trigger an automatic pause. If a rate is climbing, slow down, verify your list, and check the [Deliverability](/deliverability) guide before it trips.
</Warning>

High bounce usually means a stale or unverified recipient list — clean it and lean on [suppressions](/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.

## Related

<CardGroup cols={2}>
  <Card title="Deliverability" icon="chart-line" href="/deliverability">
    What drives these rates and how to keep them healthy.
  </Card>

  <Card title="Webhooks" icon="bell" href="/webhooks">
    The per-event stream behind the aggregates — react in real time.
  </Card>

  <Card title="Suppressions" icon="shield" href="/suppressions">
    Keep bounces and complaints from repeating.
  </Card>

  <Card title="Metrics API" icon="code" href="/api-reference/metrics/get">
    Parameters and the full response schema.
  </Card>
</CardGroup>
