Skip to content
Select themeSelect language

`GET /api/reports/overview` — windowed totals + per-dimension breakdown + gap-filled per-day series over `task_outcomes`.

GET
/api/reports/overview
curl --request GET \
--url https://example.com/api/reports/overview \
--cookie supacloud_session=<supacloud_session>
period
string

today | 7d | 30d — the reporting window (default 7d).

group_by
string

agent | model | kind | project — the breakdown axis (default agent).

Media typeapplication/json
object
breakdown
required
Array<object>
object
cost_usd
required
number format: double
input_tokens
required
integer format: int64
key
required

The dimension value: agent_type | model | run kind | project UUID string. A NULL/empty model or unmatched project folds to "unknown".

string
label
required

Human label: the project name for the project axis, else == key.

string
loc_added
required

LOC produced for this dimension value (mig 252), COALESCE 0 — see [ReportsTotals::loc_added].

integer format: int64
loc_removed
required
integer format: int64
output_tokens
required
integer format: int64
tasks
required
integer format: int64
delivery
required

#547/ADR-0049 delivery facts (closeout / governance / harness-memory / issues-closed) — workspace-wide scalars alongside totals.

object
closeout_approved
required

Closeout proposals approved in the window, windowed by decision time (reviewed_at) so a stale pending proposal does not inflate the count.

integer format: int64
closeout_pending
required

Closeout proposals awaiting review, windowed by proposal time (created_at).

integer format: int64
closeout_rejected
required

Closeout proposals rejected in the window (windowed by reviewed_at).

integer format: int64
docs_updated
required

Project docs updated (#712 K-07) — task_outcomes whose standard-closeout closeout_signals.project_docs_touched is true. 0 until the bw-infra runner emits changed_paths (same NULL-until-runner degradation as lines_added).

integer format: int64
governance_decisions
required

Privileged-override governance decisions in the window — audit_events rows matching the audited OVERRIDE_HINTS pattern set (grant / override / transfer_ownership / suspend_member / remove_member / force / bypass).

integer format: int64
harness_memory_updates
required

Harness-captured memory writes in the window — memories rows with a source_type LIKE 'harness_memory:%', windowed by updated_at.

integer format: int64
issues_closed
required

Issues delivered — completed tasks that carried a linked issue (tasks.config->>'link_issue_id'). The honest proxy for an issue closed, since the issue itself transitions via the merged PR’s Fixes #N and no dedicated issue-transition audit action exists to count directly.

integer format: int64
user_docs_updated
required

User docs updated (#712 K-07) — task_outcomes whose closeout_signals.user_docs_touched is true (0 until the runner emits paths). The closeout WIKI step is not counted — a wiki note is not a repo file, so it never appears in changed-paths; a wiki count needs a separate runner signal.

integer format: int64
group_by
required
string
period
required
string
prev
One of:
null
run_kinds
required

#626 §19 — the run-kind donut (agent/workflow/script/app) from runs.

Array<object>

#626 §19 — one slice of the run-kind donut. Sourced from runs directly, so a workflow/script/app run (which carries no task_outcomes row) is counted honestly alongside agent.

object
kind
required

The run kind — agent | workflow | script | app.

string
runs
required

Top-level runs of this kind over the window (children excluded).

integer format: int64
series
required
Array<object>
object
cost_usd
required
number format: double
day
required

ISO date YYYY-MM-DD — a NaiveDate serializes to exactly this string.

string
tasks
required
integer format: int64
top_tasks
required

#626 §11 — the 5 most expensive tasks over the window.

Array<object>

#626 §11 — one row of the Uebersicht “Teuerste Tasks” (top tasks by cost) list.

object
cost_usd
required
number format: double
project_label
required

The project name, falling back to the project UUID string.

string
task_id
required
string format: uuid
title
required

The task title (blank if the task row was deleted).

string
totals
required
object
avg_duration_secs

Mean wall-clock seconds (completed_at - started_at) over the window’s completed tasks; null when no task completed (an empty window has no duration — NOT 0, which would read as instantaneous).

number | null format: double
cost_usd
required
number format: double
cost_usd_median
required

Median per-task cost over the window (the typical task cost, robust to a few expensive outliers the mean would skew).

number format: double
cost_usd_subscription_covered
required

Cost spent under a SUBSCRIPTION credential (tasks.credential_kind = 'oauth_token', mig 211) — the honest subscription-vs-API split. API-key spend is cost_usd - cost_usd_subscription_covered.

number format: double
input_tokens
required
integer format: int64
loc_added
required

LOC produced over the window — lines added/removed across the tasks’ git diffs (mig 252). COALESCE 0 (NULLABLE column), so a window with no LOC captured — e.g. before the runner image ships the diff stat — reads 0.

integer format: int64
loc_removed
required
integer format: int64
output_tokens
required
integer format: int64
p95_duration_secs

95th-percentile wall-clock seconds; null on an empty window.

number | null format: double
prs_closed
required

PRs closed WITHOUT merging — outcomes with a non-NULL pr_closed_unmerged_at (a PR that was rejected/abandoned, not merged).

integer format: int64
prs_merged
required

PRs merged over the window — outcomes with a non-NULL pr_merged_at.

integer format: int64
prs_opened
required

PRs opened over the window — tasks whose outcome carries a non-empty pr_url (#547 honest deliverable, already per-task on task_outcomes).

integer format: int64
tasks
required
integer format: int64
tasks_failed
required

Tasks that ended failed.

integer format: int64
tasks_started
required

Tasks that ever started (tasks.started_at set) — the denominator for a success-rate gauge.

integer format: int64
tasks_succeeded
required

#626 §11 — tasks that ended completed over the window (joined tasks.status).

integer format: int64
Examplegenerated
{
"breakdown": [
{
"cost_usd": 1,
"input_tokens": 1,
"key": "example",
"label": "example",
"loc_added": 1,
"loc_removed": 1,
"output_tokens": 1,
"tasks": 1
}
],
"delivery": {
"closeout_approved": 1,
"closeout_pending": 1,
"closeout_rejected": 1,
"docs_updated": 1,
"governance_decisions": 1,
"harness_memory_updates": 1,
"issues_closed": 1,
"user_docs_updated": 1
},
"group_by": "example",
"period": "example",
"prev": {
"avg_duration_secs": 1,
"cost_usd": 1,
"cost_usd_median": 1,
"cost_usd_subscription_covered": 1,
"input_tokens": 1,
"loc_added": 1,
"loc_removed": 1,
"output_tokens": 1,
"p95_duration_secs": 1,
"prs_closed": 1,
"prs_merged": 1,
"prs_opened": 1,
"tasks": 1,
"tasks_failed": 1,
"tasks_started": 1,
"tasks_succeeded": 1
},
"run_kinds": [
{
"kind": "example",
"runs": 1
}
],
"series": [
{
"cost_usd": 1,
"day": "example",
"tasks": 1
}
],
"top_tasks": [
{
"cost_usd": 1,
"project_label": "example",
"task_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"title": "example"
}
],
"totals": {
"avg_duration_secs": 1,
"cost_usd": 1,
"cost_usd_median": 1,
"cost_usd_subscription_covered": 1,
"input_tokens": 1,
"loc_added": 1,
"loc_removed": 1,
"output_tokens": 1,
"p95_duration_secs": 1,
"prs_closed": 1,
"prs_merged": 1,
"prs_opened": 1,
"tasks": 1,
"tasks_failed": 1,
"tasks_started": 1,
"tasks_succeeded": 1
}
}

Authentication required

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}

Permission denied

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}

Structured server error

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}