Skip to main content

Messages

Looking for the product view?
The Help Center explains this surface as users see it: Your chat history.

Endpoints for reading and managing the messages in a chat. These routes are not gated by permission.ai.manage and do not require AI to be enabled on the tenant. Access is owner-scoped: both Chat and Message expose a read_access scope that filters by the requester's username, so a message you do not own resolves as 404.

A message's text lives in parts, a typed-part array (for example { "type": "text", "text": "…" }). There is no content, cost, memoryId text column, or toolUses field. The persisted columns are role, username, chatId, assistantId, parts, liked, annotations, explanation, and memoryId, plus the standard timestamps.

Message properties:

FieldTypeDescription
idstring (UUID)Message id
chatIdstring (UUID)Parent chat id
assistantIdstring (UUID) | nullAssistant that produced the message, when applicable
rolestringuser or assistant
partsarrayTyped message parts (for example { "type": "text", "text": "…" })
likedboolean | nullUser feedback: true, false, or null (no feedback)
annotationsobject | nullMessage annotations
explanationobject | nullGenerated explanation, when present
memoryIdstring | nullAssociated memory id
usernamestringOwning user
createdAt / updatedAtdateTimestamps

GET /api/chats/{id}/messages

List a chat's messages, ordered by createdAt ascending.

Authentication: Required (session)

Pre-blocks: chat.lookup

Response:

The chat's messages as a HAL collection (inf:chat-messages). Each message is serialized with its typed parts; the text of a message lives there, not in a content field.

List a chat’s messagesGET /api/chats/00000000-0000-4000-8000-000000000001/messages
GET /api/chats/{id}/messages returns the chat’s messages as a HAL collection (inf:chat-messages) ordered by createdAt ASC. Each message serializes via toUIMessage(): top-level id/role/parts, with createdAt/updatedAt/liked/memoryId/explanation/files nested under `metadata`. There is no `content`, `cost`, or `toolUses` field — message text lives in `parts` (typed parts such as { type: "text", text: "…" }).
Response · 200
[
{
"permissions": {},
"id": "00000000-0000-4000-8000-000000000002",
"role": "user",
"annotations": null,
"parts": [
{
"text": "What were the Q4 sales figures?",
"type": "text"
}
],
"chatId": "00000000-0000-4000-8000-000000000001",
"assistantId": null,
"username": "admin",
"liked": null,
"explanation": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"memoryId": null
},
{
"permissions": {},
"id": "00000000-0000-4000-8000-000000000003",
"role": "assistant",
"annotations": null,
"parts": [
{
"text": "Q4 sales reached $2.5M across all regions.",
"type": "text"
}
],
"chatId": "00000000-0000-4000-8000-000000000001",
"assistantId": null,
"username": "admin",
"liked": true,
"explanation": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"memoryId": null
},
{
"permissions": {},
"id": "00000000-0000-4000-8000-000000000004",
"role": "user",
"annotations": null,
"parts": [
{
"text": "Disregard that, never mind.",
"type": "text"
}
],
"chatId": "00000000-0000-4000-8000-000000000001",
"assistantId": null,
"username": "admin",
"liked": null,
"explanation": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"memoryId": null
}
]
Captured from the API examples test suite; ids and timestamps are normalized.

DELETE /api/chats/{id}/messages

Clear every message in a chat. The chat itself, including its metadata and settings, is preserved, and the chat is marked stale.

Authentication: Required (session)

Pre-blocks: chat.lookup

Response:

Responds 200 with an empty body (Informer convention via h.response().code(200)), not 204 No Content.

Clear all messages in a chatDELETE /api/chats/00000000-0000-4000-8000-000000000001/messages
DELETE /api/chats/{id}/messages destroys every message in the chat and marks the chat stale (chat metadata and settings are preserved). Responds 200 with an EMPTY body (Informer convention), not 204.
Response · 200 · no body
Captured from the API examples test suite; ids and timestamps are normalized.
Data loss

This operation permanently deletes all messages in the chat. Memories that referenced the deleted messages remain but lose those references.


GET /api/messages/{id}

Retrieve a single message.

Authentication: Required (session)

Pre-blocks: message.lookup

Response:

The message (inf:message), resolved through the Message read_access scope. A message the requester does not own resolves as 404.

Get a single messageGET /api/messages/00000000-0000-4000-8000-000000000001
GET /api/messages/{id} returns one message (inf:message), resolved through the Message read_access scope (owner-scoped by username); a message the requester does not own returns 404.
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/messages/00000000-0000-4000-8000-000000000001"
}
},
"permissions": {},
"id": "00000000-0000-4000-8000-000000000001",
"role": "assistant",
"annotations": null,
"parts": [
{
"text": "Q4 sales reached $2.5M across all regions.",
"type": "text"
}
],
"chatId": "00000000-0000-4000-8000-000000000002",
"assistantId": null,
"username": "admin",
"liked": true,
"explanation": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"memoryId": null
}
Captured from the API examples test suite; ids and timestamps are normalized.

PUT /api/messages/{id}

Update message feedback. The route accepts only liked.

Authentication: Required (session)

Pre-blocks: message.lookup

Request Body:

FieldTypeRequiredDescription
likedboolean | nullYestrue (liked), false (disliked), or null to clear feedback

Example Request:

{ "liked": true }

Response:

Responds 200 with the updated message. Updating invalidates the chat's prompt cache.

Set message feedbackPUT /api/messages/00000000-0000-4000-8000-000000000001
PUT /api/messages/{id} accepts only { liked } — a boolean, or null to clear feedback. Returns the updated message. Updating invalidates the chat’s prompt cache.
Request body
{
"liked": true
}
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/messages/00000000-0000-4000-8000-000000000001"
}
},
"permissions": {},
"id": "00000000-0000-4000-8000-000000000001",
"role": "user",
"annotations": null,
"parts": [
{
"text": "What were the Q4 sales figures?",
"type": "text"
}
],
"chatId": "00000000-0000-4000-8000-000000000002",
"assistantId": null,
"username": "admin",
"liked": true,
"explanation": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"tenant": "acme",
"memoryId": null
}
Captured from the API examples test suite; ids and timestamps are normalized.

DELETE /api/messages/{id}

Delete a single message and invalidate the chat's prompt cache.

Authentication: Required (session)

Pre-blocks: message.lookup

Response:

Responds 200 with an empty body (Informer convention), not 204 No Content. Deleting a message that does not exist, or one the requester does not own, is a no-op that still responds 200.

Delete a single messageDELETE /api/messages/00000000-0000-4000-8000-000000000001
DELETE /api/messages/{id} removes the message and invalidates the chat cache. Responds 200 with an EMPTY body (Informer convention via h.response().code(200)), not 204. Deleting a message that does not exist (or that the requester does not own) is a no-op that still responds 200.
Response · 200 · no body
Captured from the API examples test suite; ids and timestamps are normalized.
Message threading

Deleting a message in the middle of a conversation can affect the context for subsequent AI responses. Consider clearing all messages instead of deleting selectively.