Skip to main content
Vexa can join a meeting, capture the audio, and not transcribe it. You collect the recording afterwards and put it through whatever speech-to-text you like — a batch job overnight, a model on your own GPU, a vendor Vexa never talks to. Don’t have a key yet? Hosted: sign in at vexa.ai/signin with a Google account and copy your key from your account page — free credit, no card required. Self-hosted: make all prints a key when the stack comes up. This is not the same as Use a custom STT endpoint, which keeps Vexa’s real-time pipeline and swaps the engine behind it. Here there is no engine: nothing is transcribed during the call, and the audio file is the deliverable.

Two flags, not one

transcribe_enabled: false on its own leaves you nothing to retrieve. It turns transcription off. It does not turn recording on — recording is gated separately by recording_enabled, and a bot that ran with both off captured a meeting that now exists nowhere. Set both:
POST /bots
Each flag resolves the same way: an explicit value in the request wins, else the deployment’s TRANSCRIBE_ENABLED / RECORDING_ENABLED env, else true. A non-boolean is refused with 422 rather than coerced. Because transcribe_enabled is false, the spawn does not require an STT backend, so the 503 that normally refuses a bot on a deployment with no speech-to-text configured cannot fire. A capture-only bot joins a stack that has no ASR at all. The meeting’s transcription_provider is frozen to "none" at spawn — the durable record that this meeting was never transcribed by anyone. It surfaces in the meeting.completed webhook’s service_provenance block.

Confirm nothing was transcribed

GET /transcripts/{platform}/{native_meeting_id}
Response — 200
An empty segment list is the expected result here, not a failure. With transcription off the bot builds a no-op transcriber: audio still flows through capture and turn-gating, no speech-to-text client is ever constructed, and every window returns empty text. Nothing leaves for any STT service, and there is nothing to poll for.

Find the recording

GET /recordings
Response — 200
Wait for status: "completed". While the bot is still in the call the recording exists with status: "in_progress" and grows chunk by chunk.

/master hands you JSON, not audio

The master route returns metadata. It finalizes the recording and tells you where the bytes are; it does not serve them.
GET /recordings/{recording_id}/master
Response — 200
media_file_id is not the recording id. Both are independent random 12-digit numbers and neither can be derived from the other. Repeating the recording id in the byte path — /recordings/481159273044/media/481159273044/raw — answers 404 No such media file. Use the raw_url the response hands you, or read media_files[].id off the recording. Never construct it.

Download the audio

GET — the raw_url from above
200 with Content-Type: audio/webm (or audio/wav where the deployment records WAV). The body is a real WebM container: its first four bytes are the EBML magic 1a 45 df a3. The route honours HTTP Range, so you can pull the file in parts, resume an interrupted transfer, or stream it straight into a transcoder. See Retrieve a meeting recording.

Transcribe it on your own terms

From here it is an ordinary audio file. Nothing about the next step is Vexa’s: feed it to a local Whisper, an OpenAI-compatible endpoint, a batch service, or leave it in cold storage until somebody asks. Until you fetch it, the recording sits in the bucket configured by MINIO_* (Configuration) — on a self-host, your own object storage, which the audio never leaves.

What this path covers

What has been verified. The sequence on this page — capture-only spawn, empty transcript, finalized recording, /master, byte download — was run end-to-end against the hosted API on 2026-08-21: a bot joined a live Google Meet with transcribe_enabled: false and recording_enabled: true, both participants spoke, GET /transcripts/… returned zero segments, and the downloaded body was a WebM whose length matched the recording’s file_size_bytes exactly.Not verified by that run: video recording (there is no video path), WAV-format deployments, and the real-time customer-backend route above.