Reports
Report tiles ("reports") are per-table widgets that summarise a table's records as markdown, a single value, a progress bar, an aggregate table, or a chart (bar / line / area / pie). Over the Public API you can list, read, create, update, delete, reorder, preview, and fetch the computed values of a table's report tiles.
Access
- Account API keys (
il_live_) with access to the workspace get full report access. Reads (list,get,execute) work for any table member; mutations (create,update,delete,reorder,preview) require the key to act as a workspace admin — report authoring is an admin-level surface. - Personal API keys (
il_user_) are read-only for reports:reports/list,report/<id>/get, andreport/<id>/execute. Authoring endpoints are not available to personal keys. - Read-only keys can read/execute but cannot
create,update,delete, orreorder.
A report lives on a display table (table_id) but aggregates a source
table (source_table_id). The source defaults to the display table itself,
but may be a table exactly one lookup-hop away in the same workspace (a parent it
looks up to, or a child / sub-table that looks up to it). Field, group, and
filter ids are validated against the source table.
The report object
{
"id": 12,
"account_id": 1,
"table_id": 101,
"source_table_id": 101,
"title": "Open deals by stage",
"type": "vbar",
"config": { "action": "count", "group": "fld_stage", "sort": "value_desc", "limit": 200, "filters": [] },
"position": 0,
"created_by": 5,
"created_at": "2026-07-01 09:00:00",
"updated_at": "2026-07-01 09:00:00"
}
Types and their config shape
The type selects the tile, and config is validated/normalized per type. Field
ids (field, group, filter column) must exist on the source table.
| Type | Purpose | config keys |
|---|---|---|
markdown |
Static markdown text | text |
value |
Single aggregate number | action, field?, filters?, prefix?, suffix?, numlabel?, decimals? |
progress |
Progress bar vs a target | value keys plus max, threshold1?, threshold2?, direction ("higher"|"lower") |
table |
Grouped aggregate table | action, field?, group, filters?, limit?, sort? |
vbar / hbar / line / area / pie |
Charts | same as table |
actionis one ofcount,sum,avg,min,max. Every action exceptcountrequiresfield(the numeric field to aggregate).group(table/chart types) is required and must be a groupable field.filtersis an array of{column, compare, value, connector?}:compare∈=,!=,>,<,>=,<=,contains,not_contains,starts_with,ends_with,is_empty,is_not_empty.valueis ignored foris_empty/is_not_empty.connector(AND|OR, defaultAND) joins the row with the previous one.
sort∈value_desc,value_asc,label_asc,label_desc(defaults:label_ascfor line/area,value_descotherwise).limiton grouped types is capped at 200 rows.
Unknown / malformed config is normalized away, and the config is compiled against the source table on save — an invalid field, group, or filter is rejected with a validation error rather than persisted.
List reports for a table
GET /api/table/<table_id>/reports/list
Returns the report objects for the table, ordered by position. Readable by any
table member.
Get a single report
GET /api/table/<table_id>/report/<report_id>/get
Returns the full report object (including config). The read-before-edit
endpoint.
Fetch computed values (execute)
GET /api/table/<table_id>/report/<report_id>/execute
Runs the report against the source table and returns the renderer payload. Cached
for ~30s and auto-invalidated when the source table's data changes. Shape depends
on type:
// markdown
{ "type": "markdown", "text": "…" }
// value / progress
{ "type": "value", "scalar": 42 }
// table
{ "type": "table", "columns": ["Stage", "Count"], "rows": [{ "label": "Won", "value": 12 }] }
// chart (vbar/hbar/line/area/pie)
{ "type": "vbar", "group": [{ "label": "Won", "value": 12 }, { "label": "Lost", "value": 3 }] }
If the report can't be computed (e.g. the source table was removed), the payload
carries an error string instead of the data keys:
{ "type": "value", "error": "Source table not found" }.
Create a report
POST /api/table/<table_id>/reports/create
{
"title": "Open deals by stage",
"type": "vbar",
"source_table_id": 101,
"config": { "action": "count", "group": "fld_stage", "sort": "value_desc" }
}
title and a valid type are required. source_table_id is optional (defaults
to the display table; must be self or a one-hop related table in the same
workspace). Returns the created report. Admin-only.
Update a report
POST /api/table/<table_id>/report/<report_id>/update
Body may contain any of title, type, source_table_id, config. Omitted
keys keep their current value. The resulting config is re-validated against the
source table. Returns the updated report. Admin-only.
Delete a report
POST /api/table/<table_id>/report/<report_id>/delete
Admin-only. Returns no body.
Reorder reports
POST /api/table/<table_id>/reports/reorder
Body {"ids": [12, 9, 15]} — the desired left-to-right / top-to-bottom order.
Ids not on the table are ignored. Returns the reordered list. Admin-only.
Preview (dry run)
POST /api/table/<table_id>/reports/preview
Body {"type": "...", "config": {...}, "source_table_id": <id?>}. Runs the
aggregation without saving and returns the same payload shape as execute.
Use it to build a tile interactively before create. Admin-only.
Recommended workflow
- Fetch the source table schema (
GET /api/table/<id>/get) for field ids. reports/previewyourtype+configuntil the payload looks right.reports/createthe tile.- Poll
report/<id>/executefor live values.
Errors
| Status | Message | When |
|---|---|---|
| 403 | Endpoint not available to personal API keys |
A personal (il_user_) key called a mutating report endpoint. |
| 403 | API key is read-only |
Read-only key called create / update / delete / reorder. |
| 500 | API key not authorized for this workspace |
Key's space whitelist excludes the table's workspace. |
| 500 | Not Authorized |
Key's user is not a workspace admin (mutations). |
| 500 | Invalid Table |
table_id doesn't exist or isn't accessible. |
| 500 | Report not found |
report_id doesn't belong to the table. |
| 500 | Invalid report type / validation message |
type or config failed validation on create/update. |