---
name: suki-form-filling
description: >-
  Use when building Suki Form filling integrations with the Form filling APIs
  or SDK: authenticate, create a Form filling session, provide Medical form
  template context, stream visit audio, end the session, and retrieve
  structured medical form output.
license: SUKI_Proprietary
metadata:
  author: suki
  version: "2.4"
---

## Form filling

Use **Form filling** to turn provider-patient visit conversation into
structured medical form output based on Suki Medical form templates.

Form filling is different from:

- **Ambient**, which generates clinical notes from visit conversations.
- **Dictation**, which provides real-time speech-to-text transcription.
- **Patient Summary**, which generates pre-visit clinical context from FHIR
  data.

Form filling gives your application structured form instances that you can
review, edit, validate, save, or send to downstream workflows.

## Accuracy rules

- Do not invent endpoints, request fields, SDK methods, template IDs, response
  fields, or WebSocket message types.
- Use the **Form filling session ID** returned by the Form filling session
  create API for subsequent Form filling REST and WebSocket operations.
- The Form filling session ID is named `ambient_session_id` in the API. Do not
  confuse it with an Ambient API `ambient_session_id`.
- The Form filling session create API can optionally associate a Form filling
  session with an existing Ambient session. This does not make the two session
  identifiers interchangeable.
- Do not use Ambient `/content` as Form filling output.
- Retrieve Form filling results from `/structured-data`.
- Do not use Dictation `/ws/transcribe` for Form filling.
- Form filling uses the shared Partner WebSocket at `/ws/stream`.
- Use the Ambient-style WebSocket wire format on `/ws/stream`.
- Do not send raw binary WebSocket audio frames.
- Do not use Dictation's `audioData` or `AUDIO_END` message format on
  `/ws/stream`.
- Use real Suki Medical form template IDs. Never invent template UUIDs.
- Do not assume a template ID is valid across staging and production.
- If this skill does not define a required detail, read the relevant Form
  filling documentation or use the documentation MCP before generating code.
- Keep partner credentials and Suki Tokens out of source control and client
  code when the integration architecture requires server-side credentials.

## Choose an integration path

Once the path is known, **fetch that dedicated skill** and implement from it.

| Path | Choose when | Dedicated skill |
| --- | --- | --- |
| **Form filling API** | Your application owns Form filling UI, audio capture, and retrieval through Partner REST and `/ws/stream` | `suki-form-filling-api` |
| **Form filling SDK** | You want Suki's hosted Form filling UI without the full Web SDK | `suki-form-filling-sdk` |
| **Web SDK Form filling** | You already embed the Headed Web SDK and want Form filling from those packages | `suki-web-sdk` |

Skill URLs:

- Form filling API: https://developer.suki.ai/.well-known/agent-skills/suki-form-filling-api/SKILL.md
- Form filling SDK: https://developer.suki.ai/.well-known/agent-skills/suki-form-filling-sdk/SKILL.md
- Web SDK: https://developer.suki.ai/.well-known/agent-skills/suki-web-sdk/SKILL.md

Do not combine the API and SDK workflows unless the documentation for the
specific integration requires it.

### Environment

For direct API integrations, use staging for development and testing unless
the user explicitly requests production.

<!-- SKILL-AUTO:START environments -->
| Environment | REST | WebSocket |
| --- | --- | --- |
| Staging | `https://sdp.suki-stage.com` | `wss://sdp.suki-stage.com` |
| Production | `https://sdp.suki.ai` | `wss://sdp.suki.ai` |
<!-- SKILL-AUTO:END environments -->

Your Suki partnership configuration determines which environment and
credentials apply.

## Form filling API workflow

The API workflow is:

