REST API ↗
Integration guides

Styled drop-in

The fastest path: the prebuilt, Dialogue-branded interview. Wrap your tree in the provider, render <Interview>, theme via appearance.

Minimal example

tsx
'use client';
import { DialogueProvider } from '@dialogueai/react';
import { Interview } from '@dialogueai/react-ui';
import '@dialogueai/react-ui/styles.css';

export function Widget() {
  return (
    <DialogueProvider publishableKey="pk_live_…" bootstrapTokenProvider={getToken}>
      <Interview
        studyId="019e16c4-ce3f-7388-b236-24455b07e857"
        onCompleted={({ completionToken }) => console.log('done', completionToken)}
        onFinish={() => console.log('widget dismissed')}
      />
    </DialogueProvider>
  );
}
<Interview> must be inside <DialogueProvider>. It does not self-bootstrap the provider, but it does auto-open the study from its studyId.

Inline vs floating

appearance.layout controls positioning. 'inline' (default) fills its container; 'floating' anchors to a viewport corner over your page, a chat-bubble style pop-in.

tsx
<Interview studyId={studyId} appearance={{ layout: 'floating' }} />

Theming

The appearance prop is a small, closed token API mapped to CSS variables; you can’t inject arbitrary CSS through it. See Appearance & theming for the full surface.

tsx
<Interview
  studyId={studyId}
  appearance={{
    colorScheme: 'auto',
    variables: { colorPrimary: '#B43F7F', borderRadius: '12px' },
  }}
/>

Overriding screens

Stay in the styled layer but replace individual phase screens with slots. Each slot maps to a phase; everything else keeps the default branded screen.

tsx
<Interview
  studyId={studyId}
  slots={{
    completion: <MyThankYou />,
    // A ReactNode replaces the errored-phase screen. Read the error via
    // useInterview().error from inside your component.
    error: <MyErrorScreen />,
  }}
/>
Slot keys are not phase names (one slot can cover several phases), and the error slot’s function form is for React render crashes, not SDK errors. See the full slot → phase mapping.

Restarting the journey

Terminal phases (e.g. completed) are one-shot. To run again, remount the provider by bumping a React key. That builds a fresh core and the journey starts over.

tsx
const [runId, setRunId] = useState(0);

<DialogueProvider key={runId} bootstrapTokenProvider={getToken}>
  <Interview studyId={studyId} onFinish={() => setRunId((n) => n + 1)} />
</DialogueProvider>