---
title: "Edit, draft, or restructure a document using natural language. Preserves tables, styling, and formatting."
method: POST
path: "/v1/chat"
tags: ["v1", "mcp", "chat"]
---

# Edit, draft, or restructure a document using natural language. Preserves tables, styling, and formatting.

`POST /v1/chat`

## Request

- Base URL: `https://api.superdocs.app`
- URL: `https://api.superdocs.app/v1/chat`
- Auth: HTTP bearer

Synchronous AI chat that can rewrite specific paragraphs, add or remove table rows, restructure sections, generate new content from templates, or transform an entire document. Pass document_html only to load or replace the document; once a session holds a document the server persists it across turns, so omit it on follow-up turns. To replace the whole document with EXACT content you already hold, pass that content in document_html (a verbatim load — the AI never re-types it) or upload it via upload_document_base64; describing the content only in `message` makes the AI author it, which can drift from your text. Returns AI response text plus structural document changes (HTML edits, additions, deletions) with chunk IDs. One billable operation per document-modifying turn; very large multi-section edits bill one operation per 25 sections changed. For long-running edits or human-in-the-loop approval, use chat_async. Optional: model_tier (core/turbo/pro/max), thinking_depth (fast/balanced/deep), image_attachments for multimodal vision. RECOMMENDED for AI agents working with large documents (>20 pages): set response_mode='compact' to skip the full HTML in the response (the AI returns only per-section diffs in chunk_diffs) and save thousands of tokens per turn. To read sections in compact mode, just send a natural-language request like 'show me the force majeure section' — the AI returns the content in the reply text. Always use natural language to describe what you want; the AI handles all internal section lookups.

## Headers

- `authorization` string, nullable

## Request body