```text
authenticate
→ create Form filling session
→ optionally seed Medical form template context
→ connect to /ws/stream
→ stream visit audio
→ send end-of-stream marker
→ close WebSocket
→ end Form filling session
→ monitor status
→ retrieve structured data
````

Use a partner webhook instead of polling when your integration is configured
to receive Form filling completion notifications.

### API endpoints

<!-- SKILL-AUTO:START endpoint-table -->
| Operation | Method | Path |
| --- | --- | --- |
| Login | `POST` | `/api/v1/auth/login` |
| Register | `POST` | `/api/v1/auth/register` |
| Create session | `POST` | `/api/v1/form-filling/session/create` |
| Seed context | `POST` | `/api/v1/form-filling/session/{ambient_session_id}/context` |
| Update context | `PATCH` | `/api/v1/form-filling/session/{ambient_session_id}/context` |
| Stream audio | `WebSocket` | `/ws/stream` |
| End session | `POST` | `/api/v1/form-filling/session/{ambient_session_id}/end` |
| Session status | `GET` | `/api/v1/form-filling/session/{ambient_session_id}/status` |
| Structured data | `GET` | `/api/v1/form-filling/session/{ambient_session_id}/structured-data` |
<!-- SKILL-AUTO:END endpoint-table -->

The exact API reference remains authoritative if an endpoint changes.

## 1. Authenticate

Form filling API requests use a Suki Token.

The authentication flow is:

```text
Partner Token
→ Suki Login
→ Suki Token
→ Form filling API
```

### Login

Send the Partner ID and Partner Token to:

```http
POST /api/v1/auth/login
Content-Type: application/json
```

Example:

```json
{
  "partner_id": "your-partner-id",
  "partner_token": "your-partner-token"
}
```

Some partner authentication modes also require:

```json
{
  "provider_id": "provider-123"
}
```

Follow the Partner Authentication documentation for your partner type.

On successful authentication, Suki returns:

```text
suki_token
```

Use that token as:

```http
sdp_suki_token: {suki_token}
```

for subsequent Form filling API requests.

The Suki Token expires after approximately one hour. Refresh it before it
expires by authenticating again with a valid Partner Token.

### Unregistered users

If the provider is not registered, the Login request can fail.

Register the provider using:

```http
POST /api/v1/auth/register
```

Then authenticate again with Login.

Only register a provider when the authentication flow requires it.

### Authentication rules

* Do not send the Partner Token as `sdp_suki_token`.
* Do not send an SDP JWT as `sdp_suki_token`.
* Use the Suki Token returned by Login or Register.
* Send `sdp_provider_id` when required by your partner authentication mode.
* Keep authentication credentials secure.

## 2. Create a Form filling session

Create a session with:

```http
POST /api/v1/form-filling/session/create
```

Authenticate with:

```http
sdp_suki_token: {suki_token}
```

The request body is optional.

An empty request is valid:

```json
{}
```

The API returns HTTP `201` with:

```json
{
  "ambient_session_id": "..."
}
```

Save the returned `ambient_session_id`.

Use this identifier for:

* Session context.
* `/ws/stream`.
* Ending the session.
* Checking session status.
* Retrieving structured data.
* Other Form filling session operations.

### Optional create parameters

The create request can include:

```json
{
  "ambient_session_id": "existing-ambient-session-id",
  "correlation_id": "your-encounter-or-tracing-id"
}
```

Both fields are optional.

`correlation_id` is a client-supplied identifier for tracing or correlating
the Form filling workflow.

`ambient_session_id` can associate the Form filling session with an existing
Ambient session when applicable.

Do not assume that the optional Ambient session association makes the Ambient
and Form filling session IDs interchangeable.

For normal Form filling API calls, use the Form filling session identifier
returned by the create operation.

## 3. Seed Medical form template context

After creating the session, you can provide Form filling context.

Use:

```http
POST /api/v1/form-filling/session/{ambient_session_id}/context
```

The context request body is optional.

If you provide `form_filling`, its `values` array must contain valid
`form_template_id` values.

Example:

```json
{
  "form_filling": {
    "values": [
      {
        "form_template_id": "<template-uuid>"
      }
    ]
  }
}
```

The selected template IDs tell Suki which Medical form templates apply to the
session.

Providing template context helps Suki generate structured output for the
selected forms.

### Template IDs

Medical form template IDs are assigned by Suki.

Get the templates available to your integration from the Suki Medical Form
Templates API or from Suki Support, depending on your onboarding.

Do not:

* Invent template UUIDs.
* Copy a staging template ID into production.
* Assume every partner has access to every template.
* Assume an unsupported template ID will generate output.

Template IDs can differ between staging and production.

### Supported template types

Suki provides predefined Medical form templates, including templates such as:

* Vitals
* Neuro
* Skin
* Respiratory
* Cardiac
* GI
* GU
* MSK

Each template has a Suki-defined `type` and `template_id`.

Use the current Medical Form Templates documentation for the complete list and
field definitions.

## 4. Stream visit audio

Form filling uses the shared Partner WebSocket:

```text
GET /ws/stream
```

For staging:

```text
wss://sdp.suki-stage.com/ws/stream
```

For production:

```text
wss://sdp.suki.ai/ws/stream
```

Authenticate the connection using the Form filling session ID and Suki Token
as documented for the Partner WebSocket.

The WebSocket wire format for `/ws/stream` is the Ambient streaming format.
Exact message shapes are on the Ambient wire format documentation page (the
Streaming Wire Format hub is an overview only).

### Do not use Dictation wire format

Form filling `/ws/stream` uses:

```text
START_TIME
AUDIO with data
EVENT control messages
AUDIO with data = RU9G
```

It does **not** use Dictation's:

```text
AUDIO with audioData
EVENT with AUDIO_END
```

Do not mix the two protocols.

## 5. Send WebSocket messages

All outbound `/ws/stream` messages are JSON text frames.

Do not send raw binary audio frames.

### Start a stream segment

Send one `START_TIME` message before audio:

```json
{
  "type": "START_TIME",
  "data": "<base64-timestamp>"
}
```

The `data` value is Base64-encoded UTF-8 bytes containing an RFC 3339
timestamp.

Example timestamp:

```text
2026-04-25T12:34:56Z
```

### Send audio

Send audio using:

```json
{
  "type": "AUDIO",
  "data": "<base64-pcm-audio>"
}
```

The `data` value must be standard Base64 containing the raw PCM audio bytes.

Do not use:

* Hex encoding.
* URL-safe Base64.
* Raw binary inside JSON.
* WAV headers.

### Recommended audio format

Use:

| Setting                    | Value                                      |
| -------------------------- | ------------------------------------------ |
| Encoding                   | LINEAR16 / PCM signed 16-bit little-endian |
| Sample rate                | 16 kHz                                     |
| Channels                   | Mono                                       |
| Chunk size                 | About 100 ms                               |
| Raw bytes per 100 ms chunk | About 3200 bytes                           |

Stream audio at or near real-time speed.

Do not send a large buffered recording as quickly as possible.

### End the audio stream

For `/ws/stream`, end the stream segment with:

```json
{
  "type": "AUDIO",
  "data": "RU9G"
}
```

`RU9G` is Base64 for the ASCII string `EOF`.

Do not send:

```text
EOF
```

as plain text.

Do not use:

```json
{
  "type": "EVENT",
  "event": "AUDIO_END"
}
```

on `/ws/stream`.

`AUDIO_END` belongs to the Dictation `/ws/transcribe` protocol.

### Control events

Control events use:

```json
{
  "type": "EVENT",
  "event": "<event>"
}
```

Supported events include:

```text
PAUSE
RESUME
KEEP_ALIVE
CANCEL
ABORT
```

While a stream is paused, send `KEEP_ALIVE` according to the documented
WebSocket idle-timeout guidance.

Do not invent custom event names.

### Message order

For each `/ws/stream` segment:

```text
START_TIME
→ AUDIO
→ AUDIO
→ optional EVENT messages
→ final AUDIO with data = RU9G
```

Example:

```json
{
  "type": "START_TIME",
  "data": "<base64-timestamp>"
}
```

```json
{
  "type": "AUDIO",
  "data": "<base64-pcm-chunk>"
}
```

```json
{
  "type": "EVENT",
  "event": "PAUSE"
}
```

```json
{
  "type": "AUDIO",
  "data": "<base64-pcm-chunk>"
}
```

```json
{
  "type": "AUDIO",
  "data": "RU9G"
}
```

## 6. Close the WebSocket and end the session

After sending the final `RU9G` message:

1. Finish the WebSocket audio stream.
2. Close the WebSocket connection.
3. Call the Form filling session end endpoint.

Use:

```http
POST /api/v1/form-filling/session/{ambient_session_id}/end
```

Authenticate with:

```http
sdp_suki_token: {suki_token}
```

The end operation tells Suki that no more audio will be sent for the session
and allows processing to complete.

Do not call the REST end operation while the WebSocket is still being used to
send audio.

## 7. Monitor Form filling status

Form filling processing is asynchronous.

Check status with:

```http
GET /api/v1/form-filling/session/{ambient_session_id}/status
```

The response contains:

```json
{
  "status": "completed"
}
```

### Documented status values

The Form filling status documentation includes:

| Status      | Meaning                                                     |
| ----------- | ----------------------------------------------------------- |
| `created`   | Session has been created but has not started.               |
| `ready`     | Session is ready for audio streaming.                       |
| `running`   | Session is processing audio and generating content.         |
| `staged`    | Session is staged and ready to be processed.                |
| `paused`    | Session is paused.                                          |
| `completed` | Session completed successfully and generated final content. |
| `failed`    | Processing failed.                                          |
| `aborted`   | The session was cancelled or aborted.                       |

The API documentation has shown `staged` in the status description while some
generated API enum examples omit it. Treat the current API reference as
authoritative and do not hard-code an undocumented status.

The terminal values are:

```text
completed
failed
aborted
```

Poll until one of these terminal states.

### Polling pattern

```text
end session
→ check status
→ if non-terminal, wait
→ check again
→ if completed, retrieve structured data
→ if failed or aborted, stop
```

Do not poll continuously without a delay.

Do not retrieve structured data as the normal completion path before the
session reaches `completed`.

## 8. Retrieve structured form data

After the session reaches:

```text
completed
```

retrieve structured data with:

```http
GET /api/v1/form-filling/session/{ambient_session_id}/structured-data
```

Authenticate with:

```http
sdp_suki_token: {suki_token}
```

The response contains:

```json
{
  "structured_data": {
    "generated_values": [],
    "non_generated_values": []
  }
}
```

### `generated_values`

`generated_values` contains Medical form instances for which Suki generated
structured data.

A generated form instance can contain fields such as:

```json
{
  "correlation_id": "...",
  "created_at": "...",
  "data": {},
  "form_template_id": "...",
  "id": "...",
  "metadata": {},
  "patient_id": "...",
  "status": "MEDICAL_FORM_STATUS_COMPLETED",
  "title": "...",
  "type": "VITALS_ASSESSMENT"
}
```

Use the exact response schema from the current API reference.

### `non_generated_values`

`non_generated_values` contains form template IDs for which Suki did not
generate structured data.

Do not treat every requested template as successfully generated.

Check both:

```text
generated_values
non_generated_values
```

when determining which forms produced output.

### Structured data vs. clinical note

Form filling output is structured medical form data.

Do not expect a full Ambient clinical note.

Do not retrieve:

```text
/content
```

as a substitute for Form filling structured output.

Use:

```text
/structured-data
```

for Form filling results.

## 9. Use webhooks for completion

Form filling supports partner webhook notifications for asynchronous
processing.

For production integrations, webhooks can be used instead of tight status
polling.

The webhook payload can provide links for retrieving results.

When using webhooks:

1. Verify the webhook signature before processing the payload.
2. Identify the Form filling session.
3. Use the documented Form filling webhook payload.
4. Retrieve structured data using the appropriate Form filling API.
5. Handle duplicate deliveries safely.

Follow the `suki-webhooks` skill for webhook verification and delivery
handling.

Do not assume Form filling webhook payloads have the same structure as Ambient
webhook payloads.

## Form filling SDK

Use the **Form filling SDK** when you want Suki's hosted Form filling
experience instead of building the full REST and WebSocket workflow yourself.

The SDK provides JavaScript and React packages.

### Packages

For JavaScript:

```text
@suki-sdk/form-filling
@suki-sdk/core
```

For React:

```text
@suki-sdk/form-filling-react
@suki-sdk/core
```

Install the package for your framework together with `@suki-sdk/core`.

### SDK prerequisites

Before starting an SDK integration, you need:

* Partner credentials.
* Medical form template IDs provided by Suki.
* An HTTPS web page.
* Microphone access.
* A page container with explicit height for the hosted Form filling UI.
* Any required CSP configuration.

The Form filling SDK uses a hosted iframe.

## SDK authentication

The SDK uses:

```text
SukiAuthManager
```

Create the auth manager with the partner credentials.

Example:

```ts
import { SukiAuthManager } from "@suki-sdk/core";

