Find the reports available to you
id (for example contactsContactCountDashboard), a title, the fields that make up its
columns, and a row_key naming the field that identifies a row. Reports that declare a parent are
nested inside another report and are omitted from this list — you reach them through the parent’s
child_reports.
Fetch the rows
Adddata=true. Without it you get the configuration and no rows at all.
retrieved_at (a Unix timestamp) and visual_props, which carry
renderer hints for the returned data.
data=true is what makes a report expensive — it executes the underlying query. Fetch the config
once, cache it, and request data only when you need rows.Other flags
Any other query parameter is treated as report input — the filters and controls the report
declares in its
controls block. Send them alongside the flags:
CSV export
format=csv returns the file directly — Content-Type: text/csv with a
content-disposition: attachment header, and no JSON envelope. Don’t try to parse it as JSON.
The filename comes from the report’s own title, lowercased with spaces replaced by hyphens — not
from anything you pass in.
Running an action on selected rows
Reports can declare row actions in theiractions block. Each entry tells you its label, whether
it needs confirmation, and whether it’s destructive.
To run one, POST the row identifiers. The values come from the field named by the report’s
row_key:
row_keys is required and must be non-empty — an empty array returns 400 No rows selected. The
response shape depends on the action; only message is guaranteed.
Saved and shared reports
A custom report is a stored configuration — a report class plus saved input values. These are real records with full CRUD under/api/custom-reports, and they behave differently from the
generated configs above.
To hand one to someone without an API key, create a share URL:
url, expires and the params encoded into the token. Recipients read it through
GET /api/reports/shared/{pid}, which returns the same configuration shape — with actions filtered
down to those marked shared-safe, or removed entirely.
Gotchas
- A report that fails validation or setup returns
Report {id} could not be loadedrather than an empty result — treat it as a bad request, not an empty report. paramsis stripped from the response unless you passparams=true, so don’t rely on it being there by default.