{
  "asyncapi": "3.0.0",
  "channels": {
    "converseStream": {
      "address": "/v1/converse/stream",
      "description": "Use one connection for one conversation. Start with `initializeConnection`, then send text or add completed turns. The server keeps the conversation history until the socket closes and returns generated audio as `responseAudio` messages.",
      "externalDocs": {
        "description": "WebSocket reference and examples.",
        "url": "https://docs.kalpalabs.ai/reference#wss-v1-converse-stream"
      },
      "messages": {
        "addTurn": {
          "$ref": "#/components/messages/addTurn"
        },
        "cancelResponse": {
          "$ref": "#/components/messages/cancelResponse"
        },
        "error": {
          "$ref": "#/components/messages/error"
        },
        "initializeConnection": {
          "$ref": "#/components/messages/initializeConnection"
        },
        "responseAudio": {
          "$ref": "#/components/messages/responseAudio"
        },
        "responseCreated": {
          "$ref": "#/components/messages/responseCreated"
        },
        "responseDone": {
          "$ref": "#/components/messages/responseDone"
        },
        "sendText": {
          "$ref": "#/components/messages/sendText"
        },
        "sessionCreated": {
          "$ref": "#/components/messages/sessionCreated"
        }
      },
      "title": "Conversation stream",
      "x-close-codes": [
        {
          "action": "Retry.",
          "code": 1011,
          "meaning": "Internal server error."
        },
        {
          "action": "Fix the message before reconnecting.",
          "code": 4400,
          "meaning": "Protocol violation."
        },
        {
          "action": "Check the API key.",
          "code": 4401,
          "meaning": "Authentication failed."
        },
        {
          "action": "Reconnect.",
          "code": 4408,
          "meaning": "Initialization or idle timeout."
        },
        {
          "action": "Retry with backoff.",
          "code": 4429,
          "meaning": "Reserved for rate limiting; not currently emitted."
        },
        {
          "action": "Retry with the same key.",
          "code": 4503,
          "meaning": "API-key verification is temporarily unavailable."
        }
      ]
    },
    "ttsStream": {
      "address": "/v1/tts/{voice_id}/stream",
      "description": "Use one connection for one named voice (`voice_id` as listed by `GET /v1/voices`). Start with `initializeConnection`, then stream text with `sendText` and set `flush` to true to hear it. Each flushed utterance is generated independently in the connection's voice — no state carries from one response to the next. One response generates at a time; a flush sent mid-generation is queued (one slot) and starts when the current response settles, and a bare `cancelResponse` abandons everything undelivered — the in-flight generation, the queued utterance, and buffered text.",
      "externalDocs": {
        "description": "WebSocket reference and examples.",
        "url": "https://docs.kalpalabs.ai/reference#wss-v1-tts-voice-id-stream"
      },
      "messages": {
        "cancelResponse": {
          "$ref": "#/components/messages/ttsCancelResponse"
        },
        "error": {
          "$ref": "#/components/messages/error"
        },
        "initializeConnection": {
          "$ref": "#/components/messages/ttsInitializeConnection"
        },
        "responseAudio": {
          "$ref": "#/components/messages/responseAudio"
        },
        "responseCreated": {
          "$ref": "#/components/messages/ttsResponseCreated"
        },
        "responseDone": {
          "$ref": "#/components/messages/ttsResponseDone"
        },
        "sendText": {
          "$ref": "#/components/messages/ttsSendText"
        },
        "sessionCreated": {
          "$ref": "#/components/messages/ttsSessionCreated"
        }
      },
      "parameters": {
        "voice_id": {
          "description": "A named voice id, as listed by `GET /v1/voices`."
        }
      },
      "title": "Named-voice TTS stream",
      "x-close-codes": [
        {
          "action": "Retry.",
          "code": 1011,
          "meaning": "Internal server error."
        },
        {
          "action": "Fix the message before reconnecting.",
          "code": 4400,
          "meaning": "Protocol violation."
        },
        {
          "action": "Check the API key.",
          "code": 4401,
          "meaning": "Authentication failed."
        },
        {
          "action": "See `GET /v1/voices` for the available voices.",
          "code": 4404,
          "meaning": "Unknown voice id."
        },
        {
          "action": "Reconnect.",
          "code": 4408,
          "meaning": "Initialization or idle timeout."
        },
        {
          "action": "Retry with backoff.",
          "code": 4429,
          "meaning": "Reserved for rate limiting; not currently emitted."
        },
        {
          "action": "Retry with the same key.",
          "code": 4503,
          "meaning": "API-key verification is temporarily unavailable."
        }
      ]
    }
  },
  "components": {
    "messages": {
      "addTurn": {
        "name": "addTurn",
        "payload": {
          "properties": {
            "audio_wav_b64": {
              "description": "Base64-encoded WAV audio.",
              "minLength": 1,
              "title": "Audio Wav B64",
              "type": "string"
            },
            "speaker_id": {
              "minimum": 0,
              "title": "Speaker Id",
              "type": "integer"
            },
            "text": {
              "description": "Transcript for the audio.",
              "minLength": 1,
              "title": "Text",
              "type": "string"
            },
            "type": {
              "const": "addTurn",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "type",
            "speaker_id",
            "text",
            "audio_wav_b64"
          ],
          "title": "AddTurn",
          "type": "object"
        },
        "summary": "Adds a completed text-and-audio turn to the conversation history.",
        "title": "addTurn"
      },
      "cancelResponse": {
        "name": "cancelResponse",
        "payload": {
          "properties": {
            "response_id": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "description": "Response to cancel. Omit to cancel the current response.",
              "title": "Response Id"
            },
            "type": {
              "const": "cancelResponse",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "title": "CancelResponse",
          "type": "object"
        },
        "summary": "Stops the current response.",
        "title": "cancelResponse"
      },
      "error": {
        "name": "error",
        "payload": {
          "properties": {
            "error": {
              "$ref": "#/components/schemas/WsErrorBody"
            },
            "fatal": {
              "description": "True when the connection is about to close.",
              "title": "Fatal",
              "type": "boolean"
            },
            "response_id": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "description": "Present when the error belongs to a specific generation.",
              "title": "Response Id"
            },
            "type": {
              "const": "error",
              "default": "error",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "fatal",
            "error"
          ],
          "title": "WsError",
          "type": "object"
        },
        "summary": "Reports a WebSocket error.",
        "title": "error"
      },
      "initializeConnection": {
        "name": "initializeConnection",
        "payload": {
          "properties": {
            "api_key": {
              "description": "Your Kalpa API key.",
              "title": "Api Key",
              "type": "string"
            },
            "history_limit": {
              "anyOf": [
                {
                  "maximum": 64,
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "description": "Optional rolling number of completed turns retained for each response.",
              "title": "History Limit"
            },
            "model": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "description": "Model id. Omit for the default model.",
              "title": "Model"
            },
            "params": {
              "$ref": "#/components/schemas/GenParamsModel",
              "description": "Generation parameters for every response on this connection."
            },
            "type": {
              "const": "initializeConnection",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "type",
            "api_key"
          ],
          "title": "InitializeConnection",
          "type": "object"
        },
        "summary": "Starts and authenticates the WebSocket session. Send this message first.",
        "title": "initializeConnection"
      },
      "responseAudio": {
        "name": "responseAudio",
        "payload": {
          "properties": {
            "frame": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "description": "Backend frame counter; informational.",
              "title": "Frame"
            },
            "pcm_b64": {
              "description": "Base64-encoded raw PCM audio.",
              "title": "Pcm B64",
              "type": "string"
            },
            "response_id": {
              "title": "Response Id",
              "type": "string"
            },
            "type": {
              "const": "responseAudio",
              "default": "responseAudio",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "response_id",
            "pcm_b64"
          ],
          "title": "ResponseAudio",
          "type": "object"
        },
        "summary": "A chunk of generated audio.",
        "title": "responseAudio"
      },
      "responseCreated": {
        "name": "responseCreated",
        "payload": {
          "properties": {
            "audio_quality": {
              "enum": [
                "low",
                "medium",
                "high"
              ],
              "title": "Audio Quality",
              "type": "string"
            },
            "response_id": {
              "description": "Id for this response.",
              "title": "Response Id",
              "type": "string"
            },
            "sample_rate": {
              "title": "Sample Rate",
              "type": "integer"
            },
            "speaker_id": {
              "description": "Speaker for this response.",
              "title": "Speaker Id",
              "type": "integer"
            },
            "type": {
              "const": "responseCreated",
              "default": "responseCreated",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "response_id",
            "speaker_id",
            "sample_rate",
            "audio_quality"
          ],
          "title": "ResponseCreated",
          "type": "object"
        },
        "summary": "Confirms that response generation has started.",
        "title": "responseCreated"
      },
      "responseDone": {
        "name": "responseDone",
        "payload": {
          "properties": {
            "meta": {
              "additionalProperties": true,
              "description": "Public generation timing and runtime metadata.",
              "title": "Meta",
              "type": "object"
            },
            "response_id": {
              "title": "Response Id",
              "type": "string"
            },
            "speaker_id": {
              "title": "Speaker Id",
              "type": "integer"
            },
            "status": {
              "enum": [
                "completed",
                "cancelled"
              ],
              "title": "Status",
              "type": "string"
            },
            "text": {
              "description": "Text for the response.",
              "title": "Text",
              "type": "string"
            },
            "type": {
              "const": "responseDone",
              "default": "responseDone",
              "title": "Type",
              "type": "string"
            },
            "usage": {
              "$ref": "#/components/schemas/Usage"
            }
          },
          "required": [
            "response_id",
            "speaker_id",
            "status",
            "text",
            "usage"
          ],
          "title": "ResponseDone",
          "type": "object"
        },
        "summary": "Confirms that the response has completed or was cancelled.",
        "title": "responseDone"
      },
      "sendText": {
        "name": "sendText",
        "payload": {
          "properties": {
            "flush": {
              "default": false,
              "description": "Ends the turn and starts generation when true.",
              "title": "Flush",
              "type": "boolean"
            },
            "speaker_id": {
              "anyOf": [
                {
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "description": "Speaker for this turn. Required on the first `sendText` message.",
              "title": "Speaker Id"
            },
            "text": {
              "default": "",
              "description": "Text to append to the turn.",
              "title": "Text",
              "type": "string"
            },
            "type": {
              "const": "sendText",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "title": "SendText",
          "type": "object"
        },
        "summary": "Adds text to the current turn. Set `flush` to true to generate the response.",
        "title": "sendText"
      },
      "sessionCreated": {
        "name": "sessionCreated",
        "payload": {
          "properties": {
            "audio_quality": {
              "description": "Fidelity tier responses are rendered at.",
              "enum": [
                "low",
                "medium",
                "high"
              ],
              "title": "Audio Quality",
              "type": "string"
            },
            "channels": {
              "default": 1,
              "title": "Channels",
              "type": "integer"
            },
            "model": {
              "description": "Model serving the session.",
              "title": "Model",
              "type": "string"
            },
            "output_format": {
              "const": "pcm_s16le",
              "default": "pcm_s16le",
              "description": "Audio encoding for response chunks.",
              "title": "Output Format",
              "type": "string"
            },
            "sample_rate": {
              "description": "Response audio sample rate in Hz.",
              "title": "Sample Rate",
              "type": "integer"
            },
            "session_id": {
              "description": "Id for this conversation.",
              "title": "Session Id",
              "type": "string"
            },
            "type": {
              "const": "sessionCreated",
              "default": "sessionCreated",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "session_id",
            "model",
            "sample_rate",
            "audio_quality"
          ],
          "title": "SessionCreated",
          "type": "object"
        },
        "summary": "Confirms that the session is ready.",
        "title": "sessionCreated"
      },
      "ttsCancelResponse": {
        "name": "cancelResponse",
        "payload": {
          "properties": {
            "response_id": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "description": "Response to cancel. Omit to cancel the current response.",
              "title": "Response Id"
            },
            "type": {
              "const": "cancelResponse",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "title": "CancelResponse",
          "type": "object"
        },
        "summary": "Stops the current response. Without `response_id` it abandons everything undelivered — the\nin-flight generation, the queued utterance, and buffered text (nothing from an abandoned turn\ncan leak into the next one; a discarded queued utterance produces no responseDone). With\n`response_id` it cancels that specific response only, leaving buffer and queue intact.",
        "title": "cancelResponse"
      },
      "ttsInitializeConnection": {
        "name": "initializeConnection",
        "payload": {
          "properties": {
            "api_key": {
              "description": "Your Kalpa API key.",
              "title": "Api Key",
              "type": "string"
            },
            "generation_config": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/GenerationConfig"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "description": "Enable and tune server-side segmentation of streamed text. Omit to generate only on flush."
            },
            "model": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "description": "Model id. Omit for the default model.",
              "title": "Model"
            },
            "params": {
              "$ref": "#/components/schemas/GenParamsModel",
              "description": "Generation parameters for every response on this connection."
            },
            "type": {
              "const": "initializeConnection",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "type",
            "api_key"
          ],
          "title": "InitializeConnection",
          "type": "object"
        },
        "summary": "Starts and authenticates the session. Send this message first.",
        "title": "initializeConnection"
      },
      "ttsResponseCreated": {
        "name": "responseCreated",
        "payload": {
          "properties": {
            "audio_quality": {
              "enum": [
                "low",
                "medium",
                "high"
              ],
              "title": "Audio Quality",
              "type": "string"
            },
            "response_id": {
              "description": "Id for this response.",
              "title": "Response Id",
              "type": "string"
            },
            "sample_rate": {
              "title": "Sample Rate",
              "type": "integer"
            },
            "type": {
              "const": "responseCreated",
              "default": "responseCreated",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "response_id",
            "sample_rate",
            "audio_quality"
          ],
          "title": "ResponseCreated",
          "type": "object"
        },
        "summary": "Confirms that response generation has started.",
        "title": "responseCreated"
      },
      "ttsResponseDone": {
        "name": "responseDone",
        "payload": {
          "properties": {
            "meta": {
              "additionalProperties": true,
              "description": "Public generation timing and runtime metadata.",
              "title": "Meta",
              "type": "object"
            },
            "response_id": {
              "title": "Response Id",
              "type": "string"
            },
            "status": {
              "enum": [
                "completed",
                "cancelled"
              ],
              "title": "Status",
              "type": "string"
            },
            "text": {
              "description": "Text for the response.",
              "title": "Text",
              "type": "string"
            },
            "type": {
              "const": "responseDone",
              "default": "responseDone",
              "title": "Type",
              "type": "string"
            },
            "usage": {
              "$ref": "#/components/schemas/Usage"
            }
          },
          "required": [
            "response_id",
            "status",
            "text",
            "usage"
          ],
          "title": "ResponseDone",
          "type": "object"
        },
        "summary": "Confirms that the response has completed or was cancelled.",
        "title": "responseDone"
      },
      "ttsSendText": {
        "name": "sendText",
        "payload": {
          "properties": {
            "flush": {
              "default": false,
              "description": "Ends the utterance and starts generation when true.",
              "title": "Flush",
              "type": "boolean"
            },
            "text": {
              "default": "",
              "description": "Text to append to the utterance.",
              "title": "Text",
              "type": "string"
            },
            "type": {
              "const": "sendText",
              "title": "Type",
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "title": "SendText",
          "type": "object"
        },
        "summary": "Adds text to the pending utterance. Set `flush` to true to generate its audio. A flush that\narrives while a response is still generating is queued (one slot) and starts when that response\nsettles; only a flush arriving while another is already queued is rejected.",
        "title": "sendText"
      },
      "ttsSessionCreated": {
        "name": "sessionCreated",
        "payload": {
          "properties": {
            "audio_quality": {
              "description": "Fidelity tier responses are rendered at.",
              "enum": [
                "low",
                "medium",
                "high"
              ],
              "title": "Audio Quality",
              "type": "string"
            },
            "channels": {
              "default": 1,
              "title": "Channels",
              "type": "integer"
            },
            "model": {
              "description": "Model serving the session.",
              "title": "Model",
              "type": "string"
            },
            "output_format": {
              "const": "pcm_s16le",
              "default": "pcm_s16le",
              "description": "Audio encoding for response chunks.",
              "title": "Output Format",
              "type": "string"
            },
            "sample_rate": {
              "description": "Response audio sample rate in Hz.",
              "title": "Sample Rate",
              "type": "integer"
            },
            "session_id": {
              "description": "Id for this connection.",
              "title": "Session Id",
              "type": "string"
            },
            "type": {
              "const": "sessionCreated",
              "default": "sessionCreated",
              "title": "Type",
              "type": "string"
            },
            "voice_id": {
              "description": "The named voice every response speaks in.",
              "title": "Voice Id",
              "type": "string"
            }
          },
          "required": [
            "session_id",
            "model",
            "voice_id",
            "sample_rate",
            "audio_quality"
          ],
          "title": "SessionCreated",
          "type": "object"
        },
        "summary": "Confirms that the session is ready.",
        "title": "sessionCreated"
      }
    },
    "schemas": {
      "GenParamsModel": {
        "description": "Generation knobs, all optional — the defaults are the tuned production sampling, shared by\nevery generation endpoint (served with UI ranges at GET /v1/info).",
        "properties": {
          "acoustic_temperature": {
            "anyOf": [
              {
                "maximum": 1.5,
                "minimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Temperature for the voice's fine acoustic detail; null = follow `temperature`.",
            "title": "Acoustic Temperature"
          },
          "audio_quality": {
            "default": "high",
            "description": "Playback fidelity: high = full quality (default); lower tiers reduce fidelity, not payload size.",
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "title": "Audio Quality",
            "type": "string"
          },
          "max_new_tokens": {
            "anyOf": [
              {
                "maximum": 2048,
                "minimum": 16,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional generation cap; null uses the model's remaining context window.",
            "title": "Max New Tokens"
          },
          "temperature": {
            "default": 0.9,
            "maximum": 1.5,
            "minimum": 0,
            "title": "Temperature",
            "type": "number"
          }
        },
        "title": "GenParamsModel",
        "type": "object"
      },
      "GenerationConfig": {
        "description": "Opts the connection into server-side segmentation: audio generation starts once buffered\ntext crosses the schedule's next threshold and ends at a complete sentence, instead of waiting\nfor `flush`. Text that runs twice the threshold with no sentence boundary is cut at a clause\nor word gap instead, so first audio stays bounded. An utterance's segments stay prosodically\ncontinuous, and `flush` still marks its end. Omit the whole object for the classic\ngenerate-only-on-flush behavior.",
        "properties": {
          "chunk_length_schedule": {
            "description": "Buffered-character thresholds before each successive segment of an utterance may start generating; the last value repeats. Lower values trade prosodic context for earlier first audio.",
            "items": {
              "maximum": 2000,
              "minimum": 50,
              "type": "integer"
            },
            "maxItems": 10,
            "minItems": 1,
            "title": "Chunk Length Schedule",
            "type": "array"
          }
        },
        "title": "GenerationConfig",
        "type": "object"
      },
      "Usage": {
        "properties": {
          "input_audio_seconds": {
            "default": 0,
            "description": "Seconds of input audio supplied (converse).",
            "title": "Input Audio Seconds",
            "type": "number"
          },
          "input_chars": {
            "default": 0,
            "description": "Characters of input text billed for this request.",
            "title": "Input Chars",
            "type": "integer"
          },
          "output_audio_seconds": {
            "default": 0,
            "description": "Seconds of audio generated.",
            "title": "Output Audio Seconds",
            "type": "number"
          }
        },
        "title": "Usage",
        "type": "object"
      },
      "WsErrorBody": {
        "properties": {
          "message": {
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Id for the session or response.",
            "title": "Request Id"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "message"
        ],
        "title": "WsErrorBody",
        "type": "object"
      }
    }
  },
  "defaultContentType": "application/json",
  "info": {
    "description": "The WebSocket surface: the stateful conversational stream (multi-speaker history, text per speaker) and the named-voice TTS stream (one voice per connection, independent utterances). Both return raw-PCM audio as it is generated and complement the REST contract in `openapi.json`.",
    "title": "Kalpa Speech API — streaming WebSockets",
    "version": "0.1.0"
  },
  "operations": {
    "clientMessages": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/converseStream"
      },
      "messages": [
        {
          "$ref": "#/channels/converseStream/messages/initializeConnection"
        },
        {
          "$ref": "#/channels/converseStream/messages/sendText"
        },
        {
          "$ref": "#/channels/converseStream/messages/addTurn"
        },
        {
          "$ref": "#/channels/converseStream/messages/cancelResponse"
        }
      ],
      "summary": "Messages the client sends."
    },
    "serverMessages": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/converseStream"
      },
      "messages": [
        {
          "$ref": "#/channels/converseStream/messages/sessionCreated"
        },
        {
          "$ref": "#/channels/converseStream/messages/responseCreated"
        },
        {
          "$ref": "#/channels/converseStream/messages/responseAudio"
        },
        {
          "$ref": "#/channels/converseStream/messages/responseDone"
        },
        {
          "$ref": "#/channels/converseStream/messages/error"
        }
      ],
      "summary": "Messages the client receives."
    },
    "ttsClientMessages": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/ttsStream"
      },
      "messages": [
        {
          "$ref": "#/channels/ttsStream/messages/initializeConnection"
        },
        {
          "$ref": "#/channels/ttsStream/messages/sendText"
        },
        {
          "$ref": "#/channels/ttsStream/messages/cancelResponse"
        }
      ],
      "summary": "Messages the client sends."
    },
    "ttsServerMessages": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/ttsStream"
      },
      "messages": [
        {
          "$ref": "#/channels/ttsStream/messages/sessionCreated"
        },
        {
          "$ref": "#/channels/ttsStream/messages/responseCreated"
        },
        {
          "$ref": "#/channels/ttsStream/messages/responseAudio"
        },
        {
          "$ref": "#/channels/ttsStream/messages/responseDone"
        },
        {
          "$ref": "#/channels/ttsStream/messages/error"
        }
      ],
      "summary": "Messages the client receives."
    }
  },
  "servers": {
    "production": {
      "description": "Auth rides the first message, not handshake headers.",
      "host": "api.kalpalabs.ai",
      "protocol": "wss"
    }
  }
}
