For AI agents: markdown of this page — /docs-content-en/ai/audio.md documentation index — /llms.txt
Speech recognition
Convert audio to text via BitrixGPT 5.6 Transcribe on Bitrix24 infrastructure — no BYOK required. Neither model is offered on the international platform yet: transcription is not available there, and every request is rejected before recognition — see the Models table on the transcription page. 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 your account's money balance at the model's base price.
Whisper Large v3 Turbo is being retired. From 16 November 2026, requests with bitrix/deepdml/faster-whisper-large-v3-turbo-ct2 and requests without model are served by BitrixGPT 5.6 Transcribe. The old ID remains accepted and remains the default when model is omitted. For new integrations, explicitly set model=bitrix/bitrixgpt-5.6-transcribe.
Scope: vibe:ai
Transcribe audio
POST /v1/audio/transcriptions
Converts an audio file to text via BitrixGPT 5.6 Transcribe (see "Models" below) — no BYOK required. 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. Transcription is not available on the international platform yet: every request, including the examples below, is rejected with 404 ai_model_not_found.
The response comes in raw OpenAI format.
The
{success, data}wrapper used by the other Vibecode endpoints —/v1/deals,/v1/tasksand 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
Whisper Large v3 Turbo is being retired. From 16 November 2026, requests with bitrix/deepdml/faster-whisper-large-v3-turbo-ct2 and requests without model are served by BitrixGPT 5.6 Transcribe. The old ID remains accepted and remains the default when model is omitted. For new integrations, explicitly set model=bitrix/bitrixgpt-5.6-transcribe.
When the replacement handles a request, the response carries X-Model-Fallback: bitrix/deepdml/faster-whisper-large-v3-turbo-ct2, X-Model-Replacement: bitrix/bitrixgpt-5.6-transcribe and X-Model-Fallback-Reason: model_disabled. The replacement's language support, parameter handling and billing apply. See model lifecycle.
The X-Model-Fallback, X-Model-Replacement and X-Model-Fallback-Reason headers are not on the CORS exposure list, so a browser fetch cannot read them — read them server-side or in the developer tools.
bitrix/deepdml/faster-whisper-large-v3-turbo-ct2 |
bitrix/bitrixgpt-5.6-transcribe |
|
|---|---|---|
| Display name | bitrix/deepdml/faster-whisper-large-v3-turbo-ct2Whisper Large v3 Turbo (being retired; replacement from 16 November 2026) — not offered on the international platform yet: transcription is not available there, so every request, including one without model, is rejected with 404 ai_model_not_found |
bitrix/bitrixgpt-5.6-transcribeBitrixGPT 5.6 Transcribe — not offered on the international platform yet; requests with this ID are rejected there |
| Languages | bitrix/deepdml/faster-whisper-large-v3-turbo-ct2about 99 | bitrix/bitrixgpt-5.6-transcribe25 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 |
| Fields that affect recognition | bitrix/deepdml/faster-whisper-large-v3-turbo-ct2language, prompt, hotwords, temperature, vad_filter |
bitrix/bitrixgpt-5.6-transcribenone 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[] |
bitrix/deepdml/faster-whisper-large-v3-turbo-ct2word, segment |
bitrix/bitrixgpt-5.6-transcribeword; segment is silently dropped |
text, srt, vtt formats |
bitrix/deepdml/faster-whisper-large-v3-turbo-ct2produced by the model; billed per call | bitrix/bitrixgpt-5.6-transcribebuilt by the platform from verbose_json; all formats are billed by audio duration |
| Speaker diarization | bitrix/deepdml/faster-whisper-large-v3-turbo-ct2none | bitrix/bitrixgpt-5.6-transcribenone |
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 | Required | Default | Description |
|---|---|---|---|---|
Fieldfile |
Typefile | Requiredyes | Default— | DescriptionAudio 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 — the same way for both 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. Content that is clearly not audio — for example text, a PDF document, an image or an archive — is rejected with 400 invalid_audio before recognition, whatever the filename and Content-Type. A file in an audio format that the recognition service still could not read comes back as 400 ai_provider_rejected when the service answered with status 400 or 422, and as 502 ai_provider_unavailable when the service answered with an internal error. Maximum size — 25 MB |
Fieldmodel |
Typestring | Requiredno | Defaultdeepdml/faster-whisper-large-v3-turbo-ct2 |
DescriptionSet bitrix/bitrixgpt-5.6-transcribe for new integrations. The bitrix/ prefix is optional. The default ID is unchanged; from 16 November 2026 it is served by Transcribe, as is an explicit Whisper ID. An unknown ID or a model turned off in the catalog returns 404 ai_model_not_found. A model with status DISABLED is served by an available replacement; without one, it returns 503 model_unavailable (type service_unavailable). Both errors are returned before recognition, without a charge. Transcription is unavailable on the international platform, including when model is omitted |
Fieldlanguage |
Typestring | Requiredno | Defaultauto-detection | DescriptionLanguage code per ISO 639 (2-3 letters): en, de, fr, ru, zh, etc. Whisper uses the specified language; Transcribe detects it automatically. For Transcribe: accepted and validated, ignored during recognition; reported in X-Ignored-Params. |
Fieldprompt |
Typestring | Requiredno | Default— | DescriptionContext hint: the conversation topic, style, correct spelling of terms. Up to 2000 characters; Whisper uses only the last ~224 tokens. For Transcribe: accepted and validated, ignored during recognition; reported in X-Ignored-Params. |
Fieldhotwords |
Typestring | Requiredno | Default— | DescriptionComma-separated special words and terms that improve Whisper's recognition accuracy for rare names and brands. Up to 500 characters. For Transcribe: accepted and validated, ignored during recognition; reported in X-Ignored-Params. |
Fieldtemperature |
Typenumber | Requiredno | Default0 |
DescriptionWhisper decoder temperature from 0 to 1. 0 gives a deterministic result, higher values add variability. Out-of-range values are rejected. For Transcribe: accepted and validated, ignored during recognition; reported in X-Ignored-Params. |
Fieldvad_filter |
Typeboolean | Requiredno | Default— | Descriptiontrue enables the VAD filter: Whisper cuts out silence before recognition — fewer hallucinations on recordings with pauses. For Transcribe: accepted and validated, ignored during recognition; reported in X-Ignored-Params. |
Fieldtimestamp_granularities[] |
Typestring | Requiredno | Defaultsegment |
DescriptionTimestamp 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. With Transcribe, segment is silently dropped; word works. |
Fieldresponse_format |
Typestring | Requiredno | Defaultjson |
DescriptionResult format: json, text, srt, vtt, verbose_json |
Examples
curl — personal key
curl -X POST https://vibecode.bitrix24.com/v1/audio/transcriptions \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@call-recording.mp3" \
-F "model=bitrix/bitrixgpt-5.6-transcribe" \
-F "response_format=json"
curl — OAuth application
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 "model=bitrix/bitrixgpt-5.6-transcribe" \
-F "response_format=json"
JavaScript — personal key
const formData = new FormData()
formData.append('file', audioFile) // File or Blob object
formData.append('model', 'bitrix/bitrixgpt-5.6-transcribe')
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
const formData = new FormData()
formData.append('file', audioFile)
formData.append('model', 'bitrix/bitrixgpt-5.6-transcribe')
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 |
|---|---|---|
Fieldtext |
Typestring | DescriptionThe 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 |
|---|---|---|
Fieldtask |
Typestring | DescriptionTask type: transcribe |
Fieldlanguage |
Typestring | DescriptionCode of the detected or specified language |
Fieldduration |
Typenumber | DescriptionAudio duration in seconds |
Fieldtext |
Typestring | DescriptionThe full recognized text |
Fieldusage |
Typeobject | null | DescriptionModel usage metadata. null if the model does not return it |
Fieldwords |
Typearray | DescriptionWord-level timings for the whole response. Empty array if word-level timings were not requested |
Fieldsegments |
Typearray | DescriptionSegments with timings and recognition metadata |
Fieldsegments[].id |
Typenumber | DescriptionSegment index |
Fieldsegments[].seek |
Typenumber | DescriptionWhisper's internal recognition-window offset |
Fieldsegments[].start |
Typenumber | DescriptionSegment start in seconds |
Fieldsegments[].end |
Typenumber | DescriptionSegment end in seconds |
Fieldsegments[].text |
Typestring | DescriptionSegment text |
Fieldsegments[].tokens |
Typearray | DescriptionModel tokens for the segment text (integers) |
Fieldsegments[].temperature |
Typenumber | DescriptionDecoding temperature applied by the model |
Fieldsegments[].avg_logprob |
Typenumber | DescriptionAverage log probability of the segment tokens — a confidence metric |
Fieldsegments[].compression_ratio |
Typenumber | DescriptionCompression ratio of the segment text |
Fieldsegments[].no_speech_prob |
Typenumber | DescriptionProbability that the segment contains no speech |
Fieldsegments[].words |
Typearray | DescriptionWord-level timings inside the segment. Empty array if not requested |
Fieldsegments[].emotion |
Typestring | null | DescriptionDetected 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:
{
"text": "Hello, this is Acme LLC. We want a CRM for 50 users, budget up to 500,000 per month."
}
response_format: verbose_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,000 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,000 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:
{
"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 |
|---|---|---|
| HTTP400 | Codeno_file |
DescriptionThe 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 |
| HTTP400 | Codeempty_file |
DescriptionThe 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 |
| HTTP400 | Codeinvalid_prompt |
DescriptionThe prompt field is longer than 2000 characters |
| HTTP400 | Codeinvalid_hotwords |
DescriptionThe hotwords field is longer than 500 characters |
| HTTP400 | Codeinvalid_temperature |
DescriptionThe temperature field is not a number or is outside the 0..1 range |
| HTTP400 | Codeinvalid_vad_filter |
DescriptionThe vad_filter field is neither true nor false |
| HTTP400 | Codeinvalid_timestamp_granularities |
DescriptionThe value is not word/segment, or the response format is not verbose_json |
| HTTP400 | Codeinvalid_language |
DescriptionThe language code does not match the ISO 639 format (2-3 letters) |
| HTTP400 | Codeinvalid_idempotency_key |
DescriptionThe Idempotency-Key header fails validation: its length is outside 1–255 characters or it contains a character outside [A-Za-z0-9_.:-]. Nothing is transcribed or charged. The param field of the response is Idempotency-Key |
| HTTP400 | Codeinvalid_audio |
DescriptionThe contents of the file field are clearly not audio — for example text, a PDF document, an image or an archive. The check reads the contents before recognition; the filename and Content-Type do not affect it, and nothing is charged. The param field of the response is file. There is no point in retrying without replacing the file |
| HTTP400 | Codeai_provider_rejected |
DescriptionThe 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 |
| HTTP402 | Codeai_credentials_not_configured |
DescriptionThe bitrix provider is not configured on the platform |
| HTTP402 | Codeinsufficient_balance |
DescriptionThe PREPAY account is past its overdraft limit — checked BEFORE the recognition call (PLATFORM/PORTAL keys only, BYOK is free and not checked) |
| HTTP402 | Codeaccount_frozen |
DescriptionThe billing account is frozen due to 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 subscription key, and with your own provider key keeps working under the freeze. Until the narrowed refusal is rolled out to the portal, the freeze blocks transcription entirely and the endpoint responds with the V1 envelope carrying the code ACCOUNT_FROZEN in upper case — what the refusal covers |
| HTTP402 | Codeai_quota_exhausted |
DescriptionThe portal's monthly AI quota is exhausted — see "Known specifics" below |
| HTTP402 | Codecompany_budget_exhausted |
DescriptionThe 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 can raise. The rejection arrives only on calls that draw on the portal balance. Transcription inside the plan quota, with a Cowork subscription key and with your own provider key (BYOK) keeps working |
| HTTP403 | Codescope_missing |
DescriptionThe API key is missing the vibe:ai scope |
| HTTP404 | Codeai_model_not_found |
DescriptionUnknown ID or a model turned off in the catalog. On the international platform transcription is unavailable and every request returns this error. Checked before recognition, without a charge |
| HTTP409 | Codeidempotency_in_progress |
DescriptionThe first request with this Idempotency-Key and this file is still being transcribed. Nothing is charged. Repeat with the same key after the number of seconds in Retry-After — at most 10 |
| HTTP422 | Codeidempotency_key_reused |
DescriptionThis Idempotency-Key has already been used with a different file within the last 72 hours. Nothing is transcribed or charged — new audio needs a new key. The param field of the response is Idempotency-Key |
| HTTP503 | Codemodel_unavailable |
DescriptionA model with status DISABLED has no available replacement. The error type is service_unavailable. Checked before recognition, without a charge. When a replacement is available, it serves the request |
| HTTP413 | Coderequest_too_large |
DescriptionOne 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 |
| HTTP413 | Codeai_payload_too_large |
DescriptionThe recognition service rejected the request by size. The providerStatusCode field carries the original status 413. Retrying the same request returns the same response — split the file into parts |
| HTTP502 | Codeai_provider_unavailable |
DescriptionThe recognition service returned an authentication or internal error, including on a damaged audio file with a valid format header. 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 |
| HTTP502 | Codeai_provider_network |
DescriptionThe 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 |
| HTTP503 | Codeai_provider_timeout |
DescriptionThe recognition service 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 |
| HTTP401 | CodeMISSING_API_KEY |
DescriptionThe X-Api-Key header was not provided |
| HTTP429 | Codeai_provider_cooldown |
DescriptionThe 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 |
| HTTP429 | Codeai_congested |
DescriptionThe AI cluster pool is overloaded. The request was not executed and nothing was charged — retry it per the Retry-After header. The response carries the X-AI-Admission: shed header, not X-RateLimit-Scope |
| HTTP429 | Codeai_pacing_limited |
DescriptionA 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.
Idempotency
Send the optional Idempotency-Key header to repeat the transcription of the same file safely. If the response to the first request was lost (a dropped connection, a timeout), a repeat with the same key and the same file transcribes the audio again but charges nothing a second time: neither the Bitrix24 account's AI quota, nor money from the balance, nor the Cowork subscription quota. The response of such a repeat carries the Idempotent-Replayed: true header.
- The key is a string of 1–255 characters from
[A-Za-z0-9_.:-]. For a recording you split into parts, use the form<recording id>:<track id>:<part number>, for examplerec-8f2c:mic:12. - The key is scoped to the Bitrix24 account and the user the call is billed to, or to the API key when there is no user. A new API key of the same user does not break the repeat.
- A repeat is free for 72 hours after a successful charged call. Later, the same key is processed as a new call and charged.
- A free repeat goes through even when the quota is exhausted: this file has already been paid for.
- At most three free repeats are allowed per file. The fourth and later repeats with the same key are processed and charged as a regular call, with all quota and balance checks.
- If the first call ended with an error, the key is released, and a repeat is processed as a new charged call.
- If the first call charged nothing — for example, it ran on your own provider key — a repeat is also processed as a regular call, without the
Idempotent-Replayedheader. - The platform stores neither the transcript nor the audio — only fingerprints of the key and the file. So the response to a repeat is a fresh transcription of the same file.
- Without the
Idempotency-Keyheader the behaviour is unchanged.
Refusals related to the key — 400 invalid_idempotency_key, 409 idempotency_in_progress and 422 idempotency_key_reused — are described in Errors.
Known specifics
Transcribe detects the language automatically. It supports the 25 European languages listed above, compared with about 99 for Whisper. It does not separate speakers. language, prompt, hotwords, temperature and vad_filter are validated but do not affect recognition; sent field names are reported in X-Ignored-Params. Hints that influenced Whisper no longer do so when Transcribe serves the request. Check your recordings and required languages before migrating.
Within the quota — no charges, above the quota — the model's base price. BitrixGPT 5.6 Transcribe runs on Bitrix24 infrastructure. All its formats, including platform-rendered text, srt and vtt, are priced by audio duration and count 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 treat them as optional. The hint field in this response is a string. When the Bitrix24 account has no paid AI access, a reason: "wallet_off" response additionally carries details.learnMoreUrl — a page that describes the paid Bitrix24 plan that includes AI — and the message field names that plan. For other wallet_off causes details.learnMoreUrl is absent.
A Cowork 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 responds with 402 and the 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 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 the subscription quota, and standard billing applies as before.
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 of 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 split 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.