Appearance
Examples and template sources
Templates to copy from, and where they come from.
GET /v1/examples
List the templates people can start a report from.
The templates of every template source that is on (GET /v1/template-sources): the example gallery (examples.gallery) first, then an organisation's own sources in the order they were added, each in its own order. None is installed: POST /v1/examples/{source}/{id}/copy copies one into the catalog. Each has a status by its RFML version: available (the version this installation writes, or an older one the engine reads), too-new or unsupported, which a copy refuses. A source that can't be read is listed in sources as unavailable while the others still list. reportd keeps a remote gallery's index and a repository's listing for an hour, and a failure to read one for five minutes; a folder is read each time.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
source | query | string | Only this source's templates. |
Responses
| Status | Description | Body |
|---|---|---|
200 | The templates, and the sources they came from | object |
404 | {error: not-found}: no source of that id is on (?source=) | |
429 | The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class. | object |
503 | {error: "gallery-off"} when no source is on (examples.gallery is off, and no other source is), or {error: "gallery-unavailable", message, sources} when none of them can be read (no internet access): download an example and import it instead. |
200 body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
examples | array of SourceTemplate | yes | |
sources | array of SourceListing | yes |
GET /v1/examples/{id}
Get an example's document and JSON files.
The example gallery's template id, as GET /v1/examples/examples/{id}.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes |
Responses
| Status | Description | Body |
|---|---|---|
200 | A template's document and its JSON files (samples, schemas, tests) by path | object |
404 | The gallery has no such example | |
429 | The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class. | object |
503 | The gallery is off or can't be read, as for GET /v1/examples |
200 body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | |
id | string | yes | |
title | string | yes | |
description | string | yes | |
rfml | string | yes | |
status | available, too-new, unsupported | yes | |
reason | string | ||
document | Document | yes | |
files | object | yes |
POST /v1/examples/{id}/copy
Copy an example into the catalog.
The example gallery's template id, as POST /v1/examples/examples/{id}/copy. The draft's edit says "from example <id>".
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
environment | string | ||
id | string | ||
title | string | Sets meta.title; default the template's. | |
folder | string |
Responses
| Status | Description | Body |
|---|---|---|
201 | The new report's first draft | object |
400 | The id isn't a template id | |
404 | The gallery has no such example | |
409 | The id is taken or in the trash, the licence's template limit is reached (licence-limit), or the example needs a newer RFML version (rfml-too-new) | |
422 | {error: rfml-unsupported}: the example is of an RFML version this Reportforge can't read | |
429 | The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class. | object |
503 | The gallery is off or can't be read, as for GET /v1/examples |
201 body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
environment | string | yes | |
revision | integer | yes | |
folder | string |
GET /v1/examples/{source}/{id}
Get a template's document and JSON files.
For its thumbnail and a closer look, whatever its status. Assets aren't included.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
source | path | string | yes | A template source's id; examples is the example gallery |
id | path | string | yes |
Responses
| Status | Description | Body |
|---|---|---|
200 | A template's document and its JSON files (samples, schemas, tests) by path | object |
404 | No source of that id is on, or it has no such template | |
429 | The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class. | object |
503 | The source can't be read, as for GET /v1/examples |
200 body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | |
id | string | yes | |
title | string | yes | |
description | string | yes | |
rfml | string | yes | |
status | available, too-new, unsupported | yes | |
reason | string | ||
document | Document | yes | |
files | object | yes |
POST /v1/examples/{source}/{id}/copy
Copy a template into the catalog.
Copies the template's bundle as the first draft of a new report in environment, with the checks POST /v1/templates makes; only the copy counts against the licence's templates, and it isn't linked to its source. Without id, the copy takes its document's id, or the first of <id>-2, <id>-3… that is free.
Its RFML version is checked as GET /v1/examples does: a template that needs a newer version is refused with 409 rfml-too-new, one this Reportforge can't read with 422 rfml-unsupported. One of an older version the engine migrates is stored as the engine migrated it. The draft's edit says where it came from: "from <source name>: <path> @ <commit>" ("from example <id>" for the example gallery), and ", RFML <from> → <to>" when it was migrated.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
source | path | string | yes | A template source's id; examples is the example gallery |
id | path | string | yes |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
environment | string | ||
id | string | ||
title | string | Sets meta.title; default the template's. | |
folder | string |
Responses
| Status | Description | Body |
|---|---|---|
201 | The new report's first draft | object |
400 | The id isn't a template id | |
404 | No source of that id is on, or it has no such template | |
409 | The id is taken or in the trash, the licence's template limit is reached (licence-limit), or {error: rfml-too-new, message, rfml, needs}: the template needs a newer RFML version, and needs is the first release that writes it, when this one knows | |
422 | {error: rfml-unsupported, message, rfml}: an RFML version this Reportforge can't read | |
429 | The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class. | object |
503 | The source can't be read, as for GET /v1/examples |
201 body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
environment | string | yes | |
revision | integer | yes | |
folder | string |
GET /v1/template-sources
The template sources.
The example gallery (the preset, at examples.gallery's address), then the declared sources in the order they were added, each with what its last read found. Needs templates.sources, which agents never have.
Responses
| Status | Description | Body |
|---|---|---|
200 | The sources | object |
403 | The caller lacks templates.sources | |
429 | The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class. | object |
200 body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
sources | array of TemplateSource | yes |
PUT /v1/template-sources/{id}
Add or change a template source, or turn it on or off.
Needs templates.sources. A source other than the preset needs the template-sources licence feature (403 LicenceRequired). The preset takes only enabled. A token is a secret: reference, never a token. Audited as templates.source.add <id> or templates.source.change <id>.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes |
Request body (application/json): TemplateSourceEdit
Responses
| Status | Description | Body |
|---|---|---|
200 | The source, changed | TemplateSource |
201 | The source, added | TemplateSource |
403 | The caller lacks templates.sources, or no licence grants template-sources (LicenceRequired) | |
422 | ||
429 | The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class. | object |
DELETE /v1/template-sources/{id}
Remove a template source.
Needs templates.sources. The preset can't be removed (409 {error: preset}); it can be turned off. Reports copied from the source are untouched. Audited as templates.source.remove <id>.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes |
Responses
| Status | Description | Body |
|---|---|---|
204 | Removed | |
403 | The caller lacks templates.sources | |
404 | No source has the id | |
409 | {error: preset}: the preset can't be removed | |
429 | The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class. | object |
POST /v1/template-sources/{id}/refresh
Read a template source again now.
Needs templates.sources. A read that fails still answers 200, with the error in the source's state; a repository read before keeps listing what it read then.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes |
Responses
| Status | Description | Body |
|---|---|---|
200 | The source, with what the read found | TemplateSource |
403 | The caller lacks templates.sources, or the source needs a licence with template-sources (LicenceRequired) | |
404 | No source has the id | |
409 | {error: source-off, off}: the source is off | |
429 | The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class. | object |