Skip to main content
What you will build

20 min | Intermediate

  • Login and create a Form filling session.
  • Add form template context before streaming.
  • Stream raw PCM audio over WebSocket.
  • End the session and retrieve structured form data.
  • Handle common API errors.
Using an AI coding tool?Copy the prompt below to point your agent at the audio streaming skill and Documentation MCP. For every task skill, refer to AI coding tools.

Fetch the audio streaming skill and connect the documentation MCP.

Open in Cursor
In this tutorial, you build an end-to-end Form filling streaming client. You authenticate, create a Form filling session, add form template context, stream PCM audio over a WebSocket connection, end the session, and retrieve structured form data. Examples are provided in Python, TypeScript, and Go coding languages. By the end of this tutorial, you’ll have a working client that connects to the production endpoints https://sdp.suki.ai and wss://sdp.suki.ai/ws/stream API, and handles common API errors.
Form filling uses the same /ws/stream wire format as ambient clinical notes. The response field ambient_session_id from Create Form filling session is your Form filling session ID. Do not use an ID from Create ambient session.

Prerequisites

Before you begin, make sure you have:
  • Completed Partner onboarding and received your partner credentials.
  • You have partner_id and partner_token.
  • Optional provider_id or sdp_provider_id if your integration uses Bearer authentication or the Single Auth Token flow.
  • At least one form_template_id from Suki Medical form templates (GET /api/v1/info/suki-medical-form-templates, field template_id). This tutorial seeds a Suki template. You can also send your own form templates. Refer to Dynamic Form filling.
  • An audio file in LINEAR16 PCM format (16 kHz, mono, 16-bit little-endian). If you’re using a WAV file, remove the WAV header before streaming and send only the raw PCM audio.
Store your partner_token only on your backend. Never expose it in a client-side or public application.

Architecture

Project setup

  1. Create a script or web page in the language used by this tutorial (Python, Go, or TypeScript).
  2. Install the required dependencies:.
    • Python: pip install requests websocket-client.
    • Go: go get github.com/gorilla/websocket.
    • TypeScript (browser): No additional packages are required. The example uses the built-in fetch and WebSocket APIs.
  3. Configure your credentials:.
    • Add your partner_id.
    • Store partner_token on your backend only. Never expose it in browser code.
    • Add provider_id or sdp_provider_id only if your integration requires them.
    • Set at least one real form in context before you stream. This tutorial uses a Suki form_template_id.
  4. Prepare an audio file in LINEAR16 PCM format or a WAV file. If you use a WAV file, remove the 44-byte WAV header before streaming the PCM audio.

How WebSocket authentication works in this tutorial

Important points to remember:
  • If login fails because the provider is new, Register provider once, then log in again.
  • Send audio at least every 25 seconds, or the server closes the stream. While paused, send KEEP_ALIVE every five seconds.
  • Send raw LINEAR16 PCM. If you start from a WAV file, strip the 44-byte header first. Do not send binary WebSocket frames on this endpoint.
  • Browser protocol order matches ambient: token, then session ID (SukiAmbientAuth,<sdp_suki_token>,<ambient_session_id>).
  • Use the Form filling create response ambient_session_id as the Form filling session ID on the WebSocket.

Tutorial steps

Work through each step in order. Read the explanation, review the code example, then continue to the next step. The full code example is available in the accordion below.
1

Log In

Call the Login API with your partner credentials to receive a suki_token. Send that token later as sdp_suki_token. If the provider is new, register once, then log in again.Check: Login returns HTTP 200 and a non-empty suki_token.
2

Create a Form Filling Session

Create a session with the Form filling session API. The response field ambient_session_id is your Form filling session ID.Check: Create returns a non-empty ambient_session_id for this Form filling session.If it fails: Use the ambient_session_id from the Form filling create response as this session ID. Do not reuse an ambient clinical-notes session ID.
3

Seed Form Filling Context

Seed at least one form with the Form filling Context API before you end the session. This tutorial uses a Suki form_template_id. For partner-defined forms, send a schema instead. Refer to Dynamic Form filling.Check: At least one form is seeded (form_template_id or schema) before you end the session.If it fails: Seed at least one form with a form_template_id or schema before you call End.
4

Open the WebSocket

Open wss://sdp.suki.ai/ws/stream with the same ambient handshake. Authenticate with headers (Python/Go) or Sec-WebSocket-Protocol (browser).Check: The WebSocket opens on wss://sdp.suki.ai/ws/stream with the auth pattern for your language.
5

Stream Audio

Send START_TIME (Base64 of an RFC 3339 timestamp), then JSON AUDIO frames with Base64 LINEAR16 PCM (~100 ms chunks). End the segment with {"type":"AUDIO","data":"RU9G"}. Same wire format as ambient. Do not send binary WebSocket frames.Check: You sent START_TIME, then Base64 LINEAR16 PCM in JSON AUDIO frames, then RU9G. No binary WebSocket frames.
6

Optional Control Events

While streaming, you can send PAUSE, RESUME, or KEEP_ALIVE (every five seconds while paused).Check: While paused, you send KEEP_ALIVE every five seconds.If it fails: Send KEEP_ALIVE every five seconds while you are paused, and send audio at least every 25 seconds while you are streaming.
7

End the Session and Retrieve Results

Close the WebSocket, call End, poll status, then get structured data.Check: You called End, polled status, then retrieved structured data.
8

Handle API Errors

Map REST failures using documented code, message, and details. See API error messages.Check: Your client maps REST failures using code, message, and details.If it fails: Call login again for a fresh suki_token, then see API errors.

Full code example

Python

Troubleshooting

Use the Form filling create response ambient_session_id as the Form filling session ID. Do not use an ambient clinical-notes session ID.
Seed at least one form in context before you call end. This tutorial uses a Suki form_template_id. You can also send a partner schema. Refer to Dynamic Form filling.
Send KEEP_ALIVE every five seconds while paused, and send audio at least every 25 seconds while streaming.
Re-login for a fresh suki_token, and see API errors.

Summary

In this tutorial, you:
  • Authenticated with the Suki API.
  • Created a Form filling session and seeded form template context.
  • Streamed LINEAR16 PCM audio over a WebSocket connection.
  • Ended the session and retrieved structured form data.
For production, use the following endpoints:
  • API: https://sdp.suki.ai.
  • WebSocket: wss://sdp.suki.ai/ws/stream.

Other tutorials

Continue with another end-to-end tutorial.
Last modified on October 16, 2026