---
title: "List conversation messages"
method: GET
path: "/v1/projects/{project_id}/conversations/{conversation_id}/messages"
tags: ["Conversations"]
---

# List conversation messages

`GET /v1/projects/{project_id}/conversations/{conversation_id}/messages`

## Request

- Base URL: `https://api.naturali.ai`
- URL: `https://api.naturali.ai/v1/projects/{project_id}/conversations/{conversation_id}/messages`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.naturali.ai/authorize`, token URL `https://api.naturali.ai/token`, scopes: `mcp:access`)

Returns all messages (documents) attached to a conversation, ordered by position

## Path parameters

- `conversation_id` string, required

## Query parameters

- `limit` integer
- `offset` integer

## Response `200`

List of messages

- object
  - `data` ConversationMessageRecord[]
    - `document_id` string: Document ID
    - `role` 'user' | 'assistant' | 'system': Role of the message sender
    - `actor_id` string, nullable: Optional actor ID associated with this message
    - `agent_id` string, nullable: Optional agent ID that generated this message (set for assistant messages produced by generate)
    - `position` integer: Zero-based position in the conversation
    - `metadata` MetadataBag: Caller-owned annotations on a resource, stored as the object they were written as: the types a value was written with are the types a read returns, so a filter can ask an ordering question about a number. Unlike other body fields, keys are stored and returned verbatim in the casing supplied — they are not converted between snake_case and camelCase. No key is reserved, and that is the point: every piece of state the platform owns lives in its own typed column, so nothing written here reaches platform state. The platform never reads the bag — it is not an IAM context, not a policy input and not part of a prompt — which is what separates it from a tag bag.
    - `content` string, nullable: Full text content of the message
    - `idempotency_key` string, nullable: The idempotency key the message was posted with, null when none was sent. A channel that posts each inbound message under its provider's message id finds the transcript row for that message by this key.
  - `total` integer
  - `limit` integer
  - `offset` integer

## Other responses

- `401`: Unauthorized
- `403`: Forbidden
- `404`: Conversation not found

---

[API](https://skmtc.dev/naturali/apis/naturali-ai-api.md) · [All operations](https://skmtc.dev/naturali/apis/naturali-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/naturali/apis/naturali-ai-api/revisions/e4905b78f422?raw)
