Files & References
Endpoints for managing the files attached to an Assistant and the Assistant-to-Assistant references that point one Assistant at another.
Every route on this page is gated by ai.verify (AI enabled on the tenant AND
the caller having AI access). Entities are resolved through the read_access
model scope: assistant.lookup for the Assistant, and assistant.lookupFile
(the File assistant scope, which requires an assistant_file link) for an
attached file. The file-attach and file-update mutations require
permission.assistant.write; detaching a file requires permission.assistant.edit.
Files
GET /api/assistants/{id}/files
List the files attached to an Assistant.
Authentication: AI access (ai.verify)
Response:
A HAL collection embedding inf:file: the File rows behind the
assistant_file links (the File objects, not the join rows). Each embedded
file carries an inf:file-contents (./contents) link.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/files"
}
},
"start": 0,
"count": 2,
"total": 2,
"_embedded": {
"inf:file": [
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/files/00000000-0000-4000-8000-000000000002"
},
"inf:file-contents": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/files/00000000-0000-4000-8000-000000000002/contents"
}
},
"extension": "md",
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000002",
"filename": "q4-forecast.md",
"embedded": true,
"contentType": "text/markdown",
"lobId": null,
"role": "DOCUMENT",
"description": "Quarterly revenue forecast notes.",
"data": {},
"createdById": null,
"letterheadId": null,
"jobActionAttachmentId": null,
"jobActionId": null,
"oauthClientId": null,
"assistantId": null,
"directory": false,
"indexed": false,
"indexingStartedAt": null,
"indexingErroredAt": null,
"indexingErrorMessage": null,
"indexedAt": null,
"parentId": null,
"libraryId": null,
"remoteId": null,
"remoteUrl": null,
"size": null,
"modifiedAt": null,
"messageId": null,
"chatId": null,
"expiresAt": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"ownerId": null,
"templateId": null,
"integrationId": null
},
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/files/00000000-0000-4000-8000-000000000003"
},
"inf:file-contents": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/files/00000000-0000-4000-8000-000000000003/contents"
}
},
"extension": "md",
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000003",
"filename": "scratch-notes.md",
"embedded": true,
"contentType": "text/markdown",
"lobId": null,
"role": "DOCUMENT",
"description": null,
"data": {},
"createdById": null,
"letterheadId": null,
"jobActionAttachmentId": null,
"jobActionId": null,
"oauthClientId": null,
"assistantId": null,
"directory": false,
"indexed": false,
"indexingStartedAt": null,
"indexingErroredAt": null,
"indexingErrorMessage": null,
"indexedAt": null,
"parentId": null,
"libraryId": null,
"remoteId": null,
"remoteUrl": null,
"size": null,
"modifiedAt": null,
"messageId": null,
"chatId": null,
"expiresAt": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"ownerId": null,
"templateId": null,
"integrationId": null
}
]
}
}
POST /api/assistants/{id}/files
Attach already-existing Library files to an Assistant. This route does not
perform an upload: it creates assistant_file rows linking the named Library
files to the Assistant (for any not yet linked). Direct uploads go through
POST /api/assistants/{id}/files/_upload instead.
Authentication: AI access (ai.verify)
Pre-blocks: assistant.lookup, permission.assistant.write
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
libraryId | string | Yes | The Library that owns the files |
fileIds | array of string | Yes | File ids to attach (.single(), so a bare string is also accepted) |
There is no uploadId or name field.
Example Request:
{
"libraryId": "00000000-0000-4000-8000-000000000010",
"fileIds": ["00000000-0000-4000-8000-000000000011"]
}
Response:
Responds 200 with an empty body (Informer convention), not 201. The handler
returns nothing.
{
"libraryId": "00000000-0000-4000-8000-000000000002",
"fileIds": [
"00000000-0000-4000-8000-000000000003"
]
}
POST /api/assistants/{id}/files/_upload
Upload a file directly to an Assistant and compute its embeddings.
Authentication: AI access (ai.verify)
Pre-blocks: assistant.lookup, permission.assistant.write
Content-Type: multipart/form-data
Response:
The stored file. This route does file IO and embedding generation against live services, so it is not captured here.
GET /api/assistants/{id}/files/{file}
Get a single attached file. The {file} path param is the File id, resolved via
assistant.lookupFile (the File assistant scope, which requires an
assistant_file link).
Authentication: AI access (ai.verify)
Response:
The raw File row with an inf:file-contents (./contents) link.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/files/00000000-0000-4000-8000-000000000002"
},
"inf:file-contents": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/files/00000000-0000-4000-8000-000000000002/contents"
}
},
"extension": "md",
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000002",
"filename": "q4-forecast.md",
"embedded": true,
"contentType": "text/markdown",
"lobId": null,
"role": "DOCUMENT",
"description": "Quarterly revenue forecast notes.",
"data": {},
"createdById": null,
"letterheadId": null,
"jobActionAttachmentId": null,
"jobActionId": null,
"oauthClientId": null,
"assistantId": null,
"directory": false,
"indexed": false,
"indexingStartedAt": null,
"indexingErroredAt": null,
"indexingErrorMessage": null,
"indexedAt": null,
"parentId": null,
"libraryId": null,
"remoteId": null,
"remoteUrl": null,
"size": null,
"modifiedAt": null,
"messageId": null,
"chatId": null,
"expiresAt": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"ownerId": null,
"templateId": null,
"integrationId": null
}
PUT /api/assistants/{id}/files/{file}
Update an attached file's metadata. There is no Joi payload schema; the route is
a db.update against the File model (matched on id plus embedded: true).
Send File columns such as filename or description.
Authentication: AI access (ai.verify)
Pre-blocks: assistant.lookupFile, permission.assistant.write
Example Request:
{ "description": "Updated quarterly revenue forecast notes." }
Response:
Responds 200 with the updated File.
{
"description": "Updated quarterly revenue forecast notes."
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/files/00000000-0000-4000-8000-000000000002"
},
"inf:file-contents": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/files/00000000-0000-4000-8000-000000000002/contents"
}
},
"extension": "md",
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000002",
"filename": "q4-forecast.md",
"embedded": true,
"contentType": "text/markdown",
"lobId": null,
"role": "DOCUMENT",
"description": "Updated quarterly revenue forecast notes.",
"data": {},
"createdById": null,
"letterheadId": null,
"jobActionAttachmentId": null,
"jobActionId": null,
"oauthClientId": null,
"assistantId": null,
"directory": false,
"indexed": false,
"indexingStartedAt": null,
"indexingErroredAt": null,
"indexingErrorMessage": null,
"indexedAt": null,
"parentId": null,
"libraryId": null,
"remoteId": null,
"remoteUrl": null,
"size": null,
"modifiedAt": null,
"messageId": null,
"chatId": null,
"expiresAt": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"ownerId": null,
"templateId": null,
"integrationId": null
}
DELETE /api/assistants/{id}/files/{file}
Detach a file from an Assistant. This is a db.remove against AssistantFile:
it removes the assistant_file row but does not delete the underlying File.
Authentication: AI access (ai.verify)
Pre-blocks: assistant.lookupFile, permission.assistant.edit
edit, not writeUnlike the other file mutations on this page, detaching a file requires
permission.assistant.edit, not permission.assistant.write.
Response:
Responds 200 with an empty body (Informer convention), not 204.
GET /api/assistants/{id}/files/{file}/contents
Download the raw contents of an attached file.
Authentication: AI access (ai.verify)
Response:
The file bytes with an appropriate Content-Type header (binary, not shown).
PUT /api/assistants/{id}/files/{file}/contents
Replace the contents of an attached file.
Authentication: AI access (ai.verify)
Content-Type: multipart/form-data
Response:
The updated File. This route accepts a binary/multipart upload, so it is not captured here.
GET /api/assistants/{id}/files/{file}/embeddings/{embeddingId}/image
Retrieve an image extracted from a file's embeddings.
Authentication: AI access (ai.verify)
Response:
The image bytes with an appropriate Content-Type header (binary, not shown).
References
References are Assistant-to-Assistant pointers: one Assistant (the source) references another (the target).
GET /api/assistants/{id}/references
List the references on an Assistant.
Authentication: AI access (ai.verify)
Response:
A HAL collection embedding inf:assistant-reference, each embedding the target
inf:assistant (resolved through read_access, with its icon).
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/references"
}
},
"start": 0,
"count": 1,
"total": 1,
"_embedded": {
"inf:assistant-reference": [
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/references/00000000-0000-4000-8000-000000000002"
}
},
"id": "00000000-0000-4000-8000-000000000003",
"sourceId": "00000000-0000-4000-8000-000000000001",
"targetId": "00000000-0000-4000-8000-000000000002",
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"_embedded": {
"inf:assistant": {
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/references/00000000-0000-4000-8000-000000000002/00000000-0000-4000-8000-000000000002"
},
"inf:draft": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/draft"
},
"inf:edit": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/_edit"
},
"inf:comments": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/comments{?sort,limit}",
"templated": true
},
"inf:assistant-share": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/references/00000000-0000-4000-8000-000000000002/00000000-0000-4000-8000-000000000002/shares/{principalId}",
"templated": true
},
"inf:assistant-owner": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/owner"
},
"inf:assistant-datasets": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/datasets"
},
"inf:assistant-skills": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/skills"
},
"inf:assistant-toolkits": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/toolkits"
},
"inf:assistant-references": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/references"
},
"inf:assistant-shares": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/shares"
},
"inf:assistant-icon": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/icon"
},
"inf:assistant-secrets": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/secrets"
},
"inf:assistant-copy": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/_copy"
},
"inf:favorite": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/favorite"
},
"inf:assistant-files": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/files"
},
"inf:assistant-file-upload": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/files/_upload"
},
"inf:assistant-usage": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/usage"
},
"inf:create-image": {
"href": "https://informer.example.com/api/assistants/admin%3Asupport-assistant/_create-image"
},
"inf:chat-external": {
"href": "https://informer.example.com/assistants/admin%3Asupport-assistant/chat"
}
},
"naturalId": "admin:support-assistant",
"searchName": "support 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-000000000002",
"name": "Support Assistant",
"description": "Handles customer support inquiries.",
"slug": "support-assistant",
"ownerId": "admin",
"welcome": null,
"modelId": "00000000-0000-4000-8000-000000000004",
"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",
"icon": null,
"model": {
"naturalId": "go_everyday",
"permissions": {},
"promptPpm": null,
"completionPpm": null,
"cacheReadPpm": null,
"cacheWriteShortPpm": null,
"cacheWriteLongPpm": null,
"id": "00000000-0000-4000-8000-000000000004",
"model": null,
"slug": "go_everyday",
"provider": {
"permissions": {},
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000005",
"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"
}
}
}
}
}
]
}
}
POST /api/assistants/{id}/references
Add a reference from this Assistant to another.
Authentication: AI access (ai.verify)
Pre-blocks: assistant.lookup, permission.assistant.write
Request Body:
The payload is stripUnknown, so unrecognized fields are dropped.
| Field | Type | Required | Description |
|---|---|---|---|
targetId | string | Yes | The id of another Assistant to reference |
There is no targetType or description field. targetId must be a different
Assistant's id: references are Assistant-to-Assistant, and a self-reference
answers 400.
Example Request:
{ "targetId": "00000000-0000-4000-8000-000000000020" }
Response:
Responds 201 Created with a Location header. The body is the raw
AssistantReference row (id, sourceId, targetId, timestamps), not
HAL-shaped.
{
"targetId": "00000000-0000-4000-8000-000000000002"
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/admin%3Asales-assistant/references/00000000-0000-4000-8000-000000000002"
}
},
"id": "00000000-0000-4000-8000-000000000003",
"tenant": "acme",
"sourceId": "00000000-0000-4000-8000-000000000001",
"targetId": "00000000-0000-4000-8000-000000000002",
"updatedAt": "2026-01-15T16:20:00.000Z",
"createdAt": "2026-01-15T16:20:00.000Z"
}
GET /api/assistants/{id}/references/{targetId}
Get a single reference. The {targetId} path param is the referenced
Assistant's id; the row is looked up by sourceId plus targetId.
Authentication: AI access (ai.verify)
Response:
One AssistantReference row.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/assistants/00000000-0000-4000-8000-000000000001/references/00000000-0000-4000-8000-000000000002"
}
},
"items": [
{
"id": "00000000-0000-4000-8000-000000000003",
"sourceId": "00000000-0000-4000-8000-000000000001",
"targetId": "00000000-0000-4000-8000-000000000002",
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme"
}
],
"start": 0,
"count": 1,
"total": 1
}
DELETE /api/assistants/{id}/references/{targetId}
Remove a reference from an Assistant. This is a db.remove against
AssistantReference.
Authentication: AI access (ai.verify)
Pre-blocks: assistant.lookup, permission.assistant.write
Response:
Responds 200 with an empty body (Informer convention), not 204.