Interpreter SDK
Embed real-time interpretation into your web application. Drop in our pre-built UI or build your own with headless mode.
Preview Documentation: This documentation is tentative and subject to change. The SDK packages are not yet published to npm, and the API endpoints are not yet live. This preview is provided to help you plan your integration.
Why vitalvoice.ai
Built for critical communication where misunderstanding isn't an option:
- Domain-trained accuracy: Optimized for healthcare, law enforcement, and legal terminology
- HIPAA compliant: BAA available, no audio retention, end-to-end encryption
- Sub-second latency: Real-time interpretation for emergency response
- 57 languages: Spanish, Mandarin, Arabic, Vietnamese, Tagalog, and more - with specialized vocabulary support
Whether you're building a telehealth platform, an e-citation, court management solution, or EMS dispatch app, vitalvoice.ai handles the interpretation so you can focus on your product.
Quick Start
Note: The following packages and endpoints are tentative and not yet available. This section demonstrates the planned integration flow.
1. Install the SDK
npm install @vitalvoice/interpreter2. Get a Session Token (Server-Side)
Your backend requests a short-lived token using your API key:
curl -X POST https://api.vitalvoice.ai/v1/sessions \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"targetLanguages": ["es", "fr", "de"],
"maxDurationSeconds": 300
}'Response:
{
"sessionToken": "sess_ephemeral_abc123...",
"expiresAt": "2025-01-15T12:05:00Z",
"sessionId": "sess_def456"
}Important: Never expose your API key (
sk_live_...) in client-side code. Always request session tokens from your backend.
3. Initialize the Interpreter (Client-Side)
import { Interpreter } from '@vitalvoice/interpreter';
// Fetch token from your backend
const { sessionToken } = await fetch('/api/interpret-session', {
method: 'POST',
credentials: 'include'
}).then(r => r.json());
// Initialize interpreter
const interpreter = Interpreter.create({
sessionToken,
container: document.querySelector('.interpreter-container'),
mode: 'standard'
});
await interpreter.connect();That's it. The interpreter renders a microphone button in your container and displays interpretations in a popover.
Compliance
HIPAA
vitalvoice.ai is HIPAA compliant. We offer Business Associate Agreements (BAAs) to all partners.
What we handle:
- Encrypted transmission of all audio and text
- Zero retention of protected health information (PHI)
- SOC 2 Type II certified infrastructure
- Annual third-party security audits
Your responsibilities:
- Authenticate users before issuing session tokens
- Implement appropriate access controls in your application
- Maintain audit logs using session IDs and metadata
Contact your account manager to execute a BAA before processing PHI.
Data Handling
| Data Type | Retention | Notes |
|---|---|---|
| Audio streams | None | Processed in real-time, never stored |
| Transcripts | None | Delivered to your app, not retained |
| Session metadata | 90 days | Session IDs, timestamps, language pairs |
| Usage metrics | 1 year | Aggregated billing data only |
Authentication
Note: Authentication endpoints and flows described here are tentative. Final implementation may differ.
How It Works
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ User's Browser │ │ Your Backend │ │ Interpreter API│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ │ 1. Request session │ │ │ ─────────────────────> │ │ │ │ │ │ │ 2. POST /v1/sessions │ │ │ Authorization: sk_... │ │ │ ─────────────────────> │ │ │ │ │ │ 3. { sessionToken, ... } │ │ │ <───────────────────── │ │ │ │ │ 4. Return token │ │ │ <───────────────────── │ │ │ │ │ │ 5. Interpreter connects │ │ │ ─────────────────────────────────────────────────> │ │ │ │
Session Token Properties
- Short-lived: Tokens expire in 5 minutes if unused
- Single-use: One token, one session
- Scoped: Inherits rate limits and quotas from your API key
- Secure: Cannot be used to create additional tokens or access other endpoints
Backend Implementation Example
curl -X POST https://api.vitalvoice.ai/v1/sessions \
-H "Authorization: Bearer $VITALVOICE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"targetLanguages": ["es", "fr"],
"maxDurationSeconds": 300,
"metadata": {
"userId": "user_123",
"facility": "memorial_hospital"
}
}'Session Options
| Parameter | Type | Required | Description |
|---|---|---|---|
targetLanguages | string[] | Yes | Languages to interpret into (ISO 639-1 codes) |
maxDurationSeconds | number | No | Session time limit (default: 600, max: 1800) |
metadata | object | No | Arbitrary data for your records (returned in webhooks) |
Standard Mode
Standard mode provides a complete, pre-built UI. You provide a container element; we handle everything else.
Note: UI components and theming options are tentative and may change before release.
Basic Setup
const interpreter = Interpreter.create({
sessionToken,
container: document.querySelector('.interpreter-container'),
mode: 'standard',
targetLanguages: ['es', 'fr', 'de']
});
await interpreter.connect();What Gets Rendered
Controls (in your container):
- Microphone button with active/inactive states
- Language selector
- Mute toggle
Transcript popover (appended to <body>):
- Real-time transcript display
- Collapse/expand toggle
- Positioned in viewport corner
Configuration Options
Interpreter.create({
// Required
sessionToken: string,
container: HTMLElement,
mode: 'standard',
// Language settings
sourceLanguage: string, // Auto-detect if omitted
targetLanguages: string[], // Required
// Appearance
theme: 'light' | 'dark' | ThemeConfig,
// Transcript popover
transcript: {
position: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left',
defaultExpanded: boolean, // Default: true
}
});Custom Theming
Interpreter.create({
// ...
theme: {
primaryColor: '#6366f1',
backgroundColor: '#ffffff',
textColor: '#1f2937',
borderRadius: '8px',
fontFamily: 'Inter, system-ui, sans-serif'
}
});Headless Mode
Headless mode gives you full control over the UI. The SDK manages connections and audio capture - you render everything.
Note: The headless API is tentative and subject to change.
Basic Setup
const interpreter = Interpreter.create({
sessionToken,
container: document.querySelector('.hidden-container'),
mode: 'headless',
targetLanguages: ['es', 'fr']
});
// Listen for events
interpreter.on('interpretation', ({ original, interpreted, targetLanguage, isFinal }) => {
// Render in your UI
updateTranscript(original, interpreted);
});
interpreter.on('stateChange', (state) => {
updateConnectionStatus(state);
});
interpreter.on('error', (error) => {
showErrorMessage(error.message);
});
await interpreter.connect();
// Wire up your UI controls
document.querySelector('.mic-button').addEventListener('click', () => {
if (interpreter.isListening) {
interpreter.stopListening();
} else {
interpreter.startListening();
}
});Initialization
const interpreter = Interpreter.create(options);| Option | Type | Required | Description |
|---|---|---|---|
sessionToken | string | Yes | Token from your backend |
container | HTMLElement | Yes | Mount point for SDK internals |
mode | 'headless' | Yes | Must be 'headless' |
sourceLanguage | string | No | ISO 639-1 code, auto-detect if omitted |
targetLanguages | string[] | Yes | Languages to interpret into |
Connection Lifecycle
await interpreter.connect(); // Establish connection
interpreter.disconnect(); // End session gracefully
interpreter.destroy(); // Clean up all resourcesAudio Controls
interpreter.startListening(); // Begin capturing audio
interpreter.stopListening(); // Stop capturing audio
interpreter.mute(); // Mute microphone (stay connected)
interpreter.unmute(); // Unmute microphone
// Input device selection
const devices = await interpreter.getInputDevices();
await interpreter.setInputDevice(deviceId);State Properties
interpreter.state // 'disconnected' | 'connecting' | 'connected' | 'error'
interpreter.isListening // boolean
interpreter.isMuted // booleanEvents
// Connection state changes
interpreter.on('stateChange', (state: State) => {});
// Interpretation results
interpreter.on('interpretation', (event: InterpretationEvent) => {});
// Audio input level (for visualizers)
interpreter.on('audioLevel', (level: number) => {});
// Errors
interpreter.on('error', (error: InterpreterError) => {});InterpretationEvent structure:
interface InterpretationEvent {
original: string; // Original speech text
interpreted: string; // Interpreted text
sourceLanguage: string; // Detected or configured source
targetLanguage: string; // Interpretation target
isFinal: boolean; // false = partial, true = final
confidence?: number; // 0-1 confidence score
}Programmatic Transcript Control
Even in headless mode, you may want to use our transcript popover:
interpreter.expandTranscript();
interpreter.collapseTranscript();
interpreter.isTranscriptExpanded; // booleanFramework Wrappers
We provide thin wrappers that integrate with framework-native reactivity patterns.
Note: Framework packages are not yet published to npm. Package names and APIs are tentative.
React
npm install @vitalvoice/interpreter-reactimport { useInterpreter } from '@vitalvoice/interpreter-react';
function InterpretationUI() {
const {
interpreter,
state,
isListening,
isMuted,
interpretations,
error
} = useInterpreter({
sessionToken,
targetLanguages: ['es', 'fr'],
mode: 'headless'
});
return (
<div>
<button onClick={() => isListening ? interpreter.stopListening() : interpreter.startListening()}>
{isListening ? 'Stop' : 'Start'}
</button>
<div className="transcript">
{interpretations.map((t, i) => (
<p key={i}>{t.interpreted}</p>
))}
</div>
</div>
);
}Angular
npm install @vitalvoice/interpreter-angularimport { InterpreterService } from '@vitalvoice/interpreter-angular';
@Component({
selector: 'app-interpretation',
template: `
<button (click)="toggle()">
{{ (isListening$ | async) ? 'Stop' : 'Start' }}
</button>
<div class="transcript">
<p *ngFor="let t of interpretations$ | async">{{ t.interpreted }}</p>
</div>
`
})
export class InterpretationComponent implements OnInit, OnDestroy {
constructor(private interpreterService: InterpreterService) {}
state$ = this.interpreterService.state$;
isListening$ = this.interpreterService.isListening$;
interpretations$ = this.interpreterService.interpretations$;
async ngOnInit() {
await this.interpreterService.initialize({
sessionToken: this.sessionToken,
targetLanguages: ['es', 'fr'],
mode: 'headless'
});
}
toggle() {
this.interpreterService.toggleListening();
}
ngOnDestroy() {
this.interpreterService.destroy();
}
}Svelte
npm install @vitalvoice/interpreter-svelte<script>
import { createInterpreter } from '@vitalvoice/interpreter-svelte';
import { onMount, onDestroy } from 'svelte';
export let sessionToken;
const interpreter = createInterpreter({
sessionToken,
targetLanguages: ['es', 'fr'],
mode: 'headless'
});
const { state, isListening, interpretations } = interpreter.stores;
onMount(() => interpreter.connect());
onDestroy(() => interpreter.destroy());
</script>
<button on:click={() => interpreter.toggleListening()}>
{$isListening ? 'Stop' : 'Start'}
</button>
<div class="transcript">
{#each $interpretations as t}
<p>{t.interpreted}</p>
{/each}
</div>Webhooks
Receive server-side notifications for session events. Configure webhook endpoints in your dashboard.
Note: Webhook configuration dashboard is not yet available. Endpoint URLs are tentative.
Available Events
| Event | Description |
|---|---|
session.started | Interpretation session began |
session.ended | Session completed or timed out |
session.error | Unrecoverable error occurred |
Payload Example
{
"event": "session.ended",
"sessionId": "sess_def456",
"durationSeconds": 142,
"languagePair": {
"source": "es",
"target": "en"
},
"metadata": {
"userId": "user_123",
"facility": "memorial_hospital"
},
"timestamp": "2025-01-15T12:07:22Z"
}Verifying Signatures
All webhook payloads include a signature header for verification:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}Error Handling
Error Types
interface InterpreterError {
code: string;
message: string;
recoverable: boolean;
}| Code | Description | Recoverable |
|---|---|---|
AUTH_INVALID | Session token invalid or expired | No - request new token |
AUTH_QUOTA_EXCEEDED | Account quota exceeded | No |
CONNECTION_FAILED | Connection failed | Yes - retry connect() |
CONNECTION_LOST | Connection dropped mid-session | Yes - retry connect() |
AUDIO_PERMISSION_DENIED | User denied microphone access | Yes - prompt user |
AUDIO_DEVICE_ERROR | Microphone not available | Yes - check device |
Handling Errors
interpreter.on('error', (error) => {
if (error.recoverable) {
showRetryPrompt(error.message);
} else if (error.code === 'AUTH_INVALID') {
// Token expired, get a new one
refreshSessionToken().then(token => {
interpreter.destroy();
initializeNewInterpreter(token);
});
} else {
showErrorMessage(error.message);
}
});Usage & Billing
Note: Usage tracking APIs and billing details are tentative.
How Usage is Metered
- Billed per minute of active interpretation (while audio is being processed)
- Idle connection time is not billed
- Minimum session charge: 15 seconds
- All usage counts toward quota, including testing and development
Tracking Usage
curl https://api.vitalvoice.ai/v1/usage \
-H "Authorization: Bearer sk_live_..."{
"period": {
"start": "2025-01-01T00:00:00Z",
"end": "2025-01-31T23:59:59Z"
},
"usage": {
"minutes": 1423,
"sessions": 847
},
"quota": {
"minutes": 5000,
"remaining": 3577
}
}Session Metadata for Reporting
Tag sessions with metadata to segment usage in your own systems:
{
"targetLanguages": ["es"],
"metadata": {
"department": "emergency",
"facility_id": "hospital_123",
"encounter_type": "intake"
}
}Metadata is returned in webhooks and available via the usage API for filtering.
Rate Limits
| Limit | Default | Enterprise |
|---|---|---|
| Concurrent sessions | 10 | Custom |
| Sessions per minute | 30 | Custom |
| Max session duration | 30 min | 60 min |
When rate limited, the API returns 429 Too Many Requests with a Retry-After header. Implement exponential backoff for resilience.
Testing
Note: Test API keys are not yet available. The testing workflow described here is tentative.
Test API Keys
Use test API keys (sk_test_...) during development. Test keys:
- Use the same API as production
- Count toward your quota (budget accordingly)
- Are clearly labeled in usage reports for easy filtering
Request test keys from your account manager.
Debug Mode
Enable verbose logging during development:
const interpreter = Interpreter.create({
sessionToken,
container,
mode: 'headless',
debug: true // Logs connection events, audio levels, and timing
});Troubleshooting
No audio detected
- Check microphone permissions in browser settings
- Verify the correct input device with
getInputDevices() - Test your microphone in another application
- Ensure your page is served over HTTPS (required for microphone access)
High latency
- Check network conditions - interpretation requires stable connectivity
- Reduce
targetLanguagesto only what's needed - Contact support if latency consistently exceeds 500ms
Session immediately disconnects
- Verify your session token hasn't expired (5 minute window)
- Check that your API key is active and has available quota
- Ensure you're not exceeding concurrent session limits
"Connection failed" errors
- Check for corporate firewalls blocking connections
- Verify the user's browser is supported (see Browser Support)
- Try a different network to isolate the issue
Reference
Supported Languages
57 languages are supported. Use ISO 639-1 codes when configuring targetLanguages.
| Code | Language | Code | Language | Code | Language | ||
|---|---|---|---|---|---|---|---|
af | Afrikaans | hu | Hungarian | ru | Russian | ||
ar | Arabic | id | Indonesian | sk | Slovak | ||
az | Azerbaijani | is | Icelandic | sl | Slovenian | ||
be | Belarusian | it | Italian | sr | Serbian | ||
bg | Bulgarian | ja | Japanese | sv | Swedish | ||
bs | Bosnian | kk | Kazakh | sw | Swahili | ||
ca | Catalan | kn | Kannada | ta | Tamil | ||
cs | Czech | ko | Korean | th | Thai | ||
cy | Welsh | lt | Lithuanian | tl | Tagalog | ||
da | Danish | lv | Latvian | tr | Turkish | ||
de | German | mi | Maori | uk | Ukrainian | ||
el | Greek | mk | Macedonian | ur | Urdu | ||
en | English | mr | Marathi | vi | Vietnamese | ||
es | Spanish | ms | Malay | zh | Chinese | ||
et | Estonian | ne | Nepali | ||||
fa | Persian | nl | Dutch | ||||
fi | Finnish | no | Norwegian | ||||
fr | French | pl | Polish | ||||
gl | Galician | pt | Portuguese | ||||
he | Hebrew | ro | Romanian | ||||
hi | Hindi | hy | Armenian |
Browser Support
| Browser | Minimum Version |
|---|---|
| Chrome | 74+ |
| Firefox | 66+ |
| Safari | 14.1+ |
| Edge | 79+ |
Modern JavaScript features are required. Internet Explorer is not supported.
Security
What We Protect
- Your API key: Never exposed to browsers; only used server-to-server
- Audio streams: Encrypted in transit, processed securely, never stored
- Session tokens: Short-lived, single-use, scoped to one session
Your Responsibilities
- Authenticate users before issuing session tokens
- Set appropriate
maxDurationSecondslimits - Monitor usage via session metadata and webhooks
- Implement your own rate limiting if needed
FAQ
Can users customize the popover position?
In standard mode, configure via transcript.position. In headless mode, you control all rendering.
What happens when a session token expires?
The interpreter emits an AUTH_INVALID error. Request a new token from your backend and reinitialize.
Can I use multiple interpreters on one page?
Yes. Each Interpreter.create() call returns an independent instance.
How do I handle poor network conditions?
The SDK automatically handles reconnection for transient issues. For persistent failures, listen for CONNECTION_LOST errors and prompt users to retry.
Is there a way to get raw audio?
Not currently. Contact us if you have a specific use case.
Do you support mobile apps?
The SDK currently supports web browsers. Native iOS and Android SDKs are on our roadmap - contact your account manager for timeline updates.
Changelog
1.0.0 (Upcoming)
- Initial release
- Standard and headless modes
- Support for 57 languages
- React, Angular, and Svelte framework wrappers
Support
Note: Support channels listed below are tentative and not yet active.
- Documentation: https://platform.vitalvoice.ai/docs
- Dashboard: https://platform.vitalvoice.ai
- API Status: https://status.vitalvoice.ai
- Email: support@vitalvoice.ai
