A report is the consulting deliverable: a client-ready snapshot of the knowledge base as of a moment in time — coverage, KPIs, top entities, gaps, and what to interview next — persisted immutably and re-readable months later, byte-for-byte the same. This guide generates a snapshot with one call and fetches it back as structured JSON.
Prerequisites
A key with reports:write (generate) and reports:read (list/fetch).
A workspace with some ingested documents — a report over an empty KB is a report about an empty KB.
Generating a report computes each section against the KB at that instant and persists the result, then returns the finished snapshot — coverage matrix, KPIs, and narrative summary all present in the 201. No model is invoked; the numbers come from the persisted graph, which is why the call is fast and repeatable. Those numbers are frozen at generation — a report you hand a client in July still reads the same in December, however much the KB has grown.
POST/api/v1/reportsBearer · reports:write
Generate an as-of report snapshot over the current KB. Returns 201 with the completed snapshot — coverage and summary are computed synchronously from the persisted graph, with no model call. The PDF render, if any, follows separately.
Request body
title
string
Report title, e.g. "Northwind — Q3 engagement report". Defaults to a workspace + date title.
kind
string
engagement (default) or coverage. Chooses which snapshot the generator assembles.
Fetch one snapshot by id to get its bodies back, or list the workspace's reports to get metadata rows. The two shapes differ on purpose: GET /reports never ships coverage or summary, so listing stays cheap however large the snapshots grow.
GET/api/v1/reports/{id}Bearer · reports:read
Fetch a report snapshot: its stamped metadata plus the computed coverage matrix and narrative summary. Workspace and filesystem fields are omitted — the key already selects the workspace.
The PDF is a session download, not an API resource
/api/v1 serves the report as data — that is the form a program can diff, chart, or re-render. The rendered PDF is downloaded from the workspace UI, backed by the session-authenticated route GET /api/w/{workspaceId}/report/{id}/pdf (any member; owner/admin can trigger a render with ?render=1). A 404 with { "status": "not_rendered" } means no PDF exists yet — ask for a render, then re-request.
Rendering is serialized
Headless-Chromium PDF rendering runs on a concurrency-1 queue, so a burst of report generations queues rather than exhausting the box. The structured snapshot never waits on the PDF: POST /reports returns the computed sections immediately, and the render lands afterwards.
The leverage
One POST turns the live state of an engagement into a frozen, reproducible artifact — the paid deliverable — and because it comes back as structured JSON you can also drop the same numbers into your own dashboard, email, or Slack digest without re-deriving them. Schedule the call and a Monday-morning client report is rendered before anyone opens their inbox; every re-download of an old snapshot is identical, because the layout version that produced it is stamped in. See Scheduling, drift & alerts for the cron substrate.