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

# Rewrite Content

> Learn how Rewrite content works, when to use it, and how to build the rewrite experience in your application

export const QuickSummary = ({title = "Quick summary", updated, children}) => <div className="quick-summary-wrapper">
    <div className="quick-summary-header">
      <span className="quick-summary-icon" aria-hidden="true" />
      <span className="quick-summary-title">{title}</span>
    </div>
    <div className="quick-summary-content">{children}</div>
    {updated ? <div className="quick-summary-footer">
        <span className="quick-summary-footer-icon" aria-hidden="true" />
        <span className="quick-summary-footer-text">Last updated:</span>
        <span className="quick-summary-footer-date">{updated}</span>
      </div> : null}
  </div>;

<QuickSummary updated="October 2026">
  After a clinician selects text in a chart field or note, call <code>POST /api/v1/content/rewrite</code> with the selected text, surrounding context, and one instruction: <code>CONCISE</code>, <code>VERBOSE</code>, or <code>PATIENT\_FRIENDLY</code>. Use the returned text and selection offsets to replace the selected span in your UI. Keep both <code>selected\_text</code> and <code>surrounding\_content</code> within 5,000 characters each.
</QuickSummary>

<Info>
  **Content Rewrite is supported by:** Dictation APIs, Web SDK, Dictation SDK

  * **Dictation APIs:** You build the rewrite control in your app, call [Rewrite content](/api-reference/content/rewrite), and put the result back in the field. This page walks through that REST call. It is not part of Dictation WebSocket streaming on `/ws/transcribe`. For creating a session, streaming audio, and ending a session first, refer to [Dictation basic usage](/documentation/how-to/dictation/dictation-basic-usage).
  * **Web SDK and Dictation SDK:** You do not build this UI. Content Rewrite is already in the hosted Dictation iframe, so clinicians select text there, choose **Concise**, **Verbose**, or **Patient Friendly**, and your existing `show()` callbacks still get the updated field. Refer to [Content Rewrite](/dictation-sdk/guides/content-rewrite) for that flow.
</Info>

The [Rewrite content](/api-reference/content/rewrite) API lets clinicians rephrase text that is already visible in your application, such as a note, chart field, or scratchpad, without retyping it. Use it when they want that text shorter, more detailed, or easier for a patient to understand. The text can come from a Dictation transcript your application already placed on screen, or from any other plain text your UI manages.

## How it works

* **Select:** The clinician highlights text and chooses **Concise**, **Verbose**, or **Patient Friendly** from the rewrite control UI you built.
* **Call the API:** Your app sends that text (`selected_text`), nearby context (`surrounding_content`), start and end offsets, and the matching `instruction` to the Rewrite content API.
* **Apply the result:** The API returns rewritten text and offsets. You replace only the highlighted text and leave the rest of the text in the field as is.

<Note>
  Suki returns text to your application only. It does not write or save content to your EHR.
</Note>

## Common use cases

Content rewrite helps providers shorten long dictation, expand brief wording, or turn clinical terminology into clearer patient-friendly phrasing.

<CardGroup cols={2}>
  <Card title="Shorten Long Dictation" icon="compress">
    The provider selects text and chooses **Concise**. Call rewrite with **`CONCISE`**. The API returns a shorter version that can replace the selected text.
  </Card>

  <Card title="Expand Short Notes" icon="expand">
    The provider selects short wording and chooses **Verbose**. Call rewrite with **`VERBOSE`**. The API expands the text without adding new facts.
  </Card>

  <Card title="Write for Patients" icon="user">
    The provider selects clinical wording and chooses **Patient Friendly**. Call rewrite with **`PATIENT_FRIENDLY`**. The API rewrites jargon in plain language while keeping clinical meaning.
  </Card>

  <Card title="Rewrite After Dictation" icon="microphone">
    After Dictation inserts transcript text into a chart field or scratchpad, let the provider select and rewrite part of the text instead of retyping it or starting another Dictation session.
  </Card>

  <Card title="Rewrite an Ambient Note" icon="file-lines">
    When ambient generates a note and the provider needs clearer wording in a section, let them select that span and rewrite it without leaving note review.
  </Card>

  <Card title="Rewrite Text You Already Have" icon="share-nodes">
    Use the same rewrite call on plain text your application already manages, even when that text did not come from a Dictation session.
  </Card>
