{"openapi":"3.1.0","info":{"title":"NCSpeech API","version":"1.0.0","description":"Kazakh and Russian speech-to-text and text-to-speech with voice cloning. OpenAI-compatible /v1/audio. Auth: Bearer sk_… or X-API-Key. Streaming recognition is a WebSocket (WS /v1/audio/transcriptions/stream), described in /docs/stream.md."},"security":[{"bearerAuth":[]},{"apiKeyAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"sk"},"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"SpeechRequest":{"type":"object","required":["input"],"properties":{"input":{"type":"string","maxLength":5000,"minLength":1,"description":"text, up to 5000 characters; stress — `[+]` before the stressed vowel (`удар[+]ения`), pause — `<break short/>` or `<break long/>`"},"voice":{"type":"string","default":"asel","description":"a name from the voice list or a clone id"},"language":{"type":"string","enum":["ru","kz"],"description":"ru or kz; detected from the letters in the text by default"},"speed":{"type":"number","maximum":2.0,"minimum":0.5,"description":"speed 0.5–2.0, pitch is unchanged"},"normalize":{"type":"boolean","description":"expand numbers and symbols into words; on by default"},"seed":{"type":"integer","description":"seed so the synthesis repeats exactly"},"response_format":{"type":"string","default":"pcm","enum":["pcm","wav"],"description":"pcm streams as generated, wav returns a finished file"},"model":{"type":"string","description":"accepted and ignored: there is one model, and delivery is set by the voice and the text markup"},"instructions":{"type":"string","description":"accepted and ignored: there is one model, and delivery is set by the voice and the text markup"}},"additionalProperties":false}}},"paths":{"/v1/audio/transcriptions":{"post":{"operationId":"createTranscription","summary":"Transcribe a file","description":"One request, one file. The response has utterances with per-word timings, confidence and language.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"audio or video up to 30 minutes; the server resamples and remixes on its own"},"model":{"type":"string","description":"accepted and ignored: there is one model, and language is detected from the audio"},"language":{"type":"string","description":"accepted and ignored: there is one model, and language is detected from the audio"},"response_format":{"type":"string","default":"verbose_json","description":"verbose_json (default), json, text, srt, vtt","enum":["verbose_json","json","text","srt","vtt"]},"boost":{"type":"string","default":"","description":"words to spot as a JSON array: `[{\"word\": \"тенге\", \"weight\": 3}]`. A word is letters, groups joined by a space or hyphen, up to 50 chars; weight from 1 to 10; up to 50 words, otherwise 422. Found words come in `spotted_words`; the text does not change"},"no_vad":{"type":"boolean","default":false,"description":"skip pause splitting and use 30-second windows: helps with music and dense background"},"postprocess":{"type":"string","default":"","description":"post-processing options as an object: `{\"diarization\": true}`. Speaker separation is on by default and is not billed; the fields appear only where a channel holds more than one voice"}}}}}},"responses":{"200":{"description":"verbose_json is the only format that carries per-word boundaries, confidence, language and speaker markup. json returns text and language only, text is plain text, srt and vtt are subtitles.","content":{"application/json":{"schema":{"type":"object"},"example":{"task":"transcribe","language":"ru","duration":30.0,"text":"алло здравствуйте","segments":[{"id":0,"start":0.0,"end":3.42,"channel":0,"language":"ru","speaker":0,"speaker_source":"diarization","text":"алло здравствуйте","words":[{"word":"алло","start":0.0,"end":0.28,"confidence":0.93,"language":"ru","speaker":0,"speaker_confidence":0.98}],"spotted_words":[{"word":"тенге","start":1.2,"end":1.5,"score":18.9}]}],"billed_seconds":30.0,"billed_credits":30.0}},"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"The file is empty or never arrived: check that the field is named `file` and the form is sent as `multipart/form-data`."},"401":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."},"403":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."},"402":{"description":"This month's plan credits are used up. Top up on the Billing tab while the period is still live."},"413":{"description":"The recording is longer than 30 minutes. Split it — the parts can be sent in parallel, within the plan's concurrent limit."},"422":{"description":"Unknown `response_format`. Allowed: verbose_json, json, text, srt, vtt."},"429":{"description":"Too many parallel sessions for this account. The request was not queued — send it again."},"502":{"description":"The recognition model did not respond. The request was not billed — retry is safe."}}}},"/v1/audio/voices":{"get":{"operationId":"listVoices","summary":"Catalog and your clones","description":"Catalog voices and your clones form one list of names accepted by the voice field. Only the voice vector is stored for a clone; the uploaded audio is not kept.","responses":{"200":{"description":"The voice list returns the catalog and your clones together — these are the names accepted by the voice field. Creating a voice returns one such record plus reused.","content":{"application/json":{"schema":{"type":"object"},"example":{"voices":[{"id":"asel","type":"builtin","languages":["kz","ru"]},{"id":"arman","type":"builtin","languages":["kz","ru"]},{"id":"6b2b34f4f766bd20","type":"custom","name":"Диктор Асель","used_seconds":30.0,"created":"2026-08-07T12:00:00+05:00"}],"cloning":{"enabled":true,"used":1,"limit":20}}}}},"401":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."},"403":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."}}},"post":{"operationId":"createVoice","summary":"Create a clone from a sample","description":"Catalog voices and your clones form one list of names accepted by the voice field. Only the voice vector is stored for a clone; the uploaded audio is not kept.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file","name","rights"],"properties":{"file":{"type":"string","format":"binary","description":"sample: wav, flac, ogg or mp3; at least 2 seconds, at most 20 MB. The first 30 seconds are used"},"name":{"type":"string","description":"how the voice is named in your list"},"rights":{"type":"boolean","description":"confirmation that you may use this voice, must be true"}}}}}},"responses":{"200":{"description":"The voice list returns the catalog and your clones together — these are the names accepted by the voice field. Creating a voice returns one such record plus reused.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"A required field is missing or the sample cannot be read: `file`, `name` and `rights=true` are required, and the file must be wav, flac, ogg or mp3."},"401":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."},"403":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."},"402":{"description":"The plan's voice slots or monthly credits are used up. A slot is spent on creation and deleting a voice does not return it."},"413":{"description":"The sample was rejected: shorter than two seconds or larger than 20 MB. Only the first 30 seconds are used, so a long file gains nothing."},"422":{"description":"The sample was rejected: shorter than two seconds or larger than 20 MB. Only the first 30 seconds are used, so a long file gains nothing."},"429":{"description":"Too many parallel sessions for this account. The request was not queued — send it again."}}}},"/v1/audio/voices/{voice_id}":{"delete":{"operationId":"deleteVoice","summary":"Delete your clone","description":"Catalog voices and your clones form one list of names accepted by the voice field. Only the voice vector is stored for a clone; the uploaded audio is not kept.","parameters":[{"name":"voice_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The voice list returns the catalog and your clones together — these are the names accepted by the voice field. Creating a voice returns one such record plus reused.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."},"403":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."},"404":{"description":"You have no clone with that id. Catalog voices cannot be deleted — they return 404 as well."}}}},"/v1/audio/speech":{"post":{"operationId":"createSpeech","summary":"Synthesize speech","description":"The request mirrors the OpenAI audio API: a client written for it works after changing base_url. Audio streams as it is generated.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeechRequest"}}}},"responses":{"200":{"description":"The body is the audio itself, not JSON. pcm: int16, 24 kHz, mono, headerless. wav: the same audio with a correct header, so it arrives whole rather than streamed.","content":{"audio/pcm":{"schema":{"type":"string","format":"binary"}},"audio/wav":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."},"403":{"description":"The key is missing or unknown: check the `Authorization: Bearer` or `X-API-Key` header. A revoked key cannot be restored — create a new one."},"402":{"description":"This month's plan credits are used up. Top up on the Billing tab while the period is still live."},"404":{"description":"No catalog voice by that name, and no clone with that id belongs to you. See `GET /v1/audio/voices` for the list."},"422":{"description":"A field is out of range or the request carries an unknown field — usually `speed` outside 0.5–2.0, text longer than 5000 characters, or a stray field such as `sample_rate`: synthesis always returns 24 kHz."},"429":{"description":"Either the plan's parallel sessions are taken or the model's own queue is full. Either way the request was rejected and should be retried."},"502":{"description":"The synthesis service did not respond. The request was not billed — retry is safe."}}}}},"servers":[{"url":"https://api-studio.ncspeech.ai"}]}