Para agentes de IA: markdown desta página — /docs-content-en/ai/audio.md índice da documentação — /llms.txt

Os artigos da documentação estão disponíveis atualmente em inglês.

Speech recognition

Convert audio to text via Whisper Large v3 Turbo or BitrixGPT 5.6 Transcribe (the latter is not offered on the international platform yet — see the Models table on the transcription page) on Bitrix24 infrastructure — no BYOK required. Transcription counts against your Bitrix24 account's AI quota by audio duration: within your plan's quota nothing is charged to the balance. Beyond the quota, usage is charged to the Bitrix24 account's money balance at the model's base price.

Scope: vibe:ai

Transcribe audio

POST /v1/audio/transcriptions

Converts an audio file to text via Whisper Large v3 Turbo or BitrixGPT 5.6 Transcribe (see "Models" below) — 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, 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.

The {success, data} wrapper used by the other Vibecode endpoints — /v1/deals, /v1/tasks and others — is not returned here.

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.

Models

bitrix/deepdml/faster-whisper-large-v3-turbo-ct2 bitrix/bitrixgpt-5.6-transcribe
Display name Whisper Large v3 Turbo (default) BitrixGPT 5.6 Transcribe — not offered on the international platform yet; requests with this ID are rejected there
Languages 99 25 European: bg, hr, cs, da, nl, en, et, fi, fr, de, el, hu, it, lv, lt, mt, pl, pt, ro, sk, sl, es, sv, ru, uk
Influence recognition language, prompt, hotwords, temperature, vad_filter none of these fields — they are accepted and validated, but the model does not read them; their names come back in the X-Ignored-Params response header
timestamp_granularities[] word, segment word (segments are always returned)
text, srt, vtt formats produced by the model built by the platform from the segments; billed by duration, like json
Speaker separation none none

The X-Ignored-Params header is informational: the response body and error codes do not change. It is not on the CORS exposure list, so a browser fetch cannot read it — read it server-side or in the developer tools.

Request fields (form-data)

Field Type Req. Default Description
file file yes Audio file. The multipart part must be named exactly file. A missing filename parameter and an empty filename="" value are both accepted and replaced with the extensionless name audio — consistently for Content-Type: audio/mpeg and Content-Type: application/octet-stream. The filename extension is NOT checked: the recognition service detects the container from the content, so a name without an extension and rare voice-recorder formats are accepted just like mp3, mpeg, mpga, mp4, m4a, wav, ogg, oga, flac, webm, opus, aac, amr, 3gp, 3gpp, wma — these are listed because we pass the recognition service a format hint for them when the request carries none. A file the recognition service could not read comes back as ai_provider_rejected. Maximum size — 25 MB
model string no deepdml/faster-whisper-large-v3-turbo-ct2 Model ID — see "Models". The bitrix/ prefix is optional and is stripped automatically
language string no auto-detection Language code per ISO 639 (2-3 letters): en, de, fr, ru, 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 only the last ~224 tokens
hotwords string no Comma-separated special words and terms that improve recognition accuracy for rare names and brands. Up to 500 characters
temperature number no 0 Decoder temperature from 0 to 1. 0 gives a deterministic result, higher values add 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 adds 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 for the whole response. 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, or the file part is named something else (for example audio). The size of such a part does not affect the response: the name is read from the part header, before the contents
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)
400 ai_provider_rejected The recognition service rejected the request contents themselves (its response was 400 or 422). The providerStatusCode field carries the original status. There is no point in retrying the request unchanged
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)
402 account_frozen The portal's billing account is frozen over a debt and the transcription goes beyond the plan's monthly AI quota — spend above the quota is paid from the balance. Transcription within the quota, with a Cowork/Code subscription key, and on your own provider key keeps working under the freeze. Until the narrowed refusal reaches the portal, the freeze closes transcription entirely and answers with the V1 envelope carrying the code ACCOUNT_FROZEN in upper case — what the refusal covers
402 ai_quota_exhausted The portal's monthly AI quota is exhausted — see "Known specifics" below
402 company_budget_exhausted The monthly company spend budget set by the portal administrator is exhausted. The scope field names the budget that was hit: USER — the caller's own budget, PORTAL — the budget of the whole portal. The canRequest field tells whether an increase can be requested: true for a personal budget, false for the portal one, which only an administrator raises. The rejection arrives only on calls that draw on the portal balance. Transcription inside the plan quota, with a Cowork/Code subscription key and with your own key keeps working
403 scope_missing The API key is missing the vibe:ai scope
413 request_too_large One of the multipart limits was breached: the file is over 25 MB, or the request carries more than 16 text fields or 24 parts, or a single field is over 64 KB
502 ai_provider_unavailable The recognition service returned an authentication or internal error. The original status arrives in the providerStatusCode field when the service answered with an HTTP status. A rejection of the request contents arrives under its own ai_provider_rejected code
502 ai_provider_network The platform could not connect to the recognition service, or the connection dropped before a response. This response carries no providerStatusCode: the service never answered. Retry the request
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_provider_cooldown The transcription cluster is temporarily unavailable and the platform pauses so retries do not pile onto it. The request was not executed and nothing was charged — retry it after the number of seconds in Retry-After. This response carries neither X-RateLimit-Scope nor X-AI-Admission
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.

A Cowork/Code subscription key is metered separately. A call made with a key carrying the vibe:cowork scope does not count toward the account's AI quota. If the subscription is active and a platform administrator has set a per-minute or per-call price for a transcription model available to you, the call draws on the subscription quota: when the window is exhausted the endpoint answers 402 with code cowork_quota_exhausted, a Retry-After header and the fields window (5h, week or month), resetAt and nextTier. Until a price is set, transcription with such a key is not metered. With Whisper the text, srt and vtt formats do not report a duration, so they are billed at the per-call price; with BitrixGPT 5.6 Transcribe they are built by the platform and billed by duration.

Disabling Cowork/Code at the platform level controls product features, but does not change AI billing for an already-issued key. With an active subscription, transcription continues to use its quota, just like chat; disabling the product does not move this usage to the account wallet. Without an active subscription, transcription still does not use subscription quota, and the existing standard billing path is preserved.

Size limit — 25 MB. A file over the limit is rejected outright — 413 request_too_large, nothing is charged. 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