</CardGroup>

<Note>
  Free-form custom instructions are not supported today. The API accepts only **`CONCISE`**, **`VERBOSE`**, and **`PATIENT_FRIENDLY`**. A future release may accept a free-text `instruction` on the same endpoint.
</Note>

### What you need to build

Your application is responsible for the user experience around content rewrite. You need to build:

* Text selection in a chart field, note, or scratchpad
* Rewrite control mapped to **`CONCISE`**, **`VERBOSE`**, or **`PATIENT_FRIENDLY`**
* Context window and offset logic (up to **5,000** characters each)
* Preview or apply step that replaces only the highlighted text
* Save path through your existing EHR or application workflow

## Prerequisites

Before you start, register the provider and get an **`sdp_suki_token`**. Refer to [Provider authentication](/api-reference/provider-authentication) and [Partner authentication](/documentation/how-to/partner-authentication) for more information.

## Build the rewrite experience

Add a rewrite control next to editable text in your chart field, note, or scratchpad. Suki rewrites only the text you send in the request. Your app handles selection, calling the API, updating the field, and saving.

In practice:

* Capture the clinician's highlighted text and its offsets in the context window you will send.
* Map your UI labels (**Concise**, **Verbose**, **Patient Friendly**) to **`CONCISE`**, **`VERBOSE`**, and **`PATIENT_FRIENDLY`**.
* On success, replace that highlighted text with the returned `content` using the returned offsets. Do not auto-write to the EHR.
* Let the clinician review, then save through your existing EHR or app workflow.

### UI and application responsibilities

| UI element | Clinician action | Your application responsibility |
| :- | :- | :- |
| **Selection** | Highlights text to reshape | Capture `selected_text` and Unicode code-point offsets relative to the context window you send |
| **Rewrite control** | Chooses Concise, Verbose, or Patient Friendly | Call [Rewrite content](/api-reference/content/rewrite) with the matching `instruction` value |
| **Preview / apply** | Reviews and accepts the rewrite | Replace the span using the returned `selection` and `content`. Do not write back automatically |
| **Save** | Saves the updated field | Persist the updated content through your existing EHR or application workflow |

The workflow is:

```mermaid actions={false} theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#FFF394','primaryTextColor':'#111827','primaryBorderColor':'#FFE148','lineColor':'#FFE148','secondaryColor':'#FFF394','tertiaryColor':'#FFFADE','mainBkg':'#FFF394','secondBkg':'#FFFADE','tertiaryBorderColor':'#FFE148','border1':'#FFE148','border2':'#FFE148','arrowheadColor':'#FFE148','fontFamily':'Inter, system-ui, sans-serif','fontSize':'14px','nodeBorder':'#FFE148','edgeLabelBackground':'#FFE148','clusterBkg':'#FFFADE','clusterBorder':'#FFE148','defaultLinkColor':'#FFE148','titleColor':'#111827','nodeTextColor':'#111827'}}}%%
flowchart LR
    A["Select text<br/>in the field"] --> B["Choose Concise,<br/>Verbose, or<br/>Patient Friendly"]
    B --> C["Call rewrite"]
    C --> D["Replace span<br/>in your UI"]
    D --> E["Review and save"]

    style A fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style B fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style C fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style D fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style E fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
```

## Call the Rewrite content API

Content rewrite is a **single synchronous REST call** after you already have plain text in your UI.

1. Capture the selected text and a surrounding context window.
2. Call [Rewrite content](/api-reference/content/rewrite) with one instruction.
3. Replace the returned span in your UI, then let the clinician review and save.

Call <Badge color="blue" size="sm">POST</Badge> [Rewrite content](/api-reference/content/rewrite) API:

### Example request

```bash theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
curl --request POST \
  --url https://sdp.suki.ai/api/v1/content/rewrite \
  --header 'Content-Type: application/json' \
  --header 'sdp_suki_token: <sdp_suki_token>' \
  --header 'sdp_provider_id: <sdp_provider_id>' \
  --data '{
    "context": {
      "selection": {
        "start": 16,
        "end": 57
      },
      "surrounding_content": "Patient reports mild intermittent headache for three days."
    },
    "instruction": "CONCISE",
    "selected_text": "mild intermittent headache for three days"
  }'
```

