Base URL
http://localhost:3333/api/· Authentication · Conventions
Layout Routes
Base path: /api/layouts
Manages per-user widget layout pages for the dashboard. Each page stores a grid layout of widgets.
Get All Layouts
GET /
- Authentication: Required
- Description: Get all layout pages for the authenticated user
- Response:
{
"pages": [
{
"id": "uuid",
"user_id": "user-id",
"page_id": "dashboard",
"page_name": "Dashboard",
"page_icon": "fas fa-th",
"page_order": 0,
"route": "/dashboard",
"layout_data": "[...]",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]
}Create Layout
POST /
- Authentication: Required
- Description: Create a new layout page
- Body:
{
"page_id": "my-page",
"page_name": "My Page",
"page_icon": "fas fa-th",
"page_order": 1,
"route": "/my-page",
"layout_data": "[]"
}- Response (201):
{
"message": "Layout created",
"id": "uuid",
"page_id": "my-page"
}Update Layout
PUT /:pageId
- Authentication: Required
- Parameters:
pageId(path): Page identifier
- Description: Update a layout page (upserts if not found)
- Body:
{
"page_name": "Updated Name",
"page_icon": "fas fa-chart-bar",
"page_order": 2,
"route": "/updated-page",
"layout_data": "[...]"
}- Response:
{
"message": "Layout updated",
"page_id": "my-page"
}Delete Layout
DELETE /:pageId
- Authentication: Required
- Parameters:
pageId(path): Page identifier
- Description: Delete a layout page
- Response:
{
"message": "Layout deleted",
"page_id": "my-page"
}Reset Layout
POST /reset/:pageId
- Authentication: Required
- Parameters:
pageId(path): Page identifier
- Description: Reset a page to default layout
- Body:
{
"layout_data": "[]"
}- Response:
{
"message": "Layout reset",
"page_id": "my-page"
}Workspace Routes
Base path: /api/workspaces
Cross-device persistence for the Workspaces page (canvas tabs). Backed by the existing widget_layouts table, with rows namespaced by route = 'workspace:<id>' (no schema migration). Conflict resolution is last-write-wins per workspace on an updatedAt epoch carried inside each workspace's data.
Get Workspaces
GET /
- Authentication: Required
- Description: Get all of the authenticated user's synced workspaces
- Response:
{
"workspaces": [
{
"id": "ws_abc123",
"name": "Coding",
"order": 0,
"widgets": [],
"ai": { "provider": "groq", "model": "llama-3.1-70b" },
"updatedAt": 1730000000000
}
]
}Sync Workspaces
PUT /
- Authentication: Required
- Description: Whole-set upsert of the user's workspaces (last-write-wins per workspace on
updatedAt).deletedIdsremoves workspaces so a tab closed on one device does not resurrect from another. - Body:
{
"workspaces": [
{
"id": "ws_abc123",
"name": "Coding",
"order": 0,
"widgets": [],
"ai": null,
"updatedAt": 1730000000000
}
],
"deletedIds": ["ws_old"]
}- Response:
{
"message": "Workspaces synced",
"count": 1,
"deleted": 1
}Delete Workspace
DELETE /:id
- Authentication: Required
- Parameters:
id(path): the workspace id
- Response:
{
"message": "Workspace deleted",
"id": "ws_abc123"
}Widget Definition Routes
Base path: /api/widget-definitions
Manage custom widget definitions for the dashboard. Widgets are user-created HTML/JS components that can be placed on layout pages.
Get All Widget Definitions
GET /
- Authentication: Required
- Description: Get all widget definitions for the user (including shared ones)
- Response:
{
"widgets": [
{
"id": "cw_abc123def456",
"user_id": "user-id",
"name": "System Monitor",
"description": "Displays system metrics",
"icon": "fas fa-chart-line",
"category": "monitoring",
"widget_type": "html",
"source_code": "<div>...</div>",
"config": {},
"data_bindings": [],
"default_size": { "cols": 4, "rows": 3 },
"min_size": { "cols": 2, "rows": 2 },
"useThemeStyles": true,
"is_shared": 0,
"is_published": 0,
"version": "1.0.0",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]
}Get Widget Definition by ID
GET /:widgetId
- Authentication: Required
- Parameters:
widgetId(path): Widget definition ID
- Response:
{
"widget": { ... }
}- Error (404): Widget definition not found
Create Widget Definition
POST /
- Authentication: Required
- Body:
{
"name": "My Widget",
"description": "A custom widget",
"icon": "fas fa-puzzle-piece",
"category": "custom",
"widget_type": "html",
"source_code": "<div>Hello World</div>",
"config": {},
"data_bindings": [],
"default_size": { "cols": 4, "rows": 3 },
"min_size": { "cols": 2, "rows": 2 },
"useThemeStyles": true
}- Response (201):
{
"message": "Widget definition created",
"id": "cw_abc123def456",
"widget": { ... }
}Update Widget Definition
PUT /:widgetId
- Authentication: Required
- Parameters:
widgetId(path): Widget definition ID
- Description: Partial update — only provided fields are changed
- Body:
{
"name": "Updated Name",
"source_code": "<div>Updated</div>",
"is_shared": true,
"useThemeStyles": false
}- Response:
{
"message": "Widget definition updated",
"id": "cw_abc123def456"
}Delete Widget Definition
DELETE /:widgetId
- Authentication: Required
- Parameters:
widgetId(path): Widget definition ID
- Response:
{
"message": "Widget definition deleted",
"id": "cw_abc123def456"
}Duplicate Widget Definition
POST /:widgetId/duplicate
- Authentication: Required
- Parameters:
widgetId(path): Widget definition ID to duplicate
- Description: Create a copy of an existing widget definition with " (copy)" appended to the name
- Response (201):
{
"message": "Widget duplicated",
"id": "cw_newid123456"
}Export Widget Definition
GET /:widgetId/export
- Authentication: Required
- Parameters:
widgetId(path): Widget definition ID
- Description: Export a widget definition as a portable JSON object
- Response:
{
"export": {
"_format": "agnt-widget",
"_version": "1.0.0",
"name": "My Widget",
"description": "A custom widget",
"icon": "fas fa-puzzle-piece",
"category": "custom",
"widget_type": "html",
"source_code": "<div>Hello World</div>",
"config": {},
"data_bindings": [],
"default_size": { "cols": 4, "rows": 3 },
"min_size": { "cols": 2, "rows": 2 },
"exported_at": "2024-01-01T00:00:00Z"
}
}Import Widget Definition
POST /import
- Authentication: Required
- Description: Import a widget definition from an exported JSON object
- Body:
{
"widget_data": {
"_format": "agnt-widget",
"_version": "1.0.0",
"name": "Imported Widget",
"source_code": "<div>Imported</div>",
...
}
}- Response (201): Same as Create Widget Definition
Capture Widget Thumbnail
POST /capture-thumbnail
- Authentication: Required
- Description: Render an HTML widget in a headless Puppeteer browser and return a JPEG screenshot as a base64 data URL. The renderer reuses a persistent browser instance (auto-closed after 60s idle) and auto-dismisses any
alert/confirm/promptdialogs so popup-heavy widgets don't block. - Body:
{
"html": "<!DOCTYPE html><html>...</html>",
"storageData": { "token": "<jwt>", "...": "any other localStorage keys to inject before render" }
}html(required): Full HTML document for the widget.storageData(optional): Object whose keys/values get written into the headless page'slocalStoragebefore the widget loads. Pass the user's token here if the widget makes authenticated fetches during render.Response:
{
"thumbnail": "data:image/jpeg;base64,..."
}- Notes: Used by the widget editor and by the orchestrator's chat-driven widget flow (
generate_widget/edit_widget_code). Capture is fire-and-forget from the frontend — the resultingthumbnaildata URL is then PUT back to/api/widget-definitions/:widgetIdto persist.
Conversation Settings Routes
Base path: /api/conversations
Per-conversation bindings (active skill / active goal).
Get Conversation Settings
GET /:id/settings
- Authentication: Required
- Description: The conversation's bound skill/goal IDs (
nullif unset) - Response:
{
"conversationId": "uuid",
"activeSkillId": null,
"activeGoalId": null
}Update Conversation Settings
PATCH /:id/settings
- Authentication: Required
- Description: Attach or detach the conversation's skill/goal bindings. Pass
nullto detach; omit a field to leave it unchanged. - Body:
{
"activeSkillId": "skill-id | null",
"activeGoalId": "goal-id | null"
}- Response: Updated settings object (same shape as GET)