Skip to main content
Real phone calls require your telephony provider to reach the runtime from the public internet. This page covers VOICE_SERVER_BASE_URL, what breaks when it is wrong, and how to proxy it correctly.

Why a public URL is required

Two separate connections come inbound from your provider: Neither is outbound, so NAT traversal and firewall punching do not help. The provider must resolve and reach your hostname.

Setting it

One variable, used in two places: Both read the same value, so they cannot disagree.

The one-way door

build_answer_urls() composes:
and create_application(agent_id, answer_url) sends it to your provider when the agent is created.
Changing VOICE_SERVER_BASE_URL afterwards does not update agents that already exist. Your provider keeps calling the old URL, and those agents stop answering — with no error in VoicEra, because nothing reaches it.Fix it per agent: PATCH /api/v1/agents/{agent_id} re-provisions the application against the current value, or delete and recreate the agent. Set the variable correctly before creating telephony agents.
VoicEra currently uses the same URL for answer and hangup.

What breaks, and how it looks

Reverse proxy

The runtime serves HTTP and WebSocket on the same port, so one server block covers both — but the upgrade headers are mandatory:
Two defaults bite: without proxy_http_version 1.1 and the Upgrade/Connection headers the WebSocket never establishes, and nginx’s 60-second read timeout kills any call longer than a minute.

Tunnels for local testing

Put the assigned HTTPS hostname in VOICE_SERVER_BASE_URL, restart the API and runtime, then create your telephony agents.
Free tunnels get a new hostname every restart. Since the URL is baked in at agent-create time, recreate or PATCH your agents whenever the tunnel address changes.

Verifying

Check the runtime is reachable from outside:
Then confirm the Stream XML names the public host:
If that address says localhost, no real call will ever connect. Finally, test the WebSocket upgrade itself:
101 Switching Protocols means the proxy is configured correctly. 200 or 400 means it is not upgrading.

Security

/answer and /agent/{org_id}/{agent_id} have no authentication — they must be publicly reachable for telephony to work, and the runtime resolves everything from the path. Anyone who learns an org and agent id pair can open a pipeline session and consume your model credits.Mitigate with rate limiting at the proxy, and IP-allowlist your provider’s ranges where they publish them. See Security hardening.