- UniversalChatRequest: Send a message to the AI assistant with optional document context.
  - `message` string, required: Your message to the AI assistant.
  - `session_id` string, required: Unique session identifier. Reuse to continue a conversation.
  - `document_html` string, nullable: Current document HTML. OMIT this when the session already holds the document — the server persists it across turns, so you don't re-send it every turn; pass it only to load new content or replace the document wholesale (a verbatim load — the AI never re-types content passed here). Include data-chunk-id attributes on elements to enable targeted AI edits.
  - `user_id` string, nullable: User identifier. Automatically set from authentication — typically omit this.
  - `image_attachments` ImageAttachmentData[], nullable: Inline images for vision-based analysis (base64-encoded).
    - `id` string, required: Unique identifier for this image.
    - `name` string, required: Original filename of the image.
    - `base64Data` string, required: Base64-encoded image data.
    - `mimeType` string, required: MIME type (e.g., 'image/png', 'image/jpeg').
    - `size` integer, required: File size in bytes.
  - `model_tier` string, nullable: AI model to use: 'core' (default, fast), 'turbo' (fastest), 'pro' (advanced reasoning), 'max' (most capable).
  - `thinking_depth` string, nullable: Reasoning depth: 'fast', 'balanced' (default), or 'deep'. Controls how much analysis the AI performs.
  - `approval_mode` string, nullable: Change review mode: 'approve_all' (default, auto-applies changes) or 'ask_every_time' (pauses for your review).
  - `response_mode` 'full' | 'compact', nullable: Response shape control. 'full' (default) returns the complete updated document HTML — required by web app editors and recommended for small documents (<20 pages). 'compact' (recommended for AI agents editing large documents) suppresses the full HTML and returns only per-section diffs (chunk_diffs) for changed sections, saving thousands of tokens per turn. To read sections in compact mode, just send a natural-language request like 'show me the force majeure section' — the AI returns the content in the chat reply text.
  - `cursor_context` object, nullable: Editor cursor context at message time, used to default the insert location for new images, diagrams, or sections when the user's prompt doesn't name a position. Shape: {chunk_id: str, pos_in_chunk?: int, text_before?: str, text_after?: str}. Omit when the user typed in chat without focusing the editor first.
  - `document_id` string, nullable: Target a specific open document by id (ids come from /v1/sessions/{session_id}/documents). Omit to target the focused document (default — unchanged single-document behaviour). When set, that document becomes the focus for this turn.
  - `window_id` string, nullable: Optional identifier for the client window (set by the web app) so concurrent edits from two windows of the same chat are merged rather than overwritten. Agents/API may omit.
  - `cross_session_memory` boolean, nullable: When true, the AI carries a private rolling memory of context across THIS account's chats (off by default). Per-request override of your saved Settings default.
  - `cross_session_search` boolean, nullable: When true, the AI may search your PAST chats and documents on demand to reuse prior work and open a found document (off by default). Per-request override of your saved Settings default; never affects the always-on search of the open document.
  - `cross_session_memory_key` string, nullable: Optional per-request id of YOUR end-customer so the cross-session memory note is kept in a separate file per end-customer. Omit for one account-level note (the default / B2C).
  - `cross_session_scope` string[], nullable: Optional list of session ids to restrict cross-session SEARCH to (e.g. one end-customer's sessions). Omit to search all of this account's sessions. Only narrows within the API-key owner; ignored unless cross_session_search is on.
  - `touched_chunk_ids` string[], nullable: Optional list of chunk ids (data-chunk-id values) the user actually edited since the last sync, sent alongside document_html. When present, a chunk NOT in this list whose text is unchanged keeps its stored formatting byte-for-byte even if the client serialized it differently (protects styling from editor round-trip loss). Chunks in the list — and any chunk whose text changed — always take the submitted content. Omit for the default behavior (any differing chunk is treated as an edit).
  - `deleted_part_chunk_ids` string[], nullable: Optional list of chunk ids (data-chunk-id values) of OUT-OF-FLOW part sections (page headers/footers, footnote/endnote bodies, comments) to delete explicitly, sent alongside document_html. Out-of-flow parts absent from document_html are always KEPT — an editor view not containing them is their normal state, never a deletion — so removing one requires naming its id here. Ids that are not stored out-of-flow parts are ignored (in-flow content keeps the default behavior). Omit when deleting nothing.

## Response `200`

Successful Response

- ChatResponse: AI response with optional document changes and usage data.
  - `response` string, required: AI assistant's response text.
  - `session_id` string, required: Session identifier for this conversation.
  - `document_changes` DocumentChanges: Document modifications produced by the AI assistant.
    - `updated_html` string, nullable: Full updated document HTML with data-chunk-id attributes. Apply this to your editor to sync the document. Present in 'full' response mode (default); null in 'compact' mode.
    - `version_id` string, nullable: Document version identifier. Changes on every modification.
    - `changes_summary` string, nullable: Human-readable summary of what was changed.
    - `requires_approval` boolean, nullable: If true, changes need review via the approve endpoint before being applied.
    - `pending_changes` PendingChange[], nullable: Proposed changes awaiting approval. Present when requires_approval is true.
      - `change_id` string, required: Unique identifier for this proposed change.
      - `operation` string, required: Type of change: 'edit', 'create', or 'delete'.
      - `chunk_id` string, nullable: Target document section ID being modified or deleted.
      - `document_id` string, nullable: Identifier of the document (tab) this change applies to — lets multi-document integrators attribute each section diff to the right document.
      - `old_html` string, nullable: Previous HTML content of the section (for updates).
      - `new_html` string, nullable: Proposed new HTML content (for updates and creates).
      - `ai_explanation` string, nullable: AI-generated explanation of why this change was proposed.
    - `changes` object[], nullable: History of individual changes applied during this request.
    - `chunk_diffs` PendingChange[], nullable: Per-section before/after content for changes that were applied this turn. Present in 'compact' response mode (when updated_html is null) so the agent can verify what was modified without paying token cost for the full document. Same shape as pending_changes.
      - `change_id` string, required: Unique identifier for this proposed change.
      - `operation` string, required: Type of change: 'edit', 'create', or 'delete'.
      - `chunk_id` string, nullable: Target document section ID being modified or deleted.
      - `document_id` string, nullable: Identifier of the document (tab) this change applies to — lets multi-document integrators attribute each section diff to the right document.
      - `old_html` string, nullable: Previous HTML content of the section (for updates).
      - `new_html` string, nullable: Proposed new HTML content (for updates and creates).
      - `ai_explanation` string, nullable: AI-generated explanation of why this change was proposed.
    - `concurrent_merges` object[], nullable: Present ONLY when this request's edit collided with a concurrent edit: another session/chat committed a different change to the same section(s) while this request was processing, and the two were merged server-side. One entry per affected document: {document_id, durable_document_id, version, conflicting_sections}. When present, updated_html reflects the merged COMMITTED state — it may differ from the text this response describes; review the affected sections and re-apply anything that was superseded. Absent (null) on every non-conflicting request, including concurrent edits to DIFFERENT sections (those merge cleanly with no data loss and no notice).
  - `usage` UsageInfo: Operation usage data for the current billing cycle.
    - `monthly_used` integer, nullable: Total operations used this billing cycle.
    - `monthly_limit` integer, nullable: Maximum operations allowed per cycle. -1 means unlimited.
    - `monthly_remaining` integer, nullable: Operations remaining this cycle. -1 means unlimited.
    - `was_billable` boolean, nullable: Whether this request counted as a billable operation.
    - `ops_charged` integer, nullable: How many operations this request billed. A large multi-section edit can bill more than one (one per 25 sections edited), so monthly_used can increase by more than 1 between responses.
    - `quota_exhausted` boolean, nullable: True when you have reached your plan's operation limit with no remaining balance — the current request still completes, but further billable requests pause until you upgrade or your billing cycle resets.
    - `subscription_tier` string, nullable: Current subscription tier: 'free', 'plus', 'pro', or 'enterprise'.
    - `bucket_used` string, nullable: Which bucket this operation drew from: 'tier' or 'promo'. Null for non-billable ops.
    - `redemption_id` string, nullable: Redemption grant this op drew from, when bucket_used is 'promo'.
    - `promotions` ActivePromotionInfo[], nullable: User's currently-active promotion grants, ordered by oldest-expiring first.
      - `redemption_id` string, required: Unique identifier for this promotion grant.
      - `name` string, required: Human-friendly promotion name (e.g., 'YC SUS India 2026 cohort').
      - `ops_remaining` integer, required: Operations still available in this promotion bucket.
      - `ops_granted` integer, required: Total operations originally granted by this redemption.
      - `expires_at` string, nullable: ISO 8601 expiry timestamp. Null if the credits never expire.
  - `hint` object, nullable: Advisory guidance for API callers (additive; absent on most responses). Currently: prefer_chat_async_for_large_generations — this turn ran long enough that the same work submitted via POST /v1/chat/async would be safer (no gateway timeout risk) and reports progress.

## Other responses

- `422`: Validation Error

---

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