# REST with Client auth Source: https://api-docs.wisprflow.ai/client_api_transcribe POST /client_api Convert speech to text using client-side authentication Convert audio to text with client-side JWT authentication. This endpoint is identical to the standard `/api` endpoint but uses a client token (JWT) instead of an org-level API key. ### Request Body Base64 encoded, 16kHz wav audio. Maximum size is 25MB or 6 minutes of audio. Optional list of (ISO 639-1) language codes that the user is expected to speak. Setting the list size to 1 forces the transcription into the specified language. Not providing an input attempts autodetection on full list of languages (less accurate). Optional contextual information about the circumstances surrounding the user dictation. Flow can use these information to make its output more accurate by for example, getting names right, resolving speech ambiguities, etc. All properties are optional and will use default values if not provided. Information about the application the user is dictating into, used to customize the writing style. The name of the application. The type of the application. Currently supports the following list: * `email`: Email clients and anywhere the user would be trying to dictate an email. * `ai`: Applications where the user is conversing with an AI chatbot / agent and not a human. * `other`: Any application that does not fit in the two groups above. List of uncommon names or words relevant to the context that might be mentioned by the user. User ID in the app that the person is dictating in, like their email address in an email client application. First name of the speaker, used to make sure Flow spells the speaker's name correctly. Last name of the speaker. Text under and surrounding the cursor in the active textbox. Flow uses this information to decide casing, spacing and punctuation. The text immediately before the cursor. The text the user has highlighted. The text immediately after the cursor. Screenshot of the screen or the app the user is dictating in, for when the user is referencing something on the screen. Plaintext content of the current page in the app user is dictating in. This is a more efficient way of providing context compared to screenshot. HTML content of the app user is dictating in (a more feature-rich alternative to `content_text`). Chatbot style history of the conversation the user is dictating in. This typically applies to messaging and AI apps. Identifier of the conversation. For example name of group chat in case of a messaging app. List of names of other people in the conversation, used to get their names correct in case of uncommonly spelled names. List of recent messages in the conversation, in the chronological order. Used to identify proper context and names of things being mentioned that are not conversation participants. Type of the message sender. One of: `user`, `human`, `assistant` Content of the message. 2-digit ISO language code (e.g. 'en', 'es') Flow formats appropriately depending on if the user is prompting AI, writing an email, or other tasks. Options: 'ai', 'email', 'other' List of dictionary words to help with transcription accuracy The text immediately after the cursor. Flow uses it to decide spacing / punctuation. The text immediately before the cursor. Flow uses it to decide spacing / punctuation. The text the user has highlighted. Flow uses it to decide spacing / punctuation. ```json Response (200 OK) theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "text": "Testing testing 1, 2, 3", "detected_language": "en", "total_time": 432, "generated_tokens": 9 } ``` ```json Request theme={null} { "audio": "UklGRiQA....", "language": ["en"], "context": { "app": { "type": "email" }, "dictionary_context": [], "textbox_contents": { "before_text": "", "selected_text": "", "after_text": "" }, // ... for a full list of available fields, see the "Request Schema" page } } ``` # Client Side Auth Basics Source: https://api-docs.wisprflow.ai/client_side_auth_basics This section explains how to create and manage client JWT tokens for use in protected endpoints such as `/client_api` or the `/client_ws` endpoint. You will use your organization’s API key to generate and revoke these tokens. The tokens themselves expire automatically and can also be revoked at any time. ## Workflow Overview ### Obtain an Organization API Key You must have an org-level API key (e.g., Bearer fl-xxxxxx). This key allows you to: * Generate new client tokens * Revoke existing tokens * Revoke all tokens associated with a particular client user ID ### Generate a Client Token Use your org-level API key to call `/generate_access_token` and receive a JWT token for a specific client. You can store this JWT on the client side. This endpoint takes in a client ID, a duration in seconds for which the token remains valid, and any metadata you choose to send us in the form of a dictionary. The client ID should be consistent for every user of your application. ### Client Uses Token The client calls the "client-facing" endpoints: * `/client_api` using the JWT token in the Authorization header like so: `Bearer ` * Client websocket by passing it in the query parameter as `?client_key=Bearer%20` ### Error Responses All error responses follow a consistent JSON format: ```json theme={null} { "detail": "Error message describing the specific issue" } ``` Here are the exact responses you'll receive for each error scenario: #### Authentication Header Issues ```json theme={null} { "detail": "Authorization header is missing" } ``` ```json theme={null} { "detail": "Authorization header must start with Bearer" } ``` #### Token Format Issues ```json theme={null} { "detail": "Invalid token format" } ``` ```json theme={null} { "detail": "Invalid token format: missing required fields" } ``` #### Token Validation Issues ```json theme={null} { "detail": "Invalid token, token not found in database" } ``` ```json theme={null} { "detail": "Token has been revoked" } ``` ```json theme={null} { "detail": "Token has expired" } ``` ```json theme={null} { "detail": "Invalid token, client_id mismatch" } ``` #### Server Issues ```json theme={null} { "detail": "Internal server error during token validation" } ``` All error responses will include appropriate HTTP status codes: * 401 for authentication and token validation issues * 400 for malformed requests * 500 for server-side errors ### Error Scenarios When using client authentication, you may encounter various error scenarios. Here's a comprehensive list of possible errors and their meanings: #### Authentication Header Issues (401 Unauthorized) * **Missing Authorization Header**: The request is missing the required Authorization header * **Invalid Bearer Format**: The Authorization header must start with "Bearer " followed by the token #### Token Format Issues (401 Unauthorized) * **Invalid Token Format**: The JWT token is malformed or cannot be decoded * **Missing Required Fields**: The token is missing required fields (client\_id or token\_id) #### Token Validation Issues (401 Unauthorized) * **Token Not Found**: The token doesn't exist in our database * **Token Revoked**: The token has been explicitly revoked and is no longer valid * **Token Expired**: The token has exceeded its expiration time * **Client ID Mismatch**: The token's client ID doesn't match the expected client #### Token Expiration There are two ways a token can be determined as expired: 1. JWT signature expiration check 2. Database expiration timestamp check In both cases, you'll receive a 401 Unauthorized response with the message "Token has expired" #### Server Issues (500 Internal Server Error) In rare cases, you might encounter a server-side error during token validation. This is typically temporary and should be retried. ### Handling Token Errors When encountering these errors, you should: 1. For expired tokens: Generate a new token using your organization API key 2. For revoked tokens: Investigate why the token was revoked and generate a new one if appropriate 3. For format/header issues: Ensure you're properly formatting the Authorization header as `Bearer ` 4. For client ID mismatches: Ensure you're using the correct token for the intended client ### Best Practices 1. **Token Storage**: Securely store tokens on the client side 2. **Error Handling**: Implement proper error handling for all scenarios 3. **Token Refresh**: Set up automatic token refresh before expiration 4. **Logging**: Log token validation failures for debugging purposes # Generate Access Token Source: https://api-docs.wisprflow.ai/generate_access_token POST /generate_access_token Generate a new client token (JWT) Use your org-level API key (`Bearer fl-xxxxxx`) to create a JWT token for a specific client. The token can be used at client-facing endpoints. ```json Response (200 OK) theme={null} { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 3600 } ``` ```json Request theme={null} { "client_id": "client123", "duration_secs": 3600, "metadata": { "user_name": "John Doe", "company": "Acme Corp" } } ``` # Voice Interface API Documentation Source: https://api-docs.wisprflow.ai/introduction > "We consistently achieved 100% accuracy" - MacLife Flow's Voice interface API allows you to create magical voice interactions in your applications. Flow can convert audio into text with high accuracy across 100+ languages with a blazing fast API. What separates Flow from traditional "speech-to-text" models is that it's optimized to understand what people say, and output text in their style: with auto-edits, removing filler words, getting names right, making their message more concise while maintaining their tone and more. * **Auto edits**: "Let's meet at 6pm, actually let's do 7" -> "Let's meet at 7pm" * **Concise while maintaining tone and removing filler words**: "Search for, um, what's it called, my flight tickets" -> "Search for my flight tickets" * **Getting names right**: "Hi Tony, how's it going?" -> "Hi Tanay, how's it going?" This lets you create the same magical experience in your application that users feel using the Wispr Flow desktop and mobile clients which let them use voice everywhere on their computers. ### Two easy ways to integrate Flow 1. **WebSocket API (recommended)** Stream audio via WebSocket to `/ws` (lower latency + streaming response) 2. **REST API**: Send a POST request to `/api` (slower, for when websockets are not available) ### Two ways to authenticate 1. **API-key based auth**: Keep your API key securely on your backend. This is easier, but is going to be lower latency since the requests can't be generated client-side directly 2. **Client side auth (recommended)**: Generate access tokens for your clients to let them directly access the API. This is lower latency and also makes it easier to implement with Websockets. # Quickstart Source: https://api-docs.wisprflow.ai/quickstart Create your API keys and send your first POST request. ## Step 1: Create your API key Login to the Developer Platform ([https://platform.wisprflow.ai](https://platform.wisprflow.ai)) and go to **API Keys > Create new key**. Flow API is only available by exclusive access. Your organization must be approved by the Flow team before you can use access the dashboard. Email us at [enterprise@wisprflow.ai](mailto:enterprise@wisprflow.ai) if you have any questions. **Note**: The API key will only be shown once. Make sure you store it somewhere safe. API Keys Screenshot We recommend setting up client side auth to reduce latency. Read more on our **Client side auth** docs ## Step 2: Record audio in your application Flow accepts audio as a **base64 string of with 16kHz PCM wav**. The [MediaRecorder](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder_API) Web API records audio in `.webm` format. There's a few resources linked below to help you convert your audio to the correct format that Flow accepts. > Potential gotcha: Web apps by default record `.webm` and not `.wav`. Make sure you convert it to wav and encode it as base64 before sending. * [wavtools](https://github.com/keithwhor/wavtools) **(Recommended)** - library for both recording and streaming Waveform Audio (.wav) data in the browser. # Request Schema Source: https://api-docs.wisprflow.ai/request_schema List of the types of information that Flow can process to improve dictation accuracy. In all our transcription endpoints, there are three different inputs that you can provide to the API. ## `audio` Base64 encoded, 16kHz wav audio of the recorded speech. This is the only required field. Maximum size is 25MB or 6 minutes of audio. ## `language` Optional list of (ISO 639-1) language codes that the user is expected to speak. Setting the list size to 1 forces the transcription into the specified language. Not providing an input attempts autodetection on full list of languages (less accurate). ## `context` Optional contextual information about the circumstances surrounding the user dictation. Flow can use these information to make its output more accurate by for example, getting names right, resolving speech ambiguities, etc. All properties are optional and will use default values if not provided. Information about the application the user is dictating into, used to customize the writing style. The name of the application. The type of the application. Currently supports the following list: * `email`: Email clients and anywhere the user would be trying to dictate an email. * `ai`: Applications where the user is conversing with an AI chatbot / agent and not a human. * `other`: Any application that does not fit in the two groups above. List of uncommon names or words relevant to the context that might be mentioned by the user. User ID in the app that the person is dictating in, like their email address in an email client application. First name of the speaker, used to make sure Flow spells the speaker's name correctly. Last name of the speaker. Text under and surrounding the cursor in the active textbox. Flow uses this information to decide casing, spacing and punctuation. The text immediately before the cursor. The text the user has highlighted. The text immediately after the cursor. Screenshot of the screen or the app the user is dictating in, for when the user is referencing something on the screen. Plaintext content of the current page in the app user is dictating in. This is a more efficient way of providing context compared to screenshot. HTML content of the app user is dictating in (a more feature-rich alternative to `content_text`). Chatbot style history of the conversation the user is dictating in. This typically applies to messaging and AI apps. Identifier of the conversation. For example name of group chat in case of a messaging app. List of names of other people in the conversation, used to get their names correct in case of uncommonly spelled names. List of recent messages in the conversation, in the chronological order. Used to identify proper context and names of things being mentioned that are not conversation participants. Type of the message sender. One of: `user`, `human`, `assistant` Content of the message. ## `properties` This field has been deprecated and its functionality replaced by the `context` field above. We strongly encourage you to migrate to the new schema. You can find the equivalent fields in the new request type. If both `context` and `properties` are provided, `properties` will be ignored. 2-digit ISO language code (e.g. 'en', 'es') Flow formats appropriately depending on if the user is prompting AI, writing an email, or other tasks. Options: 'ai', 'email', 'other' List of dictionary words to help with transcription accuracy The text immediately after the cursor. Flow uses it to decide spacing / punctuation. The text immediately before the cursor. Flow uses it to decide spacing / punctuation. The text the user has highlighted. Flow uses it to decide spacing / punctuation. # REST API (slower) Source: https://api-docs.wisprflow.ai/rest_api Requests through the REST API are slower than web socket requests. We only recommend using this if web sockets are not available in the environment you will be using. ### Connect: **API-key endpoint:** `https://platform-api.wisprflow.ai/api/v1/dash/api` **Client endpoint (Recommended):** `https://platform-api.wisprflow.ai/api/v1/dash/client_api` We recommend using the client endpoint with client-side authentication to connect directly to our servers to lower latency. ### Properties (deprecated) The `properties` field has been deprecated. Please use the new `context` field defintion in "Request Schemas" instead. The API accepts the following properties in the request body. All properties are optional and will use default values if not provided. ### How to use before\_text, after\_text, selected\_text You can send `before_text`, `after_text`, `selected_text` in the properties if the text is to be entered in a textbox with the user's cursor present. This is used to match spacing and punctuation with respect to the surrounding text. For example, if the text in your textbox is `Hey |man.` where `|` is the cursor: * `after_text`: `"man."` * `before_text`: `"Hey "` This way, if the transcript is `"how's it going"`, it will return `"how's it going "` with a space at the end because it needs a space before `"man."` ### Limitations * Make sure the audio you're sending is under 25MB and under 6 minutes at a time. # REST API Quickstart Source: https://api-docs.wisprflow.ai/rest_api_quickstart This guide provides a complete working example of how to use our REST API for audio transcription. The sample project demonstrates recording audio in the browser and sending it to our API for processing. ## Sample Project Below is a complete HTML file that demonstrates: * Browser-based audio recording * Audio format conversion (WebM to 16kHz WAV) * Base64 encoding * REST API integration * Response handling You can save this as an HTML file and run it directly in your browser: ```html theme={null} Audio Recorder

