Skip to content

capability

verified July 2026

The synthesis layer for voice agents.

We do not sell the whole agent — we sell the mouth. This page is what the synthesis layer owes your stack, and the measured terms it is owed on.

01

The session, end to end

Your orchestrator holds one WebSocket per live call and sends an utterance per turn; binary PCM streams back with timing metadata on completion. Barge-in is not a feature flag — it is the shape of the protocol.

wss://tts.gandr.ai/ws — one call, one socket
const call = new WebSocket("wss://tts.gandr.ai/ws")

// an utterance per turn
call.send(JSON.stringify({
  text: "I can move that appointment for you.",
  lang: "en", voice_id: "front-desk",
  output_sample_rate: 24000
}))

call.onmessage = (ev) =>
  typeof ev.data === "string"
    ? endTurn(JSON.parse(ev.data)) // {"ttfa_ms":…,"audio_ms":…}
    : jitter.write(ev.data)        // binary PCM frames

// caller barged in: stop mid-word, answer the interruption
stopPlayback()
call.send(JSON.stringify({ text: answer, lang: "en" }))

02

What the layer owes you

  • First audio inside the turn budget: 107 ms measured, so the caller never hears the stack think.
  • A voice per caller or campaign, cloned from ten seconds, in 23 languages.
  • Failure that respects the call: past capacity the API refuses fast with a retryable busy signal, and standby lines cover your primary vendor’s bad night.
  • One request shape across all three surfaces — bytes, SSE, and the live socket — so switching transports is a config change, not a rewrite.

03

Why lines fit agents

Agent fleets scale by simultaneous conversations, not by monthly characters — so the price is per concurrent line, unmetered: $150 a month annual. Bursts spill to burst lines at $10 a line-day instead of failing, and the quarter’s forecast is lines times rate.

04

Notes — an engineer's checklist

01How does barge-in work on the socket?

Stop your playback the moment your VAD fires, then send the next utterance on the same open socket — the previous synthesis is abandoned mid-word. The interrupted characters cost nothing because nothing is metered.

02Does one socket handle a whole call?

Yes — one socket per live call, any number of turns, each turn one utterance up and a PCM stream back with its own ttfa_ms receipt. Connection setup is paid once per call instead of once per turn.

03What does my orchestrator see when capacity runs out?

A retryable 503 at_capacity, immediately — never a hung request. That is a signal your code can act on: retry, spill to a standby line, or reschedule the job.

04Can I switch a platform between SSE and the socket per customer?

Yes — the request shape (transcript, voice, output format) is identical on every surface, so the transport is a per-deployment config choice, not a second integration.

See also

Related sheets.

Your script, this API, thirty minutes — and the recording leaves with you.

Hear it on your own script