Core CRUD
Endpoints for managing Assistants: the paged collection, the legacy flat list, single-Assistant read, create, update, and delete, the skill-template catalog, and per-Assistant usage statistics.
Every route on this page is gated by AI access (ai.verify): AI must be enabled
on the tenant AND the caller must have AI access. Read access to individual
Assistants is enforced by the read_access model scope rather than a permission,
so list and lookup routes return only the Assistants the caller may see. Writes
additionally require the matching permission.
Most routes accept either the raw Assistant id (a UUID) or the compound natural
id ownerId:slug in the {id} path segment.
GET /api/assistants
List Assistants as a paged HAL collection, sorted by name. Only published
Assistants are returned (rows where editingId is null); drafts are excluded.
Authentication: Required (AI access via ai.verify)
Response:
A HAL collection embedding inf:assistant rows under _embedded. The envelope
carries the HAL paging fields start, count, and total. Each row eager-loads
its skills association (empty here), its inlined model (with the model's
provider, key stripped), a permissions map, and the full set of
inf:assistant-* rels. The query is scoped to read_access.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants"
}
},
"start": 0,
"count": 2,
"total": 2,
"_embedded": {
"inf:assistant": [
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001"
},
"inf:draft": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/draft"
},
"inf:edit": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/_edit"
},
"inf:comments": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/comments{?sort,limit}",
"templated": true
},
"inf:assistant-share": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/shares/{principalId}",
"templated": true
},
"inf:assistant-owner": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/owner"
},
"inf:assistant-datasets": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/datasets"
},
"inf:assistant-skills": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/skills"
},
"inf:assistant-toolkits": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/toolkits"
},
"inf:assistant-references": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/references"
},
"inf:assistant-shares": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/shares"
},
"inf:assistant-icon": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/icon"
},
"inf:assistant-secrets": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/secrets"
},
"inf:assistant-copy": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/_copy"
},
"inf:favorite": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/favorite"
},
"inf:assistant-files": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/files"
},
"inf:assistant-file-upload": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/files/_upload"
},
"inf:assistant-usage": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/usage"
},
"inf:create-image": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/_create-image"
},
"inf:chat-external": {
"href": "https://informer.example.com/assistants/admin%3Asales-assistant/chat"
}
},
"naturalId": "admin:sales-assistant",
"searchName": "sales assistant",
"permissions": {
"chat": true,
"edit": true,
"share": true,
"delete": true,
"write": true,
"changeOwner": true,
"copy": true,
"rename": true,
"assignTags": true
},
"id": "00000000-0000-4000-8000-000000000001",
"name": "Sales Assistant",
"description": "Helps with sales data analysis",
"slug": "sales-assistant",
"ownerId": "admin",
"welcome": "Hello! How can I help with sales today?",
"modelId": "00000000-0000-4000-8000-000000000002",
"instructions": "You are a helpful sales analyst.",
"suggestions": [
"Show me this month's top deals",
"Analyze quarterly trends"
],
"token": null,
"data": null,
"source": null,
"sourceId": null,
"folderId": null,
"editingId": null,
"shared": true,
"embedded": false,
"dispatcher": false,
"libraryId": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"skills": [],
"model": {
"naturalId": "acme-custom-opus",
"permissions": {},
"promptPpm": null,
"completionPpm": null,
"cacheReadPpm": null,
"cacheWriteShortPpm": null,
"cacheWriteLongPpm": null,
"id": "00000000-0000-4000-8000-000000000002",
"model": "claude-opus-4",
"slug": "acme-custom-opus",
"provider": {
"permissions": {},
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000003",
"name": "Anthropic",
"slug": "anthropic-1",
"type": "anthropic",
"key": null,
"managed": true,
"internal": false,
"settings": null,
"data": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z"
}
},
"icon": null
},
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000004"
},
"inf:draft": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/draft"
},
"inf:edit": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/_edit"
},
"inf:comments": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/comments{?sort,limit}",
"templated": true
},
"inf:assistant-share": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000004/shares/{principalId}",
"templated": true
},
"inf:assistant-owner": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/owner"
},
"inf:assistant-datasets": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/datasets"
},
"inf:assistant-skills": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/skills"
},
"inf:assistant-toolkits": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/toolkits"
},
"inf:assistant-references": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/references"
},
"inf:assistant-shares": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/shares"
},
"inf:assistant-icon": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/icon"
},
"inf:assistant-secrets": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/secrets"
},
"inf:assistant-copy": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/_copy"
},
"inf:favorite": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/favorite"
},
"inf:assistant-files": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/files"
},
"inf:assistant-file-upload": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/files/_upload"
},
"inf:assistant-usage": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/usage"
},
"inf:create-image": {
"href": "https://informer.example.com/api/assistants/admin%3Ascratch-assistant/_create-image"
},
"inf:chat-external": {
"href": "https://informer.example.com/assistants/admin%3Ascratch-assistant/chat"
}
},
"naturalId": "admin:scratch-assistant",
"searchName": "scratch assistant",
"permissions": {
"chat": true,
"edit": true,
"share": true,
"delete": true,
"write": true,
"changeOwner": true,
"copy": true,
"rename": true,
"assignTags": true
},
"id": "00000000-0000-4000-8000-000000000004",
"name": "Scratch Assistant",
"description": "Temporary assistant for the delete example",
"slug": "scratch-assistant",
"ownerId": "admin",
"welcome": null,
"modelId": "00000000-0000-4000-8000-000000000002",
"instructions": null,
"suggestions": null,
"token": null,
"data": null,
"source": null,
"sourceId": null,
"folderId": null,
"editingId": null,
"shared": false,
"embedded": false,
"dispatcher": false,
"libraryId": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"skills": [],
"model": {
"naturalId": "acme-custom-opus",
"permissions": {},
"promptPpm": null,
"completionPpm": null,
"cacheReadPpm": null,
"cacheWriteShortPpm": null,
"cacheWriteLongPpm": null,
"id": "00000000-0000-4000-8000-000000000002",
"model": "claude-opus-4",
"slug": "acme-custom-opus",
"provider": {
"permissions": {},
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000003",
"name": "Anthropic",
"slug": "anthropic-1",
"type": "anthropic",
"key": null,
"managed": true,
"internal": false,
"settings": null,
"data": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z"
}
},
"icon": null
}
]
}
}
Assistant properties:
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Assistant id |
naturalId | string | Compound natural id (ownerId:slug) |
name | string | Display name |
slug | string | URL-safe name |
description | string | null | Description |
instructions | string | null | System instructions for the Assistant |
welcome | string | null | Welcome message shown to users |
suggestions | array | null | Suggested prompts |
dispatcher | boolean | Whether this is a dispatcher Assistant |
modelId | string (UUID) | Preferred model id |
model | object | Eager-loaded model (provider inlined, key stripped) |
token | string | null | Encrypted at rest; never returned raw |
shared | boolean | Whether the Assistant is team-shared |
embedded | boolean | Internally-created (library/App) Assistant |
data | object | null | Custom metadata |
ownerId | string | Owning principal (server-derived) |
folderId | string | null | Folder id |
editingId | string | null | Draft pointer (null for published rows) |
icon | string | null | Icon identifier |
skills | array | Eager-loaded skill associations |
permissions | object | Caller's semantic permissions on this Assistant |
createdAt / updatedAt | date | Timestamps |
GET /api/assistants-list
The legacy flat-list endpoint: a bare array (not a HAL collection, no paging
envelope) built from a read-access SQL projection, then decorated per row with
tags and sharing. Like the paged route, it excludes drafts (editingId is
null) and embedded Assistants.
Authentication: Required (AI access via ai.verify)
Response:
A flat array. Each row is a lightweight projection that carries naturalId,
permissions, ownerName, favorite, iconId, suggestions, and tags,
rather than the full Assistant columns. sharing is included when present.
[
{
"id": "00000000-0000-4000-8000-000000000001",
"name": "Sales Assistant",
"description": "Helps with sales data analysis",
"suggestions": [
"Show me this month's top deals",
"Analyze quarterly trends"
],
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"shared": true,
"ownerId": "admin",
"folderId": null,
"username": "admin",
"favorite": false,
"iconId": null,
"naturalId": "admin:sales-assistant",
"permissions": {
"chat": true,
"edit": true,
"share": true,
"delete": true,
"write": true,
"changeOwner": true,
"copy": true,
"rename": true,
"assignTags": true
},
"ownerName": "acme Administrator",
"tags": []
},
{
"id": "00000000-0000-4000-8000-000000000002",
"name": "Scratch Assistant",
"description": "Temporary assistant for the delete example",
"suggestions": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"shared": false,
"ownerId": "admin",
"folderId": null,
"username": "admin",
"favorite": false,
"iconId": null,
"naturalId": "admin:scratch-assistant",
"permissions": {
"chat": true,
"edit": true,
"share": true,
"delete": true,
"write": true,
"changeOwner": true,
"copy": true,
"rename": true,
"assignTags": true
},
"ownerName": "acme Administrator",
"tags": []
}
]
GET /api/assistants/{id}
Retrieve a single Assistant with full detail.
Authentication: Required (AI access via ai.verify)
Pre-blocks: assistant.lookup(params.id) (resolves via read_access)
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Assistant id (raw UUID or compound ownerId:slug) |
Response:
A HAL representation of the Assistant with the inf:assistant-* rels. When a
chat owned by this Assistant exists for the current user, the handler injects a
chatId onto the response (absent in this fixture, since no such chat exists).
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant"
},
"inf:draft": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/draft"
},
"inf:edit": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/_edit"
},
"inf:comments": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/comments{?sort,limit}",
"templated": true
},
"inf:assistant-share": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/shares/{principalId}",
"templated": true
},
"inf:assistant-owner": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/owner"
},
"inf:assistant-datasets": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/datasets"
},
"inf:assistant-skills": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/skills"
},
"inf:assistant-toolkits": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/toolkits"
},
"inf:assistant-references": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/references"
},
"inf:assistant-shares": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/shares"
},
"inf:assistant-icon": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/icon"
},
"inf:assistant-secrets": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/secrets"
},
"inf:assistant-copy": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/_copy"
},
"inf:favorite": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/favorite"
},
"inf:assistant-files": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/files"
},
"inf:assistant-file-upload": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/files/_upload"
},
"inf:assistant-usage": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/usage"
},
"inf:create-image": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/_create-image"
},
"inf:chat-external": {
"href": "https://informer.example.com/assistants/admin%3Asales-assistant/chat"
}
},
"naturalId": "admin:sales-assistant",
"searchName": "sales assistant",
"permissions": {
"chat": true,
"edit": true,
"share": true,
"delete": true,
"write": true,
"changeOwner": true,
"copy": true,
"rename": true,
"assignTags": true
},
"id": "00000000-0000-4000-8000-000000000001",
"name": "Sales Assistant",
"description": "Helps with sales data analysis",
"slug": "sales-assistant",
"ownerId": "admin",
"welcome": "Hello! How can I help with sales today?",
"modelId": "00000000-0000-4000-8000-000000000002",
"instructions": "You are a helpful sales analyst.",
"suggestions": [
"Show me this month's top deals",
"Analyze quarterly trends"
],
"token": null,
"data": null,
"source": null,
"sourceId": null,
"folderId": null,
"editingId": null,
"shared": true,
"embedded": false,
"dispatcher": false,
"libraryId": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"datasets": [],
"editing": null,
"model": {
"naturalId": "acme-custom-opus",
"permissions": {},
"promptPpm": null,
"completionPpm": null,
"cacheReadPpm": null,
"cacheWriteShortPpm": null,
"cacheWriteLongPpm": null,
"id": "00000000-0000-4000-8000-000000000002",
"model": "claude-opus-4",
"slug": "acme-custom-opus",
"provider": {
"permissions": {},
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000003",
"name": "Anthropic",
"slug": "anthropic-1",
"type": "anthropic",
"key": null,
"managed": true,
"internal": false,
"settings": null,
"data": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z"
}
},
"icon": null
}
POST /api/assistants
Create an Assistant.
Authentication: Required (AI access via ai.verify)
Permission: assistants:create
Pre-blocks: ai.verify, then permission.assistants.create (requires data
wizard + AI)
Request Body:
The payload is stripUnknown, so unrecognized fields are dropped.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name |
description | string | No | Description |
instructions | string | No | System instructions |
welcome | string | No | Welcome message |
dispatcher | boolean | No | Whether this is a dispatcher Assistant (default false) |
suggestions | array | No | Suggested prompts |
model | string | No | Preferred model id |
token | string | No | API token for external access (stored encrypted) |
data | object | No | Custom metadata |
icon | string | No | Icon identifier |
shared | boolean | No | Whether the Assistant is team-shared (default false) |
model, not modelIdOn create, the preferred-model key is model (a model id string). The stored
column is modelId, and a beforeCreate hook defaults it to the go_everyday
managed model when model is omitted. The update route uses modelId instead
(see PUT below).
ownerId is server-derived from the caller, and token is encrypted at rest and
never returned raw.
Example Request:
{
"name": "Marketing Assistant",
"description": "Helps with marketing campaign analysis",
"instructions": "You are an expert marketing analyst.",
"welcome": "Hi! I can help analyze marketing campaigns.",
"suggestions": [
"Show campaign performance",
"Analyze email open rates"
],
"icon": "megaphone",
"shared": true
}
Response:
Responds 201 Created with the created Assistant and a Location header. Runs
in a database transaction.
{
"name": "Marketing Assistant",
"description": "Helps with marketing campaign analysis",
"instructions": "You are an expert marketing analyst.",
"welcome": "Hi! I can help analyze marketing campaigns.",
"suggestions": [
"Show campaign performance",
"Analyze email open rates"
],
"icon": "megaphone",
"shared": true
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant"
},
"inf:draft": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/draft"
},
"inf:edit": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/_edit"
},
"inf:comments": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/comments{?sort,limit}",
"templated": true
},
"inf:assistant-share": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/shares/{principalId}",
"templated": true
},
"inf:assistant-owner": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/owner"
},
"inf:assistant-datasets": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/datasets"
},
"inf:assistant-skills": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/skills"
},
"inf:assistant-toolkits": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/toolkits"
},
"inf:assistant-references": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/references"
},
"inf:assistant-shares": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/shares"
},
"inf:assistant-icon": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/icon"
},
"inf:assistant-secrets": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/secrets"
},
"inf:assistant-copy": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/_copy"
},
"inf:favorite": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/favorite"
},
"inf:assistant-files": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/files"
},
"inf:assistant-file-upload": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/files/_upload"
},
"inf:assistant-usage": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/usage"
},
"inf:create-image": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/_create-image"
},
"inf:chat-external": {
"href": "https://informer.example.com/assistants/admin%3Amarketing-assistant/chat"
}
},
"naturalId": "admin:marketing-assistant",
"searchName": "marketing assistant",
"permissions": {
"chat": true,
"edit": true,
"share": true,
"delete": true,
"write": true,
"changeOwner": true,
"copy": true,
"rename": true,
"assignTags": true
},
"id": "00000000-0000-4000-8000-000000000001",
"embedded": false,
"dispatcher": false,
"tenant": "acme",
"name": "Marketing Assistant",
"description": "Helps with marketing campaign analysis",
"instructions": "You are an expert marketing analyst.",
"welcome": "Hi! I can help analyze marketing campaigns.",
"suggestions": [
"Show campaign performance",
"Analyze email open rates"
],
"shared": true,
"updatedAt": "2026-01-15T16:20:00.000Z",
"createdAt": "2026-01-15T16:20:00.000Z",
"ownerId": "admin",
"modelId": "00000000-0000-4000-8000-000000000002",
"slug": "marketing-assistant",
"secrets": null,
"data": null,
"editingId": null,
"folderId": null,
"source": null,
"sourceId": null,
"token": null,
"libraryId": null
}
PUT /api/assistants/{id}
Update an Assistant.
Authentication: Required (AI access via ai.verify)
Permission: assistant:write
Pre-blocks: ai.verify, assistant.lookup(params.id), model lookup (only
when modelId is provided), then permission.assistant.write(pre.assistant)
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Assistant id (raw UUID or compound ownerId:slug) |
Request Body:
Unlike create, the model key here is modelId. The model lookup pre-block is
skipped when modelId is absent, preserving the existing model. Many fields
accept null or "" to clear them.
| Field | Type | Description |
|---|---|---|
name | string | Update display name |
description | string | null | Update description (null clears) |
instructions | string | null | Update system instructions (null clears) |
modelId | string | null | Change preferred model (null clears) |
token | string | null | Update API token (null clears) |
dispatcher | boolean | Toggle dispatcher mode |
suggestions | array | null | Update suggested prompts (null clears) |
welcome | string | null | Update welcome message (null clears) |
data | object | null | Update custom metadata (null clears) |
icon | string | null | Update icon (null clears) |
shared | boolean | Toggle team sharing |
Example Request:
{
"name": "Updated Marketing Assistant",
"instructions": "Enhanced marketing analysis instructions.",
"suggestions": [
"Campaign ROI breakdown",
"Channel attribution"
]
}
Response:
Responds 200 with the updated Assistant (resolved via the read_access
scope), not 201. Runs in a database transaction.
{
"name": "Updated Marketing Assistant",
"instructions": "Enhanced marketing analysis instructions.",
"suggestions": [
"Campaign ROI breakdown",
"Channel attribution"
]
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant"
},
"inf:draft": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/draft"
},
"inf:edit": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/_edit"
},
"inf:comments": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/comments{?sort,limit}",
"templated": true
},
"inf:assistant-share": {
"href": "https://informer.example.com/api/assistants/admin%3Amarketing-assistant/shares/{principalId}",
"templated": true
},
"inf:assistant-owner": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/owner"
},
"inf:assistant-datasets": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/datasets"
},
"inf:assistant-skills": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/skills"
},
"inf:assistant-toolkits": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/toolkits"
},
"inf:assistant-references": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/references"
},
"inf:assistant-shares": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/shares"
},
"inf:assistant-icon": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/icon"
},
"inf:assistant-secrets": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/secrets"
},
"inf:assistant-copy": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/_copy"
},
"inf:favorite": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/favorite"
},
"inf:assistant-files": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/files"
},
"inf:assistant-file-upload": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/files/_upload"
},
"inf:assistant-usage": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/usage"
},
"inf:create-image": {
"href": "https://informer.example.com/api/assistants/admin%3Aupdated-marketing-assistant/_create-image"
},
"inf:chat-external": {
"href": "https://informer.example.com/assistants/admin%3Aupdated-marketing-assistant/chat"
}
},
"naturalId": "admin:updated-marketing-assistant",
"searchName": "updated marketing assistant",
"permissions": {
"chat": true,
"edit": true,
"share": true,
"delete": true,
"write": true,
"changeOwner": true,
"copy": true,
"rename": true,
"assignTags": true
},
"id": "00000000-0000-4000-8000-000000000001",
"name": "Updated Marketing Assistant",
"description": "Helps with marketing campaign analysis",
"slug": "updated-marketing-assistant",
"ownerId": "admin",
"welcome": "Hi! I can help analyze marketing campaigns.",
"modelId": "00000000-0000-4000-8000-000000000002",
"instructions": "Enhanced marketing analysis instructions.",
"suggestions": [
"Campaign ROI breakdown",
"Channel attribution"
],
"token": null,
"data": null,
"source": null,
"sourceId": null,
"folderId": null,
"editingId": null,
"shared": true,
"embedded": false,
"dispatcher": false,
"libraryId": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"model": {
"naturalId": "go_everyday",
"permissions": {},
"promptPpm": null,
"completionPpm": null,
"cacheReadPpm": null,
"cacheWriteShortPpm": null,
"cacheWriteLongPpm": null,
"id": "00000000-0000-4000-8000-000000000002",
"model": null,
"slug": "go_everyday",
"provider": {
"permissions": {},
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000003",
"name": "Anthropic",
"slug": "anthropic",
"type": "anthropic",
"key": null,
"managed": true,
"internal": false,
"settings": null,
"data": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z"
}
},
"icon": null
}
DELETE /api/assistants/{id}
Delete an Assistant permanently.
Authentication: Required (AI access via ai.verify)
Permission: assistant:delete
Pre-blocks: ai.verify, assistant.lookup(params.id), then
permission.assistant.delete(pre.assistant)
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Assistant id (raw UUID or compound ownerId:slug) |
Response:
Responds 200 with an empty body (Informer convention), not 204. Runs in a
database transaction.
Deleting an Assistant cascades to its skills, datasets, secrets, files, and references. This cannot be undone.
GET /api/assistant-skill-templates
List the skill templates available when adding skills to an Assistant.
Authentication: Required (AI access via ai.verify)
Response:
A HAL collection (rel inf:skill-template) built from the registered
assistant-skill-builder driver catalog via the DriverManager discover. Use a
template's id when adding a skill to an Assistant.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistant-skill-templates"
}
},
"items": [
{
"detective": "00000000-0000-4000-8000-000000000001",
"id": "00000000-0000-4000-8000-000000000001:0",
"value": {
"group": "__top",
"name": "Simple Function",
"image": "/images/icons/simple-function.svg",
"skill": {
"type": "simpleFunction"
}
}
},
{
"detective": "00000000-0000-4000-8000-000000000002",
"id": "00000000-0000-4000-8000-000000000002:0",
"value": {
"group": "__top",
"name": "API Request",
"image": "/images/icons/api-request.svg",
"skill": {
"type": "apiRequest"
}
}
},
{
"detective": "00000000-0000-4000-8000-000000000003",
"id": "00000000-0000-4000-8000-000000000003:0",
"value": {
"group": "__top",
"name": "Highcharts",
"image": "/images/icons/highcharts.svg",
"skill": {
"type": "highcharts",
"name": "Highcharts"
}
}
},
"… 3 more items (6 total) — omitted from docs"
],
"start": 0,
"count": 6,
"total": 6
}
GET /api/assistants/{id}/usage
Get usage statistics for an Assistant.
Authentication: Required (AI access via ai.verify)
Pre-blocks: ai.verify, then assistant.lookup(params.id)
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Assistant id (raw UUID or compound ownerId:slug) |
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
month | string | current month | Month to aggregate the summary over |
months | integer | 12 | Trailing months for the history rollup (1-24) |
Response:
Returns { summary, history }. summary is the monthly usage aggregate from
audit.ai_log for the requested month; history is the trailing-months
monthly credits rollup. Both are pure SQL aggregates with no model-provider call.
With no usage logged, summary reports zeroes and history is an empty array.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/usage"
}
},
"summary": {
"count": 0,
"total": 0,
"average": 0
},
"history": []
}
POST /api/assistants/{id}/_copy
Duplicate an Assistant (its instructions, skills, and other configuration) into a new Assistant.
Authentication: Required (AI access + permission.assistant.copy + permission.assistants.create)
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Name for the copy. Defaults to a name derived from the original. |
Returns 201 with the new Assistant and a Location header pointing at it.
{
"name": "Order Desk Assistant (copy)"
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy"
},
"inf:draft": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/draft"
},
"inf:edit": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/_edit"
},
"inf:comments": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/comments{?sort,limit}",
"templated": true
},
"inf:assistant-share": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/shares/{principalId}",
"templated": true
},
"inf:assistant-owner": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/owner"
},
"inf:assistant-datasets": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/datasets"
},
"inf:assistant-skills": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/skills"
},
"inf:assistant-toolkits": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/toolkits"
},
"inf:assistant-references": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/references"
},
"inf:assistant-shares": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/shares"
},
"inf:assistant-icon": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/icon"
},
"inf:assistant-secrets": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/secrets"
},
"inf:assistant-copy": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/_copy"
},
"inf:favorite": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/favorite"
},
"inf:assistant-files": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/files"
},
"inf:assistant-file-upload": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/files/_upload"
},
"inf:assistant-usage": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/usage"
},
"inf:create-image": {
"href": "https://informer.example.com/api/assistants/admin%3Aorder-desk-assistant-copy/_create-image"
},
"inf:chat-external": {
"href": "https://informer.example.com/assistants/admin%3Aorder-desk-assistant-copy/chat"
}
},
"naturalId": "admin:order-desk-assistant-copy",
"searchName": "order desk assistant (copy)",
"permissions": {
"chat": true,
"edit": true,
"share": true,
"delete": true,
"write": true,
"changeOwner": true,
"copy": true,
"rename": true,
"assignTags": true
},
"id": "00000000-0000-4000-8000-000000000001",
"name": "Order Desk Assistant (copy)",
"description": "Answers questions about orders.",
"slug": "order-desk-assistant-copy",
"ownerId": "admin",
"welcome": null,
"modelId": "00000000-0000-4000-8000-000000000002",
"instructions": null,
"suggestions": null,
"token": null,
"data": null,
"source": null,
"sourceId": null,
"folderId": null,
"shared": false,
"embedded": false,
"dispatcher": false,
"libraryId": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"secrets": null,
"editingId": null
}
POST /api/assistants/{id}/_takeover
Transfer ownership of an in-progress draft Assistant to the caller. Use this when another user left a draft open and you need to continue editing it.
Authentication: Required (AI access + permission.assistant.write)
The \{id\} is the draft's id (the row whose editingId points at the
original, as returned by POST /api/assistants/\{id\}/_edit). Responds 400 if
the id is not a draft. Returns 200 with an empty body; it is a no-op when you
already own the draft.
Endpoints not captured here
The Assistant module also exposes live-AI and binary routes that depend on a model provider or on file IO against live services, so they are documented by contract only and have no captured response:
POST /api/assistants/\{id\}/_create-imagegenerates an Assistant image with a model provider.GET /api/assistants/\{id\}/iconandGET /api/assistants/\{id\}/favicon.icoreturn image bytes.- The Assistant file upload and download routes stream binary content.
- The Assistant chat route streams a live model response.
Skills, datasets, secrets, toolkits, references, sharing, ownership, drafts, comments, and favorites each live on their own page in this section.