WebRTC
Connect to an agent in the browser using the Web SDK
The Web SDK lets you embed a real-time audio and video connection to your agent directly in your web application. It provides a ready-made UI component — including the avatar widget, controls, and tooltips — that you can drop into any page.
The SDK is framework-agnostic and works with React, Vue, Angular, or vanilla JavaScript. It ships with full TypeScript support, tree-shakeable exports, and zero external dependencies in standalone mode.
For the full SDK documentation, including configuration options, event handling, and advanced usage, see the Web SDK package on npm.
Supported environments
Browsers
Chrome, Firefox, Safari, Edge
React
16.x through 19.x
Vue
2.x and 3.x
Angular
12+
Vanilla JS
No build tools required
Connecting to an agent
Create a session
Call POST /public/connections to create a WebRTC session. Specify the companion, provider configuration, and any resources you want to attach:
curl -X POST https://companion-api.napster.com/public/connections \
-H "X-Api-Key: $NAPSTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"companionId": "comp_abc123",
"providerConfig": {
"voiceId": "alloy",
"settings": {}
},
"functions": ["fn_tool1", "fn_tool2"],
"faqCollections": ["faqc_01"],
"knowledgeBaseId": "col_8f2a3b"
}'The response returns a token and a connection object containing the session id. Pass the token to the Web SDK — you don't need to decode it. Store the connection id on your backend to retrieve session details later, such as transcripts or duration.
For the full list of request body fields — including language, tags, external client identification, and provider settings — see Configuration.
Install the Web SDK
Install the SDK and its peer dependency:
npm install @touchcastllc/napster-companion-api @reduxjs/toolkitImport the SDK and its stylesheet in your application:
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
import "@touchcastllc/napster-companion-api/styles";The stylesheet can also be loaded via a <link> tag or CSS @import if you prefer not to import it in JavaScript:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css" />Add a single script tag to your HTML. All dependencies are bundled — no build tools required.
<script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.js"></script>Initialize the SDK
Pass the token from the connection response and a container element to mount the widget into:
const widget = await NapsterCompanionApiSdk.init(token, {
mountContainer: "#avatar-container",
});<div id="avatar-container"></div>
<script>
window.napsterCompanionApiSDK.init(token, {
mountContainer: "#avatar-container",
});
</script>Framework examples
import React, { useEffect, useRef } from "react";
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
import type { NapsterCompanionApiInstance } from "@touchcastllc/napster-companion-api";
import "@touchcastllc/napster-companion-api/styles";
export function CompanionWidget({ token }: { token: string }) {
const containerRef = useRef<HTMLDivElement>(null);
const instanceRef = useRef<NapsterCompanionApiInstance | null>(null);
useEffect(() => {
const initSDK = async () => {
if (!containerRef.current) return;
const result = await NapsterCompanionApiSdk.init(token, {
mountContainer: containerRef.current,
position: "bottom-right",
});
instanceRef.current = result;
};
initSDK();
return () => {
instanceRef.current?.destroy();
};
}, []);
return <div ref={containerRef} style={{ width: "100%", height: "100%" }} />;
}<template>
<div ref="containerRef"></div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from "vue";
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
import type { NapsterCompanionApiInstance } from "@touchcastllc/napster-companion-api";
import "@touchcastllc/napster-companion-api/styles";
const props = defineProps<{ token: string }>();
const containerRef = ref<HTMLElement>();
let instance: NapsterCompanionApiInstance | null = null;
onMounted(async () => {
if (!containerRef.value) return;
instance = await NapsterCompanionApiSdk.init(props.token, {
mountContainer: containerRef.value,
position: "bottom-right",
});
});
onUnmounted(() => {
instance?.destroy();
});
</script>import {
Component,
OnInit,
OnDestroy,
ElementRef,
ViewChild,
Input,
} from "@angular/core";
import {
NapsterCompanionApiSdk,
NapsterCompanionApiInstance,
} from "@touchcastllc/napster-companion-api";
@Component({
selector: "app-companion",
template: "<div #containerRef></div>",
})
export class CompanionComponent implements OnInit, OnDestroy {
@Input() token!: string;
@ViewChild("containerRef") containerRef!: ElementRef<HTMLDivElement>;
private instance: NapsterCompanionApiInstance | null = null;
async ngOnInit() {
this.instance = await NapsterCompanionApiSdk.init(this.token, {
mountContainer: this.containerRef.nativeElement,
position: "bottom-right",
});
}
ngOnDestroy() {
this.instance?.destroy();
}
}<div id="sdk-container"></div>
<script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.js"></script>
<script>
// token comes from your server after calling POST /public/connections
const sdk = window.napsterCompanionApiSDK;
sdk
.init(token, {
mountContainer: "#sdk-container",
position: "bottom-right",
})
.then(instance => {
instance.showAvatar();
});
</script>