const authManager = new SukiAuthManager({
  partnerId: "YOUR_PARTNER_ID",
  partnerToken: "YOUR_PARTNER_TOKEN",
  environment: "staging",
});
```

The SDK manages the Suki authentication flow through the auth manager.

Do not replace SDK authentication with raw REST header logic unless the SDK
documentation explicitly requires it.

### Provider fields

Depending on your authentication mode, you may need provider fields such as:

```text
providerId
providerName
providerOrgId
```

Use the fields required by your partner configuration and SDK version.

## FormFillingClient

Create a:

```text
FormFillingClient
```

with the configured `SukiAuthManager`.

Example:

```ts
import { FormFillingClient } from "@suki-sdk/form-filling";

const client = new FormFillingClient({
  authManager,
});
```

### Reuse the client

Create one `SukiAuthManager` and one `FormFillingClient` per page.

Reuse them across Form filling sessions.

Do not create a new client on every React render.

For React, create the client with `useMemo` or at module scope.

## Start a Form filling SDK session

Start the SDK with:

```text
form_template_ids
```

and optionally:

```text
correlation_id
```

Example:

```ts
await client.start({
  rootElement: document.getElementById("suki-form-container"),
  form_template_ids: ["YOUR_TEMPLATE_ID"],
  correlation_id: "YOUR_ENCOUNTER_ID",
  onReady: () => {
    console.log("Form UI ready");
  },
  onSubmit: (result) => {
    console.log(result.structured_data.generated_values);
  },
  onCancel: () => {
    console.log("Cancelled");
  },
});
```

### `form_template_ids`

`form_template_ids` is an array of Suki Medical form `template_id` values.

The IDs must be valid for your partner and environment.

Do not invent template IDs.

Template IDs can differ between staging and production.

### `correlation_id`

Pass your encounter or appointment ID as:

```text
correlation_id
```

This is strongly recommended for production integrations.

Suki includes the `correlation_id` in SDK callbacks and partner webhooks so
your application can associate the Form filling result with the correct
encounter.

If you omit it, the hosted UI creates its own ID. That ID will not match your
encounter ID, so your application must create its own mapping.

## React SDK

For React, use:

```text
FormFillingProvider
FormFilling
FormFillingClient
```

A typical structure is:

```tsx
<FormFillingProvider client={client}>
  <FormFilling
    form_template_ids={["YOUR_TEMPLATE_ID"]}
    correlation_id={encounterId}
    onReady={() => console.log("Ready")}
    onSubmit={(result) => {
      console.log(result.structured_data.generated_values);
    }}
    onCancel={() => setIsFormOpen(false)}
  />