### Example response

```json theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
{
  "content": "mild headache for 3 days",
  "request_id": "trace-123",
  "selection": {
    "start": 16,
    "end": 57
  }
}
```

The API returns **`200 OK`** when the rewrite succeeds.

### Request details

Include **`sdp_suki_token`** on every request. For single-auth partners, also send **`sdp_provider_id`**.

Send the following on every request:

* **`selected_text`**
* **`instruction`**
* **`context.selection`**
* **`context.surrounding_content`**

<Note>
  Always send **`context.surrounding_content`** so the model has enough local context. `selected_text` must be a subset of that string.
</Note>

Selection offsets use <Tooltip tip="A Unicode code point is one unit in the Unicode character set. Count limits and selection offsets use code points, not bytes or UTF-16 code units. For plain English text, the code-point count usually matches the character count.">**Unicode code points**</Tooltip> and represent a <Tooltip tip="A half-open range includes the start index and excludes the end index. For example, [16, 57) covers code points 16 through 56. Use start and end this way so the selected span length is end minus start.">**half-open range**</Tooltip>, **`[start, end)`**, relative to `surrounding_content`.

### Request fields

| Field | Required | Description |
| :- | :- | :- |
| **`selected_text`** | Yes | Exact text to rewrite. Must be a subset of `surrounding_content`. Length: **1 to 5,000** Unicode code points |
| **`instruction`** | Yes | One of `CONCISE`, `VERBOSE`, or `PATIENT_FRIENDLY` |
| **`context.surrounding_content`** | Strongly recommended | Context window that includes the selection. Maximum **5,000** Unicode code points. OpenAPI marks this field optional, but send it for a reliable rewrite |
| **`context.selection.start`** | Yes | Inclusive start offset in Unicode code points relative to `surrounding_content` |
| **`context.selection.end`** | Yes | Exclusive end offset in Unicode code points relative to `surrounding_content` |

<Warning>
  `instruction` must be exactly **`CONCISE`**, **`VERBOSE`**, or **`PATIENT_FRIENDLY`**. Do not send lowercase labels such as `concise`, spaced labels such as `patient friendly`, or free-form custom instructions. Free-form instructions are not supported.
</Warning>

<Note>
  Rewrites change phrasing, structure, or level of detail. They must not invent, remove, or change clinical facts such as diagnoses, medications, labs, or numbers.
</Note>

### Response details

| Field | Description |
| :- | :- |
| **`content`** | Rewritten replacement for `selected_text` |
| **`selection.start` / `selection.end`** | Echoed offsets so your UI replaces the correct span |
| **`request_id`** | Correlation ID for support |

<Tip>
  Store `request_id` with any support ticket about a rewrite result. It helps Technical Support trace the request end to end.
</Tip>

## Build the context window

A rewrite request uses two pieces of text from the same field: `selected_text`, which is the text the clinician selected, and `surrounding_content`, which is the nearby text the model needs to understand that selection in context.
Both can contain up to **5,000 characters**. If either field exceeds this limit, the request fails. The `selection.start` and `selection.end` offsets must point to the selected text within the `surrounding_content` you send.

