Create transcription (STT)
Transcribe uploaded files, Base64 audio or a URL, with optional timestamps and speaker labels.
Last updated on
POST /v1/audio/transcriptions accepts JSON or multipart/form-data and returns JSON. Use a workspace API key in Authorization: Bearer.
Upload a recording
Choose a model supporting transcription in the Audio catalog. The sample model accepts mono PCM WAV at 16 kHz; check the current profile before using other audio formats.
export CICORA_API_KEY="sk_..."
export AUDIO_MODEL="speechkit-stt-general"
curl --fail-with-body --silent --show-error \
https://api.cicora.ai/v1/audio/transcriptions \
-H "Authorization: Bearer $CICORA_API_KEY" \
-F "model=$AUDIO_MODEL" \
-F "file=@recording.wav;type=audio/wav" \
-F "response_format=json" -o transcript.jsonThe default successful response contains text. Optional usage may be absent. curl -F sets the multipart boundary: do not set Content-Type manually.
Send Base64 or a URL
JSON uses input_audio with exactly one source. For inline data, send canonical Base64 bytes without a data: prefix and specify format:
import { readFile } from "node:fs/promises";
const response = await fetch("https://api.cicora.ai/v1/audio/transcriptions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CICORA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: process.env.AUDIO_MODEL,
input_audio: {
data: (await readFile("recording.wav")).toString("base64"),
format: "wav",
},
response_format: "json",
}),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
console.log((await response.json()).text);Alternatively, provide a publicly reachable HTTP(S) URL. Replace the illustrative URL with your actual file URL:
{
"model": "speechkit-stt-general",
"input_audio": {
"url": "https://media.example.com/recording.wav",
"format": "wav"
},
"response_format": "json"
}The platform fetches and validates the file before recognition. Private/local network URLs and URLs containing credentials are not allowed. If format is omitted for a URL, it must be inferable from the path extension; specify it for signed or extensionless URLs. Do not send both data and url.
Request fields
| Field | Type | Behavior |
|---|---|---|
model | string, required | Public model ID supporting transcription |
input_audio | object, JSON only | data + format, or url + optional format |
file | binary, multipart only | One audio or video file |
language | string | Two-letter lowercase ISO-639-1 code, such as en or ru; omission requires automatic language support |
response_format | json or verbose_json | Defaults to json |
timestamp_granularities | array of word/segment | Used only with verbose_json; ignored with json |
diarize | boolean | Speaker labels; requires model support and verbose_json, which also enables word timestamps |
keyterms | string array | Recognition hints, only when supported; at most 1,000 terms of 1–100 characters, with possible lower model limits |
temperature | number | Only within the selected model's published range |
provider, session_id, user, trace | objects or strings | Common Audio options |
In multipart, use repeated timestamp_granularities[] fields for timestamps, true/false for diarize, and JSON strings for provider and trace. For keyterms, use a JSON array in one field: -F 'keyterms=["Acme","SpeechKit"]'. Repeated keyterms[] also works for short lists, but the request allows at most 32 text fields in total, plus one file; a JSON-array field avoids consuming one field per term. Do not send both array representations. Unsupported fields are rejected rather than silently forwarded.
Timestamps and response
curl --fail-with-body --silent --show-error \
https://api.cicora.ai/v1/audio/transcriptions \
-H "Authorization: Bearer $CICORA_API_KEY" \
-F "model=$AUDIO_MODEL" \
-F "file=@recording.wav;type=audio/wav" \
-F "response_format=verbose_json" \
-F "timestamp_granularities[]=word" \
-F "timestamp_granularities[]=segment" -o transcript.json{
"text": "Hello world",
"task": "transcribe",
"duration": 2.4,
"words": [
{"word": "Hello", "start": 0.2, "end": 0.8},
{"word": "world", "start": 0.9, "end": 1.5}
],
"segments": [{"id": 0, "text": "Hello world", "start": 0.2, "end": 1.5}]
}Times are seconds from the start of the audio. Additional fields such as language, confidence, speaker labels and entities appear only when returned by the selected model. Missing confidence is not zero confidence. Diarization identifies speakers, not their real-world identity.
File and model limits
Multipart files and inline Base64 accept at most 25 MiB (26,214,400 bytes) of source media. Base64 expands the JSON body; the limit applies to decoded bytes. URL imports accept at most 100 MiB (104,857,600 bytes). Model limits can be lower and also constrain duration, codec, sample rate and channels. The cabinet's direct upload flow has separate limits and does not increase the multipart or inline API limit.
Recognized format names are wav, mp3, mp4, m4a, ogg, webm, flac, pcm, mov, mpeg and mpg. This list describes input parsing, not universal model support. In particular, raw PCM lacks self-describing geometry and must pass media inspection; prefer WAV for PCM recordings.
Video is accepted when it contains a decodable audio track. The media validator extracts audio for recognition; visual content is not transcribed. For multipart video, send the actual file MIME type, for example file=@recording.mp4;type=video/mp4. The extracted audio must fit the selected model's profile. A silent or corrupt video is rejected.