Skip to content

fix: Support hour ranges, datetime windows, and hourly timeseries buckets - #69

Merged
sergical merged 2 commits into
mainfrom
fix/sub-day-date-ranges
Oct 26, 2026
Merged

sergical merged 2 commits into
mainfrom
fix/sub-day-date-ranges

Conversation

@sergical

@sergical sergical commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Stacked on #66. Merge #65 and #66 first; GitHub then retargets this PR to main.

Problem

User feedback PLAUSIBLE-MCP-Q (from our own deployment, release 0.9.0): get_breakdown with date_range: "1h" returned Plausible API returned 400: #/date_range: Invalid date range "1h". The user wanted the custom events from the last ~10 minutes, and get_timeseries had no sub-day buckets.

Plausible's query schema accepts "24h" as its only hour shorthand. Our dateRangeSchema accepted any \d+h, so the error reached Plausible instead of failing at our schema. The same schema also accepts two things we did not expose: a pair of ISO 8601 datetimes (date_time_range) and the time:hour dimension.

Changes

  • Nh works for any N. encodeDateRange sends "Nh" as [now - N hours, now] in UTC, to second precision. This includes "24h", so all hour ranges follow one rule.
  • Sub-day windows. date_range accepts "<datetime>,<datetime>", where each datetime is YYYY-MM-DDTHH:MM:SS with Z or ±HH:MM. A pair that mixes a date and a datetime is rejected, as Plausible also rejects it.
  • Hourly buckets. get_timeseries accepts granularity: "hour", which maps to time:hour.
  • No silent truncation. Plausible returns at most 10,000 rows and drops the rest without a flag, which an hourly series over a long range reaches. get_timeseries now fails at that limit and tells the caller to narrow date_range or use a coarser granularity. PLAUSIBLE_MAX_ROWS moves to plausible.ts, so get_breakdown uses the same constant.
  • Docs. SERVER_INSTRUCTIONS and the field descriptions show the new forms. They also say that minute buckets are not available, because time:minute is internal to Plausible.

Tests

  • dateRangeSchema accepts and rejects each form.
  • The client encodes a datetime pair as a tuple, and "1h" as a rolling window under fake timers.
  • get_timeseries maps "hour" to time:hour, and rejects a 10,000-row result.

pnpm typecheck, pnpm build and pnpm test (288 tests, on top of the updated #66) pass locally.

Created with Claude Code

…kets

Plausible's Stats API v2 accepts only "24h" as an hour shorthand, but the
date_range schema let any "Nh" through, so "1h" reached Plausible and came
back as a 400. The server now sends every "Nh" as the equivalent rolling
datetime window ending now.

date_range also accepts two ISO 8601 datetimes with offsets for sub-day
windows, and get_timeseries accepts granularity "hour" (time:hour). Minute
buckets are internal to Plausible and stay unavailable.

Hourly buckets make long series reach Plausible's 10,000-row limit, which
it applies without a flag. get_timeseries now fails with an actionable
error at that limit instead of returning a series that ends early.

Fixes PLAUSIBLE-MCP-Q

Co-authored-by: Claude <claude@anthropic.com>
@sergical
sergical force-pushed the fix/sub-day-date-ranges branch from 165bd4c to bab4cf7 Compare October 26, 2026 18:50
Hourly buckets make long series reach the limit, which Plausible applies
without a flag. Return an actionable error instead of a series that ends
early. PLAUSIBLE_MAX_ROWS moves to plausible.ts so get_breakdown shares it.

Co-authored-by: Claude <claude@anthropic.com>
@sergical
sergical changed the base branch from feat/agent-friendly-errors-and-paging to main October 26, 2026 18:59
@sergical sergical closed this Oct 26, 2026
@sergical sergical reopened this Oct 26, 2026
@sergical
sergical merged commit b026013 into main Oct 26, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant