> ## 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.

# Form Filling SDK Session Workflow

> How Form filling sessions start, run, and deliver structured data to your application

<div className="quick-summary-wrapper">
  <div className="quick-summary-header">
    <span className="quick-summary-icon" aria-hidden="true" />

    <span className="quick-summary-title">Quick summary</span>
  </div>

  <div className="quick-summary-content">
    When you call `start()` or render `<FormFilling>`, the SDK opens Suki's hosted UI in your page. The clinician fills forms by voice, then submits for processing. Pass one value in `form_template_ids` to skip form selection; pass more than one to show the selection screen first.

    <br />

    <br />

    Structured results arrive in your app through `onSubmit` after processing completes. For production, also register a partner webhook so your server receives the same data even if the clinician closes the browser early.
  </div>

  <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">July 2026</span>
  </div>
</div>

When you call **`client.start()`** or render **`<FormFilling>`**, the SDK opens Suki's <Tooltip tip="Suki-controlled UI loaded inside your web page for Form filling or Dictation." cta="View in Glossary" href="/Glossary/h">hosted iframe</Tooltip> in your page. The clinician completes the session there by voice. After processing, structured JSON arrives in your app through **`onSubmit`** and on your server through your [Partner webhook](/documentation/webhook/overview).

Create **`SukiAuthManager`** and <Tooltip tip="Main class in the Form filling SDK that opens Form filling sessions in your page." cta="View in Glossary" href="/Glossary/f">**`FormFillingClient`**</Tooltip> once per page. Open Form filling only when the clinician is ready.

## How a session works

