SDK Integration
The AI Interview SDK allows you to embed voice-to-voice interviews directly into your website or application. No backend required.
Installation
Using npm:
npm install @ai-interview/sdk
Using yarn:
yarn add @ai-interview/sdk
Using CDN:
<script src="https://unpkg.com/@ai-interview/sdk@latest"></script>
Quick Start
Basic Usage
import InterviewSDK from '@ai-interview/sdk';
// Mount the interview embed
const embed = InterviewSDK.mount('#interview-container', {
invite: 'YOUR_INVITE_TOKEN',
});
// Listen to events
embed.on('completed', (payload) => {
console.log('Interview completed:', payload);
});
HTML + Script Tag
<!DOCTYPE html>
<html>
<head>
<title>AI Interview</title>
</head>
<body>
<div id="interview-container"></div>
<script src="https://unpkg.com/@ai-interview/sdk@latest"></script>
<script>
InterviewSDK.mount('#interview-container', {
invite: 'inv_8f7d9e2c1a0b3h4k5j6m',
});
</script>
</body>
</html>
Configuration
Mount Options
| Name | Type | Description |
|---|---|---|
invite* | string | Unique invite token for the interview session |
baseUrl | string | Base URL for the embed (default: production URL) |
theme | object | Custom theme colors and styling |
locale | string | Language locale (e.g., "en", "es", "fr") |
autoStart | boolean | Auto-start interview without consent screen (default: false) |
Theme Options
Customize the look and feel:
InterviewSDK.mount('#interview-container', {
invite: 'YOUR_TOKEN',
theme: {
primary: '#146EF5', // Primary brand color
background: '#0f172a', // Background color
text: '#f1f5f9', // Text color
borderRadius: '12px', // Border radius for elements
fontFamily: 'Inter, sans-serif', // Custom font
},
});
White Label
The Pro and Enterprise plans allow full white-labeling, including custom domains and removal of AI Interview branding.
Events
Event Listeners
Listen to interview lifecycle events:
const embed = InterviewSDK.mount('#container', options);
// Interview lifecycle
embed.on('start', () => {
console.log('Interview started');
});
embed.on('pause', () => {
console.log('Interview paused');
});
embed.on('resume', () => {
console.log('Interview resumed');
});
embed.on('completed', (payload) => {
console.log('Interview completed:', payload);
// payload.sessionId - Session ID for API calls
// payload.transcript - Partial transcript (if enabled)
});
// Error handling
embed.on('error', (payload) => {
console.error('Error:', payload.message);
// Handle errors gracefully
});
// Progress tracking
embed.on('progress', (payload) => {
console.log(`Progress: ${payload.percentage}%`);
// Update UI with progress
});
Event Reference
| Name | Type | Description |
|---|---|---|
start | void | Interview has started |
pause | void | Interview was paused by participant |
resume | void | Interview was resumed |
progress | { percentage: number } | Progress update (0-100) |
completed | { sessionId: string, transcript?: string } | Interview successfully completed |
error | { message: string, code: string } | An error occurred |
Methods
Instance Methods
const embed = InterviewSDK.mount('#container', options);
// Add event listener
embed.on('completed', handler);
// Remove event listener
embed.off('completed', handler);
// Remove embed from DOM
embed.destroy();
// Get current session ID (if started)
const sessionId = embed.getSessionId();
// Check if interview is in progress
const isActive = embed.isActive();
Advanced Usage
React Integration
import { useEffect, useRef } from 'react';
import InterviewSDK from '@ai-interview/sdk';
function InterviewEmbed({ inviteToken }) {
const containerRef = useRef(null);
const embedRef = useRef(null);
useEffect(() => {
if (containerRef.current && !embedRef.current) {
embedRef.current = InterviewSDK.mount(containerRef.current, {
invite: inviteToken,
theme: {
primary: '#146EF5',
},
});
embedRef.current.on('completed', (payload) => {
console.log('Interview completed:', payload.sessionId);
// Handle completion
});
}
return () => {
if (embedRef.current) {
embedRef.current.destroy();
embedRef.current = null;
}
};
}, [inviteToken]);
return <div ref={containerRef} className="interview-container" />;
}
Vue Integration
<template>
<div ref="interviewContainer" class="interview-container"></div>
</template>
<script>
import InterviewSDK from '@ai-interview/sdk';
export default {
name: 'InterviewEmbed',
props: {
inviteToken: {
type: String,
required: true,
},
},
data() {
return {
embed: null,
};
},
mounted() {
this.embed = InterviewSDK.mount(this.$refs.interviewContainer, {
invite: this.inviteToken,
});
this.embed.on('completed', (payload) => {
this.$emit('completed', payload);
});
},
beforeUnmount() {
if (this.embed) {
this.embed.destroy();
}
},
};
</script>
Custom Invite Tokens
Generate invite tokens via API, then use in SDK:
// 1. Get invite token from your backend
const response = await fetch('/api/create-interview', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId: '123' }),
});
const { inviteToken } = await response.json();
// 2. Mount SDK with dynamic token
InterviewSDK.mount('#container', {
invite: inviteToken,
});
Styling
Container Sizing
The embed automatically fills its container:
.interview-container {
width: 100%;
max-width: 800px;
height: 600px;
margin: 0 auto;
border-radius: 12px;
overflow: hidden;
}
Responsive Design
.interview-container {
width: 100%;
aspect-ratio: 16 / 9;
max-width: 1000px;
}
@media (max-width: 768px) {
.interview-container {
aspect-ratio: 9 / 16;
height: 100vh;
}
}
Security
Token Validation
Invite tokens are:
- One-time use only
- Expire after configured period
- Cryptographically signed
- Cannot be reused after completion
Domain Restrictions
Restrict which domains can embed interviews:
- Go to Settings → Security
- Enable Domain Whitelist
- Add allowed domains
- SDK will refuse to load on unauthorized domains
Production Domains
Always configure domain restrictions before launching to production to prevent unauthorized embedding.
Error Handling
Common Errors
embed.on('error', (error) => {
switch (error.code) {
case 'INVALID_TOKEN':
// Token is invalid or expired
console.error('Invalid or expired invite token');
break;
case 'ALREADY_USED':
// Token was already used
console.error('This interview has already been completed');
break;
case 'MICROPHONE_DENIED':
// User denied microphone access
console.error('Microphone permission required');
break;
case 'NETWORK_ERROR':
// Network connectivity issues
console.error('Network connection lost');
break;
default:
console.error('An error occurred:', error.message);
}
});
Graceful Degradation
Handle unsupported browsers:
if (!InterviewSDK.isSupported()) {
document.getElementById('interview-container').innerHTML = `
<div class="unsupported-browser">
<h3>Unsupported Browser</h3>
<p>Please use Chrome, Firefox, Safari, or Edge to participate in this interview.</p>
</div>
`;
} else {
InterviewSDK.mount('#interview-container', options);
}
Browser Support
| Browser | Minimum Version | |---------|----------------| | Chrome | 80+ | | Firefox | 75+ | | Safari | 14+ | | Edge | 80+ |
WebRTC and Web Audio API are required. Mobile browsers on iOS and Android are fully supported.
Examples
See our Examples section for complete working demos:
- Static HTML - Vanilla JavaScript integration
- React App - React component example
- Vue App - Vue component example
Troubleshooting
Embed Not Loading
Check:
- Invite token is valid and not expired
- Container element exists in DOM
- No JavaScript errors in console
- Domain is whitelisted (if restrictions enabled)
Audio Issues
Common causes:
- Microphone permission not granted
- Using HTTP instead of HTTPS (required for mic access)
- Browser doesn't support WebRTC
- Firewall blocking WebSocket connections
Event Not Firing
Ensure:
- Event listener added before interview starts
- Correct event name (case-sensitive)
- Handler function is valid
- No errors breaking JavaScript execution