Embeddable Pamela Voice AI widget for any website
npm install @thisispamela/widgetEmbeddable Pamela Voice AI widget for any website. Add AI-powered phone calls with a single script tag.
Primary CDN (when available):
``html`
unpkg / jsDelivr (npm-backed):
`html`
Example:
`html`
`bash`
npm install @thisispamela/widget
`javascript
import Pamela from '@thisispamela/widget';
Pamela.init({ apiKey: 'pk_live_xxx', mode: 'floating' });
`
Get your API key from developer.thisispamela.com. API keys are created and managed in the API settings panel.
| Option | Type | Default | Description |
| ------------- | ------ | -------------- | ------------------------------ |
| apiKey | string | required\* | API key |accessToken
| | string | required\* | OAuth access token (alternative to apiKey) |mode
| | string | 'floating' | 'floating' \| 'modal' \| 'inline' \| 'none' |theme
| | string | 'auto' | 'light' \| 'dark' \| 'auto' |position
| | string | 'bottom-right' | Floating button position |baseUrl
| | string | Production API | Custom API base URL |defaults
| | object | — | Default voice, agentName, callerName, maxDuration |styles
| | object | — | CSS variable overrides: --pamela-accent, --pamela-primary, --pamela-background, --pamela-text, --pamela-border-radius, --pamela-font |
\* Either apiKey or accessToken is required (not both)
Start a call programmatically.
`javascript`
const call = await Pamela.call({
to: '+15551234567',
task: 'Schedule a demo for tomorrow at 2pm',
voice: 'auto',
agentName: 'Pamela',
callerName: 'Acme Corp',
});
Get call status or cancel an in-progress call.
Events: call:start, call:update, call:complete, call:error, modal:open, modal:close.
Remove the widget and clean up.
Add call buttons to existing elements:
`html
data-pamela-call
data-to="+15551234567"
data-task="Schedule a demo"
data-voice="auto"
data-label="Call with Pamela"
>
The widget discovers these on load and watches for dynamically added elements. When you click an inline button, the modal opens (if you use
mode: 'inline') and shows call status and transcript until the call completes.Modal mode
Use the full modal UI (phone input, task textarea, voice select, status + transcript):
`javascript
Pamela.init({ apiKey: 'pk_live_xxx', mode: 'modal' });
// Open the modal programmatically if you want:
Pamela.show();
`Theming
The widget uses CSS variables aligned with the Pamela design system (light and dark). Themes: Light (default), Dark (auto-detected via
prefers-color-scheme, .dark class, or data-pamela-theme="dark"). Pass theme: 'light' or theme: 'dark' to force, or theme: 'auto' (default). Override at init with styles: { '--pamela-primary': '#f97316', '--pamela-background': '#ffffff', '--pamela-text': '#1f2937', '--pamela-border-radius': '8px', '--pamela-font': '...' } or override tokens in your CSS on .pamela-widget-root.Distribution
- Full bundle:
dist/widget.js (IIFE), dist/widget.esm.js (ESM), dist/widget.d.ts (types)
- Minified: npm run build:min produces dist/widget.min.js for production/CDN
- npm: npm publish (package @thisispamela/widget, publishConfig.access: public)
- CDN URLs: https://unpkg.com/@thisispamela/widget (recommended), https://cdn.jsdelivr.net/npm/@thisispamela/widget (alternative)Local demo
After
npm run build, serve the package directory and open demo.html (e.g. npx serve . then visit /demo.html). Replace apiKey in the script with a valid key to test the floating button and call flow.Security
API keys used in the widget are visible in the frontend. Use project/domain allowlists in the dashboard and prefer restricted public keys (
pk_*`) for widget use. See WIDGET_ARCHITECTURE.md.See docs/architecture/WIDGET_ARCHITECTURE.md for bundle strategy, security, and implementation details.