API Reference
Complete TapKit API Reference
API Reference
TapKitElement
The <tap-kit> Web Component element.
API Summary
Lifecycle
| API | Description |
|---|---|
ready | Promise that resolves when initialization is complete |
isInitialized | Whether initialization is complete (boolean) |
UI Control
| API | Description |
|---|---|
show() | Show chat container |
hide() | Hide chat container |
isOpen | Chat open state (boolean) |
Course Information
| API | Description |
|---|---|
setCourse({ courseId, clipId, userId?, clipPlayHead? }) | Update course information |
Events (kit.events)
| API | Description |
|---|---|
seekTimeline({ clipPlayHead, clipId }) | Request timeline seek |
onTimelineSeek(callback) | Subscribe to timeline seek events, returns unsubscribe function |
onAlarmFadeIn(handler) | Subscribe to alarm display events, returns unsubscribe function |
Video (kit.video) (deprecated - use videoTarget instead)
| API | Description |
|---|---|
bind(config, clipId?) | Bind video player (timeline sync) |
unbind() | Unbind video player |
Properties
apiKey: string (write-only)
Security
Must be set via property only. Do not use as HTML attribute.
kit.apiKey = 'your-api-key'; // O
// <tap-kit api-key="..."> Don't useuserId: string
kit.userId = 'user-123';
// or <tap-kit user-id="user-123">courseId: string
kit.courseId = 'course-456';clipId: string
kit.clipId = 'clip-789';clipPlayHead: number
Playback position in seconds.
kit.clipPlayHead = 100;language: "ko" | "en"
Language setting. Default is "ko".
kit.language = 'en';
// or <tap-kit language="en">mode: "inline" | "floating" | "sidebar"
Display mode. Default is "inline".
| Value | Description |
|---|---|
inline | Embed in page content (default) |
floating | Compact floating widget |
sidebar | Full-height sidebar on the right |
kit.mode = 'floating';
// or <tap-kit mode="sidebar">allowLayoutToggle: boolean
Whether to show the toggle button between floating ↔ sidebar modes. Default is true.
kit.allowLayoutToggle = false; // Hide layout toggle buttonvideoTarget: HTMLVideoElement | VideoPlayerAdapter
Declarative binding for video player synchronization. Recommended over video.bind().
// HTMLVideoElement
kit.videoTarget = document.querySelector('video');
// VideoPlayerAdapter (YouTube, Vimeo, etc.)
kit.videoTarget = {
getCurrentTime: () => player.getCurrentTime(),
setCurrentTime: (time, clipId) => player.seekTo(time), // clipId for cross-clip seeking (optional)
};videoTarget persists through lifecycle changes (mode changes, reconnections).
buttonId: string
Custom button element ID.
debug: boolean
Enable debug logging.
Static Properties
TapKit.version: string (read-only)
Returns the current SDK version.
console.log(TapKit.version); // "2.1.0"TapKit.buildEnv: string (read-only)
Returns the current build environment. ("prod", "staging", "dev", "demo")
console.log(TapKit.buildEnv); // "prod"Advanced Properties
The properties below are for testing/development environments. Not typically used in production.
apiUrl: string
Backend API URL. Used for staging/demo environment testing.
kit.apiUrl = 'https://tapapistaging.coxwave.link';tapUrl: string
iframe URL. For internal testing only, do not modify.
environment: "dev" | "prod" | "staging" | "demo"
Environment setting. Affects logging level and default URLs.
kit.environment = 'staging';root: HTMLElement (deprecated)
Deprecated
This property no longer affects positioning. In floating/sidebar modes, the container always renders to document.body.
// ❌ Don't use
kit.root = document.getElementById('chat-container');Read-only Properties
isOpen: boolean (read-only)
Check if chat is currently open.
isInitialized: boolean (read-only)
Check if SDK initialization is complete.
ready: Promise<void> (read-only)
Promise that resolves when SDK is ready.
await kit.ready;
kit.show();Methods
show(): void
Show the chat window.
hide(): void
Hide the chat window.
setCourse(course): void
Update course information.
interface SetCourseParams {
userId?: string;
courseId: string; // Required
clipId: string; // Required
clipPlayHead?: number;
}kit.setCourse({
courseId: 'course-999',
clipId: 'clip-001',
clipPlayHead: 50
});Events
tap-kit:ready
Fired when SDK initialization is complete.
kit.addEventListener('tap-kit:ready', () => {
console.log('TapKit is ready!');
});tap-kit:error
Fired when an error occurs during initialization.
kit.addEventListener('tap-kit:error', (e) => {
console.error('TapKit error:', e.detail.error);
});tap-kit:iframe-retry
Fired when retrying after iframe load failure.
interface IframeRetryEvent {
attempt: number; // Current retry count
error: Error; // The error that occurred
nextDelay: number; // Wait time until next retry (ms)
}kit.addEventListener('tap-kit:iframe-retry', (e) => {
console.log(`Retrying iframe... (attempt ${e.detail.attempt}, retry in ${e.detail.nextDelay}ms)`);
console.error('Error:', e.detail.error.message);
});kit.events
Event-related APIs.
kit.events.seekTimeline(params): void
Seek timeline to a specific position.
interface SeekTimelineParams {
clipPlayHead: number; // Position to seek (seconds)
clipId: string;
}kit.events.seekTimeline({ clipPlayHead: 100, clipId: 'clip-789' });kit.events.onTimelineSeek(handler): () => void
Listen for timeline seek events. Returns an unsubscribe function.
const unsubscribe = kit.events.onTimelineSeek((playHead, clipId) => {
console.log(`Seeking to ${playHead}s: ${clipId}`);
videoElement.currentTime = playHead;
});
// Unsubscribe
unsubscribe();kit.events.onAlarmFadeIn(handler): () => void
Listen for alarm arrival events.
const unsubscribe = kit.events.onAlarmFadeIn((alarm) => {
console.log('New alarm:', alarm.message);
});kit.video
Deprecated
The kit.video.bind() API is deprecated. Use the videoTarget property instead.
videoTarget is more stable as it automatically persists through lifecycle changes.
Video player synchronization API.
Why is video.bind important?
Using video.bind():
- AI tutor recognizes current playback position for accurate answers
- Auto-seek when clicking specific segments in chat
- Automatic new clipId tracking when calling
setCourse()
kit.video.bind(config, clipId?): void
Synchronize video player with TapKit.
| Parameter | Type | Required | Description |
|---|---|---|---|
config | HTMLVideoElement | VideoPlayerAdapter | Yes | Video element or custom adapter |
clipId | string | Auto-tracked from SDK settings if omitted |
interface VideoPlayerAdapter {
getCurrentTime: () => number;
setCurrentTime: (time: number, clipId?: string) => void; // clipId for cross-clip seeking
}Auto-tracking (recommended):
kit.video.bind(videoElement);
// When changing courses later, new clipId is automatically used
kit.setCourse({ courseId: 'new-course', clipId: 'new-clip' });Custom adapter (YouTube, etc.):
kit.video.bind({
getCurrentTime: () => player.getCurrentTime(),
// clipId is optional - used for cross-clip seeking
setCurrentTime: (time, clipId) => player.seekTo(time, true),
});kit.video.unbind(): void
Disconnect video player synchronization.
kit.video.unbind();createTapKit()
Factory API for programmatically creating and controlling <tap-kit> Web Component elements.
Available in both npm package and CDN.
- npm:
import { createTapKit } from '@coxwave/tap-kit' - CDN:
window.createTapKit(...)
For React projects, we recommend the useTapKit Hook.
Syntax
// npm package
import { createTapKit } from '@coxwave/tap-kit';
const tapkit = createTapKit(options);
tapkit.mount(); // Add to DOM (required)
await tapkit.ready; // Wait for initialization
tapkit.show(); // Show chat windowParameters
| Property | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes | TapKit API key |
userId | string | User ID | |
courseId | string | Course ID | |
clipId | string | Clip ID | |
clipPlayHead | number | Initial playback position (seconds) | |
language | 'ko' | 'en' | Language setting | |
mode | 'inline' | 'floating' | 'sidebar' | Display mode (default: 'floating') | |
allowLayoutToggle | boolean | Allow floating↔sidebar toggle (default: true) | |
videoTarget | HTMLVideoElement | VideoPlayerAdapter | Video player binding | |
buttonId | string | Custom button element ID | |
debug | boolean | Enable debug logging |
Advanced Options (for testing/development):
| Property | Type | Description |
|---|---|---|
apiUrl | string | Backend API URL (e.g., 'https://tapapistaging.coxwave.link') |
tapUrl | string | iframe URL (internal testing only) |
environment | 'dev' | 'prod' | 'staging' | 'demo' | Environment setting |
Event Handlers:
| Property | Type | Description |
|---|---|---|
onReady | () => void | Called when SDK initialization is complete |
onError | (error: Error) => void | Called when an error occurs |
onTimelineSeek | (time: number, clipId: string) => void | Timeline seek event |
onAlarmFadeIn | (info: unknown) => void | Alarm display event |
Return Value: TapKitFactoryControl
| Property/Method | Type | Description |
|---|---|---|
ready | Promise<void> | Initialization complete promise |
isReady | boolean | Whether initialization is complete |
isOpen | boolean | Chat open state |
isMounted | boolean | Whether mounted to DOM |
mount(container?) | void | Add to DOM (required) |
unmount() | void | Remove from DOM |
show() | void | Show chat window |
hide() | void | Hide chat window |
setCourse(course) | void | Update course info |
events | EventManager | Events API |
video | VideoController | Video API |
element | TapKitElement | null | Access internal element |
destroy() | void | Clean up instance |
Example (npm package)
import { createTapKit } from '@coxwave/tap-kit';
const tapkit = createTapKit({
apiKey: 'your-api-key',
userId: 'user-123',
courseId: 'course-456',
clipId: 'clip-789',
// Environment settings (for testing)
apiUrl: 'https://tapapistaging.coxwave.link',
environment: 'staging',
// Event handlers
onReady: () => console.log('Ready!'),
onTimelineSeek: (time, clipId) => {
videoElement.currentTime = time;
},
});
// Add to DOM (required)
tapkit.mount();
// Or add to specific container
tapkit.mount(document.getElementById('chat-container'));
// Wait for initialization
await tapkit.ready;
// Show chat window
tapkit.show();
// Clean up
tapkit.destroy();Example (CDN)
<script src="https://files.edutap.ai/tap-sdk/loader.js"></script>
<script>
const kit = window.createTapKit({
apiKey: 'your-api-key',
userId: 'user-123',
courseId: 'course-456',
clipId: 'clip-789'
});
document.body.appendChild(kit);
kit.ready.then(() => kit.show());
</script>CSS Variables
For CSS variables for UI styling, see the Styling Guide.
TypeScript Types
TapKitConfig
Type for Legacy Class API (new TapKit()) constructor.
interface TapKitConfig {
apiKey: string;
}CreateTapKitOptions
Configuration type for createTapKit() and useTapKit() APIs.
interface CreateTapKitOptions {
// Required
apiKey: string;
// Course Information
userId?: string;
courseId?: string;
clipId?: string;
clipPlayHead?: number;
// Display Options
language?: 'ko' | 'en';
mode?: 'inline' | 'floating' | 'sidebar';
allowLayoutToggle?: boolean;
videoTarget?: HTMLVideoElement | VideoPlayerAdapter;
buttonId?: string;
debug?: boolean;
// Advanced Options (for testing/development)
apiUrl?: string;
tapUrl?: string;
environment?: 'dev' | 'prod' | 'staging' | 'demo';
// Event Handlers
onReady?: () => void;
onError?: (error: Error) => void;
onTimelineSeek?: (clipPlayHead: number, clipId: string) => void;
onAlarmFadeIn?: (messageInfo: AlarmMessageInstanceType) => void;
}TapKitElement
Type for the <tap-kit> Web Component element.
interface TapKitElement extends HTMLElement {
// Properties
apiKey: string;
userId?: string;
courseId?: string;
clipId?: string;
clipPlayHead?: number;
language?: 'ko' | 'en';
mode?: 'inline' | 'floating' | 'sidebar';
allowLayoutToggle: boolean;
videoTarget?: HTMLVideoElement | VideoPlayerAdapter;
buttonId?: string;
debug: boolean;
// Advanced Properties
apiUrl?: string;
tapUrl?: string;
environment?: 'dev' | 'prod' | 'staging' | 'demo';
/** @deprecated This property no longer affects positioning */
root?: HTMLElement;
// Read-only
readonly isOpen: boolean;
readonly isInitialized: boolean;
readonly ready: Promise<void>;
// Methods
show(): void;
hide(): void;
setCourse(params: SetCourseParams): void;
// Sub-APIs
readonly events: {
seekTimeline(params: { clipPlayHead: number; clipId: string }): void;
onTimelineSeek(handler: (playHead: number, clipId: string) => void): () => void;
onAlarmFadeIn(handler: (messageInfo: AlarmMessageInstanceType) => void): () => void;
};
/** @deprecated Use videoTarget property instead */
readonly video: {
bind(config: HTMLVideoElement | VideoPlayerAdapter, clipId?: string): void;
unbind(): void;
};
}AlarmMessageInstanceType
Type for alarm message information.
interface AlarmMessageInstanceType {
type: 'basic:welcome' | 'basic:default' | 'feat:quiz' | 'feat:guide' | 'feat:progress' | 'custom:cheer';
content: AlarmElement;
}
interface AlarmElement {
tag: string;
props?: Record<string, unknown>;
children?: (AlarmElement | string)[];
payload?: {
type: 'startChat';
message: string;
pingMessageId?: string;
};
}VideoPlayerAdapter
Interface for custom video player (YouTube, Vimeo, Video.js, etc.) integration.
interface VideoPlayerAdapter {
/** Current playback time (seconds) */
getCurrentTime: () => number;
/**
* Set playback time
* @param time - Time to seek (seconds)
* @param clipId - Target clip ID for cross-clip seeking (optional)
*/
setCurrentTime: (time: number, clipId?: string) => void;
}
/** HTMLVideoElement or custom adapter */
type VideoPlayerConfig = HTMLVideoElement | VideoPlayerAdapter;TapButtonElement
The <tap-button> Web Component is a floating button for opening AI tutor chat.
Basic Usage
<!-- Use with TapKit (auto toggle) -->
<tap-kit user-id="user-123" course-id="course-456" clip-id="clip-789"></tap-kit>
<tap-button position="bottom-right" size="large"></tap-button>
<script>
const kit = document.querySelector('tap-kit');
kit.apiKey = 'your-api-key';
</script><tap-button> automatically connects with <tap-kit> on the same page, toggling the chat window when clicked.
Attributes
position: string
Specifies the button's screen position. Default is "bottom-right".
| Value | Description |
|---|---|
bottom-right | Bottom-right of screen (default) |
bottom-left | Bottom-left of screen |
top-right | Top-right of screen |
top-left | Top-left of screen |
custom | Custom position (specify with inline style) |
<tap-button position="bottom-left"></tap-button>
<!-- Custom position example -->
<tap-button position="custom" style="top: 100px; right: 50px;"></tap-button>size: string
Specifies button size. Default is "large".
| Value | Size |
|---|---|
small | 48px |
medium | 56px |
large | 64px (default) |
<tap-button size="small"></tap-button>floating: string
Sets positioning mode. Default is floating (fixed) mode.
| Value | Description |
|---|---|
| (omitted) | Floating mode (position: fixed) |
"false" | Static mode (normal document flow) |
<!-- Floating mode (default) -->
<tap-button></tap-button>
<!-- Static mode: placed like normal element -->
<tap-button floating="false"></tap-button>language: string
Sets tooltip language. Default is "ko".
<tap-button language="en"></tap-button>tutor-name: string
Tutor name to display in tooltip. Default text is shown if not set.
<tap-button tutor-name="AI Tutor"></tap-button>Custom Icon
Use slots to customize button content.
<tap-button position="bottom-right">
<img src="/my-tutor-icon.svg" alt="AI Tutor" />
</tap-button>CSS Shadow Parts
Provides CSS Shadow Parts for external styling.
tap-button::part(button) {
background: linear-gradient(135deg, #6366f1, #8b5cf6);
border-radius: 50%;
}
tap-button::part(tooltip) {
background: #1f2937;
color: white;
}Events
tap-button:click
Fired when button is clicked. Chat toggles automatically if <tap-kit> is present.
const button = document.querySelector('tap-button');
button.addEventListener('tap-button:click', (e) => {
console.log('Button clicked', e.detail);
});