@sayna-ai/node-sdk is the server-side toolkit for Sayna. It streams audio over WebSocket, sends and receives transcripts and TTS audio, calls REST endpoints, issues LiveKit tokens, manages SIP hooks, and verifies signed SIP webhooks. Everything is fully typed for TypeScript.
Install
Quick start (realtime)
livekitConfig as the fourth constructor argument to have the server join a LiveKit room, and set the final boolean to true when you want data-channel control without audio streaming.
REST API (no WebSocket required)
await client.health()→{ status: string }health check.await client.getVoices()→Record<string, Voice[]>voice catalog grouped by provider.await client.speakRest(text, ttsConfig)→ArrayBufferaudio synthesized over HTTP. Useful when you do not need an open socket.await client.getLiveKitToken(roomName, participantName, participantIdentity)→{ token, livekit_url, room_name, participant_identity }for joining LiveKit from the browser or another client.await client.getRecording(streamId)→ArrayBufferOGG recording for a completed session (useclient.streamIdafter ready).await client.getSipHooks()→ current SIP webhook hooks from the runtime cache.await client.setSipHooks(hooks)→ upserts SIP webhook hooks (matching hosts are replaced, new hosts are added).
SIP hooks (REST)
Manage SIP webhook forwarding via REST:getSipHooks()returns{ hooks: SipHook[] }.setSipHooks(hooks: SipHook[])replaces hooks with matchinghost(case-insensitive) and adds new hosts, then returns the merged list.
SipHook shape:
| field | type | description |
|---|---|---|
host | string | SIP domain pattern to match. |
url | string | HTTPS destination for webhook events. |
WebSocket client
Constructing the client
new SaynaClient(url, sttConfig?, ttsConfig?, livekitConfig?, withoutAudio?, apiKey?, streamId?)
| argument | purpose |
|---|---|
url | Sayna server URL (http(s) or ws(s)). |
sttConfig (STTConfig) | Default speech-to-text provider config sent on connect. |
ttsConfig (TTSConfig) | Default text-to-speech provider config. |
livekitConfig (LiveKitConfig?) | Optional LiveKit room configuration. |
withoutAudio (boolean) | Disable audio streaming when you only need data-channel control (default false). |
apiKey (string?) | Optional API key for HTTP + WebSocket auth (falls back to SAYNA_API_KEY). |
streamId (string?) | Optional session identifier for recording paths; server generates one when omitted. |
Lifecycle and state
await client.connect()to establish the socket and send the initial config. Resolves after the server sends a ready message.client.readyandclient.connectedexpose readiness and connection state.await client.disconnect()to close the socket and clean up.- LiveKit metadata becomes available when enabled:
client.livekitRoomName,client.livekitUrl,client.saynaParticipantIdentity,client.saynaParticipantName. - Session identifier:
client.streamIdmirrors thestream_idreturned in thereadymessage (or the value you provided).
Sending data
await client.speak(text, flush?, allowInterruption?)to enqueue speech (defaults flush and interruption totrue).await client.onAudioInput(audioData)to stream raw audio for STT.await client.sendMessage(message, role, topic?, debug?)to send data-channel messages.await client.clear()to clear the TTS queue.await client.ttsFlush(allowInterruption?)to flush the queue with an empty speak.
Receiving events
Register callbacks to integrate with your agent logic:registerOnSttResult(cb)for transcription results.registerOnTtsAudio(cb)for streaming TTS audio buffers.registerOnError(cb)for error messages.registerOnMessage(cb)for participant messages.registerOnParticipantDisconnected(cb)when a participant leaves.registerOnTtsPlaybackComplete(cb)when queued speech finishes.
SIP webhook receiver
UseWebhookReceiver to validate SIP webhooks cryptographically (HMAC-SHA256, constant-time comparison, 5-minute replay window, and strict payload validation).
- Constructor:
new WebhookReceiver(secret?)uses the provided secret orSAYNA_WEBHOOK_SECRET. receiver.receive(headers, body)verifies the signature and returns a typedWebhookSIPOutputcontaining participant, room, phone numbers, room prefix, and SIP host. It throwsSaynaValidationErrorif validation fails.