cicora.ai / docs
Audio API

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.

Terminal
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.json

The 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:

transcribe.mjs
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:

URL request body
{
  "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

FieldTypeBehavior
modelstring, requiredPublic model ID supporting transcription
input_audioobject, JSON onlydata + format, or url + optional format
filebinary, multipart onlyOne audio or video file
languagestringTwo-letter lowercase ISO-639-1 code, such as en or ru; omission requires automatic language support
response_formatjson or verbose_jsonDefaults to json
timestamp_granularitiesarray of word/segmentUsed only with verbose_json; ignored with json
diarizebooleanSpeaker labels; requires model support and verbose_json, which also enables word timestamps
keytermsstring arrayRecognition hints, only when supported; at most 1,000 terms of 1–100 characters, with possible lower model limits
temperaturenumberOnly within the selected model's published range
provider, session_id, user, traceobjects or stringsCommon 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

Terminal
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
Example verbose response
{
  "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.

Troubleshooting

On this page