API reference
Events
The lifecycle event bus. Same names and payloads whether you subscribe via hooks or the vanilla loader. Names are stable; payload fields are additive.
Subscribing
Reacttsx
const { on } = useInterview(studyId);
useEffect(() => {
const off = on('completed', ({ completionToken }) => { /* … */ });
return off; // on() returns an unsubscribe
}, [on]);Vanillajs
Dialogue('on', 'completed', (p) => console.log(p));
Dialogue('off', 'completed', handler);Event catalog
| Event | Payload |
|---|---|
ready | { userId: string } |
phase | { phase: Phase } |
consent | { accepted: boolean } |
permission | { kind: 'camera'|'microphone'|'screen-share'; status; errorCode? } |
connection | { quality: ConnectionQuality; reason? } |
completed | { interviewId; durationSeconds; completionToken } |
aborted | { reason: AbortReason } |
screenedOut | { redirectUrl: string | null } |
studyClosed | { reason: 'study_not_active' | 'study_quota_exceeded' } |
alreadyCompleted | { interviewId: string | null } |
error | { code: ErrorCode; message; recoverable } |
Payload enums
ts
type ConnectionQuality = 'excellent' | 'good' | 'poor' | 'lost' | 'reconnecting';
type AbortReason = 'consent.declined' | 'unload' | 'host.abort' | 'backend.abandoned';
type PermissionStatus = 'granted' | 'denied' | 'dismissed' | 'not-readable' | 'not-found' | 'overconstrained';The
completionToken on completed may be null, so handle both cases. See The interview journey for the full Phase union.