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

# Date ranges

> from and to, the eleven presets, the hourly grain on a one-day window, and why every day is a UTC day.

Every metric endpoint takes the same two optional parameters.

```
?from=2026-07-16&to=2026-08-14
```

|             |                                                  |
| ----------- | ------------------------------------------------ |
| Format      | `YYYY-MM-DD`                                     |
| Both bounds | **Inclusive**                                    |
| Default     | The last **30 days ending today**                |
| Reversed    | Swapped, not rejected — the caller meant a range |

Omitting `to` uses today. Omitting `from` uses 29 days before `to`.

The resolved range is echoed back as `range` on every response, so a client always renders the window it actually got. **That matters more than it used to:** your plan clamps how far back a range may reach, and a clamped range is answered rather than refused — see below.

## The eleven presets

The dashboard offers no free calendar. Every metric is counted per bucket and the nightly pass lags by one day, so an arbitrary start date buys nothing a preset does not already answer.

**Rolling:** `Today`, `Yesterday`, `Last 3 days`, `Last 7 days`, `Last 30 days`, `Last 90 days`.

**Calendar:** `This month`, `Last month`, `Last 3 months`, `This year`, `Last year`.

The two kinds are not interchangeable, and that is why both exist. `Last 3 months` is three **finished** months, not ninety rolling days — the rolling version is already there under its own name, and the calendar one is the window you can hold against the three months before it without it moving as you read. `This month` and `This year` run from the first of the period to today.

A single day is a whole number of days like any other window, so `from` and `to` are simply the same date and nothing behind the picker has a special case for it.

## A one-day window is hourly

`tool_hours` is keyed by the hour, so the grain follows the range:

| Range          | Grain | Points      |
| -------------- | ----- | ----------- |
| `from == to`   | Hour  | 24          |
| Anything wider | Day   | One per day |

The API decides this and returns `granularity` beside the series, rather than a chart guessing from the number of points. Ninety days of hours would be 2,160 bars nobody can read.

Hourly labels are **UTC**, like every bucket in the product.

<Note>
  `Today` has no retries, first-call success or tool pairs — those are written by the [nightly pass](/api/concepts/nightly-pass), which has not run for today yet. `Yesterday` is the shortest window where every metric in the product has a figure.
</Note>

## Your plan clamps the range

Every metric route narrows the range to your plan's history window rather than refusing it. A bookmark from a cancelled subscription answers with seven days, not an error.

| Plan       | How far back |
| ---------- | ------------ |
| Free       | 7 days       |
| Pro, Scale | Everything   |

The counters themselves are **never deleted** — one row per hour per tool per client costs almost nothing to keep — so this hides rather than destroys. Upgrading reveals history that was already there. See [Plans](/billing/plans).

## Days are UTC days

This is the one that matters.

Ingest buckets a call into an hour with `date_trunc('hour', started_at at time zone 'utc')`, and every read resolves its range the same way. If the two sides ever disagreed about where a day starts, every number in the product would be quietly wrong at the edges and nothing would complain.

So there is one function that turns `from`/`to` into UTC day strings, and everything uses it.

The `timezone` on your [company profile](/company/profile) is display only. Nothing reads it into a query.

## Gap filling

Series that go into a chart — the overview's `series`, the sparklines, a tool's own series — carry **one entry per bucket in the range**, including buckets with nothing.

A quiet day plots as zero rather than vanishing and making the line look continuous when it is not.

## Comparison windows

The `deltas` on the overview compare against the **preceding window of equal length**. A 30-day range compares against the 30 days before it.

Two rules:

* A previous period of **zero yields no delta**, not an infinite one. Going from nothing to something is a start, not a percentage.
* Under a [tool or client filter](/metrics/overview), the previous window is scoped by the same filter — so "up 12%" compares like with like rather than one tool against six.

## The nightly slice

Retries, first-call success and tool pairs are only meaningful for days the [nightly pass](/api/concepts/nightly-pass) has walked. Every response carries `nightly_as_of` — the last covered day, or `null` if the range is entirely today.

The denominator for first-call success is calls on covered days, not all calls in range.

## Session ranges

[Sessions](/metrics/sessions) are counted by `started_at` across the whole range rather than summed per bucket, because a session that opens at 23:50 and closes at 00:10 is one session. Summing bucketed counts would make it two, and would halve cost per session.

## MCP tools take last\_days as well

The [MCP tools](/mcp/tools) accept `last_days` alongside `from`/`to`, because a model asked for "the last 30 days" would otherwise have to know today's date and do arithmetic — and a model that is one day out reports a number that is quietly wrong rather than visibly broken. A count cannot be off by one.

Explicit dates still win when given. "March" is a real question and no number of days expresses it.

## Related

* [The nightly pass](/api/concepts/nightly-pass)
* [The overview](/metrics/overview)
