> ## Documentation Index
> Fetch the complete documentation index at: https://chatbase.co/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Conversations & History

> Manage conversations, load message history, and navigate paginated results with the Chatbase Android SDK.

## Starting and Continuing Conversations

<Steps>
  <Step title="Send a message">
    Send a message to start a new conversation. The SDK creates one automatically if no `conversationId` is provided.

    ```kotlin theme={null}
    val response = client.sendMessage("Hello!")
    ```
  </Step>

  <Step title="Get the conversation ID">
    The conversation ID is returned in the response metadata:

    ```kotlin theme={null}
    val conversationId = response.metadata.conversationId
    ```
  </Step>

  <Step title="Continue the conversation">
    Pass the `conversationId` to subsequent calls:

    ```kotlin theme={null}
    val followUp = client.sendMessage(
        message = "Tell me more",
        conversationId = conversationId
    )
    ```
  </Step>
</Steps>

<Tip>
  The SDK automatically tracks the current conversation ID. After your first `sendMessage`, subsequent calls without an explicit `conversationId` reuse the same conversation:

  ```kotlin theme={null}
  client.sendMessage("First message")             // starts a new conversation
  client.sendMessage("Follow-up")                 // continues the same conversation
  println(client.currentConversationId)            // "conv_abc123"
  ```
</Tip>

## newConversation

`interface ChatbaseClient` — **Package:** `com.chatbase.sdk`

```kotlin theme={null}
fun newConversation()
```

Clear the current conversation ID so the next `sendMessage` starts a new conversation.

```kotlin theme={null}
client.newConversation()
client.sendMessage("Brand new conversation!")
```

## listConversations

```kotlin theme={null}
suspend fun listConversations(
    cursor: String? = null,
    limit: Int? = null
): Page<Conversation>
```

Retrieve a paginated list of conversations.

<ParamField body="cursor" type="String?">
  Opaque cursor from a previous response. Omit to start from the beginning.
</ParamField>

<ParamField body="limit" type="Int?">
  Number of items per page, between 1 and 100. Defaults to 20.
</ParamField>

```kotlin theme={null}
val page = client.listConversations(limit = 20)

page.data.forEach { conversation ->
    println("${conversation.id} — ${conversation.title}")
    println("  Status: ${conversation.status}")
}

println("Total: ${page.total}")
println("Has more: ${page.hasMore}")
```

### Conversation

`data class Conversation` — **Package:** `com.chatbase.sdk.model`

```kotlin theme={null}
data class Conversation(
    val id: String,
    val title: String?,
    val createdAt: Long,
    val updatedAt: Long,
    val userId: String?,
    val status: ConversationStatus
)
```

<ResponseField name="id" type="String" required>
  Unique conversation ID.
</ResponseField>

<ResponseField name="title" type="String?">
  Auto-generated or server-assigned title.
</ResponseField>

<ResponseField name="createdAt" type="Long" required>
  Creation timestamp (Unix epoch seconds).
</ResponseField>

<ResponseField name="updatedAt" type="Long" required>
  Timestamp of the last message (Unix epoch seconds).
</ResponseField>

<ResponseField name="userId" type="String?">
  The identified user who owns this conversation, or `null` for anonymous (device-scoped) conversations.
</ResponseField>

<ResponseField name="status" type="ConversationStatus" required>
  `ONGOING`, `ENDED`, or `TAKEN_OVER`.
</ResponseField>

## listMessages

```kotlin theme={null}
suspend fun listMessages(
    conversationId: String,
    cursor: String? = null,
    limit: Int? = null
): Page<Message>
```

Retrieve messages in a conversation.

<ParamField body="conversationId" type="String" required>
  The conversation to fetch messages from.
</ParamField>

<ParamField body="cursor" type="String?">
  Opaque cursor from a previous response. Omit to start from the newest messages.
</ParamField>

<ParamField body="limit" type="Int?">
  Number of items per page, between 1 and 100. Defaults to 20.
</ParamField>

<Note>
  Messages are returned in **reverse chronological order** — the first page contains the most recent messages. Within each page, messages are ordered oldest to newest.
</Note>

```kotlin theme={null}
val page = client.listMessages(conversationId, limit = 50)

page.data.forEach { message ->
    val role = if (message.role == Role.USER) "You" else "Agent"
    val text = message.parts
        .filterIsInstance<Part.Text>()
        .joinToString("") { it.text }
    println("$role: $text")
}
```

### Message

`data class Message` — **Package:** `com.chatbase.sdk.model`

```kotlin theme={null}
data class Message(
    val id: String,
    val role: Role,
    val parts: List<Part>,
    val createdAt: Long?,
    val feedback: Feedback?,
    val metadata: MessageMetadata?
)
```

<ResponseField name="id" type="String" required>
  Unique message ID.
</ResponseField>

<ResponseField name="role" type="Role" required>
  `USER` or `ASSISTANT`.
</ResponseField>

<ResponseField name="parts" type="List<Part>" required>
  Message content parts (text, tool calls, tool results).
</ResponseField>

<ResponseField name="createdAt" type="Long?">
  Creation timestamp (Unix epoch seconds). Absent on some older messages.
</ResponseField>

<ResponseField name="feedback" type="Feedback?">
  `POSITIVE`, `NEGATIVE`, or `null`.
</ResponseField>

<ResponseField name="metadata" type="MessageMetadata?">
  <Expandable title="properties">
    <ResponseField name="score" type="Double?">
      Confidence/relevance score.
    </ResponseField>
  </Expandable>
</ResponseField>

## Pagination

`data class Page<T>` — **Package:** `com.chatbase.sdk.model`

All list methods return a `Page<T>` with built-in pagination support.

```kotlin theme={null}
data class Page<T>(
    val data: List<T>,
    val cursor: String?,
    val hasMore: Boolean,
    val total: Int
)
```

<ResponseField name="data" type="List<T>" required>
  Items on this page.
</ResponseField>

<ResponseField name="cursor" type="String?">
  Cursor for the next page. `null` if no more pages.
</ResponseField>

<ResponseField name="hasMore" type="Boolean" required>
  Whether more pages exist.
</ResponseField>

<ResponseField name="total" type="Int" required>
  Total item count across all pages.
</ResponseField>

```kotlin theme={null}
val canLoadMore: Boolean
```

`true` if `hasMore` is true and `cursor` is non-null.

```kotlin theme={null}
suspend fun loadMore(): Page<T>?
```

Load the next page. Returns a new `Page` with the older items prepended to the existing `data`, so you always have the full accumulated list. Returns `null` if there are no more pages.

### Paginating Through All Results

```kotlin theme={null}
var page = client.listConversations(limit = 20)

while (true) {
    page.data.forEach { conversation ->
        println(conversation.title)
    }

    if (!page.canLoadMore) break
    page = page.loadMore() ?: break
}
```

## Related

<CardGroup cols={2}>
  <Card title="Streaming" icon="wave-pulse" href="/docs/android-sdk/streaming">
    Send messages and stream responses
  </Card>

  <Card title="User Identity" icon="user" href="/docs/android-sdk/user-identity">
    Scope conversations to users
  </Card>
</CardGroup>
