OpenAI Realtime
OpenAI’s Realtime API exposes a single WebSocket that handles speech-to-text, LLM reasoning, and text-to-speech in one pass. Pair it with Teler and you have a working AI voice agent in minutes.
Reference repos
Section titled “Reference repos”Prerequisites
Section titled “Prerequisites”- An OpenAI account with Realtime API access
- A Teler account with an active API key
- One Teler phone number on your account (the
from_number) - An ngrok auth token (for local development)
- Docker and Docker Compose
Configuration
Section titled “Configuration”| Variable | Required | Default | Description |
|---|---|---|---|
OPENAI_API_KEY | yes | none | Your OpenAI API key. |
TELER_API_KEY | yes | none | Your Teler API key from the dashboard. |
NGROK_AUTHTOKEN | yes (local) | none | ngrok auth token for the public tunnel. |
SERVER_DOMAIN | auto | none | Public URL exposed to Teler. Detected from ngrok automatically. |
5-minute setup
Section titled “5-minute setup”git clone https://github.com/frejun-tech/teler-openai-bridgecd teler-openai-bridgecp .env.example .env# fill OPENAI_API_KEY, TELER_API_KEY, NGROK_AUTHTOKENdocker compose up -d --buildgit clone https://github.com/frejun-tech/teler-openai-node-bridgecd teler-openai-node-bridgecp .env.example .env# fill OPENAI_API_KEY, TELER_API_KEY, NGROK_AUTHTOKENdocker compose up -d --buildInitiate a call
Section titled “Initiate a call”curl -X POST http://localhost:8000/api/v1/calls/initiate-call \ -H "Content-Type: application/json" \ -d '{ "from_number": "+91XXXXXXXXXX", "to_number": "+91XXXXXXXXXX" }'The phone rings; the OpenAI agent answers. Talk to it.
Architecture
Section titled “Architecture”The bridge implements the standard 3-endpoint pattern documented in Media Streaming → Bridge:
| Endpoint | Direction | Purpose |
|---|---|---|
POST /api/v1/calls/initiate-call | client → bridge | Trigger an outbound call. |
POST /api/v1/calls/flow | Teler → bridge | Returns a stream Call Flow. |
WS /api/v1/calls/media-stream | Teler → bridge | Bidirectional audio. |
POST /api/v1/webhooks/receiver | Teler → bridge | Lifecycle webhooks. |
Inside the WebSocket handler, the bridge opens a parallel WebSocket to the OpenAI Realtime API and relays audio in both directions.
Audio quirks
Section titled “Audio quirks”OpenAI Realtime returns 24 kHz PCM. Teler operates at 8 kHz (or 16 kHz if you configure it). The bridge handles downsampling automatically; you don’t need to touch this unless you fork the repo.
Production deployment
Section titled “Production deployment”- Replace ngrok with a real public host: Fly.io, Railway, ECS, or your own infra.
- Pin the Docker image with a tagged release rather than
:latest. - Set
SERVER_DOMAINexplicitly in production; auto-detect is for local only. - Forward Teler webhooks to your backend rather than the bridge for durability.
- Rotate
OPENAI_API_KEYandTELER_API_KEYquarterly.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Likely cause | Fix |
|---|---|---|
| Phone rings but silence | Missing OPENAI_API_KEY or invalid | Check container logs; recreate .env |
| Bridge can’t be reached | ngrok not running or SERVER_DOMAIN stale | docker compose restart; wait for ngrok |
| Garbled / chipmunk audio | Sample rate mismatch | Should not happen with this bridge; file an issue if it does |
| Long latency on first response | Cold start of Realtime session | Send a tiny warm-up message before connecting the call |
Next steps
Section titled “Next steps” Other recipes ElevenLabs, Gemini, Vapi, and more.
Bridge architecture The conceptual model behind every recipe.
WebSocket protocol The exact messages flowing through the bridge.