Appearance
Embed Widget
Add an AI-powered assistant to any website with a single <script> tag. The Universal API embed widget supports text chat, voice conversations, or both — with a toggle for end users to switch between modes.
Quick Start
1. Create an Embed Token
bash
curl -X POST https://api.universalapi.co/embed/create \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agentId": "YOUR_TEXT_AGENT_ID",
"voiceAgentId": "YOUR_VOICE_AGENT_ID",
"allowedDomains": ["yourdomain.com", "localhost"],
"greeting": "Hi! How can I help you today?"
}'2. Add the Script Tag
Paste the returned snippet into your HTML:
html
<script src="https://cdn.universalapi.co/embed/widget.js"
data-text-agent="YOUR_TEXT_AGENT_ID"
data-voice-agent="YOUR_VOICE_AGENT_ID"
data-token="emb_pk_live_..."
async></script>That's it! A floating chat button appears on your page.
Modes
The widget supports three modes, controlled by the data-mode attribute or set at token creation:
| Mode | Description | Default when |
|---|---|---|
text | Text chat only (streaming HTTP) | Only agentId provided |
voice | Voice only (WebSocket audio via Nova Sonic) | Only voiceAgentId provided |
both | Both with toggle tabs | Both agents provided |
Text Only
html
<script src="https://cdn.universalapi.co/embed/widget.js"
data-text-agent="TEXT_AGENT_ID"
data-token="emb_pk_live_..."
async></script>Voice Only
html
<script src="https://cdn.universalapi.co/embed/widget.js"
data-voice-agent="VOICE_AGENT_ID"
data-token="emb_pk_live_..."
async></script>Both (with Toggle)
html
<script src="https://cdn.universalapi.co/embed/widget.js"
data-text-agent="TEXT_AGENT_ID"
data-voice-agent="VOICE_AGENT_ID"
data-token="emb_pk_live_..."
data-mode="both"
async></script>When mode is both, users see tabs to switch between 💬 Chat and 🎙️ Voice.
Why Separate Agents?
Text and voice agents use fundamentally different technologies:
- Text agents use streaming HTTP with models like Claude, Nova, or GPT — optimized for detailed, formatted responses with markdown, code blocks, and tool use.
- Voice agents use WebSocket audio with Amazon Nova Sonic — optimized for real-time, natural conversation with low latency audio.
By specifying separate agent IDs, you can optimize each experience independently. For example, use a tool-heavy research agent for text and a fast conversational agent for voice.
Configuration Options
| Attribute | Description | Default |
|---|---|---|
data-text-agent | Text chat agent ID | — |
data-voice-agent | Voice agent ID | — |
data-token | Embed token (emb_pk_live_...) | Required |
data-mode | "text", "voice", or "both" | Auto-detected |
data-position | "bottom-right" or "bottom-left" | "bottom-right" |
data-color | Brand color (hex) | "#6366f1" |
data-greeting | Greeting message | "Hi! How can I help you today?" |
data-title | Header title (overrides agent name) | Agent name |
data-subtitle | Secondary text below the title | — |
data-logo | Circular avatar image URL in header | 🤖 emoji |
data-initial-prompt | Auto-sent on load; agent's reply becomes the opening message | — |
data-placeholder | Input field placeholder text | "Ask me anything..." |
data-size | "compact", "standard", or "large" | "standard" |
Customization
Branding
Add your logo, title, and subtitle to make the widget match your brand:
html
<script src="https://cdn.universalapi.co/embed/widget.js"
data-text-agent="YOUR_AGENT_ID"
data-token="emb_pk_live_..."
data-title="Acme Support"
data-subtitle="We typically reply instantly"
data-logo="https://yourdomain.com/logo.png"
data-color="#0066cc"
async></script>Initial Prompt (Contextual Greeting)
Instead of a static greeting, use data-initial-prompt to send a hidden message to the agent on load. The agent's response becomes the opening message — perfect for context-aware greetings:
html
<script src="https://cdn.universalapi.co/embed/widget.js"
data-text-agent="YOUR_AGENT_ID"
data-token="emb_pk_live_..."
data-initial-prompt="The user just landed on the pricing page. Greet them and offer to help compare plans."
async></script>The prompt is invisible to the user — they only see the agent's reply as the first message.
Size Presets
Choose from three sizes to fit your layout:
| Size | Dimensions | Best for |
|---|---|---|
compact | 340 × 480 | Mobile-first sites, sidebars |
standard | 400 × 580 | Most websites (default) |
large | 440 × 640 | Desktop-focused, complex agents |
html
<script src="https://cdn.universalapi.co/embed/widget.js"
data-text-agent="YOUR_AGENT_ID"
data-token="emb_pk_live_..."
data-size="large"
async></script>JavaScript API
Control the widget programmatically via window.UniversalAPIWidget:
javascript
// Open/close the widget
UniversalAPIWidget.open();
UniversalAPIWidget.close();
// Switch between text and voice (only in "both" mode)
UniversalAPIWidget.switchTo('voice');
UniversalAPIWidget.switchTo('text');
// Listen for events
UniversalAPIWidget.on('ready', () => console.log('Widget loaded'));
UniversalAPIWidget.on('open', () => console.log('Panel opened'));
UniversalAPIWidget.on('close', () => console.log('Panel closed'));
UniversalAPIWidget.on('voiceStart', () => console.log('Voice session started'));
UniversalAPIWidget.on('voiceEnd', () => console.log('Voice session ended'));
UniversalAPIWidget.on('transcript', (msg) => console.log('Transcript:', msg));
// Check state
console.log(UniversalAPIWidget.getMode()); // "text" | "voice" | "both"
console.log(UniversalAPIWidget.getActiveTab()); // "text" | "voice"
console.log(UniversalAPIWidget.isReady()); // true/false
console.log(UniversalAPIWidget.version); // "3.0.0"Security
- Domain allowlist — Tokens only work on approved domains
- Rate limiting — Per-day and per-IP limits prevent abuse
- Token revocation — Instantly disable a widget by revoking its token
- Shadow DOM isolation — Widget styles don't leak into your page
- No credentials exposed — The
emb_pk_live_token is a restricted publishable key; your API keys are never sent to the browser
Billing
Widget usage is billed to the token owner's account at standard rates:
- Text chat: Normal agent invocation credits (varies by model + tools used)
- Voice: ~50 credits/minute while connected (Nova Sonic real-time audio)
See Pricing for details.