KugelAudio · AsyncAPI Specification

KugelAudio TTS Streaming API

Version v1

API Evangelist description of KugelAudio's documented WebSocket streaming surface. KugelAudio publishes no AsyncAPI document of its own; this file is GENERATED from the provider's own published wire-format reference and is not an authoritative provider artifact. Every channel, message, and field below is transcribed from the docs pages listed in x-apievangelist-sources — none are invented. The three streaming channels are absent from the provider's OpenAPI (https://api.kugelaudio.com/openapi.json), which covers only the REST surface, so this is the only machine-readable description of the streaming contract.

View Spec View on GitHub VoiceText-to-SpeechSpeech SynthesisVoice AIVoice CloningAudioArtificial IntelligenceMachine LearningStreamingReal-TimeConversational AIEuropeData SovereigntyGDPRCompanyAsyncAPIEventsWebSockets

Channels

streamSpeech
One request per connection cycle; audio chunks stream back and the cycle ends with a `final` message carrying stats and per-request usage. The socket is reusable across requests.
streamInput
Token-by-token text input for LLM agents. Send config once (sticky for the connection), stream text, then flush to end the turn. One turn equals one backend session; idle turns auto-flush after about 5 seconds and emit a warning frame.
multiContext
Up to 20 independent audio streams over a single connection, each addressed by context_id. Contexts auto-close after 20 seconds of inactivity; an empty-text frame acts as a keep-alive.

Messages

✉
generateRequest
Generation request
✉
configMessage
Session config
✉
textMessage
textMessage
✉
flushMessage
flushMessage
✉
cancelMessage
Barge-in
✉
closeMessage
closeMessage
✉
contextText
Context text frame
✉
contextFlush
contextFlush
✉
closeContext
closeContext
✉
closeSocket
closeSocket
✉
updateSettings
updateSettings
✉
settingsUpdated
settingsUpdated
✉
audioChunk
Audio chunk
✉
wordTimestamps
wordTimestamps
✉
finalWithUsage
Request complete
✉
errorFrame
Error frame

Servers

wss
production
Canonical geo-routed WebSocket endpoint.
wss
eu
Direct EU WebSocket endpoint.

AsyncAPI Specification

