@identifyorg/js-sdk
v0.1.0
Published
IdentifyOrg JS SDK — video/voice calls, live streaming, and a live chat widget. Zero build step, wraps livekit-client.
Maintainers
Readme
@identifyorg/js-sdk
Video calls, voice calls, live streaming, and a drop-in live chat widget —
one JS file, no build step. Works in plain <script> tags, in any bundler,
and inside a React Native WebView (so it doubles as the cross-platform
glue for hybrid mobile apps).
Under the hood it wraps livekit-client
(the same open-source WebRTC engine that powers LiveKit's official SDKs) and
adds IdentifyOrg's auth, metering, and a ready-made chat UI on top. IdentifyOrg
never re-implements WebRTC — LiveKit does the actual media routing.
Install
Script tag (no build step):
<script src="https://cdn.identifyorg.com/sdk/identifyorg-sdk.js"></script>npm:
npm install @identifyorg/js-sdk livekit-clientimport { IdentifyOrg } from "@identifyorg/js-sdk";Get your key
- Register at identifyorg.com and log in.
POST /v1/keyswith{ "name": "Web Widget", "live": false, "scope": "publishable" }(or create one from the dashboard).- Use that publishable key (
io_test_pub_.../io_live_pub_...) here.
Never put a secret key (
vl_*_sk...) in browser or mobile code. Secret keys can verify BVN/NIN/FRSC and touch billing — they belong on your server only (see the Node/Python/Go server SDKs). Publishable keys can only mint realtime call/chat tokens, so they're safe to ship to every client.
Video / voice call
const identifyorg = new IdentifyOrg({ apiKey: "io_test_pub_..." });
const call = await identifyorg.joinCall({
type: "video", // "video" | "voice" | "stream"
identity: "user-123",
displayName: "Ada",
localVideoEl: document.getElementById("local-video"),
remoteContainerEl: document.getElementById("remote-videos"),
});
call.on("participantDisconnected", (p) => console.log(p.identity, "left"));
// later
await call.leave();To join an existing room (e.g. the other side of a 1:1 call), pass the
same roomName your backend/other client used.
Live streaming (one-to-many)
// Broadcaster
const stream = await identifyorg.joinCall({ type: "stream", identity: "host-1", role: "publisher", localVideoEl });
// Viewer — much cheaper per-minute rate, no publish grant
const view = await identifyorg.joinCall({
type: "stream",
roomName: stream.roomName,
identity: "viewer-99",
role: "viewer",
remoteContainerEl: document.getElementById("player"),
});Live chat widget (fastest path)
const identifyorg = new IdentifyOrg({ apiKey: "io_test_pub_..." });
identifyorg.mountChatWidget({ visitorName: "Guest" }); // floating widget, bottom-rightThat's the entire integration — a floating "Chat with us" bubble appears, connects to a metered chat channel, and handles send/receive.
White-label the widget
const identifyorg = new IdentifyOrg({
apiKey: "io_test_pub_...",
theme: {
primaryColor: "#7C3AED", // header + send button
onPrimaryColor: "#ffffff", // text/icons on top of primaryColor
surfaceColor: "#0f0f14", // widget body background
textColor: "#f5f5f5",
borderRadius: "16px",
},
});
identifyorg.mountChatWidget({ visitorName: "Guest" });
// or override per-call without changing the client's default theme:
identifyorg.mountChatWidget({ theme: { primaryColor: "#E11D48" } });Implemented with CSS custom properties (--vl-primary, --vl-surface, etc.)
scoped to the widget container, so the whole thing reskins from one config
object — no CSS overrides needed.
Headless chat (custom UI, or bridging into a mobile WebView)
const chat = await identifyorg.joinChat({ visitorId: "visitor-42", visitorName: "Guest" });
chat.onMessage((msg) => console.log(msg.from, msg.text));
chat.send("Hello!");Pricing (billed per participant-minute, charged when the session ends)
| Type | Price | |---|---| | Voice call | ₦1.00 / participant-minute | | Video call | ₦2.50 / participant-minute | | Live stream (per viewer) | ₦1.50 / participant-minute | | Chat | ₦0.20 / minute the channel is open |
Get live prices any time: GET /v1/pricing (no auth required).
Cross-platform note
This same script works unmodified inside a React Native WebView — many
teams use it to get calling/chat into a hybrid app without a native
dependency. For a fully native experience, use the platform SDKs in
sdks/react-native, sdks/flutter, sdks/kotlin instead, which wrap
LiveKit's native client for lower latency and OS-level features (CallKit,
PiP, background audio).
