Kalpa Labs Speech API
Text-to-speech and conversational generation.
Text-to-speech and conversational generation.
openapi: 3.1.0
info:
contact:
name: Kalpa Labs
url: https://kalpalabs.ai/
description: 'The Kalpa Speech API turns text into natural speech (**TTS**) and continues a multi-speaker
conversation as the next speaker (**converse**), returning generated text + 24 kHz audio.
**Authentication.** Every `/v1` request needs an API key, sent either as
`Authorization: Bearer <key>` (preferred) or an `X-API-Key: <key>` header.
**Rate limits.** Requests are metered per key. When you exceed your limit you receive
`429 Too Many Requests` with a `Retry-After` header; every response carries `X-RateLimit-*` headers.
**Audio.** Audio crosses the wire as base64-encoded 16-bit PCM WAV (mono, 24 kHz).
This document is the single source of truth for the contract — the docs reference, the studio''s
typed client, and the SDKs are all generated from it.
'
license:
name: Proprietary
title: Kalpa Meta Speech API
version: 0.1.0
servers:
- description: Production
url: https://api.kalpalabs.ai
- description: Local development
url: http://localhost:8080
tags:
- description: Text-to-speech and conversational generation.
name: Speech
paths:
/v1/converse:
post:
description: Given a conversation, complete its last ('open') turn. A speaker-only open turn is authored (text + audio); an open turn with text is rendered as that speaker, conditioned on the prior turns (contextual TTS).
operationId: converse_v1_converse_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ConverseRequest'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/ConverseResponse'
description: Successful Response
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Missing or invalid API key.
'422':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Request validation failed.
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Rate limit exceeded.
'502':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: The inference backend failed.
security:
- ApiKeyAuth: []
summary: Complete the open (final) turn of a conversation
tags:
- Speech
/v1/converse/stream:
post:
description: 'Same request as /v1/converse; the response is a text/event-stream: one `meta` event, `audio` chunk events as audio is generated (`pcm_b64` = base64 raw 16-bit LE PCM at `sample_rate`), then exactly one `end` (reply text, audio_seconds, usage, meta) or `error`. First audio arrives after one ~80 ms frame instead of after the whole clip; closing the connection aborts generation.'
operationId: converse_stream_v1_converse_stream_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ConverseRequest'
required: true
responses:
'200':
content:
application/json:
schema: {}
description: Successful Response
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Missing or invalid API key.
'422':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Request validation failed.
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Rate limit exceeded.
'502':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: The inference backend failed.
security:
- ApiKeyAuth: []
summary: Complete the open turn, streaming audio as it is generated
tags:
- Speech
/v1/tts:
post:
description: Render the given text as speech (24 kHz mono WAV) in the requested speaker's voice.
operationId: tts_v1_tts_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/TtsRequest'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/TtsResponse'
description: Successful Response
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Missing or invalid API key.
'422':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Request validation failed.
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Rate limit exceeded.
'502':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: The inference backend failed.
security:
- ApiKeyAuth: []
summary: Synthesize speech from text
tags:
- Speech
/v1/tts/{voice_id}:
post:
description: Render the given text as speech (24 kHz mono WAV) in one of the named voices from GET /v1/voices. Default `params` match Kalpa's published evaluation settings.
operationId: tts_voice_v1_tts__voice_id__post
parameters:
- description: A named voice id, as listed by GET /v1/voices.
in: path
name: voice_id
required: true
schema:
description: A named voice id, as listed by GET /v1/voices.
title: Voice Id
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/VoiceTtsRequest'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/TtsResponse'
description: Successful Response
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Missing or invalid API key.
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unknown voice id.
'422':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Request validation failed.
'429':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Rate limit exceeded.
'502':
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: The inference backend failed.
security:
- ApiKeyAuth: []
summary: Synthesize speech from text in a named voice
tags:
- Speech
components:
schemas:
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
GenParamsModel:
description: 'Generation knobs, all optional — the defaults are the tuned starting point (served with UI
ranges at GET /v1/info).'
properties:
acoustic_temperature:
anyOf:
- maximum: 1.5
minimum: 0
type: number
- type: '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 = smaller, lower-fidelity audio.'
enum:
- low
- medium
- high
title: Audio Quality
type: string
max_new_tokens:
default: 512
maximum: 2048
minimum: 16
title: Max New Tokens
type: integer
penalty_window:
default: 20
maximum: 80
minimum: 1
title: Penalty Window
type: integer
repetition_penalty:
default: 3
maximum: 6
minimum: 0
title: Repetition Penalty
type: number
temperature:
default: 0.7
maximum: 1.5
minimum: 0
title: Temperature
type: number
top_k:
anyOf:
- minimum: 1
type: integer
- type: 'null'
description: Sample from the k most-likely tokens; null = full vocabulary.
title: Top K
title: GenParamsModel
type: object
ErrorBody:
properties:
message:
title: Message
type: string
request_id:
anyOf:
- type: string
- type: 'null'
title: Request Id
type:
title: Type
type: string
required:
- type
- message
title: ErrorBody
type: object
ErrorResponse:
description: The envelope returned for every 4xx/5xx.
properties:
error:
$ref: '#/components/schemas/ErrorBody'
required:
- error
title: ErrorResponse
type: object
VoiceGenParamsModel:
description: '`GenParamsModel` with the defaults `/v1/tts/{voice_id}` generates under when the caller sends
none — the sampling Kalpa''s published side-by-side evaluations used (`evals/sxs`), so external
benchmark runs reproduce our numbers out of the box.'
properties:
acoustic_temperature:
anyOf:
- maximum: 1.5
minimum: 0
type: number
- type: '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 = smaller, lower-fidelity audio.'
enum:
- low
- medium
- high
title: Audio Quality
type: string
max_new_tokens:
default: 512
maximum: 2048
minimum: 16
title: Max New Tokens
type: integer
penalty_window:
default: 20
maximum: 80
minimum: 1
title: Penalty Window
type: integer
repetition_penalty:
default: 0
maximum: 6
minimum: 0
title: Repetition Penalty
type: number
temperature:
default: 0.9
maximum: 1.5
minimum: 0
title: Temperature
type: number
top_k:
anyOf:
- minimum: 1
type: integer
- type: 'null'
default: 40
description: Sample from the k most-likely tokens; null = full vocabulary.
title: Top K
title: VoiceGenParamsModel
type: object
ConverseRequest:
description: 'Complete the open (final) turn of a conversation.
Every turn except the last must carry ``text`` and/or ``audio_wav_b64`` (grounded history). The
**last** turn is the one to generate: it may be ``speaker``-only (model authors text + audio) or
``speaker`` + ``text`` (render that text as contextual TTS). A last turn already carrying both text
and audio has nothing to generate → ``400``.'
properties:
conversation:
description: The conversation, oldest turn first; the last turn is the open turn to complete.
items:
$ref: '#/components/schemas/ConversationTurnModel'
maxItems: 64
minItems: 1
title: Conversation
type: array
model:
anyOf:
- type: string
- type: 'null'
description: Public model id (see GET /v1/models). Omit/null for the default model.
examples:
- kalpa-beta-v0.3
title: Model
params:
$ref: '#/components/schemas/GenParamsModel'
required:
- conversation
title: ConverseRequest
type: object
VoiceTtsRequest:
description: '``TtsRequest`` minus ``speaker`` (the voice determines it) with eval-default sampling.
The response is a plain ``TtsResponse`` — the voice is whatever the caller put in the path.'
properties:
model:
anyOf:
- type: string
- type: 'null'
description: Public model id (see GET /v1/models). Omit/null for the default model.
examples:
- kalpa-beta-v0.3
title: Model
params:
$ref: '#/components/schemas/VoiceGenParamsModel'
text:
description: Text to speak.
examples:
- Hey there! How are you doing today?
maxLength: 8000
minLength: 1
title: Text
type: string
required:
- text
title: VoiceTtsRequest
type: object
ConversationTurnModel:
properties:
audio_wav_b64:
anyOf:
- type: string
- type: 'null'
description: Base64 16-bit PCM WAV of this turn's audio, if any.
title: Audio Wav B64
speaker:
default: '0'
description: Role label for this turn (one of the model's `speakers`).
title: Speaker
type: string
text:
anyOf:
- maxLength: 8000
type: string
- type: 'null'
description: Text spoken in this turn, if known.
title: Text
title: ConversationTurnModel
type: object
ConverseResponse:
properties:
meta:
additionalProperties: true
title: Meta
type: object
model:
title: Model
type: string
reply:
$ref: '#/components/schemas/ConverseReply'
request_id:
title: Request Id
type: string
usage:
$ref: '#/components/schemas/Usage'
required:
- request_id
- model
- reply
- usage
title: ConverseResponse
type: object
TtsResponse:
properties:
audio:
$ref: '#/components/schemas/AudioPayload'
meta:
additionalProperties: true
description: Backend-specific diagnostics (latency, frames, …).
title: Meta
type: object
model:
title: Model
type: string
request_id:
title: Request Id
type: string
text:
description: The text that was spoken (echoes the request).
title: Text
type: string
usage:
$ref: '#/components/schemas/Usage'
required:
- request_id
- model
- text
- audio
- usage
title: TtsResponse
type: object
ConverseReply:
properties:
audio:
anyOf:
- $ref: '#/components/schemas/AudioPayload'
- type: 'null'
speaker:
title: Speaker
type: string
text:
title: Text
type: string
required:
- speaker
- text
title: ConverseReply
type: object
AudioPayload:
properties:
audio_quality:
description: Fidelity tier this audio was rendered at (high = full quality).
enum:
- low
- medium
- high
title: Audio Quality
type: string
data_b64:
description: Base64-encoded 16-bit PCM WAV (mono).
title: Data B64
type: string
format:
default: wav
description: Container/encoding of `data_b64` (16-bit PCM WAV).
title: Format
type: string
sample_rate:
description: Sample rate of the audio in Hz.
examples:
- 24000
title: Sample Rate
type: integer
required:
- sample_rate
- audio_quality
- data_b64
title: AudioPayload
type: object
TtsRequest:
properties:
model:
anyOf:
- type: string
- type: 'null'
description: Public model id (see GET /v1/models). Omit/null for the default model.
examples:
- kalpa-beta-v0.3
title: Model
params:
$ref: '#/components/schemas/GenParamsModel'
speaker:
default: '0'
description: Speaker role to render the text as (one of the model's `speakers`; see GET /v1/models).
title: Speaker
type: string
text:
description: Text to speak.
examples:
- Hey there! How are you doing today?
maxLength: 8000
minLength: 1
title: Text
type: string
required:
- text
title: TtsRequest
type: object
securitySchemes:
ApiKeyAuth:
description: 'Your Kalpa API key, sent as `Authorization: Bearer <key>` (or the `X-API-Key` header).'
scheme: bearer
type: http