---
title: "Read conversation messages"
method: GET
path: "/api/apps/{app_id}/chat/full-conversation"
---

# Read conversation messages

`GET /api/apps/{app_id}/chat/full-conversation`

<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Returns the app's AI chat, both the messages sent to the AI and the replies it produced, oldest first.

An assistant message can have empty `content` when the whole turn is carried by tool calls, so treat an empty message as work the AI did rather than an error. Messages with `hidden` set to `true` are internal and do not appear in the app editor, so skip them to reconstruct the transcript shown there.

A tool call whose `status` is `waiting_for_user_input` means the AI has paused and cannot continue until that call is answered. Read its `arguments_string` to see what it is asking to do, then answer it with [Submit tool-call input](/api-reference/submit-tool-call-input) to let the turn continue. A waiting call carries its arguments in full, while a call that is not waiting can carry them cut short. The browser-typing tools are redacted either way, so a call from one of those cannot be reviewed before approving it.

<Warning>The response includes fields beyond the ones documented here. Don't rely on undocumented response fields, as they can change at any time.</Warning>

## Path parameters

- `app_id` string, required — ID of the app whose conversation to read.

## Query parameters

- `limit` integer, nullable — Maximum number of messages to return, counted back from the newest. Omit to return the whole conversation.
- `skip` integer, nullable — Number of messages to skip, counted back from the newest. Combine with `limit` to page back through the conversation. For example, `skip=20` with `limit=20` returns the 20 messages before the 20 most recent.

## Response `200`

Successful Response

- ConversationDetail — A window of messages from an app's AI chat.
  - `id` string, nullable — ID of the conversation.
  - `messages` ConversationMessageSummary[], nullable — The requested window of messages, oldest first.
    - `id` string, nullable — ID of the message.
    - `role` 'user' | 'assistant' | 'system', nullable — Who produced the message. A `user` message is a prompt sent to the AI, an `assistant` message is the AI's reply, and a `system` message is a platform-generated note.
    - `content` string, nullable — Text of the message. Empty on assistant turns whose work is carried entirely by tool calls, and on internal diff messages.
    - `file_urls` string[], nullable — URLs of the files attached to the message, or `null` if it has none.
    - `hidden` boolean, nullable — Whether the message is internal and hidden from the chat in the app editor.
    - `checkpoint_id` string, nullable — ID of the [checkpoint](/developers/references/app-management/get-started/concepts#checkpoints) this message produced, or `null` if it produced none. Pass it as `checkpoint_id` to [Deploy an app](/api-reference/deploy-an-app) to deploy that version.
    - `tool_calls` ConversationToolCallSummary[], nullable — Tool calls the AI made on this message, or `null` on messages that made none. A call with `status` set to `waiting_for_user_input` is holding the turn open until it is answered.
      - `id` string, nullable — ID of the tool call. Pass it as `tool_call_id` to [Submit tool-call input](/api-reference/submit-tool-call-input) when `status` is `waiting_for_user_input`.
      - `name` string, nullable — Name of the tool the AI is calling.
      - `status` 'running' | 'success' | 'error' | 'stopped' | 'waiting_for_user_input', nullable — Where the tool call is. Either `running`, `success`, `error`, `stopped`, or `waiting_for_user_input`. The last one means the turn is paused until the call is answered.
      - `requires_user_input` boolean, nullable — Whether this tool call has to be approved or rejected before the turn can continue.
      - `arguments_string` string, nullable — What the AI asked the tool to do, as a JSON object encoded in a string. Parse it to see the arguments before answering a call that is waiting. On a call whose `requires_user_input` is `true` the value is complete rather than shortened, which is the case that matters, because approving without reading it is approving blind. On any other call it can be cut to the first 500 characters. The one exception either way is the browser-typing tools, `local_browser_type` and `local_browser_press_key`, which always replace what was typed with `[redacted]` so a password or one-time code is never returned, waiting or not. Approving one of those means approving a value you cannot see. It is an empty string on a tool call that takes no arguments.
    - `usage` MessageUsageSummary
      - `prompt_tokens` integer, nullable — Tokens the model read for this message, including the conversation history it was given.
      - `completion_tokens` integer, nullable — Tokens the model generated for this message.
      - `credits_charged` number, nullable — Credits charged for this message, or `null` if it was not billed.
    - `metadata` MessageMetadataSummary
      - `created_date` string, date-time, nullable — Time the message was created, as a UTC timestamp in ISO 8601 format.
      - `created_by_email` string, nullable — Email of the user whose turn produced the message, or `anonymous` on a message Base44 created with no user in context.

## Other responses

- `401` — Missing or invalid credentials.
- `403` — You don't have access to this app.
- `404` — App not found.
- `422` — The `limit` or `skip` is not an integer.

---

[API](https://skmtc.dev/adexad/apis/base44-app-management-api.md) · [All operations](https://skmtc.dev/adexad/apis/base44-app-management-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/adexad/base44-app-management-api/revisions/7f5ce8287501/schema)
