The BeeSTT API transcribes call recordings from your own software with the same prepaid credits BeePanel uses. It returns the transcript with speaker labels, a short summary, and the language, in one JSON response. It needs a customer portal account and an API key, not a Pro license.
All requests go to https://beestt.beepanel.io over HTTPS.
Before you start
- A customer portal account with BeeSTT credits. Sign in with Portal sign-in at the top of this site. Credit prices are on the pricing page.
- An API key. In the portal, open BeeSTT > API keys and choose Create key; for your first key the portal asks you to accept the current terms with Accept and create key. Copy the key at once: it is shown only this one time.
- Recordings in one of the accepted formats: Ogg/Opus, PCM WAV, or GSM 6.10 WAV (WAV49). BeeSTT reads the format from the file's content; the file name and its extension do not matter.
Authentication
Send the key in the Authorization header of every request:
Authorization: Bearer bstt_...
A key starts with bstt_ and is 48 characters long. Keep it secret, like a
password. If it is exposed, choose Revoke next to it in the portal and
create a new one; work already accepted under the revoked key is still billed, and its
results can no longer be read with that key. Let running jobs finish before
revoking.
Checking the key
GET /v1/balance returns the key's account balance and costs nothing. Use
it to check that the key works:
curl https://beestt.beepanel.io/v1/balance \
-H "Authorization: Bearer $BEESTT_API_KEY"
{ "success": true, "data": { "balance_micro_usd": 4250000 } }
balance_micro_usd is an integer in millionths of a US dollar.
Transcribing a recording
Send the recording as multipart/form-data to
POST /v1/audio/transcriptions:
curl https://beestt.beepanel.io/v1/audio/transcriptions \
-H "Authorization: Bearer $BEESTT_API_KEY" \
-F model=beestt-1 \
-F file=@call.wav
| Field | Required | Value |
|---|---|---|
file |
Yes | The recording, up to 24 hours; the whole request may be up to 256 MiB. |
model |
Yes | Always beestt-1. |
response_format |
No | diarized_json, the only format and the default. |
beestt_feedback_code, beestt_feedback_job_id |
No, but both or neither | See Asking for a new transcript. |
Every other field, such as language or prompt, is refused with an
error rather than ignored. BeeSTT detects the language itself.
BeeSTT waits up to 10 seconds for the result. A recording finished within
that time returns 200 with the result. A 200, a 202, and an error from a failed job carry the job's
identifier in the Beestt-Job-Id header.
{
"task": "transcribe",
"language": "en",
"text": "Thank you for calling. How can I help?",
"segments": [
{
"type": "transcript.text.segment",
"start": 0,
"end": 4,
"text": "Thank you for calling. How can I help?",
"speaker": "A"
}
],
"beestt": {
"job_id": "01928f6e-6f3c-7a1b-9c2d-3e4f5a6b7c8d",
"result_status": "ok",
"interaction_state": "normal",
"summary": "The agent greets the caller and offers help.",
"speakers": [{ "id": "A", "name": null }]
}
}
languageis the recording's dominant language as an ISO 639-1 code, orundwhen it cannot be determined. Speech in other languages is translated into it, andbeestt.translated_from_languagesthen lists those languages.segmentscarry the text with its start and end in seconds and a speaker label (A,B, and so on, by first appearance).beestt.speakersgives a speaker's name only when the recording states it; otherwisenameisnull.beestt.result_statusisok,partial(usable text with a part missing),no_usable_speech(silence or unintelligible speech), orlanguage_unsupported. The last two carry no text.beestt.interaction_stateis the model's estimate of how the conversation went:positive,normal,tense,problematic, orundetermined. It is an estimate, not a business result.beestt.summary,beestt.speakers, andbeestt.translated_from_languagesare left out when empty.
Long recordings
A recording that is not finished within 10 seconds returns 202:
{
"id": "01928f6e-6f3c-7a1b-9c2d-3e4f5a6b7c8d",
"object": "audio.transcription.job",
"status": "processing"
}
The Location header gives the job's path, and Retry-After the seconds to
wait. Do not send the recording again; ask for the job instead. The response
below is shortened:
curl https://beestt.beepanel.io/v1/jobs/01928f6e-6f3c-7a1b-9c2d-3e4f5a6b7c8d \
-H "Authorization: Bearer $BEESTT_API_KEY"
{
"success": true,
"data": {
"job_id": "01928f6e-6f3c-7a1b-9c2d-3e4f5a6b7c8d",
"status": "completed",
"result_expired": false,
"result": { "task": "transcribe", "language": "en", "text": "..." }
}
}
statusisreceived,processing, orbilling_pendingwhile the job runs, andcompletedorfailedat the end. A failed job carries only afailure_message, without an error code, and is not billed.resultis the same object a200returns, andnulluntil the job completes.- A result is kept for a limited time. After that the job still answers,
with
result_expiredset totrueandresultset tonull. - Asking for a job is free.
Asking for a new transcript
If a result is wrong, send the same recording again with feedback on the earlier result:
curl https://beestt.beepanel.io/v1/audio/transcriptions \
-H "Authorization: Bearer $BEESTT_API_KEY" \
-F model=beestt-1 \
-F file=@call.wav \
-F beestt_feedback_code=text_inaccurate \
-F beestt_feedback_job_id=01928f6e-6f3c-7a1b-9c2d-3e4f5a6b7c8d
beestt_feedback_job_id is the earlier completed job of this recording
under the same key. speakers_mixed, text_incomplete, text_inaccurate, and
summary_poor produce a new transcript, billed as a new one. With other the feedback is recorded and the stored result is returned
again, billed like any repeat submission.
Billing
- Every completed result is billed, including
partial,no_usable_speech, andlanguage_unsupported. Prices and the minimum billed length are on the pricing page. - A failed job, a refused request, and a recording that exceeds a billing bound set for the key are not billed.
- Sending the same recording again while its job is still running returns that job, at no charge. Sending it again after the job completed is billed again: while the earlier result is still kept, BeeSTT returns that same result. To get a new transcript, send feedback; see Asking for a new transcript.
- When the balance does not cover a recording, BeeSTT refuses it with
insufficient_balancebefore transcribing it.
Using an OpenAI client library
POST /v1/audio/transcriptions follows the request and response shapes of
the OpenAI Audio API's transcription endpoint, for the fields listed above.
It is tested with the official OpenAI Go library; other OpenAI client
libraries that let you set the base URL should work the same way but are not
tested. Such a library can send requests
to https://beestt.beepanel.io/v1 with the BeeSTT key, the model
beestt-1, and the response format diarized_json. Keep in mind:
- the library may treat a
202as success; check for HTTP status202, or anobjectmember set toaudio.transcription.job, and then ask for the job; GET /v1/jobs/{job_id}andGET /v1/balanceare BeeSTT's own endpoints; call them directly;- the
beesttobject is an addition the library may not type; read it from the raw JSON; - if the library retries failed requests on its own, a submission retried after a lost response can be billed again; turn automatic retries off for submissions.
Errors
POST /v1/audio/transcriptions returns errors in this shape:
{
"error": {
"message": "The requested model does not exist. Submit the generic BeeSTT model.",
"type": "invalid_request_error",
"param": "model",
"code": "model_not_found"
}
}
GET /v1/jobs/{job_id} and GET /v1/balance return them in this shape:
{
"success": false,
"error": {
"code": "job_not_found",
"message": "No such job exists for this API key."
}
}
Messages are in English. Act on code, not on the message text.
| HTTP | code |
Meaning and what to do |
|---|---|---|
| 400 | missing_parameter |
A required field is missing; param names it. |
| 400 | unsupported_parameter |
A field BeeSTT does not accept was sent. Remove it. |
| 400 | invalid_feedback |
The feedback code is not one of the five, or the earlier job is not a completed job of this recording under this key. |
| 401 | invalid_api_key |
The key is missing, malformed, or unknown. |
| 402 | insufficient_balance |
The balance does not cover the recording. Add credits in the portal. |
| 403 | key_revoked |
The key was revoked. Create a new one. |
| 403 | agreement_required |
The account has not accepted the current terms. Contact support. |
| 404 | model_not_found |
model is not beestt-1. |
| 404 | job_not_found |
No such job exists for this key. |
| 413 | upload_too_large |
The request exceeds 256 MiB. |
| 415 | unsupported_media_type |
The recording is not Ogg/Opus, PCM WAV, or GSM 6.10 WAV, is longer than 24 hours or cannot be read, or the request is not multipart/form-data. |
| 422 | usage_limit_exceeded |
The recording exceeds a billing bound set for this key; nothing was billed. |
| 429 | rate_limit_exceeded |
The key sent too many requests or has too many jobs running. Wait and retry. |
| 502 | generation_failed |
The transcription failed and nothing was billed. Send the recording again. |
| 500, 503 | internal_error, service_unavailable, pipeline_unavailable, tariff_unavailable |
BeeSTT cannot take requests right now. Retry later. |
Related articles
OpenAI is a trademark of its owner. BeeSTT is an independent service and is not affiliated with or endorsed by OpenAI.