Skip to main content
GET
Get one report

Authorizations

Authorization
string
header
required

An agent key (rpk_...) created in Settings → API & MCP, sent as Authorization: Bearer rpk_.... Bearer only: a cookie session can never drive this API. An OAuth 2.1 access token obtained from the same host works identically and lands on the same ceiling.

Headers

X-Workspace-Id
string

Which workspace to read. Omit it and you get the account’s home workspace, which on an agency account is often not where the live businesses are. A workspace this credential cannot read is refused with 403 rather than quietly answered from the default.

Path Parameters

id
string
required

The report id.

Response

The report.

id
string

Unique id.

workspace_id
string
template
string

Which template to render. PR-9 ships only 'monthly_reputation_report'; PR-13 adds 'competitor_comparison'. Stored as a string (not enum) so adding new templates doesn't require a migration.

period_start
string
period_end
string
status
string

queued | rendering | completed | failed

pdf_url
string

Relative path under /uploads/reports/<workspace_id>/.pdf. Public — filename includes a UUID so URLs are unguessable.

error_message
string

Truncated render-failure reason. Surfaced to the user inline on the failed row.

started_at
string
completed_at
string
render_token
string

Short-lived JWT (~5min) the worker mints for the requested_by user so Puppeteer can authenticate against the SPA preview route. Cleared on completion.

report_data
object

Aggregated data the report renders from. Populated by the worker (server/lib/reportData.js) BEFORE Puppeteer launches, then never touched again — reports are immutable historical artifacts. Top-level keys are namespaced so future PRs extend cleanly: report_data.workspace, .agency, .period, .previousPeriod, .reputationScore, .reviews, .mentions, .responses are PR-10. PR-11 adds .business_location and .insights ({ topThemes, notableReviews, notableMentions, recommendations } — any of which may be null when its LLM call failed). PR-13's competitor template will add .competitors. Treat unknown keys as forward-compat; never assume the full shape.

business_location_id
string

BusinessLocation this report scopes its Reviews data to. PR-11+ requires this for new reports (enforced at the route, not the schema, so existing PR-10 rows with null values stay valid). Reports without it are labelled 'Workspace Rollup (Historical)' in the UI and cannot be shared.

source
string
scheduled_report_id
string

When source='scheduled', points at the ScheduledReport that triggered this run. Lets the UI link back to the schedule's settings + retry buttons.

period_label
string

PR-14: human-readable period label, computed once at create time via server/lib/periodLabel.js. 'April 2026' for full calendar months, 'Q1 2026' for full calendar quarters, 'Mar 15 – Apr 28, 2026' otherwise. Stored on the row so the Reports list can render without recomputing per row. Older rows (pre-PR-14) have null and the UI falls back to computing from period_start/end on read.

public_share_id
string

Unguessable URL-safe token (12 chars, ~10²¹ search space). Generated when the agency owner enables sharing; cleared on disable; regenerated on re-enable so old URLs stay 404. Null when not currently shared.

is_public
boolean

Per-report public-share toggle. Independent of public_share_id presence — a report can have an old share_id with is_public=false (revoked); the public route requires both.

share_view_count
integer

Incremented on each public-page render. Async write — never blocks the response. No IP tracking in PR-11.

share_created_at
string