Pinecall

TTS Providers

Text-to-speech providers, voices, and tuning parameters.

Voice format#

// Recommended: friendly alias (always lowercase)
{ voice: "elevenlabs/sarah" }
{ voice: "cartesia/yumiko" }
{ voice: "polly/lucia" }

// Full config object (for tuning parameters)
{ voice: { provider: "elevenlabs", voice_id: "...", speed: 1.1 } }

The legacy provider:rawId format (e.g. "elevenlabs:EXAVITQu4vr4xnSDxMaL") still works but is not recommended.

Managed vs bring-your-own-key (BYOK)#

Data-driven from the rate table — see Managed vs BYOK for the full list and the live GET /api/rates/models query.

TTS providerManaged (no key needed)Notes
elevenlabs✅ YesDefault, recommended
cartesia (sonic-3.5)✅ Yes
polly (AWS)✅ Yes
soniox (tts-rt-v1)✅ Yes28 voices, 63 languages. Same key as Soniox STT
rime❌ BYOK onlyAdd a Rime key under Provider Keys
xai (Grok)❌ BYOK onlySame xAI key as Grok LLM

BYOK enforcement: configuring rime without a saved Rime key rejects agent registration with PROVIDER_KEY_REQUIRED. With your own key, that usage is billed by the provider directly — not deducted from your Pinecall credits.

Discovering voices#

Use the CLI to browse voices. Without flags, you get a catalog overview:

# Overview — shows providers, voice counts, languages
pinecall voices

# List voices for a provider + language
pinecall voices --provider=elevenlabs --language=es

# Preview a voice (plays audio in your terminal)
pinecall voices play elevenlabs/sarah

Every voice gets a friendly alias auto-generated from its name — use it directly in your config:

{ voice: "elevenlabs/sarah" }    // → Sarah - Mature, Reassuring
{ voice: "elevenlabs/agustin" }  // → Agustin - Conversational & Relaxed

Or use the fetchVoices REST helper:

import { fetchVoices } from "@pinecall/sdk";

const voices = await fetchVoices({ provider: "elevenlabs", language: "es" });
voices.forEach((v) => console.log(`${v.name} → ${v.provider}/${v.alias ?? v.id}`));

Using a voice in an agent#

voice goes on the agent config (or per phone number / per call). Use a provider/alias shortcut, or the full config object documented per provider below — both forms are interchangeable anywhere voice is accepted.

import { Pinecall } from "@pinecall/sdk";

const pc = new Pinecall(); // reads PINECALL_API_KEY

// Shortcut form
const agent = pc.agent("support", {
  voice: "elevenlabs/sarah",
  stt: "deepgram/flux",
  llm: "openai/gpt-5.4-nano",
  prompt: "You are a friendly support agent.",
});

// Full config object form (same field, with tuning)
pc.agent("support", {
  voice: { provider: "cartesia", voice_id: "a0e99841-...", model: "sonic-3.5", speed: 1.0, emotion: "neutral" },
  stt: "deepgram/flux",
  llm: "openai/gpt-5.4-nano",
  prompt: "...",
});

Per-number and per-call overrides use the same voice value:

agent.addPhoneNumber("+34911234567", { voice: "elevenlabs/valentina", language: "es" });
call.update({ voice: "cartesia/blake" });   // mid-call swap

ElevenLabs#

voice: {
  provider: "elevenlabs",
  voice_id: "JBFqnCBsd6RMkjVDRZzb",
  speed: 1.0,
  stability: 0.5,
  similarity_boost: 0.75,
  style: 0,
  use_speaker_boost: true,
}

Shortcut: "elevenlabs/sarah"

Model selection (auto for non-English)#

The server picks the ElevenLabs model from your language:

LanguageDefault modelWhy
en (or unset)eleven_flash_v2_5Fastest, optimized for real-time streaming
Any non-English (es, fr, de, …)eleven_multilingual_v2Flash/Turbo don't normalize text, so Spanish & other languages mispronounce numbers, dates, currency and abbreviations. The multilingual model reads them naturally.

