Admin Run Rollup
const url = 'https://example.com/api/billing/admin/run-rollup';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"device_basis":"mtd_max","dry_run":true,"organization_id":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","period_date":"2026-04-15"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/api/billing/admin/run-rollup \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "device_basis": "mtd_max", "dry_run": true, "organization_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "period_date": "2026-04-15" }'Superuser-only, env-gated DRY-RUN of the §13.7 tier tariff (TODO-119).
Returns what the stack computes for organization_id through period_date
from its real counters and stored usage_daily evidence, so a live suite
can assert the billed amount (the nightly rollup has no on-demand trigger).
The result is a preview, not the invoice: for a closed month it can differ
from run_tier_period_billing when that job would skip the month (final
day never settled into usage_daily) or withhold it (BUG-293 mid-period
downgrade guard), and for today it also folds in the live active-device
count the nightly settle pass has not stored yet. See AdminRollupResponse.
Strictly read-only: no usage_daily upsert, no evidence-chain event, no
freeze-gate key, no gateway call, no audit row. dry_run=false is refused
with 422 because a real settle/bill is deliberately not exposed here.
Hidden (404) unless BILLING_ADMIN_ROLLUP_ENABLED is true.
Authorizations
Section titled “ Authorizations ”Request Bodyrequired
Section titled “ Request Bodyrequired ”POST /api/billing/admin/run-rollup (TODO-119) — a dry-run tariff preview.
dry_run exists so the wire contract already names the thing that would
one day be a real settle/bill; today only true is accepted and false
is refused with 422 by the route.
Responses
Section titled “ Responses ”Successful Response
The §13.7 tier tariff for one org/period, itemized. Never charged.
This is a PREVIEW, not the invoice. For a closed month it can legitimately
differ from what run_tier_period_billing (the period-boundary job) would
do: that job skips a month whose final day was never settled into
usage_daily, withholds an overage charge under the BUG-293 mid-period
downgrade guard, and uses only stored day rows, whereas this preview, when
period_date is today (UTC), also folds in today’s live active-device
count (the row tonight’s settle pass would write). For a settled, closed
month with no tier change the two agree field for field.
object
Example generated
{ "datapoint_overage_blocks": 1, "datapoint_overage_cents": 1, "datapoint_overage_qty": 1, "datapoint_overage_rate_cents": 1, "device_basis": 1, "device_basis_kind": "example", "device_basis_sample_days": 1, "device_overage_cents": 1, "device_overage_qty": 1, "device_overage_rate_cents": 1, "dry_run": true, "flat_cents": 1, "included_datapoints_month": 1, "included_devices": 1, "month_start": "2026-04-15", "mtd_metric_points": 1, "organization_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "overage_allowed": true, "overage_enabled": true, "overage_on": true, "overage_suppressed": true, "overage_suppressed_reason": "example", "period_date": "2026-04-15", "plan_code": "example", "total_cents": 1, "unbilled_datapoint_overage_cents": 1, "unbilled_device_overage_cents": 1}Validation Error
object
object
object
Example generated
{ "detail": [ { "ctx": {}, "input": "example", "loc": [ "example" ], "msg": "example", "type": "example" } ]}