Counts at the speed
of light. Give or take.
API calls, AI tokens, compute seconds, credits. Pourlines reads your meterspec, ships the number to the customer's screen, and lets Claude / Codex / Cursor write the hooks for you. Or Terraform, for the enterprise side of the room.
Meterspec in. Drip out.
Three moving parts. One file you commit, one stream the SDK subscribes to, one number on the customer's screen.
Write the meterspec.
Declare your meters in a single file. Counters, gauges, deduplication keys, decimal precision. Versioned with your code.
meterspec.tomlSend the events.
One pour.track() call per event. The number lands on the customer's screen before the request closes. Idempotent by default. Spills get reconciled, not double-counted.
Streamed, not polled.
One hook. The exact count streams into the customer's browser as it changes — no polling, no five-minute lag, no "refresh to see your balance." Same primitive powers usage dashboards, credit balances, and overage alerts.
usePourMeter() · streams liveA spec you commit.
A hook you subscribe to.
# the schema artifact. lives in your repo.
[meter.tokens]
kind = "counter"
unit = "tokens"
dedupe_on = "event_id"
precision = 0
brim_at = 1_000_000 # soft cap → ● spill
[meter.compute]
kind = "gauge"
unit = "seconds"
window = "1m"
on_dry = "alert.team"import { pour, usePourMeter } from "@pour/sdk";
// fire and forget. idempotent on event_id.
pour.track("tokens", { qty: 2_413, event_id });
// live counter, no polling.
function Balance() {
const { value, status } = usePourMeter("tokens");
return <Counter n={value} status={status} />;
// ● on tap · ticks at p99 4ms
}Events, aggregated.
Same compile.
If you can express it as events aggregated over time, grouped by something, MeterSpec compiles it. Euros, grams of CO₂, DORA incidents, SLA breaches, chargeback units — same abstraction, same audit-grade pipeline, same TypeScript document. Below: one event family, two projections — a Stripe-shaped billing meter and a CSRD-shaped reporting meter — sharing one row so the invoice and the regulator number cannot drift.
- Billing & usage
- Carbon attribution · Scope 2/3
- AI Act energy disclosure
- Internal cost allocation · chargeback
- SLA & error-budget tracking
- DORA incidents · GDPR access requests
- Inventory throughput · defect rates
- Continuous signals — discretize first
- Custom math beyond CEL · no UDFs
- Predictions & forecasts
- Pure analytics needing full history
- High-cardinality blowups (group_by event_id)
[[families]] name = "acme.platform.agent-run" event_id_field = "agent_run_id" event_time_field = "completed_at" [families.schema.duration_ms] # drives billing type = "integer"; required = true [families.schema.energy_joules] # drives carbon type = "float"; required = true [families.schema.grid_intensity_g_per_kwh] type = "float"; required = true [families.schema.carbon_g] type = "float"; required = true [families.compliance] jurisdiction = ["eu", "eu_restricted"] audit_retention_years = 7
[[meters]]
name = "agent-hours-billing"
kind = "billing" # → Stripe
[meters.source]
kind = "family"; family = "acme.platform.agent-run"
[meters.aggregate]
fn = "SUM"
value = "duration_ms / 3600000.0"
window = "billing_cycle"
group_by = ["customer_id"]
[meters.billing]
model = "combined"; currency = "EUR"
included_units = 100
tiers = [
{ up_to = 1000, unit_amount = 0.45 },
{ up_to = "infinity", unit_amount = 0.30 },
]
[meters.compliance]
regulatory_regimes = ["dora"][[meters]]
name = "agent-carbon-attribution"
kind = "reporting" # no Stripe, no entitlement
[meters.source]
kind = "family"; family = "acme.platform.agent-run"
[meters.aggregate]
fn = "SUM"
value = "carbon_g / 1000.0" # grams → kg CO2e
group_by = ["customer_id", "region"]
[meters.aggregate.window] # 30-day rolling
kind = "rolling"
duration_seconds = 2592000
[meters.compliance]
regulatory_regimes = ["csrd", "ai_act"]
audit_retention_years = 10One event log.
Every agent-run writes once, to one Kafka topic, with both duration_ms and carbon_g on the same row. No second pipeline. No second schema. No second auditor evidence chain.
Two compiled pipelines.
Pourlines reads the document and emits a billing projection (Stripe-shaped, billing_cycle window) and a reporting projection (30-day rolling, customer × region). Both deterministic. Both replayable.
One compliance posture.
Residency, jurisdiction, audit retention live on the family. Reporting meters can tighten retention (10y for CSRD), never loosen it. The compliance manifest is generated at compile time.
energy_joules + risk class declared on the family. Energy disclosure is a projection, not a side report.Pourlines does not measure emissions. It attributes them — faithfully — from upstream signals you provide on the event (energy_joules × grid_intensity_g_per_kwh → carbon_g). The arithmetic is yours; the pipeline is ours.
When the meter moves,
your agent moves with it.
Hooks are typed events. Recipes on top, webhooks underneath. Wire them by hand with Terraform, or point Claude / Codex / Cursor at the Pour MCP and let the agent author and ship them. Every hook ships with a payload schema, an agent prompt, and a replay log.
{
"id": "evt_01HZQ8TMK3...",
"trigger": "on.balance.low",
"at": "2026-05-04T18:32:14.041Z",
"balance": { "before": 4.92, "after": 4.92 },
"threshold": 5.00,
"account": { "id": "acc_acme", "tier": "on_tap" },
"idempotency_key": "balance.low:2026-05-04T18:32"
}One MCP. All the tools.
Install once. Your agent gets meter.read · billing.topUp · rate.set · hook.replay · invoice.post with typed args, examples, and golden tests. Docs are written for LLMs first.
$ npx @pour/mcp install ✓ wrote ~/.config/mcp/pour.toml ✓ workspace: acme/prod
Or just commit it.
For the enterprise side of the room. Hooks as code, reviewed in PR, deployed by your existing pipeline. Same engine underneath.
resource "pour_hook" "topup_brim" {
trigger = "on.balance.low"
recipe { name = "topup", args = { pack = 100 } }
}Top up. Subscribe.
Or meter the overage.
Most metering vendors only know one shape of invoice. Pourlines ships three primitives so your pricing page can be whatever shape your product is.
Prepaid credits.
Drip them down.
Customers buy a balance up front. Pourlines decrements the live counter as events arrive. Auto-refill thresholds, soft brims, hard cutoffs.
Flat plans.
Live usage inside.
Monthly or annual subscriptions, with included quotas you can actually see go down. Upgrade, downgrade, or pause without exporting a CSV.
Subscription plus
true overage.
Combine a base plan with usage-based overage. Pour computes the bill in-stream, so the customer's dashboard shows the same number that lands on the invoice.
Batch reports tomorrow.
Or the number, now.
CSV exports. Cron jobs. Customer support tickets.
- Counts settle once a day. Maybe.
- Schema migrations require a maintenance window.
- Dropped events show up in next month's invoice.
- The dashboard is a Looker view someone built in 2022.
- Pricing engines you can't read. Tiers you can't change.
Meterspec in. Live counter out. p99 4ms.
- Counts in the customer's browser before they refresh.
- Decant a meterspec without dropping a single event.
- Spills are reconciled in-stream. No double counting.
- Forecourt is the dashboard. The drip is the API.
- Pricing tiers you ship in a PR.
Numbers, not adjectives.
Same tiers.
Three ways to pay.
Flat monthly. Live counters inside the plan. Cancel monthly.
Pour is opening in waves.
Reserve a spot.
We're onboarding a handful of design partners per week. EU-first, regulated workloads first. Tell us what you'd meter and we'll be in touch.