For AI agents: markdown of this page — /docs-content-en/ai/audio/transcriptions.md documentation index — /llms.txt

Transcribe audio

POST /v1/audio/transcriptions

Converts an audio file to text via Whisper Large v3 Turbo — no BYOK required. The transcription counts toward the Bitrix24 account's AI quota by audio duration: within the plan's quota nothing is charged to the balance, above the quota the usage is charged to the account's money balance at the model's base price. Accepts the file via multipart/form-data. The request and response format is compatible with POST /v1/audio/transcriptions from the OpenAI API.

The response comes in raw OpenAI format.

There is no {success, data} wrapper used by the other Vibecode endpoints — /v1/deals, /v1/tasks and others.

This is done for compatibility with the OpenAI SDK. If you have a single client that checks if (!response.success), add an exception for the AI Router.

Request fields (form-data)

Field Type Req. Default Description
file file yes Audio file. Supported: mp3, mp4, mpeg, mpga, m4a, wav, webm, flac, ogg. Maximum size — 25 MB
model string no deepdml/faster-whisper-large-v3-turbo-ct2 Whisper model ID. The bitrix/ prefix is optional and is stripped automatically
language string no auto-detection Language code per ISO 639 (2-3 letters): ru, en, de, fr, zh, etc. Specifying the language speeds up recognition
prompt string no Context hint: the conversation topic, style, correct spelling of terms. Up to 2000 characters, the model uses the last ~224 tokens
hotwords string no Special words and terms separated by commas — improve recognition accuracy for rare names and brands. Up to 500 characters
temperature number no 0 Decoder temperature from 0 to 1. 0 — deterministic result, higher — more variability. Out-of-range values are rejected
vad_filter boolean no true enables the VAD filter: the model cuts out silence before recognition — fewer hallucinations on recordings with pauses
timestamp_granularities[] string no segment Timestamp granularity: word or segment (the field can be repeated). Only with response_format=verbose_json. With word, each segment is augmented with a words array carrying the timing and probability of each word
response_format string no json Result format: json, text, srt, vtt, verbose_json

Examples

curl — personal key

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/audio/transcriptions \
  -H "X-Api-Key: YOUR_API_KEY" \
  -F "file=@call-recording.mp3" \
  -F "language=en" \
  -F "response_format=json"

curl — OAuth application

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/audio/transcriptions \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -F "file=@call-recording.mp3" \
  -F "language=en" \
  -F "response_format=json"

JavaScript — personal key

javascript
const formData = new FormData()
formData.append('file', audioFile)  // File or Blob object
formData.append('language', 'en')
formData.append('response_format', 'json')

const res = await fetch('https://vibecode.bitrix24.com/v1/audio/transcriptions', {
  method: 'POST',
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
  body: formData,
})

const result = await res.json()
console.log('Recognized text:', result.text)

JavaScript — OAuth application

javascript
const formData = new FormData()
formData.append('file', audioFile)
formData.append('language', 'en')

const res = await fetch('https://vibecode.bitrix24.com/v1/audio/transcriptions', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
  body: formData,
})

const result = await res.json()
console.log('Text:', result.text)

Response fields

The response structure depends on response_format. The json format (default) is the most compact, verbose_json — with timings.

`response_format: json`

Field Type Description
text string The full recognized text

`response_format: text`

The response is a plain string with the recognized text, without a JSON wrapper.

`response_format: verbose_json`

Field Type Description
task string Task type: transcribe
language string Code of the detected or specified language
duration number Audio duration in seconds
text string The full recognized text
usage object | null Model usage metadata. null if the model does not return it
words array Word-level timings at the whole-response level. Empty array if word-level timings were not requested
segments array Segments with timings and recognition metadata
segments[].id number Segment ordinal number
segments[].seek number Whisper's internal recognition-window offset
segments[].start number Segment start in seconds
segments[].end number Segment end in seconds
segments[].text string Segment text
segments[].tokens array Model tokens for the segment text (integers)
segments[].temperature number Decoding temperature applied by the model
segments[].avg_logprob number Average log probability of the segment tokens — a confidence metric
segments[].compression_ratio number Compression ratio of the segment text
segments[].no_speech_prob number Probability that the segment contains no speech
segments[].words array Word-level timings inside the segment. Empty array if not requested
segments[].emotion string | null Detected emotion of the segment. null if not detected

`response_format: srt` / `vtt`

The response is subtitles in SubRip Text or WebVTT format.

Response example

response_format: json:

JSON
{
  "text": "Hello, this is Acme LLC. We want a CRM for 50 users, budget up to 500 thousand per month."
}

response_format: verbose_json:

JSON
{
  "task": "transcribe",
  "language": "en",
  "duration": 8.42,
  "text": "Hello, this is Acme LLC. We want a CRM for 50 users, budget up to 500 thousand per month.",
  "usage": null,
  "words": [],
  "segments": [
    {
      "id": 0,
      "seek": 0,
      "start": 0.0,
      "end": 3.2,
      "text": "Hello, this is Acme LLC.",
      "tokens": [50365, 2425, 11, 341, 307],
      "temperature": 0.0,
      "avg_logprob": -0.38,
      "compression_ratio": 1.12,
      "no_speech_prob": 0.02,
      "words": [],
      "emotion": null
    },
    {
      "id": 1,
      "seek": 320,
      "start": 3.2,
      "end": 8.42,
      "text": "We want a CRM for 50 users, budget up to 500 thousand per month.",
      "tokens": [50414, 1003, 13767, 295, 1500],
      "temperature": 0.0,
      "avg_logprob": -0.41,
      "compression_ratio": 1.20,
      "no_speech_prob": 0.01,
      "words": [],
      "emotion": null
    }
  ]
}

Error response example

400 no_file — the file field was not provided:

JSON
{
  "error": {
    "message": "Audio file is required. Send as multipart/form-data with field \"file\".",
    "type": "invalid_request_error",
    "code": "no_file"
  }
}

Errors

HTTP Code Description
400 no_file The file field was not provided in multipart/form-data
400 empty_file The file field was provided, but the file is empty (0 bytes). Common cause: curl -F "file=path" without the @ prefix — curl sends the path string instead of the file contents
400 invalid_prompt The prompt field is longer than 2000 characters
400 invalid_hotwords The hotwords field is longer than 500 characters
400 invalid_temperature The temperature field is not a number or is outside the 0..1 range
400 invalid_vad_filter The vad_filter field is neither true nor false
400 invalid_timestamp_granularities The value is not word/segment, or the response format is not verbose_json
400 invalid_language The language code does not match the ISO 639 format (2-3 letters)
402 ai_credentials_not_configured The Bitrix provider is not configured on the platform
402 insufficient_balance The PREPAY account is past its overdraft — checked BEFORE the recognition call (PLATFORM/PORTAL keys only, BYOK is free and not checked). A fully frozen account is rejected earlier with ACCOUNT_FROZEN
402 ai_quota_exhausted The portal's monthly AI quota is exhausted — see "Known specifics" below
403 scope_missing The API key is missing the vibe:ai scope
502 ai_provider_unavailable The Whisper service returned an error or is unavailable
503 ai_provider_timeout Whisper did not respond within 15 minutes — the file is too long or the service is overloaded. For recordings longer than ~30 minutes, split them into parts
401 MISSING_API_KEY The X-Api-Key header was not provided
429 ai_congested The AI cluster pool is overloaded. The request was not executed, nothing was charged, retry it per the Retry-After header. The response carries the X-AI-Admission: shed header, not X-RateLimit-Scope
429 ai_pacing_limited A daily or weekly pacing window is exceeded. This is not quota exhaustion — repeat the request after the time in the Retry-After header. See Pacing (day/week smoothing)

The full list of common API errors — Errors.

Known specifics

Hints improve accuracy on rare terms. The prompt field sets the context — the conversation topic, style, correct spelling of terms. The hotwords field lists comma-separated special words the decoder gives higher priority to. The difference on the phrase "discussing the NeuralDeep integration with Kimi and the RAG approach":

Request Result
Without hints "…the neural-dip integration with Key Me and the rug approach for search…"
With hotwords "…the NeuralDeep integration with Kimi and the RAG approach for search…"

Within the quota — no charges, above the quota — the model's base price. Whisper runs on Bitrix24 infrastructure. Transcription is priced by audio duration and counts toward the Bitrix24 account's monthly AI quota. As long as usage stays within the plan's quota, nothing is charged to the account balance. Above the quota, usage is charged to the account's money balance at the model's base catalog price. On accounts with quota control enabled, a request may return 402 ai_quota_exhausted when the monthly limit is exhausted. The reason field distinguishes three cases: breaker — the hourly over-quota spending breaker fired, wallet_empty — the quota is exhausted and the account balance has no funds, wallet_off — over-quota spend is not available for the account. The resetAt field is the moment when requests will start passing again; for wallet_off it may be absent. In the wallet_empty case the response may additionally carry a hint string and a topupUrl link to top up the balance — both fields appear when enforced quota control and the top-up hint are enabled on the platform, so read them as optional. The hint field in this response is a string.

Size limit — 25 MB. For long recordings, split the file into parts up to 25 MB and stitch the results on the client side. One hour of mp3 at 128 kbit/s is about 60 MB — you will have to cut it.

Request timeout — 15 minutes. Transcription takes roughly 5-15% of the audio length. A 5-minute file (5-7 MB mp3) transcribes in 15-45 seconds. On a timeout, 503 ai_provider_timeout is returned.

See also