</FormFillingProvider>
```

Create and reuse the client rather than creating it during every render.

## SDK callbacks

The SDK provides callbacks including:

* `onReady`
* `onSubmit`
* `onCancel`

The `onSubmit` result includes structured data.

For example:

```ts
onSubmit: (result) => {
  console.log(result.structured_data.generated_values);
}
```

The result also includes the Form filling session identifier.

Use the callback type definitions and current SDK documentation for the
complete `FormFillingResult` schema.

## SDK UI container

The Form filling hosted UI needs a container with actual height.

For example:

```html
<div
  id="suki-form-container"
  style="width: 100%; height: 600px;"
></div>
```

Do not mount the Form filling UI into a container with zero or undefined
height.

Ensure the page runs over HTTPS and the browser has microphone permission.

## API vs SDK

Choose the API when:

* You need full control over audio capture.
* You want to build your own Form filling UI.
* You need direct control over session lifecycle.
* You need direct access to REST and WebSocket APIs.

Choose the SDK when:

* You want Suki's hosted Form filling UI.
* You want Suki to handle the browser recording experience.
* You want structured results through SDK callbacks.
* You do not need to build the complete Form filling UI yourself.

Do not use the SDK when you need raw `/ws/stream` control that the hosted
experience does not expose.

## Common mistakes

### Using the Ambient session ID for Form filling calls

Both Ambient and Form filling APIs use the field name:

```text
ambient_session_id
```

But the identifiers represent different sessions.

Do not take the ID returned by Ambient session creation and use it as the
Form filling session ID.

Use the Form filling session identifier returned by:

```text
POST /api/v1/form-filling/session/create
```

for Form filling operations.

The create API can explicitly associate a Form filling session with an
existing Ambient session when applicable. That is different from treating
the IDs as interchangeable.

### Using `/content` for Form filling results

Wrong:

```text
GET /content
```

Form filling results are structured medical form data.

Correct:

```text
GET /structured-data
```

### Using Dictation `/ws/transcribe`

Wrong:

```text
/ws/transcribe
```

Form filling uses:

```text
/ws/stream
```

### Using `AUDIO_END` on `/ws/stream`

Wrong:

```json
{
  "type": "EVENT",
  "event": "AUDIO_END"
}
```

That is the Dictation streaming pattern.

For `/ws/stream`, end the audio segment with:

```json
{
  "type": "AUDIO",
  "data": "RU9G"
}
```

### Sending raw binary WebSocket frames

The Partner WebSocket expects JSON text frames.

Encode audio as standard Base64 and place it in the `data` field of an
`AUDIO` message.

### Sending WAV files as PCM

Do not send WAV container headers as audio data.

Send raw PCM signed 16-bit little-endian audio.

### Inventing template IDs

Do not use randomly generated UUIDs.

Use template IDs supplied by Suki or returned by the appropriate Medical Form
Templates API.

### Assuming all requested forms generate output

A session can contain:

```text
generated_values
```

and:

```text
non_generated_values
```

Check both collections.

A requested template can appear in `non_generated_values` when Suki did not
generate structured data for it.

### Creating a new SDK client on every render

Wrong:

```text
React render
→ new SukiAuthManager
→ new FormFillingClient
```

Create the auth manager and client once and reuse them.

### Omitting `correlation_id` in production

Without `correlation_id`, the hosted UI generates its own identifier.

Your application then has to map that session back to the correct encounter.

Pass your encounter or appointment ID as `correlation_id` when possible.

### Mixing API and SDK authentication

The API workflow uses the Suki Token in API headers.

The SDK workflow uses `SukiAuthManager`.

Do not copy raw API authentication logic into SDK code unless the SDK
documentation requires it.

## Non-negotiable rules

Before generating or reviewing Form filling API code, verify:

* [ ] The integration is using the Form filling API, not Ambient or Dictation.
* [ ] The correct environment is being used.
* [ ] Authentication produces a valid Suki Token.
* [ ] `sdp_suki_token` is used for Form filling API requests.
* [ ] `sdp_provider_id` is included when required.
* [ ] The Form filling session ID comes from Form filling session creation.
* [ ] Ambient and Form filling session IDs are not treated as interchangeable.
* [ ] Real Suki Medical form template IDs are used.
* [ ] Template IDs match the target environment.
* [ ] Context is seeded with valid `form_template_id` values when context is
  used.
* [ ] `/ws/stream` is used for Form filling audio.
* [ ] WebSocket messages use JSON text frames.
* [ ] Audio is Base64-encoded raw PCM.
* [ ] Audio uses the documented LINEAR16 format.
* [ ] `START_TIME` is sent before audio.
* [ ] Audio chunks use `AUDIO.data`.
* [ ] The stream ends with `AUDIO.data = RU9G`.
* [ ] Dictation `AUDIO_END` is not used on `/ws/stream`.
* [ ] The WebSocket is closed before the REST end call.
* [ ] Session status is monitored after ending the session.
* [ ] Polling stops at `completed`, `failed`, or `aborted`.
* [ ] Structured output is retrieved from `/structured-data`.
* [ ] Both `generated_values` and `non_generated_values` are handled.
* [ ] Webhook processing uses the Form filling webhook schema when webhooks
  are used.
* [ ] SDK clients are reused when using the Form filling SDK.
* [ ] SDK sessions use valid `form_template_ids`.
* [ ] SDK sessions use `correlation_id` when possible.
* [ ] The SDK UI container has explicit height.
* [ ] HTTPS and microphone permissions are configured.
* [ ] Credentials are not committed to source control.

## Implementation checklist

### Form filling API

* [ ] Authenticate with Partner Token.
* [ ] Obtain `suki_token`.
* [ ] Create a Form filling session.
* [ ] Save the returned `ambient_session_id`.
* [ ] Seed template context if required.
* [ ] Connect to `/ws/stream`.
* [ ] Authenticate the WebSocket with the Form filling session.
* [ ] Send `START_TIME`.
* [ ] Stream Base64-encoded PCM audio.
* [ ] Send the final `RU9G` marker.
* [ ] Close the WebSocket.
* [ ] End the Form filling session.
* [ ] Monitor session status.
* [ ] Stop when status is `completed`, `failed`, or `aborted`.
* [ ] Retrieve `/structured-data` after completion.
* [ ] Process `generated_values`.
* [ ] Handle `non_generated_values`.

### Form filling SDK

* [ ] Install the correct JavaScript or React package.
* [ ] Install `@suki-sdk/core`.
* [ ] Obtain valid Suki Medical form template IDs.
* [ ] Create one `SukiAuthManager` per page.
* [ ] Create one `FormFillingClient` per page.
* [ ] Reuse the client across sessions.
* [ ] Provide `form_template_ids`.
* [ ] Provide `correlation_id` when possible.
* [ ] Mount the hosted UI into a container with explicit height.
* [ ] Verify HTTPS and microphone access.
* [ ] Handle `onReady`.
* [ ] Handle `onSubmit`.
* [ ] Handle `onCancel`.
* [ ] Process `result.structured_data`.

## When to read more

<!-- SKILL-AUTO:START canonical-docs -->
- [Form Filling API Quickstart](https://developer.suki.ai/form-filling-api-reference/quickstart): Authenticate, create a Form filling session, stream audio, end the session, and retrieve structured form output on staging
- [Form Filling SDK Quickstart](https://developer.suki.ai/form-filling-sdk/quickstart): Install Form filling SDK packages, configure SukiAuthManager and FormFillingClient, and start your first Form filling session with form_template_ids
- [Form Filling Overview](https://developer.suki.ai/documentation/concepts/form-filling/form-filling-overview): Start here for Form filling: when to use structured medical forms, Form filling APIs vs the Form filling SDK, templates, and integration paths
- [Form Filling Templates](https://developer.suki.ai/documentation/concepts/form-filling/form-filling-templates): Learn what Suki Medical form templates are, the supported assessment types, and how Form filling APIs and the Form filling SDK use them in your integration
- [Partner Authentication Mechanisms](https://developer.suki.ai/documentation/how-to/partner-authentication): Compare and choose the right authentication mechanism for your APIs and SDKs, including Partner Token exchange, JWKS, and provider registration
- [Ambient Streaming Wire Format](https://developer.suki.ai/documentation/how-to/audio-streaming/websocket-streaming-wire-format-ambient): Format and send Base64 audio chunks as JSON text frames on GET /ws/stream for Ambient and Form filling sessions, including message types, order, and PCM chunking
- [llms-full.txt](https://developer.suki.ai/llms-full.txt): Full-site dump for broad cross-product questions
<!-- SKILL-AUTO:END canonical-docs -->


## Sister skills

<!-- SKILL-AUTO:START sister-skills -->
* Form filling API:
  [https://developer.suki.ai/.well-known/agent-skills/suki-form-filling-api/SKILL.md](https://developer.suki.ai/.well-known/agent-skills/suki-form-filling-api/SKILL.md)
* Form filling SDK:
  [https://developer.suki.ai/.well-known/agent-skills/suki-form-filling-sdk/SKILL.md](https://developer.suki.ai/.well-known/agent-skills/suki-form-filling-sdk/SKILL.md)
* Web SDK:
  [https://developer.suki.ai/.well-known/agent-skills/suki-web-sdk/SKILL.md](https://developer.suki.ai/.well-known/agent-skills/suki-web-sdk/SKILL.md)
* Ambient:
  [https://developer.suki.ai/.well-known/agent-skills/suki-ambient/SKILL.md](https://developer.suki.ai/.well-known/agent-skills/suki-ambient/SKILL.md)
* Audio streaming:
  [https://developer.suki.ai/.well-known/agent-skills/suki-audio-streaming/SKILL.md](https://developer.suki.ai/.well-known/agent-skills/suki-audio-streaming/SKILL.md)
* Webhooks:
  [https://developer.suki.ai/.well-known/agent-skills/suki-webhooks/SKILL.md](https://developer.suki.ai/.well-known/agent-skills/suki-webhooks/SKILL.md)
* Dictation:
  [https://developer.suki.ai/.well-known/agent-skills/suki-dictation/SKILL.md](https://developer.suki.ai/.well-known/agent-skills/suki-dictation/SKILL.md)
<!-- SKILL-AUTO:END sister-skills -->