Raw ↑
asyncapi: 3.0.0
info:
  title: KugelAudio TTS Streaming API
  version: v1
  description: >-
    API Evangelist description of KugelAudio's documented WebSocket streaming
    surface. KugelAudio publishes no AsyncAPI document of its own; this file is
    GENERATED from the provider's own published wire-format reference and is not
    an authoritative provider artifact. Every channel, message, and field below
    is transcribed from the docs pages listed in x-apievangelist-sources — none
    are invented. The three streaming channels are absent from the provider's
    OpenAPI (https://api.kugelaudio.com/openapi.json), which covers only the
    REST surface, so this is the only machine-readable description of the
    streaming contract.
  contact:
    name: KugelAudio
    url: https://docs.kugelaudio.com
    email: hello@kugelaudio.com
  x-apievangelist-generated: '2026-07-19'
  x-apievangelist-method: generated
  x-apievangelist-sources:
    - https://docs.kugelaudio.com/api-reference/tts/stream
    - https://docs.kugelaudio.com/api-reference/tts/stream-input
    - https://docs.kugelaudio.com/api-reference/tts/multi-context
    - https://docs.kugelaudio.com/api-reference/tts/audio-formats
    - https://docs.kugelaudio.com/api-reference/errors
servers:
  production:
    host: api.kugelaudio.com
    protocol: wss
    description: Canonical geo-routed WebSocket endpoint.
    security:
      - $ref: '#/components/securitySchemes/apiKeyQuery'
  eu:
    host: api.eu.kugelaudio.com
    protocol: wss
    description: Direct EU WebSocket endpoint.
    security:
      - $ref: '#/components/securitySchemes/apiKeyQuery'
channels:
  streamSpeech:
    address: /ws/tts
    title: Stream Speech
    description: >-
      One request per connection cycle; audio chunks stream back and the cycle
      ends with a `final` message carrying stats and per-request usage. The
      socket is reusable across requests.
    messages:
      generateRequest: {$ref: '#/components/messages/generateRequest'}
      updateSettings: {$ref: '#/components/messages/updateSettings'}
      audioChunk: {$ref: '#/components/messages/audioChunk'}
      wordTimestamps: {$ref: '#/components/messages/wordTimestamps'}
      settingsUpdated: {$ref: '#/components/messages/settingsUpdated'}
      finalWithUsage: {$ref: '#/components/messages/finalWithUsage'}
      errorFrame: {$ref: '#/components/messages/errorFrame'}
  streamInput:
    address: /ws/tts/stream
    title: Stream Input
    description: >-
      Token-by-token text input for LLM agents. Send config once (sticky for the
      connection), stream text, then flush to end the turn. One turn equals one
      backend session; idle turns auto-flush after about 5 seconds and emit a
      warning frame.
    messages:
      configMessage: {$ref: '#/components/messages/configMessage'}
      textMessage: {$ref: '#/components/messages/textMessage'}
      flushMessage: {$ref: '#/components/messages/flushMessage'}
      cancelMessage: {$ref: '#/components/messages/cancelMessage'}
      closeMessage: {$ref: '#/components/messages/closeMessage'}
      updateSettings: {$ref: '#/components/messages/updateSettings'}
      audioChunk: {$ref: '#/components/messages/audioChunk'}
      wordTimestamps: {$ref: '#/components/messages/wordTimestamps'}
      errorFrame: {$ref: '#/components/messages/errorFrame'}
  multiContext:
    address: /ws/tts/multi
    title: Multi-Context Streaming
    description: >-
      Up to 20 independent audio streams over a single connection, each
      addressed by context_id. Contexts auto-close after 20 seconds of
      inactivity; an empty-text frame acts as a keep-alive.
    messages:
      contextText: {$ref: '#/components/messages/contextText'}
      contextFlush: {$ref: '#/components/messages/contextFlush'}
      closeContext: {$ref: '#/components/messages/closeContext'}
      closeSocket: {$ref: '#/components/messages/closeSocket'}
      updateSettings: {$ref: '#/components/messages/updateSettings'}
      audioChunk: {$ref: '#/components/messages/audioChunk'}
      errorFrame: {$ref: '#/components/messages/errorFrame'}
operations:
  sendGenerateRequest:
    action: send
    channel: {$ref: '#/channels/streamSpeech'}
    messages:
      - {$ref: '#/channels/streamSpeech/messages/generateRequest'}
  receiveStreamedAudio:
    action: receive
    channel: {$ref: '#/channels/streamSpeech'}
    messages:
      - {$ref: '#/channels/streamSpeech/messages/audioChunk'}
      - {$ref: '#/channels/streamSpeech/messages/finalWithUsage'}
  sendTurnText:
    action: send
    channel: {$ref: '#/channels/streamInput'}
    messages:
      - {$ref: '#/channels/streamInput/messages/configMessage'}
      - {$ref: '#/channels/streamInput/messages/textMessage'}
      - {$ref: '#/channels/streamInput/messages/flushMessage'}
  receiveTurnAudio:
    action: receive
    channel: {$ref: '#/channels/streamInput'}
    messages:
      - {$ref: '#/channels/streamInput/messages/audioChunk'}
  sendContextText:
    action: send
    channel: {$ref: '#/channels/multiContext'}
    messages:
      - {$ref: '#/channels/multiContext/messages/contextText'}
  receiveContextAudio:
    action: receive
    channel: {$ref: '#/channels/multiContext'}
    messages:
      - {$ref: '#/channels/multiContext/messages/audioChunk'}
components:
  securitySchemes:
    apiKeyQuery:
      type: httpApiKey
      name: api_key
      in: query
      description: >-
        API key supplied as the api_key query parameter on the WebSocket URL.
        An Authorization Bearer header is also accepted where the client
        supports setting headers on the handshake.
  messages:
    generateRequest:
      name: generateRequest
      title: Generation request
      contentType: application/json
      payload:
        type: object
        required: [text, voice_id]
        properties:
          text: {type: string, maxLength: 10000}
          model_id: {type: string, default: kugel-3}
          voice_id: {type: integer}
          cfg_scale: {type: number, default: 2.0, minimum: 1.2, maximum: 2.5}
          temperature: {type: number, default: 0.4, minimum: 0, maximum: 1}
          max_new_tokens: {type: integer, default: 2048, minimum: 1, maximum: 8192}
          sample_rate: {type: integer, default: 24000, enum: [8000, 16000, 22050, 24000]}
          output_format: {type: string, description: 'Combined codec + rate token, e.g. ulaw_8000.'}
          normalize: {type: boolean, default: true}
          language: {type: string, description: ISO 639-1 code.}
          speed: {type: number, default: 1.0, minimum: 0.8, maximum: 1.2}
          word_timestamps: {type: boolean, default: false}
          speaker_prefix: {type: boolean, default: true}
          dictionary_ids: {type: array, maxItems: 50, items: {type: integer}}
    configMessage:
      name: configMessage
      title: Session config
      contentType: application/json
      payload:
        type: object
        properties:
          voice_id: {type: integer}
          model_id: {type: string}
          cfg_scale: {type: number}
          temperature: {type: number, default: 0.4}
          sample_rate: {type: integer, default: 24000}
          normalize: {type: boolean, default: true}
          language: {type: string}
          word_timestamps: {type: boolean, default: false}
          flush_timeout_ms: {type: integer, default: 500}
          max_buffer_length: {type: integer, default: 1000}
          chunk_length_schedule: {type: array, items: {type: integer}, default: [5, 80, 150, 250]}
          auto_mode: {type: boolean, default: false}
          speed: {type: number, default: 1.0}
          dictionary_ids: {type: array, items: {type: integer}}
    textMessage:
      name: textMessage
      contentType: application/json
      payload:
        type: object
        required: [text]
        properties:
          text: {type: string}
          flush: {type: boolean}
    flushMessage:
      name: flushMessage
      contentType: application/json
      payload:
        type: object
        properties:
          flush: {type: boolean, const: true}
    cancelMessage:
      name: cancelMessage
      title: Barge-in
      description: Abandons the current turn immediately; the socket stays open.
      contentType: application/json
      payload:
        type: object
        properties:
          cancel: {type: boolean, const: true}
    closeMessage:
      name: closeMessage
      description: >-
        Ends the current session while the WebSocket stays open.
        {"end_session": true} is an accepted alias; {"close_socket": true} ends
        the session and closes the connection.
      contentType: application/json
      payload:
        type: object
        properties:
          close: {type: boolean, const: true}
    contextText:
      name: contextText
      title: Context text frame
      description: >-
        Creates or addresses a context. An empty-text frame acts as a keep-alive
        that resets the context inactivity timeout without generating audio.
      contentType: application/json
      payload:
        type: object
        required: [context_id]
        properties:
          context_id: {type: string}
          text: {type: string}
          flush: {type: boolean}
          output_format: {type: string}
          voice_settings:
            type: object
            properties:
              voice_id: {type: integer}
              cfg_scale: {type: number}
              max_new_tokens: {type: integer}
    contextFlush:
      name: contextFlush
      contentType: application/json
      payload:
        type: object
        required: [context_id]
        properties:
          context_id: {type: string}
          flush: {type: boolean, const: true}
    closeContext:
      name: closeContext
      description: >-
        Closes a context, letting queued sentences finish. With
        "immediate": true it cancels in-flight generation and drops buffered
        text (barge-in).
      contentType: application/json
      payload:
        type: object
        required: [context_id]
        properties:
          context_id: {type: string}
          close_context: {type: boolean, const: true}
          immediate: {type: boolean}
    closeSocket:
      name: closeSocket
      contentType: application/json
      payload:
        type: object
        properties:
          close_socket: {type: boolean, const: true}
    updateSettings:
      name: updateSettings
      description: >-
        Sets sticky defaults for six generation parameters. Identity and
        audio-format fields (voice_id, model_id, sample_rate, output_format,
        dictionary_ids) are rejected with a VALIDATION_ERROR frame.
      contentType: application/json
      payload:
        type: object
        properties:
          update_settings:
            type: object
            properties:
              cfg_scale: {type: number}
              temperature: {type: number}
              speed: {type: number}
              max_new_tokens: {type: integer}
              language: {type: string}
              normalize: {type: boolean}
    settingsUpdated:
      name: settingsUpdated
      contentType: application/json
      payload:
        type: object
        properties:
          settings_updated: {type: boolean}
          settings: {type: object}
    audioChunk:
      name: audioChunk
      title: Audio chunk
      contentType: application/json
      payload:
        type: object
        properties:
          audio: {type: string, contentEncoding: base64, description: Base64-encoded audio data.}
          enc: {type: string, example: pcm_s16le}
          idx: {type: integer, description: Zero-based chunk index.}
          sr: {type: integer, description: Sample rate in Hz.}
          samples: {type: integer}
          context_id: {type: string, description: Present on the multi-context channel only.}
    wordTimestamps:
      name: wordTimestamps
      description: >-
        Emitted after audio chunks when word_timestamps is enabled. Note the
        docs describe start_ms/end_ms/char_start/char_end/score while the
        OpenAPI WordTimestamp schema names start_s/end_s/confidence — a
        provider spec-vs-docs drift recorded in data-model/.
      contentType: application/json
      payload:
        type: object
        properties:
          word_timestamps:
            type: array
            items:
              type: object
              properties:
                word: {type: string}
                start_ms: {type: integer}
                end_ms: {type: integer}
                char_start: {type: integer}
                char_end: {type: integer}
                score: {type: number}
    finalWithUsage:
      name: finalWithUsage
      title: Request complete
      description: >-
        Sent on /ws/tts when the request completes, carrying stats and per-request
        usage. The streaming channels emit a lighter end-of-audio `final` without
        usage, followed by session_closed.
      contentType: application/json
      payload:
        type: object
        properties:
          final: {type: boolean}
          chunks: {type: integer}
          total_samples: {type: integer}
          dur_ms: {type: number}
          gen_ms: {type: number}
          rtf: {type: number, description: Real-time factor (gen_ms / dur_ms).}
          usage:
            type: object
            properties:
              audio_seconds: {type: number, description: The unit billing is based on.}
              characters: {type: integer}
              cost_cents: {type: ['number', 'null'], description: 'Actual charge in EUR cents; null with cost_unavailable when undeterminable.'}
              currency: {type: string, example: eur}
              model_id: {type: string}
              cost_unavailable: {type: boolean}
    errorFrame:
      name: errorFrame
      title: Error frame
      description: >-
        Same JSON envelope as HTTP errors. WebSocket close codes are separate
        from the JSON code field — see errors/kugelaudio-error-codes.yml.
      contentType: application/json
      payload:
        type: object
        properties:
          error: {type: string, description: Display text only; do not parse.}
          error_code: {type: string, enum: [VALIDATION_ERROR, MISSING_VOICE_ID, UNAUTHORIZED, INSUFFICIENT_CREDITS, NOT_FOUND, RATE_LIMITED, INTERNAL_ERROR, MODEL_UNAVAILABLE, TOO_MANY_CONTEXTS]}
          code: {type: integer}
          context_id: {type: string}

Work with this as data

Every AsyncAPI spec here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for asyncapi

4 MCP tools reach this
  • find_asyncapisBrowse and filter every AsyncAPI spec in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This AsyncAPI spec
curl "https://apis.io/api/v1/asyncapis/kugelaudio-tts-asyncapi"
All asyncapi
curl "https://apis.io/api/v1/asyncapis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.