```mermaid actions={false} theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#FFF394','primaryTextColor':'#111827','primaryBorderColor':'#FFE148','lineColor':'#FFE148','secondaryColor':'#FFF394','tertiaryColor':'#FFFADE','mainBkg':'#FFF394','secondBkg':'#FFFADE','tertiaryBorderColor':'#FFE148','border1':'#FFE148','border2':'#FFE148','arrowheadColor':'#FFE148','fontFamily':'Inter, system-ui, sans-serif','fontSize':'14px','nodeBorder':'#FFE148','edgeLabelBackground':'#FFE148','clusterBkg':'#FFFADE','clusterBorder':'#FFE148','defaultLinkColor':'#FFE148','titleColor':'#111827','nodeTextColor':'#111827'}}}%%
flowchart TB
    subgraph short["Field is 5,000 characters or less"]
        direction LR
        SBefore["Text before"] --> SSel["selected_text"] --> SAfter["Text after"]
    end

    short --> SOut["surrounding_content = entire field<br/>offsets point into that string"]

    subgraph long["Field is longer than 5,000 characters"]
        direction LR
        LOmit1["Not sent"] --> LBefore["Text before"] --> LSel["selected_text"] --> LAfter["Text after"] --> LOmit2["Not sent"]
    end

    long --> LOut["surrounding_content = window ≤ 5,000 characters<br/>offsets point into the window only"]

    style SBefore fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style SSel fill:#FFE148,stroke:#E5C200,stroke-width:2px,color:#111827
    style SAfter fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style SOut fill:#FFFADE,stroke:#FFE148,stroke-width:2px,color:#111827
    style LOmit1 fill:#F3F4F6,stroke:#D1D5DB,stroke-width:2px,color:#6B7280
    style LBefore fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style LSel fill:#FFE148,stroke:#E5C200,stroke-width:2px,color:#111827
    style LAfter fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style LOmit2 fill:#F3F4F6,stroke:#D1D5DB,stroke-width:2px,color:#6B7280
    style LOut fill:#FFFADE,stroke:#FFE148,stroke-width:2px,color:#111827
```

### When the field is 5,000 characters or less

If the field is **5,000 characters or less**, send the entire field as `surrounding_content` and set the selection offsets to the position of the highlighted text in that string.

### When the field is longer than 5,000 characters

If the field is longer than **5,000 characters**, send only a portion that still contains the selection. Include enough text before and after the selection to keep useful context, stay within the limit, and when possible keep the selection near the middle of that portion. Set `selection.start` and `selection.end` against the `surrounding_content` you send, not against the original full field.

<Tip>
  When possible, keep the selection near the middle of the context window so the model sees enough text on both sides without sending an oversized payload.
</Tip>

## Rewrite workflow

A typical rewrite workflow is:

<Steps>
  <Step title="Authenticate">
    Obtain an **`sdp_suki_token`** for the provider.
  </Step>

  <Step title="Capture the Selection">
    Let the clinician highlight text in a chart field or note. Capture `selected_text`, surrounding context, and Unicode selection offsets.
  </Step>

  <Step title="Call Rewrite Content">
    Call [Rewrite content](/api-reference/content/rewrite) with one instruction: **`CONCISE`**, **`VERBOSE`**, or **`PATIENT_FRIENDLY`**.
  </Step>

  <Step title="Replace the Span">
    Use the response `content` and `selection` to replace the highlighted span in the same context window you sent. Keep the rest of the field unchanged.
  </Step>

  <Step title="Confirm and Save">
    Keep the original text available until the clinician accepts the rewrite. Then save through your existing EHR or application workflow.
  </Step>
</Steps>

## Example code

<div className="doc-guide-btn-row">
  <a href="/api-reference/content/rewrite" className="doc-guide-btn">
    Rewrite Content API
  </a>
</div>

