# Voice

URL: https://bridge.wekoya.tech/docs/voice
Updated: 2026-11-08

> Turn calls, voice notes and lessons into text, and text into natural speech, on the same key and balance. The routes are OpenAI's, so the OpenAI SDK's…

Turn calls, voice notes and lessons into text, and text into natural speech, on the same key and balance. The routes are OpenAI's, so the OpenAI SDK's `audio.transcriptions` and `audio.speech` work as they are: point the client at Bridge and use `nova-3` to listen and `aura-2` to speak, both by Deepgram, or Google's Gemini models below.

```
import os
from openai import OpenAI

bridge = OpenAI(api_key=os.environ["WEKOYA_API_KEY"], base_url="https://wekoya-api.wekoya.tech/v1")

# Speech to text: a recording up to 25 MB and 60 minutes.
with open("call.mp3", "rb") as audio:
    transcript = bridge.audio.transcriptions.create(model="nova-3", file=audio)
print(transcript.text)

# Text to speech: up to 2,000 characters a request.
speech = bridge.audio.speech.create(
    model="aura-2",
    voice="thalia",
    input="Your transfer of fifty thousand naira was received.",
)
speech.write_to_file("reply.mp3")
```

```
import fs from "node:fs"
import OpenAI from "openai"

const bridge = new OpenAI({ apiKey: process.env.WEKOYA_API_KEY, baseURL: "https://wekoya-api.wekoya.tech/v1" })

const transcript = await bridge.audio.transcriptions.create({
  model: "nova-3",
  file: fs.createReadStream("call.mp3"),
  response_format: "verbose_json",          // segments with start and end times
  timestamp_granularities: ["word", "segment"],
})

const speech = await bridge.audio.speech.create({ model: "aura-2", voice: "thalia", input: "Welcome back.", response_format: "wav" })
fs.writeFileSync("welcome.wav", Buffer.from(await speech.arrayBuffer()))
```
Model | Route | Price | Limits |
`nova-3` | `POST /v1/audio/transcriptions` | About ₦7.55 a minute of audio; ₦9.13 with `language: "multi"`. Billed by the second. | 25 MB and 60 minutes a file. mp3, wav, m4a, ogg, opus, webm, flac and most other formats. |
`aura-2` | `POST /v1/audio/speech` | About ₦52.65 per 1,000 characters, roughly ₦50 a spoken minute. | 2,000 characters a request; split longer text. `mp3` (default), `opus`, `aac`, `flac`, `wav`, `pcm`, and `mulaw` or `alaw` for phone lines. |
`gemini-3.5-transcribe` | `POST /v1/audio/transcriptions` | About ₦5 a minute. | 85+ languages, Hausa among them (`language: "ha"`). 20 MB and 60 minutes a file (30 with speakers or timings; 10 as text, srt or vtt). `vocabulary`: names and terms to listen for. |
`gemini-3.8-flash-tts`, `-lite-tts` | `POST /v1/audio/speech` | About ₦20 and ₦13 a spoken minute. | 30 voices (`Kore` by default), and two-speaker dialogues. `wav` (default), `pcm`, `mulaw` or `alaw`. |

A transcription answers with its cost, like a chat reply. `response_format` can be `json`, `text`, `verbose_json` (segments, and words with `timestamp_granularities`), `srt` or `vtt`; for text formats and for speech, the cost is in the `X-Bridge-Cost` header.

```
{
  "text": "Your transfer of 50,000 naira was received on October 9.",
  "usage": { "type": "duration", "seconds": 7 },
  "wekoya": { "cost": 0.89, "currency": "NGN", "seconds": 7 }
}
```

```
# Who said what: diarize labels each segment and word with a speaker.
curl https://wekoya-api.wekoya.tech/v1/audio/transcriptions \
  -H "Authorization: Bearer $WEKOYA_API_KEY" \
  -F file=@meeting.m4a -F model=nova-3 -F diarize=true -F response_format=verbose_json

# Subtitles, ready for a video player:
curl https://wekoya-api.wekoya.tech/v1/audio/transcriptions \
  -H "Authorization: Bearer $WEKOYA_API_KEY" \
  -F file=@lesson.mp3 -F model=nova-3 -F response_format=srt

# The voices, filtered by language:
curl "https://wekoya-api.wekoya.tech/v1/audio/voices?language=en" -H "Authorization: Bearer $WEKOYA_API_KEY"
```

#### Languages and voices
`language` is English (`en`) unless you set it. Use English for English spoken with any accent, an ISO code such as `fr`, `es`, `pt` or `de` for another language, or `multi` when a recording moves between languages. For Hausa, use `gemini-3.5-transcribe`. Yoruba, Igbo and Nigerian Pidgin are not supported yet, and a request for them is refused with nothing charged. Aura voices speak English, Spanish, French, German, Italian, Dutch and Japanese: name one by its short name (`thalia`) or full id (`aura-2-thalia-en`), and list them all with `GET /v1/audio/voices` (add `?model=gemini-3.8-flash-tts` for Gemini's, each with its style). For a dialogue, pass two `speakers` (`[{"name": "Ada", "voice": "Kore"}, {"name": "Tunde", "voice": "Puck"}]`) and write the input as `Ada: …` lines. OpenAI's own voice names such as `alloy` and its `instructions` are not available: these voices would read instructions aloud, so choose a voice whose style fits. Speed control and audio translation are not offered. For audio as it is spoken, see [Live transcription](https://bridge.wekoya.tech/docs/live).
Everything that applies to chat applies here: key scopes and model allow-lists, end users and their budgets, and the same errors. A request that fails costs nothing. Voice runs on your Wekoya balance only. Recordings are not used to train any model. Voice models are left out of `GET /v1/models` so chat pickers never offer them; list them with `GET /v1/models?type=audio`.