eleven_multilingual_v2 is billed at a higher rate than flash (it's a higher-quality model). If you'd rather keep the faster/cheaper flash model for a non-English agent, use the flash shortcut or pin the model explicitly (both below).

flash: true — keep flash on a non-English agent#

The multilingual model trades a little latency for much better pronunciation. If your non-English agent should prioritize lowest latency / lowest cost over pronunciation quality, set the top-level flash flag — it opts out of the multilingual auto-default and keeps eleven_flash_v2_5:

const agent = pc.agent("sofia", {
  prompt: "Sos Sofía, asistente de la clínica.",
  llm: "openai/gpt-5.4-nano",
  voice: "elevenlabs/agus",
  stt: "deepgram/flux",
  language: "es",
  flash: true,        // ← stay on eleven_flash_v2_5 despite language: "es"
});

flash is a sibling of language (not inside voice), so it reads cleanly with the rest of the shortcuts. Semantics:

ConfigResulting ElevenLabs model
language: "es"eleven_multilingual_v2 (auto)
language: "es", flash: trueeleven_flash_v2_5
language: "en" (with or without flash)eleven_flash_v2_5
voice: { model: "..." } (any flash/language)the pinned model — explicit always wins

Notes:

  • ElevenLabs only. flash has no effect on Cartesia or Polly.
  • No-op for English — English already defaults to flash.
  • An explicit voice: { model } always wins over flash. Use flash: true for the common "I want the cheap fast model" case; use the model field when you need a specific model id.
  • Works per-channel too: phoneNumbers: [{ number, language: "es", flash: true }].

Override the model with the optional model field — it always wins over both the auto-default and flash:

voice: {
  provider: "elevenlabs",
  voice_id: "JBFqnCBsd6RMkjVDRZzb",
  model: "eleven_multilingual_v2",  // or "eleven_flash_v2_5" / "eleven_turbo_v2_5"
}

The model is part of the voice config, so it hot-reloads with it — agent.update({ voice }) and a same-provider call.update({ voice }) keep the model/language already in effect unless you pass a new one.

Tuning notes:

  • stability higher = more consistent, less expressive
  • similarity_boost higher = closer to the cloned voice
  • style 0–1, adds expressiveness (slight latency cost)

Cartesia#

voice: {
  provider: "cartesia",
  voice_id: "a0e99841-438c-4a64-b679-ae501e7d6091",
  model: "sonic-3.5",   // latest; also "sonic-3" / "sonic-latest"
  speed: 1.0,
  volume: 1.0,
  emotion: null,
  language: "en",
}

Shortcut: "cartesia/yumiko"

Tuning notes:

  • model: "sonic-3.5" — latest/fastest Cartesia model (sub-90ms, 42 languages), designed for streaming. sonic-3 and sonic-latest also available.
  • emotion accepts named emotion presets (check Cartesia docs for the current list)

AWS Polly#

voice: {
  provider: "polly",
  voice_id: "Joanna",
  engine: "neural",        // "neural" | "standard"
  language: "en-US",
  rate: "medium",          // "slow" | "medium" | "fast" | "+10%" / "-10%"
  volume: "medium",        // "soft" | "medium" | "loud" | "+6dB" / "-6dB"
  pitch: "+5%",            // standard engine only
}

Shortcut: "polly/joanna"

Tuning notes:

  • engine: "neural" is required for natural-sounding output. The older standard engine is robotic.
  • rate / volume accept named levels or relative values; pitch only applies to the standard engine.
  • Polly is the cheapest option but the least natural — fine for IVR-style flows, not for engaging conversation.

Rime (BYOK)#

Ultra-natural, expressive English. Requires your own Rime key.

voice: {
  provider: "rime",
  voice_id: "cove",      // Rime speaker id
  model: "mistv2",        // or "arcana" (most expressive)
  speed: 1.0,
}

Shortcut: "rime/cove"

Soniox (managed)#

Real-time TTS in 63 languages with 28 voices — no key needed. One Soniox key serves both Soniox TTS and STT, and Pinecall holds it.

voice: {
  provider: "soniox",
  voice_id: "Lucia",    // Soniox voice name
  model: "tts-rt-v1",
  language: "es",
}

Shortcut: "soniox/lucia" (aliases are the lowercase voice name).

Every voice speaks every one of the 63 languages — the voice does not pin the language, language does. What differs is the accent the voice carries:

AccentVoices
NeutralMaya, Daniel, Noah, Nina, Emma, Jack, Adrian, Claire, Grace, Owen, Mina, Kenji
SpanishRafael, Mateo, Lucia, Sofia
BritishOliver, Arthur, Isla, Victoria
AustralianCooper, Mason, Ruby, Elise
IndianArjun, Rohan, Priya, Meera

pinecall voices --provider=soniox --language=es ranks the accent-matching voices first but still lists the rest — any of them will speak Spanish.

Soniox publishes no preview URLs, so preview_url is null and previews are synthesized on demandpinecall voices play soniox/lucia (or GET /api/sdk/voice-preview?provider=soniox&voice=Lucia&lang=es) renders a short mp3 through the live model.

xAI Grok (BYOK)#

Expressive Grok voices: ara, eve, leo, rex, sal. Uses the same xAI key as Grok LLM (XAI_API_KEY). Requires your own key.

voice: {
  provider: "xai",
  voice_id: "eve",   // ara | eve | leo | rex | sal
  speed: 1.0,
}

Shortcut: "xai/eve"

Which to choose#

ProviderBest forTrade-off
ElevenLabsMost natural-sounding outputHigher cost per character
CartesiaReal-time streaming, low latencySmaller voice library
PollyCheap IVR, simple flowsLess natural
RimeUltra-natural expressive EnglishBYOK only; English-focused
SonioxMultilingual (63 langs, 28 voices), pairs with Soniox STT on one keyPer-utterance, not sentence-streamed
xAI GrokExpressive Grok voices (ara/eve/leo/rex/sal)BYOK only

For most agents, start with ElevenLabs (eleven_flash_v2_5) or Cartesia (sonic-3.5). Use Polly only for high-volume, low-engagement flows.

Hot-reloading voices#

Voice can change at any time:

// Agent-wide
agent.update({ voice: "cartesia/blake" });

// One call only
call.update({ voice: "elevenlabs/daniel" });

// Per-channel override
agent.addPhoneNumber("+34911234567", {
  voice: "elevenlabs/valentina",
});

What's next#