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). deletedIds removes 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/prompt dialogs 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's localStorage before 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 resulting thumbnail data URL is then PUT back to /api/widget-definitions/:widgetId to 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 (null if 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 null to 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)