**Language tabs (agents):** Equivalent code samples are available in TypeScript and Python. Humans see one language at a time. Use the variant that matches the user's stack. The behavior is the same across tabs.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
    const response = await fetch("https://sdp.suki.ai/api/v1/content/rewrite", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        sdp_suki_token: sdpSukiToken,
        sdp_provider_id: sdpProviderId,
      },
      body: JSON.stringify({
        context: {
          selection: {
            start: 16,
            end: 57,
          },
          surrounding_content:
            "Patient reports mild intermittent headache for three days.",
        },
        instruction: "CONCISE", // Exact enum values only: CONCISE, VERBOSE, or PATIENT_FRIENDLY.
        selected_text: "mild intermittent headache for three days",
      }),
    });

    if (!response.ok) {
      throw new Error(`Rewrite content failed: ${response.status}`);
    }

    const result = await response.json();

    // result.content — replacement text
    // result.selection — offsets for write-back
    // result.request_id — share with Technical Support if needed
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
    import requests

    response = requests.post(
        "https://sdp.suki.ai/api/v1/content/rewrite",
        headers={
            "Content-Type": "application/json",
            "sdp_suki_token": sdp_suki_token,
            "sdp_provider_id": sdp_provider_id,
        },
        json={
            "context": {
                "selection": {
                    "start": 16,
                    "end": 57,
                },
                "surrounding_content": (
                    "Patient reports mild intermittent headache for three days."
                ),
            },
            "instruction": "CONCISE",  # Exact enum values only: CONCISE, VERBOSE, or PATIENT_FRIENDLY.
            "selected_text": "mild intermittent headache for three days",
        },
    )

    response.raise_for_status()

    result = response.json()

    # result["content"] — replacement text
    # result["selection"] — offsets for write-back
    # result["request_id"] — share with Technical Support if needed
    ```
  </Tab>
</Tabs>

## Handle rewrite failures

Rewrite should not block clinical documentation. If the request fails, keep the original selection on screen and keep chart save available. Match the error id on [Ambient and Dictation error messages](/api-reference/error-messages#content-rewrite) when you debug.

| Status | Error id (examples) | When it happens | What to do |
| :- | :- | :- | :- |
| **`400`** | `invalid_rewrite_content_request`, `provider_user_inactive`, missing or invalid `sdp_provider_id` | Validation failed (instruction, selection offsets, required `context`, or length limits), or the provider user is not active | Fix the request. Show a clear error on the rewrite control only |
| **`401`** | `invalid_sdp_token`, `provider_not_registered` | Missing, expired, or invalid Suki Token, or other single-auth identity failure | Refresh authentication, then retry |
| **`403`** | `content_rewrite_not_enabled`, `permission_denied`, partner claim failures | Rewrite is not enabled, or the authenticated user cannot access rewrite | Check entitlements with [Suki Technical Support](mailto:support@suki.ai). Keep `request_id` when present |
| **`500`** | `failed_to_get_enable_content_rewrite_config`, `failed_to_get_user_specialty` | Unexpected server or config error | Retry quietly. Keep `request_id` for support |

For step-by-step fixes, refer to [Content rewrite returns 400, 403, or 500](/documentation/troubleshooting/content-rewrite-fails).

<Steps>
  <Step title="Keep the Original Text">
    Do not clear or replace the selection if rewrite fails. Leave the clinician on the same field or note.
  </Step>

  <Step title="Keep Save Available">
    Do not disable EHR or chart save because rewrite failed.
  </Step>

  <Step title="Offer a Quiet Retry">
    Let the clinician retry from the rewrite control only. Store `request_id` when you open a support ticket.
  </Step>
</Steps>

<Note>
  **Implementation checklist:**

  * Send `selected_text`, `instruction`, `context.selection`, and `surrounding_content`.
  * Use the exact instruction values: **`CONCISE`**, **`VERBOSE`**, or **`PATIENT_FRIENDLY`**.
  * Keep both text fields within **5,000** characters each (`selected_text` must also be at least 1 character). See [`invalid_rewrite_content_request`](/api-reference/error-messages#content-rewrite).
  * Preview or confirm before writing the replacement back.
  * Never block Approve / Save when rewrite fails.
</Note>

These cases come from the warnings and rules on this page.

| Problem | What to do |
| :- | :- |
| Invalid `instruction` value | `instruction` must be exactly **`CONCISE`**, **`VERBOSE`**, or **`PATIENT_FRIENDLY`**. Do not send lowercase labels, spaced labels, or free-form instructions. |
| Rewrite fails | Do not clear or replace the selection if rewrite fails. Never block Approve / Save when rewrite fails. |

## Next steps

<Icon icon="file-lines" iconType="solid" /> **[Rewrite content](/api-reference/content/rewrite)** - Request fields, limits, and examples.

<Icon icon="file-lines" iconType="solid" /> **[Ambient and Dictation error messages](/api-reference/error-messages#content-rewrite)** - Rewrite error ids and HTTP mappings.

<Icon icon="file-lines" iconType="solid" /> **[Content rewrite returns 400, 403, or 500](/documentation/troubleshooting/content-rewrite-fails)** - Fix validation, entitlement, and auth failures.

<Icon icon="file-lines" iconType="solid" /> **[Dictation basic usage](/documentation/how-to/dictation/dictation-basic-usage)** - Create a session, stream audio, and end the session before rewrite.

<Icon icon="file-lines" iconType="solid" /> **[Content Rewrite](/dictation-sdk/guides/content-rewrite)** - Hosted iframe flow for Web SDK and Dictation SDK.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.