Skip to content

BeeSTT API

Last updated:

Browse articles
On this page

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 }]
	}
}
  • language is the recording's dominant language as an ISO 639-1 code, or und when it cannot be determined. Speech in other languages is translated into it, and beestt.translated_from_languages then lists those languages.
  • segments carry the text with its start and end in seconds and a speaker label (A, B, and so on, by first appearance). beestt.speakers gives a speaker's name only when the recording states it; otherwise name is null.
  • beestt.result_status is ok, partial (usable text with a part missing), no_usable_speech (silence or unintelligible speech), or language_unsupported. The last two carry no text.
  • beestt.interaction_state is the model's estimate of how the conversation went: positive, normal, tense, problematic, or undetermined. It is an estimate, not a business result.
  • beestt.summary, beestt.speakers, and beestt.translated_from_languages are 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": "..." }
	}
}
  • status is received, processing, or billing_pending while the job runs, and completed or failed at the end. A failed job carries only a failure_message, without an error code, and is not billed.
  • result is the same object a 200 returns, and null until the job completes.
  • A result is kept for a limited time. After that the job still answers, with result_expired set to true and result set to null.
  • 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, and language_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_balance before 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 202 as success; check for HTTP status 202, or an object member set to audio.transcription.job, and then ask for the job;
  • GET /v1/jobs/{job_id} and GET /v1/balance are BeeSTT's own endpoints; call them directly;
  • the beestt object 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.

OpenAI is a trademark of its owner. BeeSTT is an independent service and is not affiliated with or endorsed by OpenAI.

Can’t find what you need? Write to support@beepanel.io.