What you get:
  • A voice conversation from the phone to EESI over WebRTC: echo cancellation, Opus, and interruptions handled for you.
  • Your API key stays on your server. The app gets a one-use secret that opens a session your server already set up and locked: instructions, voice, tools.
  • Limits the app cannot change: the longest a call may last and how long a silence it may sit through.
  • Audio never passes through your server.

Run it

Your server mints a secret and hands the app the relay servers it may need to reach EESI from a mobile network:
server.mjs
The app opens the call. This is React Native with react-native-webrtc; the WebRTC libraries for Swift and Kotlin take the same steps:
Nur’s voice arrives as the call’s remote audio track, which the WebRTC library plays. Events (what the person said, Nur’s words, when it starts and stops) arrive as JSON on the events channel, and the app can send events there too: events.send(JSON.stringify({ type: "response.create" })) once the channel opens has Nur speak first. Close the peer connection to hang up. The secret is spent by the first call that presents it and expires after a minute if unused, so ask your server for a new one for each call.

Good to know

  • With eesi_lock: "all", the app can still stream audio, send the person’s typed messages and ask for a reply, but cannot change who Nur is or what it may do.
  • When a limit is reached the app receives {"type": "eesi.hangup", "reason": "silence"} (or max_duration) and the call ends.
  • eesi_webhook posts what was said to your server as it happens, signed, and eesi_data keeps a call out of training or out of recordings.

Next

Client secrets

Locks, limits, webhooks and what a session’s words may be used for.

Live conversation

Session settings, voices, interruptions and every event.

Tools and MCP servers

Let Nur look things up or act in your app.

Voices

Built-in voices, or clone your brand’s own.