<Steps>
  <Step title="The Iframe Loads">
    The hosted UI loads inside your container on your web page.
  </Step>

  <Step title="The Clinician Selects Forms (Multi-Form Only)">
    If you passed more than **one** `template_id` in `form_template_ids`, the clinician sees a selection screen. All forms start checked. They confirm which forms to fill, then start recording.

    If you passed **only one** `template_id`, this step is skipped. Recording starts right away.
  </Step>

  <Step title="The Clinician Records and Submits">
    The clinician speaks to fill the selected forms. They can pause, resume, cancel, or submit.

    If they cancel, your app receives **`onCancel`** and **`form-filling:cancelled`**. No structured data is returned.

    If they tap **Close** during recording, a confirmation appears. **Resume Session** returns to recording. **Cancel Session** ends the session with no results.
  </Step>

  <Step title="Suki Processes the Session">
    Submit does not return structured data immediately. Suki processes the recording first. The hosted UI shows a processing screen.

    When structured data is ready, **`onSubmit`** runs and your app receives a **`FormFillingResult`**. Refer to [Payload shape](/form-filling-sdk/guides/callbacks#formfillingresult-payload-shape) to learn more about what it returns.
  </Step>
</Steps>

<Note>
  Before the iframe opens, **`FormFillingClient.start()`** validates **`form_template_ids`**. Unsupported IDs are dropped. If none remain, the SDK emits **`SUKI_FF_001`** and does not open the UI.
</Note>

## Single-form session

<span id="single-form-session" />

A **single-form session** starts Form filling with **one** `template_id` in **`form_template_ids`**. Suki opens the hosted UI and the clinician goes **straight to recording**. There is no form selection screen.

Use this pattern when your app already knows which template the clinician needs, for example a vitals assessment, a skin check, or another fixed form tied to a workflow step in your UI.

**What it lets you do**

* **Skip selection:** The clinician does not pick forms from a list. Recording starts as soon as the iframe loads.
* **Focused workflow:** One session maps to one Medical form template. Your **`onSubmit`** handler receives structured data for that template in **`structured_data.generated_values`**.
* **Faster path:** Fewer steps between opening Form filling and speaking, which suits repeat tasks during a shift.
* **Same callbacks and webhook flow:** Pass **`correlation_id`**, handle **`onSubmit`**, and register a [Partner webhook](/documentation/webhook/overview) the same way as a multi-form session.

The hosted UI shows the **form name** and a **recording banner** so the clinician knows which form they are filling.

Below is an example of how to start a single-form session with one **`template_id`** in **`form_template_ids`**:

```jsx React theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{isFormOpen && (
  <FormFilling
    form_template_ids={["YOUR_TEMPLATE_ID"]}
    correlation_id={encounterId}
    onSubmit={(result) => {
      handleResult(result);
      setIsFormOpen(false);
    }}
    onCancel={() => setIsFormOpen(false)}
  />
)}
```

## Multi-form session

<span id="multi-form-session" />

A **multi-form session** starts Form filling with **two or more** `template_id` values in **`form_template_ids`**. Suki opens the hosted UI on a **selection screen** first. The clinician confirms which forms to fill, then starts recording.

Use this pattern when one visit or workflow may need **several** Medical form templates, and the clinician should choose which ones apply this time. For example, a head-to-toe assessment where vitals, skin, and neurological forms might all be relevant, but not every form is needed on every round.

**What it lets you do**

* **Offer a form menu:** Pass every template your workflow supports. The clinician picks the subset for this session instead of you hard-coding one form per launch.
* **One recording, multiple forms:** The clinician can fill more than one selected form in a single session. **`onSubmit`** may return multiple entries in **`structured_data.generated_values`**, one per completed form.
* **Change selection during the session:** All forms start selected. The clinician can add or remove forms before or during recording. At least one form must stay selected; when only one remains, they cannot deselect it.
* **Route results per template:** Loop over **`generated_values`** and map each item to the right EHR section using **`form_template_id`** and **`type`**.
* **Same callbacks and webhook flow:** Pass **`correlation_id`**, handle **`onSubmit`**, and register a [Partner webhook](/documentation/webhook/overview) the same way as a single-form session.

Below is an example of how to start a multi-form session with several **`template_id`** values in **`form_template_ids`**:

```jsx React theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
<FormFilling
  form_template_ids={["template-a", "template-b", "template-c"]}
  correlation_id={encounterId}
  onSubmit={(result) => {
    for (const form of result.structured_data.generated_values) {
      routeToEhrSection(form);
    }
  }}
/>
```

## Submit and processing

<span id="get-structured-data" />

When the clinician taps **submit**, the hosted UI moves to a processing screen. Your app does not receive structured data at that moment.

Suki processes the session on the backend. When processing finishes, **`onSubmit`** runs in the browser with a **`FormFillingResult`**. The iframe is removed after that callback for a normal foreground session.

### Processing screen states

While Suki processes the session, the hosted UI may show:

* **Uploading** if the clinician submitted while offline. **Close** is disabled until the upload finishes.
* **Processing** while Suki generates structured data. **Close** is available.
* **Timeout** if processing takes longer than 60 seconds online. **Close** is still available. If the clinician leaves this screen open, results still arrive as **`onSubmit`** / **`form-filling:submitted`** for the same foreground session.

If the clinician closes the processing screen before results reach the SDK, your app receives **`form-filling:closed`**. No **`onSubmit`** from that action.

### Handling results via onSubmit

Use `onSubmit` to update your app when a clinician submits a form. For example, you can display the completed forms or show a confirmation message.

For production, register a [Partner webhook](/documentation/webhook/overview) during [Partner onboarding](/documentation/get-started/partner-onboarding). When processing is complete, Suki sends the same structured results to your server, even if the clinician has already closed the browser.

Use `correlation_id` and `ambient_session_id` to match the results to the correct patient record. If the webhook does not include the full structured data, call [Get Form filling structured data](/form-filling-api-reference/form-filling-sessions/structured-data) to retrieve it.

<Warning>
  Do not rely on **`onSubmit`** alone to save results. Processing may finish after the clinician closes the tab. Use a webhook in production.
</Warning>

Refer to [Callbacks](/form-filling-sdk/guides/callbacks), the [Webhook handler example](/form-filling-sdk/examples/webhook-handler), and the [EHR handoff example](/form-filling-sdk/examples/ehr-handoff).

### Handling background results

**`form-filling:background-submitted`** fires when structured data arrives for a session that is no longer the foreground session: the result's **`ambient_session_id`** does not match the session currently open (for example, the clinician closed the timeout or processing screen and started a new session, or a prior or offline session finished while a newer session is open). In React, handle it with **`onBackgroundSubmit`**. The iframe stays open.

If the clinician stays on the timeout screen for the same session, late results still arrive as normal **`onSubmit`** / **`form-filling:submitted`**, not as background-submitted.

## Next steps

<Icon icon="file-lines" iconType="solid" /> Refer to [Callbacks](/form-filling-sdk/guides/callbacks) for all session callbacks and events

<Icon icon="file-lines" iconType="solid" /> Refer to [Configuration](/form-filling-sdk/guides/configuration) for **`form_template_ids`**, **`correlation_id`**, and session options

<Icon icon="file-lines" iconType="solid" /> Refer to [Javascript integration](/form-filling-sdk/javaScript-integration/javaScript) and [React integration](/form-filling-sdk/react-integration/react) for full setup steps
