Appearance
Libraries
Libraries, their drafts and releases, and the components they export.
GET /v1/libraries
Component libraries in an environment.
Libraries live on the environment branches at libraries/<name>/<version>/ (releases, immutable) and libraries/<name>/draft/ (the working copy). A library holds library.json, its manifest ({name, version, notes, description, components: {name: path}, reports: {name: path}, pages: {name: path}, theme: path, fonts: {family: LibraryFontFamily}}), the files it names and any assets. Documents import them as library:<name> with a version range, embed reports as library:<name>/<report> and use assets as library:<name>/<path>. pages are RFML page templates (§9.1), each with the id its name gives it, which the studio copies into reports; no document imports them. fonts are the declared font families, which the studio's font pickers list; the engine never reads them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
environment | query | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | {environment, libraries: [{name, description, latest, versions, draft}]} | |
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 | No git environments (sourceControl.driver is not git) |
POST /v1/libraries
Create a library (library.write).
Writes the draft's manifest, {name, description}. A name any environment already holds is refused, so promoting never meets another library of the same name.
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
environment | string | ||
name | string | yes | |
description | string |
Responses
| Status | Description | Body |
|---|---|---|
201 | The draft: | |
400 | The name isn't lower-case letters, digits and hyphens | |
403 | No library.write | |
409 | There is already a library with this name | |
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 |
GET /v1/libraries/{name}
One library release, or its draft.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
environment | query | string | ||
version | query | string | A release version, or draft; defaults to the latest release. |
Responses
| Status | Description | Body |
|---|---|---|
200 | ||
404 | No such library or version, or (error in-trash, with the item) the library is in the trash | |
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/libraries/{name}
Move a library to the trash.
Takes the library from every environment at once: each branch gets a commit "trash library <name>" that removes the draft and adds libraries/<name>/trashed/item.json, and the trash item keeps each branch's draft. The releases stay, so published reports that pin one keep rendering it; nothing else sees the library (listings, GET /v1/components, its routes answer 404 in-trash), a draft that imports it gets ref/library-in-trash, and its name is held until it is restored or purged (POST /v1/trash/{item}/restore, DELETE /v1/trash/{item}). Needs library.write in every environment. Audited as library.trash.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
Responses
| Status | Description | Body |
|---|---|---|
200 | object | |
403 | The caller lacks library.write in some environment | |
404 | No such library, or (error in-trash) it is in the trash already | |
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 |
|---|---|---|---|
name | string | ||
status | trashed | ||
item | TrashItem |
GET /v1/libraries/{name}/files/{path}
Read one file of a library release or draft.
Served with nosniff and a sandboxing Content-Security-Policy; X-Library-Version names the version.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
path | path | string | yes | Path inside the library, e.g. components/remittance-slip.json. May contain slashes. |
environment | query | string | ||
version | query | string | A release version, or draft; defaults to the latest release. |
Responses
| Status | Description | Body |
|---|---|---|
200 | The file's bytes | |
404 | No such file | |
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 |
PUT /v1/libraries/{name}/draft/files/{path}
Write one file of the library's draft (library.write).
The body is the file's bytes. The first write creates the draft, starting from the latest release. JSON files must be JSON; images and fonts must be what their extension says. library.json must name this library. Shared images go in the library named shared.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
path | path | string | yes | Path inside the library, e.g. components/remittance-slip.json. May contain slashes. |
environment | query | string |
Request body (application/octet-stream): string (binary)
Responses
| Status | Description | Body |
|---|---|---|
200 | ||
400 | Bad path, or content that doesn't match it | |
403 | No library.write | |
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/libraries/{name}/draft/files/{path}
Remove one file from the library's draft (library.write).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
path | path | string | yes | Path inside the library, e.g. components/remittance-slip.json. May contain slashes. |
environment | query | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | ||
404 | No such file in the draft | |
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/libraries/{name}/release
Release the draft as an immutable version (library.release).
The engine checks the library (/v1/validate-library), and each page template as a document of its own (/v1/validate, with the library's theme and components; its errors are at /pages/<name>); errors block the release (422). A page template needs a size, and an id that is its name in the manifest (400 otherwise). Versions are full semantic versions and can't be written twice (409). Agents may release only under agents.publish: allow. validated is always true (the engine checked the release); an engine that can't check it fails the release.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
environment | string | ||
version | string | yes | Semantic version, e.g. 2.1.0. |
notes | string | Release notes, kept in the release's manifest as notes. |
Responses
| Status | Description | Body |
|---|---|---|
201 | The release: | |
409 | The version exists; releases can't be changed | |
422 | The engine rejected the change or the document has errors: {error:"invalid", message, diagnostics}. A lock violation is an edit/locked diagnostic. | |
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/libraries/{name}/promote
Copy one library release to another environment.
Needs template.read in from and library.release in to. Copying a release the target holds unchanged does nothing; one that differs is 409. Promoting a template carries the releases it pins along by itself.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
version | string | The release; empty for the latest. | |
from | string | ||
to | string | Defaults to the environment after from. |
Responses
| Status | Description | Body |
|---|---|---|
200 | The release in the target environment | |
409 | The target holds a different copy of the release | |
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 |
GET /v1/libraries/{name}/changes
What the draft changes since a release, and the version that suggests.
Compares the draft with a release (from, default the latest): components, reports, page templates (the manifest's pages), the theme and other files added, changed or removed. bump is major when a component, prop, slot, part, report, the theme or a file is removed, or a prop becomes required; minor when anything is added; patch otherwise; "" when nothing changed. suggested is from moved by bump (a patch when nothing changed), or 1.0.0 before the first release. notes are release notes made from the changes.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
environment | query | string | ||
from | query | string | The release to compare with; defaults to the latest. |
Responses
| Status | Description | Body |
|---|---|---|
200 | {environment, name, from, changes: [{kind: component|report|page|theme|file|manifest, name, change: added|changed|removed, details, bump}], bump, suggested, notes} | |
404 | No such library, draft or release | |
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 |
GET /v1/libraries/{name}/releases
A library's releases, newest first.
Each release with its notes, the commit that wrote it on this environment's branch (its release, or its promotion) with that commit's author and time, and its status in every environment the caller may read: ok, missing or differs.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
environment | query | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | {environment, name, releases: [{version, notes, author, time, commit, tree, environments: {env: ok|missing|differs}}]} | |
404 | No such library | |
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 |
GET /v1/libraries/{name}/dependents
The reports in an environment that use a library.
Each report that uses the library, with what its published copy pins (from its lockfile) and what its draft references (imports, subreports and library: assets, each with its range and the release it resolves to now). published or draft is null where that copy doesn't use the library. Reports in the trash are left out. Worked out when asked; published copies are read once per branch tip. Needs template.read in the environment.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
environment | query | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | {environment, library, dependents: [{template, name, published: {version, pins: [{ref, kind, version}]} | null, draft: {revision, range, resolves, refs: [{ref, kind, range, resolves}]} | null}]}; kind is import, subreport or asset | |
404 | No such library in the environment | |
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 | No git environments (sourceControl.driver is not git) |
POST /v1/libraries/{name}/update
Move reports to a release of a library (template.publish).
For each report, its published copy (not its draft) is published again as a new version, "Update <library> to <version>", with only its pins for the library moved to version: in imports, subreports and library: assets. A range in the document that doesn't include version widens to ^version; that is the only change to the document. Other libraries and data sources keep their pins, and remote assets their stored copies. The publish pipeline runs as usual, tests included under tests.publishGate. Then the draft follows: its ranges that don't include version widen, as one draft edit with source library-update, and its other unpublished edits stay as they are. templates defaults to every report whose published copy uses the library. A dry run writes nothing. Each report (not in a dry run) is audited as library.update, with the commit when it was published. Agents may update only under agents.publish: allow, and dry-run always.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | Library name, e.g. billing |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
environment | string | ||
version | string | yes | The release, e.g. 2.3.0. |
templates | array of string | The reports to update; empty for every one that uses the library. | |
dryRun | boolean |
Responses
| Status | Description | Body |
|---|---|---|
200 | {environment, library, version, dryRun, results: [{template, status, message, from, changes: [{from, to}], revision, diagnostics, tests, draft: {status, message, revision, changes}}]}. status is published (would be, in a dry run), tests-failed (with the test report, under tests.publishGate block), conflict (the report has errors with the release, a library report keeps another release, or something changed meanwhile; with the diagnostics) or skipped (nothing to update: no published copy, it doesn't use the library, it pins the release already, or it is frozen). draft.status is updated, unchanged or conflict; draft is absent when there was no publish or no draft. | |
400 | version is not a release version | |
403 | No template.publish, or an agent under agents.publish other than allow | |
404 | No such library or release in the environment | |
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 | No git environments (sourceControl.driver is not git) |
GET /v1/components
Components the libraries of an environment export.
For each library's latest release (or one library's version), the components the engine says it exports (/v1/validate-library, cached per release), each with the import that brings it in and its stored definition (§14.1: description, props schema, slots).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
environment | query | string | ||
library | query | string | ||
version | query | string | With library only. |
Responses
| Status | Description | Body |
|---|---|---|
200 | {environment, components: [{name, library, version, import, definition}], libraries: [{name, version, valid, validated, diagnostics}]} | |
404 | The library named isn't in the environment | |
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 |