MIKODES VOX docs
v2.0.0
Live demo Get help
● Set up · Keys and settings

Configuration
every key, where it lives.

VOX reads its keys from the console's key file or the process environment. This page lists every variable, what it is for and where to get it. A template with every name and no values: deploy/vox.env.example.

01Where keys live

WhereHowNotes
Console → Setup (single-user)Each key has a live test for Anthropic, ElevenLabs, Twilio, Telnyx and Google, plus the optional Telegram bot (getMe) and SMTP server (TLS and log-in, no mail sent).Saved to app/data/secrets.env, mode 0600, ignored by git. The console never shows a key back, only its last four characters.
Process environmentdeploy/vox.env for Docker, EnvironmentFile for systemd, or your shell.The environment wins over the file; the console then shows that key read-only.
No automatic .env

The code does not read a .env file by itself, neither Python nor Node. To use one by hand: chmod 600 .env, then set -a; . ./.env; set +a in the same terminal. A key that ever reached git is leaked: replace it.

In SaaS mode every key is the operator's. Customers never enter or see a key; setup routes answer 403 OPERATOR_ONLY in a customer's console.

The worker re-reads the key file on every round. The media server and the console token are read at start, so restart after changing them.

02Required for calls

python -m voice check lists all missing ones at once and exits with code 2.

VariableUsed forWhere to get it
ANTHROPIC_API_KEY Requiredthe conversation (Claude), research, agent tasks, mail triage, the briefingAnthropic Console → Settings → API Keys → Create Key. Check that Billing has credit. console.anthropic.com
ELEVENLABS_API_KEY Requiredspeech-to-text and text-to-speechElevenLabs → Settings → API Keys. elevenlabs.io
ELEVENLABS_VOICE_ID Requiredthe voice VOX speaks withElevenLabs → Voices → pick a voice that handles your call language → Copy voice ID. Listen to it on a real phone line first.
TWILIO_ACCOUNT_SID RequiredtelephonyTwilio Console → Account Info (starts with AC). console.twilio.com
TWILIO_AUTH_TOKEN Requiredtelephony, webhook signatures, hanging up when the disclosure failsTwilio Console → Account Info → Show
TWILIO_FROM_NUMBER Requiredthe number VOX calls fromTwilio Console → Phone Numbers → Active numbers. Voice-capable, international format (+…).
VOX_PUBLIC_HOST Requiredthe public host the provider reachesYour domain, host name only, e.g. vox.example.com. No https://, no path (a scheme and a trailing / are stripped).

03Telnyx instead of Twilio

Calls go through Twilio whenever its three variables are all set; otherwise through Telnyx Call Control v2 as soon as any TELNYX_ variable is set, and then all four are required.

VariableUsed forWhere to get it
TELNYX_API_KEYplacing the call and hanging it up when the disclosure failsTelnyx portal → Keys & Credentials → API Keys
TELNYX_FROM_NUMBERthe number VOX calls fromTelnyx portal → My Numbers
TELNYX_CONNECTION_IDthe Call Control Application the calls go throughTelnyx portal → Voice → Programmable Voice → your app → Application ID
TELNYX_PUBLIC_KEYverifying that a webhook really came from Telnyx (Ed25519)Telnyx portal → Keys & Credentials → Public Key (Base64)
  1. Call Control webhookIn the Telnyx portal set the Call Control Application's webhook URL to https://<VOX_PUBLIC_HOST>/call/telnyx (API v2) and assign TELNYX_FROM_NUMBER to it. Audio streams to wss://<VOX_PUBLIC_HOST>/ws/telnyx.
  2. TextsMessaging → create a Messaging Profile, API v2, inbound webhook https://<VOX_PUBLIC_HOST>/sms/telnyx, and assign the number. Without it no text goes out or comes in.
  3. Calls inSet VOX_CALL_PIN. On Telnyx the PIN is typed only (keypad), not spoken.

WhatsApp stays Twilio-only. The rings, the disclosure and the one-time stream secret work the same. Telnyx has Unverified against a real account.

04Optional

