What is the Web SDK?
The Web SDK is a small piece of code you drop into your website. When a visitor clicks a “Talk to us” button, it opens a live voice conversation with your OneInbox agent — right in the browser, using their microphone.
Think of it like a live chat widget, but for voice.
What it handles for you:
- Asking the browser for microphone permission
- Streaming audio in real time (both directions)
- Showing live transcripts as the conversation happens
- Mute, unmute, and hang up
What your team sets up:
- An agent on OneInbox (the AI that answers)
- A button or widget on your site that starts the call
How it fits into your product
When a visitor clicks “Call”:
- Your website asks your server: “start a call for this visitor”
- Your server creates the call via the OneInbox API and gets back a short-lived access token
- The Web SDK uses that token to connect the visitor’s browser to the agent
- The conversation starts — live, two-way voice
Your server holds your secret API key. The browser only ever receives a one-time token that expires when the call ends — so nothing sensitive is exposed to visitors.
Two packages
| Package | Use it when |
|---|
@oneinbox/web-sdk | Plain JavaScript or any framework |
@oneinbox/web-sdk-react | React apps — gives you a ready-made hook |
Both do the same thing. The React package just wraps the core one with React-friendly patterns.
Two ways to start a call
Option 1 — Publishable key (simpler)
A publishable key (oi_pk_…) is a special key that is safe to put directly in your website’s code. It can only start calls — it can’t read your data or make changes. You lock it to your domain so only your site can use it.
Getting a publishable key:
- Go to the OneInbox dashboard
- Navigate to Settings → Publishable Keys
- Click Create key, give it a name, and add your allowed origins (e.g.
https://yoursite.com)
- Copy the key — it starts with
oi_pk_live_…
Publishable keys are created in the dashboard only — there is no API endpoint for this.
They are scoped to web calls and locked to the origins you register. Requests from
unregistered origins receive a 403 ORIGIN_NOT_ALLOWED error.
With a publishable key, the SDK handles everything. No server call needed:
const oi = new OneInbox("oi_pk_live_…");
await oi.start("agt_…", { variables: { customer_name: "Sama" } });
Option 2 — Token from your server (more control)
If you already have a backend and want full control over when and how calls are started, your server creates the call and sends a short-lived token to the browser. The SDK connects using that token.
// Your server calls POST /v1/calls/web and returns these two values
const { participant_token, server_url } = await yourBackend.startCall(agentId);
const oi = new OneInbox("unused");
await oi.start({ token: participant_token, serverUrl: server_url });
See Web calls for the backend side.
Install
# Vanilla JavaScript / any framework
npm install @oneinbox/web-sdk livekit-client
# React
npm install @oneinbox/web-sdk-react @oneinbox/web-sdk livekit-client react
livekit-client is a required companion package that handles the audio connection.
Vanilla example
import { OneInbox } from "@oneinbox/web-sdk";
const oi = new OneInbox("oi_pk_live_…");
// React to what happens during the call
oi.on("call-start", () => showCallUI());
oi.on("call-end", () => showIdleUI());
oi.on("transcript", (t) => appendTranscript(t.role, t.text)); // live captions
oi.on("error", (e) => showError(e.message));
// Start the call — pass the visitor's name so the agent greets them
await oi.start("agt_…", { variables: { customer_name: "Sama" } });
// During the call
oi.setMuted(true); // mute the visitor's mic
oi.setMuted(false); // unmute
await oi.stop(); // hang up
What you can listen to
| Event | What it means |
|---|
call-start | The call connected — show your active call UI |
call-end | The call ended — return to idle state |
transcript | A new line of speech was heard — update captions or a chat log |
speech-start / speech-end | Someone started or stopped speaking — animate a speaking indicator |
volume-level | How loud the visitor’s mic is right now (0–1) — drive a mic level bar |
error | Something went wrong — show an error message |
Controls
| Method | What it does |
|---|
oi.start(agentId, { variables }) | Start the call |
oi.stop() | End the call |
oi.setMuted(true / false) | Mute or unmute the visitor’s mic |
oi.isMuted() | Returns true if the mic is currently muted |
oi.status | Current state: idle, connecting, active, or ending |
React example
import { OneInboxProvider, useOneInbox } from "@oneinbox/web-sdk-react";
// Wrap your app once at the top level
function App() {
return (
<OneInboxProvider publishableKey="oi_pk_live_…">
<CallWidget agentId="agt_…" />
</OneInboxProvider>
);
}
// Use the hook anywhere inside the provider
function CallWidget({ agentId }) {
const { start, stop, status, transcripts, isAgentSpeaking, isMuted, setMuted } = useOneInbox();
const active = status === "active";
return (
<div>
<button onClick={() => (active ? stop() : start(agentId))}>
{active ? "Hang up" : "Talk to us"}
</button>
{active && (
<button onClick={() => setMuted(!isMuted)}>
{isMuted ? "Unmute" : "Mute"}
</button>
)}
<p>{isAgentSpeaking ? "Agent is speaking…" : status}</p>
{transcripts.map((t, i) => (
<p key={i}><b>{t.role}:</b> {t.text}</p>
))}
</div>
);
}
useOneInbox() gives you everything you need to build a call UI:
| Value | What it is |
|---|
status | Current call state (idle, connecting, active, ending) |
transcripts | Every line of the conversation so far |
isAgentSpeaking | true while the agent is talking |
isMuted | true if the visitor’s mic is muted |
volume | Mic level in real time (0–1) |
error | The last error, if any |
start / stop / setMuted | Controls |
Web SDK vs Web calls API
Both are part of the same flow — the Web calls API creates the session, and the Web SDK joins it from the browser.
| Web SDK | Web calls API |
|---|
| Who uses it | Your website visitors | Your server |
| What it does | Joins a live voice session | Creates the session |
| Where it runs | Browser | Your backend |
| Guide | This page | Web calls |