Quickstart
Echo a live call back to yourself in five minutes. The fastest way to confirm your integration works: stand up a WebSocket server that echoes the caller's audio back. When you call in and hear yourself, the full loop — connect, receive audio, return audio — is proven. Swap the echo for your ASR → LLM → TTS from there.
1. Run the echo bot
Pick your language, install one dependency, and start it on a public host with a valid TLS certificate.
Python (short)
import asyncio, json, websockets
async def handler(ws):
async for msg in ws:
if isinstance(msg, bytes):
await ws.send(msg) # echo caller audio back
else:
e = json.loads(msg)
if e.get("type") == "session_start":
print("call from", e.get("customer_phone"))
elif e.get("type") == "session_end":
break
async def main():
async with websockets.serve(handler, "0.0.0.0", 8080, max_size=None):
await asyncio.Future()
asyncio.run(main())
Python (full sample)
Install with pip install websockets, then python echo_bot.py.
#!/usr/bin/env python3
"""
Fonada Audio Streaming — minimal echo bot.
Fonada connects to this server for each call, sends `session_start` (JSON text),
then streams the caller's audio as binary PCM16 frames. This bot echoes every
audio frame straight back, so the caller hears themselves. That single loop
proves the whole integration: connect -> receive audio -> return audio.
Run:
pip install websockets
python echo_bot.py
Then give Fonada your URL, e.g. wss://your-host:8080/stream
"""
import asyncio
import json
import websockets
async def handler(ws):
async for message in ws:
if isinstance(message, bytes):
# Raw PCM16 little-endian mono from the caller — echo it back.
await ws.send(message)
else:
event = json.loads(message)
etype = event.get("type")
if etype == "session_start":
print(f"Call started: session={event.get('session_id')} "
f"from={event.get('customer_phone')} "
f"rate={event.get('audio', {}).get('input_sample_rate')}")
elif etype == "session_end":
print("Call ended by Fonada.")
break
else:
print(f"Control message: {etype}")
async def main():
async with websockets.serve(handler, "0.0.0.0", 8080, max_size=None):
print("Echo bot listening on ws://0.0.0.0:8080")
await asyncio.Future() # run forever
if __name__ == "__main__":
asyncio.run(main())
JavaScript (full sample)
Install with npm install ws, then node echo_bot.js.
// Fonada Audio Streaming — minimal echo bot.
//
// Fonada connects to this server for each call, sends `session_start` (JSON
// text), then streams the caller's audio as binary PCM16 frames. This bot
// echoes every audio frame straight back, so the caller hears themselves —
// proving the full loop: connect -> receive audio -> return audio.
//
// Run:
// npm install ws
// node echo_bot.js
// Then give Fonada your URL, e.g. wss://your-host:8080/stream
const { WebSocketServer } = require("ws");
const wss = new WebSocketServer({ port: 8080 });
console.log("Echo bot listening on ws://0.0.0.0:8080");
wss.on("connection", (ws) => {
ws.on("message", (data, isBinary) => {
if (isBinary) {
// Raw PCM16 little-endian mono from the caller — echo it back.
ws.send(data);
} else {
const event = JSON.parse(data.toString());
switch (event.type) {
case "session_start":
console.log(
`Call started: session=${event.session_id} ` +
`from=${event.customer_phone} ` +
`rate=${event.audio?.input_sample_rate}`
);
break;
case "session_end":
console.log("Call ended by Fonada.");
ws.close();
break;
default:
console.log(`Control message: ${event.type}`);
}
}
});
});
2. Give Fonada your URL
Share your wss:// endpoint (e.g. wss://your-host:8080/stream) with your onboarding contact, along with the sample rate and encoding you want.
3. Call in and listen
Dial your Fonada number. You should hear your own voice echoed back with minimal delay.