Appearance
Studio (HTML artifacts)
Studio is where the agent builds live HTML dashboards ("artifacts") from a conversation. Artifacts are versioned, can be refreshed against their data sources, duplicated, restored, and shared through permanent links.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /microservices/agent/artifact-chat/ | Build or edit a page with the agent |
| GET | /microservices/artifacts/ | My artifacts |
| GET | /microservices/artifacts/{artifact_id}/ | Artifact metadata |
| PATCH | /microservices/artifacts/{artifact_id}/ | Rename an artifact |
| DELETE | /microservices/artifacts/{artifact_id}/ | Delete an artifact |
| GET | /microservices/artifacts/{artifact_id}/delete-impact/ | What deleting an artifact removes |
| GET | /microservices/artifacts/{artifact_id}/versions/ | Version history |
| POST | /microservices/artifacts/{artifact_id}/render-url/ | Get an embeddable URL |
| POST | /microservices/artifacts/{artifact_id}/refresh/ | Refresh the page's data |
| POST | /microservices/artifacts/{artifact_id}/restore/ | Restore a version |
| POST | /microservices/artifacts/{artifact_id}/duplicate/ | Duplicate an artifact |
| GET | /artifacts/links/ | My permanent links |
| POST | /artifacts/links/ | Create a permanent link |
| DELETE | /artifacts/links/{uid}/ | Revoke a permanent link |
POST /microservices/agent/artifact-chat/
Build or edit a page with the agent
The same contract as POST /microservices/agent/chat/ (see Chat AI), bound to the data sources you select and, when editing, to one artifact:
file_uids— up to 5 uploaded spreadsheets/CSVs from My Data;source_refs— up to 3 registered SQL connections (ds:<id>);artifact_id— an artifact you created, to edit instead of building new;mode: ask— a read-only conversation about a published page (the page'sstateand visible rows may be sent so "the number top-left" is answerable).
The skill is pinned to the artifact builder; the agent can only build against the selected sources. A successful build/update returns dashboard_id in the reply — the artifact id to render. Use one conversation_id per source set.
Auth: Session token · In the app: Studio → chat
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
timeout | integer | no | Default: 600. |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
conversation_id | string | yes | |
message | string | yes | |
file_uids | string (uuid)[] | no | |
source_refs | string[] | no | |
artifact_id | string | no | |
mode | string ("build", "ask") | no | Default: "build". |
chat_session_id | integer | no | |
reasoning_effort | string | no |
json
{
"conversation_id": "8a7b6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d",
"message": "Build a sales dashboard with revenue by region and a monthly trend.",
"source_refs": [
"ds:7"
]
}Response 200 — The agent's reply; dashboard_id identifies the built artifact.
| Field | Type | Description |
|---|---|---|
status | string | completed — answer holds the reply. queued — the turn is queued behind another one; the reply will arrive on the ws/chat/{conversation_id} socket. missing_param, clarification, interrupted — the agent needs input; the question is in message. |
answer | string | The reply (Markdown). |
message | string | The agent's question when it needs input. |
turn_id | string | |
queue_position | integer | |
mgid | string | Present when the turn produced a dashboard chart (fetch it with GET /microservices/dashboard-data/?mgid=). |
dashboard_id | string | Present when the turn published a Studio artifact. |
generated_files_urls | string[] | Media URLs of files the turn produced (documents, images). Sign them to download. |
json
{
"status": "completed",
"turn_id": "7c1f0c1e-2b8f-4a6e-9c0a-1e4b6f2d3a55",
"answer": "Q3 revenue grew **12.4% year over year**, driven by the enterprise segment (+19%) …\n",
"generated_files_urls": []
}Response 400 — Too many sources, unknown file, or invalid mode.
Response 403 — Artifact or source not yours.
Example
bash
curl -X POST "https://api.example.com/microservices/agent/artifact-chat/" \
-H "Authorization: Token $FINBLADE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"conversation_id":"8a7b6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d","message":"Build a sales dashboard with revenue by region and a monthly trend.","source_refs":["ds:7"]}'GET /microservices/artifacts/
My artifacts
Auth: Session token · In the app: Studio gallery
Response 200 — Artifacts, newest first (service response).
| Field | Type | Description |
|---|---|---|
artifacts | object[] | |
artifacts[].artifact_id | string | |
artifacts[].title | string | |
artifacts[].kind | string | dashboard, report, … |
artifacts[].version | integer | Latest version number. |
artifacts[].created_at | string (date-time) | |
artifacts[].updated_at | string (date-time) | |
artifacts[].dataset_names | string[] | |
artifacts[].sources | object | The data behind the page, keyed by source ref (file:<uid> for uploaded spreadsheets, ds:<id> for registered connections). |
artifacts[].change_note | string | |
artifacts[].created_by | object | |
artifacts[].created_by.user_id | string | |
artifacts[].created_by.username | string | |
artifacts[].created_by.organization_name | string |
Response 503 — Studio service not configured.
Example
bash
curl -X GET "https://api.example.com/microservices/artifacts/" \
-H "Authorization: Token $FINBLADE_TOKEN"GET /microservices/artifacts/{artifact_id}/
Artifact metadata
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id | string | yes |
Response 200 — Metadata (no HTML).
| Field | Type | Description |
|---|---|---|
artifact_id | string | |
title | string | |
kind | string | dashboard, report, … |
version | integer | Latest version number. |
created_at | string (date-time) | |
updated_at | string (date-time) | |
dataset_names | string[] | |
sources | object | The data behind the page, keyed by source ref (file:<uid> for uploaded spreadsheets, ds:<id> for registered connections). |
change_note | string | |
created_by | object | |
created_by.user_id | string | |
created_by.username | string | |
created_by.organization_name | string |
json
{
"artifact_id": "art_7f6e5d4c",
"title": "Sales dashboard",
"kind": "dashboard",
"version": 3,
"created_at": "2026-09-10T09:00:00Z",
"updated_at": "2026-09-21T14:12:00Z",
"dataset_names": [
"orders",
"customers"
],
"sources": {
"ds:7": {
"type": "sql",
"source_ref": "ds:7",
"name": "Warehouse (read-only)"
}
},
"change_note": "Added region filter",
"created_by": {
"user_id": "42",
"username": "jane",
"organization_name": "Acme"
}
}Response 403 — Not the creator.
Response 404 — Unknown artifact.
Example
bash
curl -X GET "https://api.example.com/microservices/artifacts/art_7f6e5d4c/" \
-H "Authorization: Token $FINBLADE_TOKEN"PATCH /microservices/artifacts/{artifact_id}/
Rename an artifact
Recorded as a new version; the chat thread and board tiles that carry the name follow.
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id | string | yes |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
title | string | yes |
Response 200 — Renamed.
| Field | Type | Description |
|---|---|---|
artifact_id | string | |
title | string | |
version | integer |
Example
bash
curl -X PATCH "https://api.example.com/microservices/artifacts/<artifact_id>/" \
-H "Authorization: Token $FINBLADE_TOKEN"DELETE /microservices/artifacts/{artifact_id}/
Delete an artifact
Deletes the artifact with every version, plus the board tiles that show it and the conversations bound to it (with their files and charts). Boards themselves are kept.
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id | string | yes |
Response 200 — Deleted, with counts.
| Field | Type | Description |
|---|---|---|
artifact_id | string | |
deleted | boolean | |
sessions | integer | |
tiles | integer | |
boards | integer | |
files | integer | |
errors | string[] | |
versions | integer | |
queries | integer |
Example
bash
curl -X DELETE "https://api.example.com/microservices/artifacts/<artifact_id>/" \
-H "Authorization: Token $FINBLADE_TOKEN"GET /microservices/artifacts/{artifact_id}/delete-impact/
What deleting an artifact removes
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id | string | yes |
Response 200 — Impact report (sessions, tiles, files).
Example
bash
curl -X GET "https://api.example.com/microservices/artifacts/<artifact_id>/delete-impact/" \
-H "Authorization: Token $FINBLADE_TOKEN"GET /microservices/artifacts/{artifact_id}/versions/
Version history
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id | string | yes |
Response 200 — Versions.
| Field | Type | Description |
|---|---|---|
artifact_id | string | |
versions | object[] | |
versions[].version | integer | |
versions[].title | string | |
versions[].change_note | string | |
versions[].created_at | string (date-time) |
Example
bash
curl -X GET "https://api.example.com/microservices/artifacts/<artifact_id>/versions/" \
-H "Authorization: Token $FINBLADE_TOKEN"POST /microservices/artifacts/{artifact_id}/render-url/
Get an embeddable URL
Mints a short-lived viewer token and returns the URL to load in an <iframe> (/artifacts/{id}/render/?token=…&version=…). Optionally pin a version and pass a small state object (≤ 2 KB, e.g. the selected filter) that the page receives on load.
Auth: Session token · In the app: Studio viewer; dashboard tiles of kind html_artifact
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id | string | yes |
Request body (application/json, optional)
| Field | Type | Required | Description |
|---|---|---|---|
version | integer | no | |
state | object | no |
Response 200 — URL and token.
| Field | Type | Description |
|---|---|---|
artifact_id | string | |
version | integer | |
title | string | |
kind | string | |
url | string (uri) | |
token | string |
json
{
"artifact_id": "art_7f6e5d4c",
"version": 3,
"title": "Sales dashboard",
"kind": "dashboard",
"url": "https://api.example.com/artifacts/art_7f6e5d4c/render/?token=eyJ…&version=3",
"token": "eyJ…"
}Response 400 — Bad version or state.
Example
bash
curl -X POST "https://api.example.com/microservices/artifacts/<artifact_id>/render-url/" \
-H "Authorization: Token $FINBLADE_TOKEN"POST /microservices/artifacts/{artifact_id}/refresh/
Refresh the page's data
Retires every cached query result for the artifact so the next render shows current data. Reload the page afterwards.
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id | string | yes |
Response 200 — Refreshed (service response).
Example
bash
curl -X POST "https://api.example.com/microservices/artifacts/<artifact_id>/refresh/" \
-H "Authorization: Token $FINBLADE_TOKEN"POST /microservices/artifacts/{artifact_id}/restore/
Restore a version
Makes version N the latest again as a new version that copies it; nothing is rewritten.
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id | string | yes |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
version | integer | yes |
Response 200 — Restored (service response with the new version).
Response 400 — version not an integer.
Example
bash
curl -X POST "https://api.example.com/microservices/artifacts/<artifact_id>/restore/" \
-H "Authorization: Token $FINBLADE_TOKEN"POST /microservices/artifacts/{artifact_id}/duplicate/
Duplicate an artifact
A new artifact of yours copying the latest version (own id, own history, version 1).
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id | string | yes |
Request body (application/json, optional)
| Field | Type | Required | Description |
|---|---|---|---|
title | string | no |
Response 200 — The new artifact (service response).
| Field | Type | Description |
|---|---|---|
artifact_id | string | |
title | string | |
kind | string | dashboard, report, … |
version | integer | Latest version number. |
created_at | string (date-time) | |
updated_at | string (date-time) | |
dataset_names | string[] | |
sources | object | The data behind the page, keyed by source ref (file:<uid> for uploaded spreadsheets, ds:<id> for registered connections). |
change_note | string | |
created_by | object | |
created_by.user_id | string | |
created_by.username | string | |
created_by.organization_name | string |
json
{
"artifact_id": "art_7f6e5d4c",
"title": "Sales dashboard",
"kind": "dashboard",
"version": 3,
"created_at": "2026-09-10T09:00:00Z",
"updated_at": "2026-09-21T14:12:00Z",
"dataset_names": [
"orders",
"customers"
],
"sources": {
"ds:7": {
"type": "sql",
"source_ref": "ds:7",
"name": "Warehouse (read-only)"
}
},
"change_note": "Added region filter",
"created_by": {
"user_id": "42",
"username": "jane",
"organization_name": "Acme"
}
}Example
bash
curl -X POST "https://api.example.com/microservices/artifacts/<artifact_id>/duplicate/" \
-H "Authorization: Token $FINBLADE_TOKEN"GET /artifacts/links/
My permanent links
Auth: Session token · In the app: My Data → Artifacts → Get link / Permanent links
Response 200 — Live links.
Array of:
| Field | Type | Description |
|---|---|---|
uid | string (uuid) | |
url | string | Media-relative URL with ?link=<token>; prefix with the API host. |
media_path | string | |
name | string | |
artifact_uid | string, nullable | The generated-file uid, when minted from one. |
created_at | string (date-time) | |
last_accessed_at | string (date-time), nullable | |
access_count | integer |
Example
bash
curl -X GET "https://api.example.com/artifacts/links/" \
-H "Authorization: Token $FINBLADE_TOKEN"POST /artifacts/links/
Create a permanent link
Mints a public link to one of your generated files, by artifact_uid (from GET /artifacts/) or by media_path. Idempotent — the same file returns the same link. The link is public and never expires; revoke it with DELETE.
Auth: Session token
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
artifact_uid | string (uuid) | no | |
media_path | string | no |
json
{
"artifact_uid": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
}Response 201 — The link.
| Field | Type | Description |
|---|---|---|
uid | string (uuid) | |
url | string | Media-relative URL with ?link=<token>; prefix with the API host. |
media_path | string | |
name | string | |
artifact_uid | string, nullable | The generated-file uid, when minted from one. |
created_at | string (date-time) | |
last_accessed_at | string (date-time), nullable | |
access_count | integer |
json
{
"uid": "5e4d3c2b-1a0f-4e9d-8c7b-6a5f4e3d2c1b",
"url": "/media/Acme/file_writer/jane/pdf/board-pack.pdf?link=Zk9Qm2Lp8Xc4Vb7N",
"media_path": "Acme/file_writer/jane/pdf/board-pack.pdf",
"name": "board-pack.pdf",
"artifact_uid": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"created_at": "2026-09-22T09:00:00Z",
"last_accessed_at": null,
"access_count": 0
}Response 400 — Neither id nor path, or the file cannot be linked.
json
{
"detail": "Authentication credentials were not provided."
}Response 404 — Unknown artifact.
Example
bash
curl -X POST "https://api.example.com/artifacts/links/" \
-H "Authorization: Token $FINBLADE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"artifact_uid":"0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"}'DELETE /artifacts/links/{uid}/
Revoke a permanent link
The URL stops working on the next request.
Auth: Session token
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
uid | string (uuid) | yes |
Response 204 — Revoked.
Response 404 — Not your link.
Example
bash
curl -X DELETE "https://api.example.com/artifacts/links/<uid>/" \
-H "Authorization: Token $FINBLADE_TOKEN"