---
title: "Send chat message"
method: POST
path: "/api/apps/{app_id}/chat/message"
---

# Send chat message

`POST /api/apps/{app_id}/chat/message`

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

Sends a message to the app's AI builder and runs the turn it starts. This is how you build an app after creating it.

The request stays open until the builder finishes the whole turn, so it can take several minutes on a large change. The response is the app once the turn settles, with the messages it produced under `conversation.messages`. Read the newest `assistant` message for the builder's reply, and `status.state` to see how the turn ended. Each turn consumes credits.

<Warning>A turn that fails still returns `200`. Check `status.state`: `error` means the turn failed, and `status.error_source` says where. `paywall` there means you ran out of credits and no work was done.</Warning>

<Note>If the builder is already busy with an earlier message, this app may queue yours instead of running it now. The response is then `{"queued": true}` with the queue's state, and it carries none of the fields below. Check for `queued` before reading the app.</Note>

<Warning>The response includes fields beyond the ones documented here. Don't rely on undocumented response fields, as they can change at any time. Send only the fields documented here. Other request fields are not supported and their behavior can change.</Warning>

## Path parameters

- `app_id` string, required — ID of the app whose builder chat this request acts on.

## Request body

- object
  - `content` string, required — What you want the AI builder to do. Up to 100,000 characters.
  - `file_urls` string[] — URLs of files to attach to the message, such as a screenshot or a mockup for the builder to work from.

## Response `200`

The app once the turn finished, or the queue state if the message was queued.

- ChatTurnResponse — The app document the chat endpoints return once a turn settles. The real payload is the whole app document, so this is a strict subset: the fields a caller needs to see what the turn did and whether it succeeded.
  - `id` string, nullable — ID of the app.
  - `name` string, nullable — Display name of the app.
  - `status` AppStatusResponse
    - `state` 'ready' | 'processing' | 'error', required — Where the app is in its build lifecycle. Ready means idle with no build in progress, processing means the app is being generated or modified, and error means the last build failed. This tracks building, not publishing.
    - `details` string, nullable — Human readable note about the current state, such as what is being processed or why it failed, or `null` when there is nothing to report.
    - `request_id` string, nullable — ID of the request that last changed the status, or `null` if the status has never changed. Useful when reporting an issue.
    - `last_updated_date` string, date-time, nullable — Time the status was last updated.
    - `error_source` string, nullable — Where the failure originated when the state is error, or `null` otherwise.
    - `paywall_context` PaywallStatusContextResponse
      - `billing_organization_id` string, required — ID of the billing organization the paywall was evaluated against.
      - `user_id` string, required — ID of the user the paywall was evaluated for.
      - `evaluated_at` string, date-time, required — Time the paywall condition was evaluated.
  - `conversation` ChatTurnConversation
    - `id` string, nullable — ID of the conversation.
    - `messages` ConversationMessageSummary[], nullable — The conversation's messages once the request finished, oldest first.
      - `id` string, nullable — ID of the message.
      - `role` 'user' | 'assistant' | 'system', nullable — Who produced the message. `user` is a prompt sent to the AI builder, `assistant` is the builder's reply, and `system` 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/overview#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 builder 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 you answer it.
        - `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 builder is calling.
        - `status` 'running' | 'success' | 'error' | 'stopped' | 'waiting_for_user_input', nullable — Where the tool call is. `waiting_for_user_input` means the turn is paused until you answer it.
        - `requires_user_input` boolean, nullable — Whether this tool call needs you to approve or reject it before the turn can continue.
      - `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.
        - `created_by_email` string, nullable — Email of the user whose turn produced the message.

## Other responses

- `400` — `content` is missing or longer than 100,000 characters.
- `401` — Missing or invalid credentials.
- `403` — You don't have access to this app.
- `404` — App not found.
- `409` — The app is busy with another operation that blocks new messages.
- `422` — Validation Error
- `503` — The server is shutting down or the app's queue is unavailable. Retry the request.

---

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