SDKs
One protocol. Five platforms.
Every SDK wraps the same wire protocol, so an agent behaves the same whether the caller is in Chrome, on an iPhone or inside a Flutter app.
Web
TypeScriptBrowser SDK over Socket.IO, WebRTC and mediasoup-client. Exposes the VoxeraClient class with a typed event map for session state, transcripts and audio.
Public release in progress — the source is available on request in the meantime.
React Native
TypeScriptiOS and Android from one codebase. The useVoxera hook owns the client lifecycle, merges streamed chunks into one message per reply, and handles the Android microphone permission for you.
npm install @voxera/sdk-react-nativeiOS
SwiftNative Swift SDK exposing VoxeraClient and a SwiftUI-ready VoxeraViewModel, with AVAudioSession handling built in.
Public release in progress — the source is available on request in the meantime.
Android
KotlinNative Kotlin SDK with coroutine-based session control and Flow events.
Public release in progress — the source is available on request in the meantime.
Flutter
DartDart SDK over a Pigeon-generated platform channel, sharing the same native iOS and Android transports.
Public release in progress — the source is available on request in the meantime.
The same call, on every platform
WebTypeScript
Public release in progressBrowser SDK over Socket.IO, WebRTC and mediasoup-client. Exposes the VoxeraClient class with a typed event map for session state, transcripts and audio.
import { VoxeraClient } from "@voxera/sdk-web";
const client = new VoxeraClient({
appKey: process.env.VOXERA_PUBLISHABLE_KEY!,
serverUrl: "https://rtc.voxera-voice.com",
userId: "user-123",
modelConfig: { provider: "openai", model: "gpt-4.1-mini" },
ttsConfig: { provider: "openai", voiceId: "marin" },
additionalSystemPrompts: ["Keep spoken answers concise."],
});
client.on("remoteStream", (stream) => {
audioElement.srcObject = stream;
});
await client.connect();React NativeTypeScript
@voxera/sdk-react-nativeiOS and Android from one codebase. The useVoxera hook owns the client lifecycle, merges streamed chunks into one message per reply, and handles the Android microphone permission for you.
import { useVoxera } from "@voxera/sdk-react-native";
export function VoiceScreen() {
const { start, leave, isActive, messages, speakingState } = useVoxera();
return (
<View>
<Button
title={isActive ? "End call" : "Start call"}
onPress={() =>
isActive
? leave()
: start({
appKey: PUBLISHABLE_KEY,
serverUrl: "https://rtc.voxera-voice.com",
userId: "user-123",
})
}
/>
{messages.map((message) => (
<Text key={message.id}>{message.content}</Text>
))}
</View>
);
}iOSSwift
Public release in progressNative Swift SDK exposing VoxeraClient and a SwiftUI-ready VoxeraViewModel, with AVAudioSession handling built in.
import SwiftUI
import VoxeraSDK
struct VoiceView: View {
@StateObject private var voxera = VoxeraViewModel()
var body: some View {
VStack {
Text(voxera.isConnected ? "Connected" : "Idle")
Button("Start call") {
voxera.configure(
VoxeraConfig(
appKey: publishableKey,
serverUrl: "https://rtc.voxera-voice.com",
userId: "user-123"
)
)
voxera.connect()
}
}
}
}AndroidKotlin
Public release in progressNative Kotlin SDK with coroutine-based session control and Flow events.
import com.voxera.sdk.VoxeraClient
import com.voxera.sdk.VoxeraConfig
private val voxera = VoxeraClient(context)
lifecycleScope.launch {
voxera.connect(
VoxeraConfig(
appKey = PUBLISHABLE_KEY,
serverUrl = "https://rtc.voxera-voice.com",
userId = "user-123",
)
)
voxera.messages.collect { message ->
binding.transcript.append(message.content)
}
}FlutterDart
Public release in progressDart SDK over a Pigeon-generated platform channel, sharing the same native iOS and Android transports.
import 'package:voxera_flutter/voxera_flutter.dart';
final voxera = VoxeraClient();
await voxera.connect(
const VoxeraConfig(
appKey: publishableKey,
serverUrl: 'https://rtc.voxera-voice.com',
userId: 'user-123',
),
);
voxera.messages.listen((message) {
setState(() => _transcript.add(message.content));
});Hear it before you build on it
The demo is the real pipeline, not a recording. Talk to it, interrupt it, and decide from there.