Complete working example available: This guide references the basic React example in our examples repository. Clone it to see a fully functional implementation, then follow this guide to understand how it works and adapt it to your needs.
This guide uses ROPC (Resource Owner Password Credentials) authentication, matching the React basic example.
What you’ll learn
By following this guide, you’ll understand:- How to architect a secure client-server integration
- Why ROPC authentication works well for embedded EHR scenarios
- How to use the Web Component API with React
- How to manage the interaction lifecycle programmatically
- Key customization points and production considerations
Prerequisites
Before starting, ensure you have:- Node.js 18+ installed
- Corti API access with valid credentials
- OAuth client configured for ROPC (Resource Owner Password Credentials) flow
- User account created in Corti Console for authentication
- Basic familiarity with React and Express
Architecture overview
The integration follows a client-server architecture: Backend (Express Server):- Handles OAuth authentication using ROPC flow via
@corti/sdk - Provides configuration endpoint for environment-specific settings
- Keeps sensitive credentials server-side
- Runs on port 8013 by default
- Fetches auth tokens and configuration from backend
- Embeds Corti Assistant using
@corti/embedded-webWeb Component - Manages interaction lifecycle (create, navigate, handle events)
- Uses React 19’s Suspense for async data loading
- Runs on port 8015, with
/apiproxied to the backend
- Security: Credentials stay on the server, never exposed to the browser
- Separation of concerns: Auth logic separate from UI logic
- Development speed: Simple to run and test locally
Key concepts
Authentication flow
- Backend authenticates with Corti using stored credentials (ROPC)
- Frontend requests tokens from backend
/api/authendpoint - Web Component receives tokens and authenticates the embedded session
- No user interaction required - seamless experience
Web Component integration
The integration uses<CortiEmbeddedReact>, a React wrapper around the standard Web Component:
- Type-safe: Full TypeScript support with IDE autocomplete
- React-friendly: Hooks-based API (
useCortiEmbeddedApi) - Event handling: Native React event props for Assistant callbacks
- Lifecycle management: Automatic cleanup and ref management
Interaction lifecycle
Every clinical encounter in Corti Assistant is called an “interaction”:- Create interaction - Define encounter metadata (type, identifier, timestamps)
- Navigate to session - Load the session view with recording interface
- User records - Clinician documents the encounter
- Handle events - React to document generation, errors, state changes
- Link Corti sessions to your EHR’s encounter IDs
- Pre-fill encounter metadata from your system
- Control when and how sessions start
- Track interactions in your database
Implementation guide
Project structure
Step 1: Backend setup
Purpose: Securely authenticate with Corti and provide tokens to the frontend. Key file:server.ts
What it does:
/api/auth- Uses@corti/sdkto perform ROPC authentication/api/config- Returns base URL based on environment (EU/US)/api/health- Provides a simple backend health check- CORS configured for the local Vite dev server origin
- Backend port defaults to 8013; frontend origin defaults to
http://localhost:8015
Step 2: Frontend data fetching
Purpose: Fetch auth tokens and config before rendering the Assistant. Key file:src/lib/auth.ts
What it does:
- Promise-based API calls to backend
- Simple in-memory caching to prevent duplicate requests
- Separates data fetching logic from UI components
Step 3: App root with suspense
Purpose: Coordinate parallel data fetching and handle loading states. Key file:src/App.tsx
Key pattern: React 19’s use() hook with Suspense for async data
- Parallel fetching: Config and auth load simultaneously
- Declarative loading: Suspense fallback handles loading UI automatically
- Error boundaries: Easy to add error handling at the boundary level
Step 4: Embedded Assistant component
Purpose: Render the Web Component and manage the interaction lifecycle. Key file:src/components/EmbeddedAssistant.tsx
Core responsibilities:
- Render
<CortiEmbeddedReact>with configuration - Use
useCortiEmbeddedApihook to access API methods - Handle
onReadyevent to authenticate and configure the embedded app - Set interaction-level options before creating the interaction
- Create the interaction and navigate to the session route
- Manage status display and error states
onReady- Authenticate, configure app UI, set interaction options, create interaction, navigate to sessiononEvent- Receive Assistant events for logging or workflow integrationonError- Display errors to user
Running the example
Clone and run the complete example:/api requests to that backend.
Customization points
Interaction creation
The example creates an interaction inEmbeddedAssistant.tsx after authentication and configuration:
Assistant configuration
The example callsapi.configureApp() after authentication for app-level UI settings:
api.setInteractionOptions() for interaction-level options:
Event and error handling
The example wiresonEvent and onError callbacks on <CortiEmbeddedReact>:
Production considerations
Environment variables
Never commit credentials to version control:CORS configuration
Update CORS for production domains:Next steps
Build on the React basic example with the current Embedded API:- Document export - Handle document events and save generated content to your host application
- Session management - Store created interaction IDs and navigate back with
api.navigate("/session/<id>") - App configuration - Use
api.configureApp()for UI, appearance, locale, and network settings - Interaction options - Use
api.setInteractionOptions()for mode, document actions, spoken language, and templates - Event monitoring - Use
onEventandonErrorto track Assistant activity in your application
Troubleshooting
CORS errors
If you see CORS errors, verify Vite’s dev server origin matches theCLIENT_ORIGIN used by server.ts. The example uses strict port 8015 for Vite and port 8013 for the backend.
Fix: Set CLIENT_ORIGIN to match your frontend URL:
Authentication fails
- Verify credentials in
.envmatch your Corti Console setup - Ensure OAuth client has “Direct Access Grants” enabled for ROPC
- Check user account exists and is active in your Corti tenant
- Verify
CORTI_ENVIRONMENTmatches your tenant region (eu/us)
Web Component not loading
- Check browser console for import errors
- Verify
@corti/embedded-webpackage is installed correctly - Ensure
baseURLmatches your region (https://assistant.eu.corti.app) - Confirm microphone permissions are granted (required for recording)
Double initialization in Dev Mode
This is expected with React 19 StrictMode. ThehasInitialized ref guard prevents issues. In production builds, StrictMode is disabled and this won’t occur.