VariableUsed forWhere to get it
VOX_ADMIN_TOKENa fixed console token (16+ characters) instead of a new random one at every start. Recommended for Docker and systemd.Any random string, e.g. python -c "import secrets; print(secrets.token_urlsafe(32))"
GOOGLE_OAUTH_CLIENT_FILEsingle-user: path to your Google OAuth client JSON of type Desktop app (Gmail read-only, Calendar)Google Cloud Console: enable the Gmail API (and Calendar API), add yourself as a test user, Credentials → OAuth client ID → Desktop app → download JSON. Then python -m voice mail-auth / calendar-auth.
TWILIO_WHATSAPP_FROMtexts via WhatsApp instead of SMSTwilio Console → WhatsApp senders. Messages outside the 24-hour window need an approved template.
VOX_CALL_PIN4–8 digits the owner enters when calling VOX. Without it inbound calls are refused politely (caller ID can be spoofed).Choose it.
TELEGRAM_BOT_TOKENmessages to your verified Telegram chat@BotFather → /newbot
TELEGRAM_WEBHOOK_SECRETcommands by Telegram (webhook https://<VOX_PUBLIC_HOST>/telegram); updates without it get 40316–256 of A-Z a-z 0-9 _ - you make up
SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_FROMe-mail to your verified address; in SaaS mode also account e-mailsYour mail provider. Port 587 STARTTLS (default) or 465 TLS; VOX never sends unencrypted. SMTP_FROM like VOX <noreply@example.com>; the domain should have SPF and DKIM.
VOX_TTS_BACKEND, VOX_PIPER_URLpiper = the voice comes from your own Piper serverLocal speech
VOX_STT_BACKEND, VOX_WHISPER_URLwhisper = recognition by your own whisper.cpp serverLocal speech

File path settings must point to a regular file (not a symlink) of at most 64 KB inside the home directory or the VOX data directory.

05SaaS keys

VariableUsed forWhere to get it
STRIPE_SECRET_KEYCheckout, Customer Portal, cancelling a deleted customer's subscriptionStripe Dashboard → Developers → API keys (sk_test_… for test mode), or a restricted key. dashboard.stripe.com
STRIPE_WEBHOOK_SECRETverifying webhook eventsThe signing secret (whsec_…) of the endpoint you create (Earnings)
GOOGLE_OAUTH_WEB_CLIENT_FILEcustomers connect their own Gmail and CalendarOperator panel → Google. Or place the file at data/saas/google_oauth_web_client.json.
TELEGRAM_BOT_TOKEN, TELEGRAM_WEBHOOK_SECRET, SMTP_*customers' Telegram and e-mail messages through your bot and serverAs above. Never copied into a customer's environment.

06Other variables

VariableWhereMeaning
VOX_SAAS_URLprocess environment onlySaaS: base URL for links in e-mails. If unset: the branding base URL, else https://VOX_PUBLIC_HOST.
VOX_DATA_DIRenvironmentanother data directory than app/data (same as --data-dir)
VOX_ADMIN_PORT / VOX_MEDIA_PORTDocker Composeports for the compose file (8766 / 8765), not VOX settings
VOX_PUBLIC_DEMOenvironment1 serves a directory made by scripts/make_demo.py read-only. Never on real data.
NLTK_DATAenvironmentwhere NLTK finds punkt_tab if you installed it with setup-nltk --dir
VOX_PIPER_BIN, VOX_PIPER_MODELshell onlythe terminal briefing speaks through a local Piper binary instead of a server
VOX_WAKEWORD_MODEL, VOX_WAKEWORD_MELSPEC, VOX_WAKEWORD_EMBEDDING, VOX_WAKEWORD_THRESHOLDenvironmentonly for wakeword-test with models you bring (below)

07Local speech (optional)

Off by default. With it, calls use your own Piper (text-to-speech) and/or whisper.cpp (speech-to-text) servers instead of ElevenLabs. VOX installs, bundles and downloads none of them; it only talks to them over HTTP. There is no fallback: a chosen engine that does not answer is an error, never a quiet switch to ElevenLabs. Plain http:// is accepted only on this computer (127.0.0.1, localhost, ::1).

You chooseElevenLabs keys a call still needs
nothing (default)ELEVENLABS_API_KEY + ELEVENLABS_VOICE_ID
VOX_TTS_BACKEND=piperELEVENLABS_API_KEY (speech-to-text)
VOX_STT_BACKEND=whisperboth (the voice is still ElevenLabs)
bothnone
VOX_TTS_BACKEND=piper
VOX_PIPER_URL=http://127.0.0.1:5000
VOX_STT_BACKEND=whisper
VOX_WHISPER_URL=http://127.0.0.1:8080/inference
python -m voice local-check --lang en
Licence traps

Use rhasspy/piper (MIT), never OHF-Voice/piper1-gpl (GPL-3.0); the PyPI package piper-tts is MIT only up to 1.2.0. Every Piper loads libespeak-ng (GPL-3.0-or-later) in its own process, which is why VOX runs it only as a separate program. Each Piper voice has its own licence card; read it. All pretrained openWakeWord models are CC BY-NC-SA 4.0 (non-commercial), so VOX ships no wake word, only a hook for models you bring. Full steps: docs/08-INSTALLATION.md, "Local speech".

With whisper.cpp, recognition starts when the caller stops talking, so answers come later; keep barge-in on vad. Local speech has Unverified on a real call.