Quickstart
Your first call in five steps
This page answers one question: how do I make the first thing work? One happy path: authenticate, create a room, place a real WebRTC call from the browser, and listen for events. Set BASE to your deployment (e.g. https://dev.somvad.com).
1 · Get access & a token
Request platform access at info@somvad.com. Then exchange credentials for a bearer token. The token's tenant_id selects which per-tenant profile you act as. Microsoft Entra (OIDC) tokens are accepted on the same endpoints when enabled.
curl
# public endpoint: returns a JWT TOKEN=$(curl -s $BASE/auth/login -H 'content-type: application/json' \ -d '{"email":"trader@bank.com","tenant_id":"<TENANT_ID>","password":"<pw>"}' \ | jq -r .access_token) curl -s $BASE/auth/me -H "Authorization: Bearer $TOKEN" # -> {"user_id":"…","role":"member","tenant_id":"…"}
Every request below sends Authorization: Bearer $TOKEN unless marked public.
2 · Create a conference
A Conference is the platform's voice primitive: an ad-hoc call, a private call, a hoot, a line. Create one with visibility: "tenant" so anyone on the desk may see and join it.
curl
CID=$(curl -s $BASE/conferences -H "Authorization: Bearer $TOKEN" \ -H 'content-type: application/json' \ -d '{"name":"London Rates","visibility":"tenant"}' | jq -r .id)
3 · Ask where to connect
Audio never touches this API. The control plane assigns a media mixer and hands back its own wss:// endpoint and room. status:"spawning" means a mixer is autoscaling. Poll /join until "ready".
curl
curl -s -X POST $BASE/conferences/$CID/join -H "Authorization: Bearer $TOKEN" # -> {"room":"7003","mixer_id":"mixer-1", # "ws_url":"wss://mixer-1.sip.<domain>","status":"ready"}
4 · Connect audio from the browser
Use the SDK. conferences.join gives you the placement; browser.config gives you a fresh per-call SIP credential plus ICE/TURN servers; connect() registers SIP-over-WSS against the assigned mixer and returns a Phone. AEC/echo constraints are applied for you, and call() rejects honestly on failure, no optimistic "connected".
typescript · @somvad/sdk-core
import { SomvadClient, connect } from '@somvad/sdk-core' const client = new SomvadClient({ baseUrl: BASE, token }) const placement = await client.conferences.join(conferenceId) const cfg = await client.browser.config() const phone = await connect(cfg, placement.ws_url) await phone.call(placement.room, document.querySelector('audio')!) phone.setMuted(false) // you're live
5 · Listen for realtime events
One WebSocket carries presence, chat, targeted signals (incoming calls, line state), and live captions. It replays missed frames on reconnect and re-delivers still-ringing calls on connect.
typescript · @somvad/sdk-core
import { SomvadEvents } from '@somvad/sdk-core' const events = new SomvadEvents({ baseUrl: BASE, token }).connect() events.on('signal', (s) => { if (s.event === 'incoming_call') ring(s) }) events.on('presence', updateDirectory) events.on('chat', appendMessage)
React in 40 lines
Prefer hooks?
@somvad/sdk-react wraps all of this behind one provider and a useCall() hook that runs join → placement → SIP/WebRTC → mute → hang-up → QoS report for you. See the SDK page.