---
title: "Send Data Chat Message"
method: POST
path: "/api/v1/apps/{app_id}/data-chat/{chat_id}/message"
tags: ["apps-data-chat"]
---

# Send Data Chat Message

`POST /api/v1/apps/{app_id}/data-chat/{chat_id}/message`

Send one turn on an existing app-data-chat thread.

Rate-limited at the Ask Netter budget (20/minute) — every request here
buys an agent turn, unlike the four thread routes above.

## Path parameters

- `app_id` string, uuid, required
- `chat_id` string, uuid, required

## Request body

- AppDataChatMessageRequest
  - `content` string, required
  - `page_queries` AppPageQuery[]
    - `sql` string, required
    - `title` string, nullable
  - `focus` AppFocus — What the user highlighted, resolved against the bundle's widget registry. CLIENT-SUPPLIED, GROUNDING ONLY — the same contract as `AppPageQuery` above. `sql` is rendered into the agent's turn as text describing what the widget ran; it is never parsed, never validated as SQL and never handed to an executor. Every statement that actually runs is authored by the agent and passes the guard. Caps mirror the client's own (`buildSelectionFocus` / `toFocus` in DMI_front). They are restated here because the client is not the security boundary — a request need not come from our page.
    - `text` string, required
    - `widget_title` string, nullable
    - `widget_kind` string, nullable
    - `sql` string, nullable
    - `columns` string[]
    - `rows` object[]
    - `cell` AppFocusCell — Where the highlighted value sits in the widget's own result set. Present only when the bundle's runtime VALUE-MATCHED the displayed value to a cell. Its absence is meaningful and is rendered as such: a number the matcher could not find in any recorded query is almost always computed in the app's JavaScript, and that is the signal telling the agent to read the app's code instead of re-querying.
      - `column` string, required
      - `row_index` integer, required
      - `ambiguous` boolean
    - `raw_value` union
      - string
      - integer
      - number
      - boolean
  - `app_version_id` string, uuid, nullable — The app version the client is actually rendering — the previewed draft on the builder page. Absent on the viewer page, where the server falls back to `App.current_version_id`. Validated against this app server-side; a version belonging to another app is ignored, not honoured.
  - `embed_host_app_id` string, uuid, nullable — Set when this app is running as an embedded widget inside another app. Authorization then requires VIEWER on that host plus an active embed binding — see domains/apps/application/embed_access.py.

## Response `200`

Successful Response

- AppDataChatTurnResponse
  - `status` 'generating'

## Other responses

- `422` — Validation Error

## Changes

> 35 revisions in range; 1 not diffed.

- **2026-09-10** `d27876ec4b74` — 1 breaking, 2 info
  - the `page_queries/items/sql` request property's maxLength was decreased to `5000`
  - added the new optional request property `app_version_id`
  - added the new optional request property `focus`
- **2026-09-09** `1d0069006494` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/netter/apis/dmi-backend/changes/api/v1/apps/:app_id/data-chat/:chat_id/message/post.md)

---

[API](https://skmtc.dev/netter/apis/dmi-backend.md) · [All operations](https://skmtc.dev/netter/apis/dmi-backend/llms.txt) · [OpenAPI document](https://skmtc.dev/netter/apis/dmi-backend/revisions/77d4fd215b57?raw)
