Report templates
A report template is a presentation format — a Liquid document with no binding to any workspace, project, user, or period. A report freely combines any template with any scope and date range at render time. Templates are instance-scoped: every authenticated user can read them to compose a report, but creating, editing, disabling, and deleting them is gated.
Permissions
Section titled “Permissions”Reading templates requires only read scope and any authenticated session. Managing them —
POST, PATCH, PATCH …/state, and DELETE — requires an instance admin or a user with the
template-author capability (user.canManageTemplates), not a workspace role.
The template object
Section titled “The template object”| Field | Type | Description |
|---|---|---|
id |
string | Unique identifier. |
name |
string | Display name (1–100 chars). |
description |
string | null | Optional description (≤ 1000 chars). |
body |
string | The Liquid template body (1–50000 chars). |
enabled |
boolean | Whether the template can back new/edited reports. Disabled templates are hidden from the report tabs. |
isDefault |
boolean | Whether this is the instance default — the template the compose form preselects. Exactly one template holds it. |
nameTemplate |
string | null | Liquid that generates a new report’s initial name (suggestedName in the preview). |
noteTemplate |
string | null | Liquid that generates a new report’s initial note (suggestedNote). |
defaultDateRange |
string | null | The date range a new report starts with (today, yesterday, this_week, last_week, this_month, last_month), or null to fall back to Today. |
createdBy |
string | null | The user who created it, or null for the seeded starter templates. |
createdAt |
string | null | ISO 8601 creation instant. |
updatedAt |
string | null | ISO 8601 last-update instant. |
List templates
Section titled “List templates”GET /api/v1/report-templates scope: read
Returns all templates. The starter catalog (Daily, Weekly, Monthly, from @spantail/templates) is
seeded once at instance bootstrap — when the first user, the instance admin, signs up — in that
request’s Accept-Language, so reports are always composable; Daily is the instance default.
Listing does not seed.
Create a template
Section titled “Create a template”POST /api/v1/report-templates scope: write
Requires instance admin or the template-author capability. Created templates are enabled.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Display name (1–100 chars). |
body |
string | yes | Liquid template body (1–50000 chars). |
description |
string | no | Optional description (≤ 1000 chars). |
nameTemplate |
string | no | Liquid for a new report’s initial name. |
noteTemplate |
string | no | Liquid for a new report’s initial note. |
defaultDateRange |
string | no | Default date range for a new report (today, yesterday, this_week, last_week, this_month, last_month). |
Returns 201 Created.
Get a template
Section titled “Get a template”GET /api/v1/report-templates/:id scope: read
Returns a single template. Unknown id returns 404.
Update a template
Section titled “Update a template”PATCH /api/v1/report-templates/:id scope: write
Requires instance admin or the template-author capability. All body fields are optional; send just what changes. Use Set template state to enable or disable instead.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | no | Display name (1–100 chars). |
description |
string | null | no | Description (≤ 1000 chars), or null to clear. |
body |
string | no | Liquid template body (1–50000 chars). |
nameTemplate |
string | null | no | Liquid for a new report’s initial name, or null to clear. |
noteTemplate |
string | null | no | Liquid for a new report’s initial note, or null to clear. |
defaultDateRange |
string | null | no | Default date range, or null to fall back to Today. |
Set template state
Section titled “Set template state”PATCH /api/v1/report-templates/:id/state scope: write
Requires instance admin or the template-author capability. Enables or disables a template,
separately from body edits. A disabled (archived) template can no longer back a new or edited
report, but existing reports stay viewable and shareable. The instance default cannot be
disabled while it holds the flag — that returns 409 conflict; set another template as default
first.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
enabled |
boolean | yes | true to enable, false to disable. |
Set as default
Section titled “Set as default”PATCH /api/v1/report-templates/:id/default scope: write
Requires instance admin or the template-author capability. Makes this template the sole
instance default — the one the compose form preselects — clearing the flag from whichever
template held it. A disabled template cannot become the default (409 conflict). Returns the
updated template.
Delete a template
Section titled “Delete a template”DELETE /api/v1/report-templates/:id scope: write
Requires instance admin or the template-author capability. Two guards return 409 conflict: a
template still referenced by saved reports cannot be deleted (disable it instead), and the
instance default cannot be deleted while it holds the flag (set another template as default
first). Returns 204 No Content on success.