Audio Recorder

Status: Ready
``` ## Key Features This sample project demonstrates several important features: 1. **Audio Recording**: * Browser-based audio recording using the MediaRecorder API * Automatic conversion from WebM to WAV format * Resampling to 16kHz mono audio 2. **Audio Processing**: * WAV file generation with proper headers * Base64 encoding for API transmission 3. **API Integration**: * REST API authentication * JSON payload formatting * Response handling and display 4. **User Interface**: * Simple recording controls * Audio playback * Status updates * Response display ## Usage 1. Replace `` with your actual API key 2. Save the file with a `.html` extension 3. Open in a modern web browser 4. Click "Start Recording" to begin recording 5. Click "Stop Recording" to stop and send to the API 6. View the transcription response below the audio player Make sure you're using a modern browser that supports the MediaRecorder API and WebAudio API. The sample requires HTTPS or localhost for microphone access. # REST with API key auth Source: https://api-docs.wisprflow.ai/rest_api_transcribe POST /api Convert speech to text using the REST API Convert audio to text with support for multiple languages and context awareness. Use your API key for authentication. ### Request Body Base64 encoded, 16kHz wav audio. Maximum size is 25MB or 6 minutes of audio. Optional list of (ISO 639-1) language codes that the user is expected to speak. Setting the list size to 1 forces the transcription into the specified language. Not providing an input attempts autodetection on full list of languages (less accurate). Optional contextual information about the circumstances surrounding the user dictation. Flow can use these information to make its output more accurate by for example, getting names right, resolving speech ambiguities, etc. All properties are optional and will use default values if not provided. See [Request Schema](/request_schema) page for an exhaustive list of context attributes. Legacy API schema for providing context. Use the equivalent fields in the `context` field instead. If both `context` and `properties` are provided, `properties` will be ignored. See [Request Schema](/request_schema) page for an exhaustive list of properties. ```json Response (200 OK) theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "text": "Testing testing 1, 2, 3", "detected_language": "en", "total_time": 432, "generated_tokens": 9 } ``` ```json Request theme={null} { "audio": "UklGRiQA....", "language": ["en"], "context": { "app": { "type": "email" }, "dictionary_context": [], "textbox_contents": { "before_text": "", "selected_text": "", "after_text": "" }, // ... for a full list of available fields, see the "Request Schema" page } } ``` # Revoke Client Tokens Source: https://api-docs.wisprflow.ai/revoke_client_tokens POST /revoke_client_tokens Revoke all tokens for a specific client Use your org-level API key to revoke every token associated with a particular client\_id. ```json Response (200 OK) theme={null} { "status": "success", "message": "All tokens for client successfully revoked" } ``` ```json Request theme={null} { "client_id": "client123" } ``` # Revoke Token Source: https://api-docs.wisprflow.ai/revoke_token POST /revoke_token Revoke a specific client token Use your org-level API key to revoke a single JWT token, rendering it invalid for future requests. ```json Response (200 OK) theme={null} { "status": "success", "message": "Token successfully revoked" } ``` ```json Request theme={null} { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` # Usage & Billing Source: https://api-docs.wisprflow.ai/usage_billing All models are charged based on usage tokens. Once you get started with the API, head on over to Developer Platform's Billing to add in your payment method. This is also where you can see your API usage, which we update in near-realtime. Once your credits are over, you will be billed once a month. More details on payment will be outlined in your contract. > At this moment we don't have support to add API limits directly in the dashboard, make sure you use the API in your code responsibly. # Warm Up API Source: https://api-docs.wisprflow.ai/warm_up_api GET /warmup_dash Warm up the API connection to minimize latency Use this endpoint to warm up your connection to Flow's servers. This helps minimize latency for subsequent API calls by establishing and maintaining a connection. ### How it works When you call this endpoint: 1. A connection is established with Flow's servers 2. Server-side resources are pre-allocated 3. The connection is kept warm for a period of time 4. Subsequent API calls will have lower latency We recommend calling this endpoint before you expect to make API calls, especially for latency-sensitive applications. ```json Response (200 OK) theme={null} { "status": "warmed" } ``` ```bash Request theme={null} curl -X GET "https://platform-api.wisprflow.ai/api/v1/dash/warmup_dash" \ -H "Authorization: Bearer YOUR_API_KEY" ``` # Overview: Warm up (REST) Source: https://api-docs.wisprflow.ai/warm_up_rest_api The Warm-up REST API helps optimize latency and ensure smooth dictation sessions by maintaining a warm connection to Flow's servers. This is useful for REST API calls for both API-key and client-side auth. ## How to Use To optimize latency and ensure smooth dictation sessions using Flow API, you should warm up the API connection as follows: ### Call the Warmup Endpoint at Session Start As soon as the user starts a dictation, send a request to the warmup endpoint. This prepares the connection for low latency operation by eliminating potential "cold start" delays. ### Maintain Connection with Keep-Alive Use connection keep-alive settings to maintain a persistent connection for the duration of your session. A recommended keep-alive timeout is 60 seconds. When the keep-alive period ends, send another warmup request to refresh the connection. ### How It Works 1. **SSL/TLS Handshake**: Completes the initial SSL handshake 2. **TCP Connection Establishment**: Creates and maintains a persistent TCP connection 3. **Server Resource Initialization**: Ensures server-side resources are loaded and ready 4. **Connection Pool Preparation**: Prepares connection pools for subsequent requests ### Code Examples ###### Python Example ```python theme={null} import requests # Create a session to reuse the connection session = requests.Session() # First, warm up the connection session.get("https://platform-api.wisprflow.ai/api/v1/dash/warmup_dash") # Now use the warmed connection for the API call def transcribe_audio(api_key, audio_base64): response = session.post( "https://api.flowvoice.ai/api/v1/dash/api", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "audio": audio_base64, "properties": {} } ) return response.json() # Example usage api_key = "your_api_key" audio_base64 = "UklGRiQA..." # Your base64 encoded audio result = transcribe_audio(api_key, audio_base64) print(f"Transcription: {result['text']}") ``` ###### JavaScript/TypeScript Example ```typescript theme={null} async function warmupConnection(): Promise { try { const response = await fetch('https://platform-api.wisprflow.ai/api/v1/dash/warmup_dash'); return response.ok; } catch (error) { console.error('Warmup failed:', error); return false; } } // Import Axios and HTTPS import axios from 'axios'; import https from 'https'; // Create an Axios client with keep-alive const client = axios.create({ baseURL: 'https://api.flowvoice.ai', httpsAgent: new https.Agent({ keepAlive: true, keepAliveMsecs: 60000, // 60 seconds maxSockets: 10 }) }); // Function to transcribe audio using the API async function transcribeAudio(apiKey: string, audioBase64: string): Promise { try { const response = await client.post('/api/v1/dash/api', { audio: audioBase64, properties: {} }, { headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' } }); return response.data; } catch (error) { console.error('API call failed:', error); throw error; } } // Example usage (async () => { const apiKey = 'your_api_key'; const audioBase64 = 'UklGRiQA...'; // Your base64 encoded audio // Warm up the connection const isWarmedUp = await warmupConnection(); if (isWarmedUp) { console.log('Connection warmed up successfully.'); } else { console.log('Failed to warm up the connection.'); } // Call the API try { const result = await transcribeAudio(apiKey, audioBase64); console.log(`Transcription: ${result.text}`); } catch (error) { console.error('Failed to transcribe audio:', error); } })(); ``` ### Request No request body needed. ### Response # WebSocket API Source: https://api-docs.wisprflow.ai/websocket_api Access the Flow WebSocket API ## How it works ### Connect: Open a WebSocket connection to the server **API-key endpoint:** `wss://platform-api.wisprflow.ai/api/v1/dash/ws?api_key=Bearer%20` **Client auth endpoint (Recommended):** `wss://platform-api.wisprflow.ai/api/v1/dash/client_ws?client_key=Bearer%20` We recommend using the client endpoint with client-side authentication to connect directly to our servers to lower latency. ### Send Messages: * **Start**: Begin a new transcription session * **Append**: Send audio chunks sequentially, ideally 1-second chunks Make sure the chunks you send are of the same duration. Varying durations can cause unexpected failures. ### Receive Responses: Partial and final results are returned during the session. | TYPE | DESCRIPTION | Example | | ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------- | | auth | Authenticates the client with the server | `{ "type": "auth", "access_token": "..." }` | | append | Sends a chunk of audio data and (optionally) metadata to the server | `{ "type": "append", "audio": "...chunk_audio...", "position": 0 }` | | commit | Mark the end of audio | `{ "type": "commit", "total_packets": 284 }` | Once connected, the first message you send must be a start message, with any API properties you'd like to pass in. After receiving confirmation that the session started, you can send multiple chunks of audio data. You must stream base64-encoded single-channel 16-bit (int16) PCM wav data sampled at 16 KHz. When you finish sending all audio chunks, you MUST send a commit message that includes the total number of audio chunks sent. ## Step-by-Step Guide ### Establish WebSocket Connection Connect to the WebSocket server using your API key: ```javascript theme={null} const ws = new WebSocket("wss://platform-api.wisprflow.ai/api/v1/dash/ws?api_key=Bearer%20"); ws.onopen = () => { console.log("WebSocket connected"); }; ws.onerror = (error) => { console.error("WebSocket error:", error); }; ws.onclose = () => { console.log("WebSocket closed"); }; ``` ### Start a Session Send a start message to initialize the transcription session: ```javascript theme={null} ws.send(JSON.stringify({ type: "auth", access_token: "...", language: ["en"], // If known beforehand, set to list of languages the user speaks context: { // Optional contextual information used to improve dictation quality when applicable app: { name: "Weather Forecast Chatbot", type: "ai" // one of {email, ai, other} }, dictionary_context: [], // list of uncommon names or words relevant to the context user_identifier: "john_doe_1", user_first_name: "John", user_last_name: "Doe", textbox_contents: { before_text: "", // text immediately before cursor position selected_text: "", // text highlighted by cursor for replacement after_text: "" // text immediately after cursor position }, screenshot: null, // screenshor for when speaking about something on the screen content_text: null, // plaintext content of the app user is dictating in content_html: null, // HTML content of the app user is dictating in conversation: { // chatbot style history of conversation (messaging or AI app) id: "ai_chat_126", // conversation identifier participants: ["John Doe", "AI Assistant"], // list of people the user might be addresing messages: [ // list of messages in conversation, in chronological order { role: "user" // One of {user, human, assistant} content: "How is the weather in SF today?" }, { role: "assistant" content: "It's partly cloudy. Do you want to know the temperature?" } ] } } })); ``` Upon successful authentication, the server will respond with an `"auth"` message. ### Stream Audio Send audio chunks using append messages. Ensure each chunk is Base64-encoded and includes a sequential chunk\_number: ```javascript theme={null} ws.send(JSON.stringify({ type: "append", position: 0, audio_packets: { packets: [base64Audio1, base64Audio2, base64Audio3, ...], // you can send any number of packets volumes: [volume1, volume2, volume3, ...], // The number of volumes must match the number of packets packet_duration: BUFFER_SIZE / audioContext.sampleRate, // in seconds audio_encoding: "wav", // pcm wav data byte_encoding: "base64" // set to "binary" for reduced message size (see "Network Optimization" below) } })); ``` If you send 4 packets in the first and second `append` messages, the third append message must have `position: 8` ### Receive Final Transcription When all audio chunks have been sent, send a final append message with `final: true`: ```javascript theme={null} ws.send(JSON.stringify({ type: "commit", total_packets: n })); ws.onmessage = (event) => { const response = JSON.parse(event.data); if (response.status == "text") { if (response.final) { // final transcription result (websocket will close) console.log("Final server response"); } else { // intermediate transcription result (roughly every 30 seconds) console.log("Interim server response"); } } else if (response.status == "error") { // unrecoverable (websocket will close) console.log("Server returned error response"); } else { // other information console.log("Server returned other response"); } }; ``` ## Responses ### Connection Authenticated ```json theme={null} { "status": "auth" } ``` ### Commit Acknowledgement ```json theme={null} { "status": "info", "message": { "event": "commit_received" } } ``` ### Partial Transcriptions ```json theme={null} { "status": "text", "position": 180, "final": false, "body": { "text": "This is a partial transcription...", "detected_language": "en" } } ``` ### Final Transcription ```json theme={null} { "status": "text", "position": 205, "final": false, "body": { "text": "This is a partial transcription... and this is the full text.", "detected_language": "en" } } ``` ## Network Optimization To reduce the message size being sent over the network, instead of encoding binary data (audio and screenshot) using base64, you can serialize the message into the MessagePack format and send as binary data. To enable binary transmission mode, add the following field to the websocket header: ```typescript theme={null} Encoding: 'msgpack' ``` Also, set `byte_encoding: "binary"` in the append messages. When binary transmission mode is activated, the responses received over the websocket will also be serialized using MessagePack and will need deserialization by the client. # WebSocket Quickstart Source: https://api-docs.wisprflow.ai/websocket_quickstart This guide provides a complete working example of how to use our WebSocket API for real-time audio streaming and transcription. ## Sample Project Below is a complete HTML file that demonstrates: * WebSocket connection and authentication * Microphone access and audio processing * Real-time audio streaming * Handling transcription responses You can save the following two blocks of code as HTML and Javascript files respectively and serve them using a local server to test it directly in your browser: ### webSocketClient.html ```html theme={null} WebSocket Audio Stream

Audio Streaming via WebSocket

Status: Ready
Transcript will appear here...
``` ### audioProcessorWorklet.js ```javascript theme={null} class AudioProcessor extends AudioWorkletProcessor { constructor() { super(); this.port.onmessage = (event) => { if (event.data.type === 'setSampleRate') { this.targetSampleRate = event.data.sampleRate; this.bufferSize = event.data.bufferSize; this.port.postMessage({ type: 'ready' }); } }; this.buffer = []; } process(inputs, outputs, parameters) { const inputData = inputs[0][0]; // Convert to Float32Array if needed const floatData = new Float32Array(inputData); this.buffer.push(...floatData); // Send data when we have enough samples if (this.buffer.length >= this.bufferSize) { const chunk = new Float32Array(this.buffer.slice(0, this.bufferSize)); this.port.postMessage({ type: 'audioData', data: chunk }); this.buffer = this.buffer.slice(this.bufferSize); } return true; } } registerProcessor('audioProcessorWorklet', AudioProcessor); ``` ## Key Features This sample project demonstrates several important features: 1. **WebSocket Connection**: Establishes a secure WebSocket connection with verbose mode enabled 2. **Audio Processing**: * Captures audio from the microphone * Resamples to 16kHz * Converts to the correct format (16-bit PCM WAV) 3. **Streaming Protocol**: * Sends audio in chunks * Tracks packet positions * Calculates audio volumes * Handles final message with `final: true` 4. **Response Handling**: * Authentication responses * Info messages (in verbose mode) * Transcription updates * Error handling ## Usage 1. Replace `` with your actual API key 2. Replace `` with your access token 3. Save the file with a `.html` extension 4. Open in a modern web browser 5. Click "Start Streaming" to begin recording and transcribing 6. Click "Stop Streaming" to end the session Make sure you're using a modern browser that supports the WebAudio API and WebSocket connections. The sample requires HTTPS or localhost for microphone access. Safari is known to handle microphone access differently.