Skip to main content
The Corti Embedded Assistant API enables seamless integration of Corti Assistant into host applications, such as Electronic Health Record (EHR) systems, web-based clinical portals, or native applications using embedded WebViews. The implementation provides a robust, consistent, and secure interface for parent applications to control and interact with embedded Corti Assistant.
The details outlined below are for you to embed the Corti Assistant “AI scribe solution” natively within your application. To lean more about the full Corti API, please see more here

Overview

This implementation provides a robust, consistent, and secure interface for parent applications to control and interact with the embedded Corti Assistant. The API supports both asynchronous (postMessage) and synchronous (window object) integration modes.

Integration Modes

1. PostMessage API

This method is recommended for iFrame/WebView integration
  • Secure cross-origin communication
  • Works with any iframe or WebView implementation
  • Fully asynchronous with request/response pattern
PostMessage Example
<!-- Load the embedded Corti iframe -->
<iframe id="corti-iframe" src="/embedded" width="100%" height="600px"></iframe>

<script>
const iframe = document.getElementById('corti-iframe');
let isReady = false;

// Listen for the ready event
window.addEventListener('message', async (event) => {
  if (event.data?.type === 'CORTI_EMBEDDED_EVENT' && event.data.event === 'ready') {
    isReady = true;
    console.log('Corti embedded app is ready');

    // Start the integration flow
    await authenticateUser();
  }
});

async function authenticateUser() {
  // Send authentication request
  iframe.contentWindow.postMessage({
    type: 'CORTI_EMBEDDED',
    version: 'v1',
    action: 'auth',
    requestId: 'auth-1',
    payload: {
      mode: 'stateful',
      accessToken: 'your-access-token',
      refreshToken: 'your-refresh-token'
    }
  }, '*');
}
</script>

2. Window API

This method is recommended for direct integration
  • Synchronous typescript API via window.CortiEmbedded
  • Promise-based methods
  • Ideal for same-origin integrations
Windows API Example
// Wait for the embedded app to be ready
window.addEventListener('message', async (event) => {
  if (event.data?.type === 'CORTI_EMBEDDED_EVENT' && event.data.event === 'ready') {
    // Use the window API directly
    const api = window.CortiEmbedded.v1;
    const user = await api.auth({
      mode: 'stateful',
      accessToken: 'your-access-token',
      refreshToken: 'your-refresh-token'
    });

    console.log('Authenticated user:', user);
  }
});

Authentication

Authenticate the user session with the embedded app:
iframe.contentWindow.postMessage({
  type: 'CORTI_EMBEDDED',
  version: 'v1',
  action: 'auth',
  requestId: 'unique-id',
  payload: {
    mode: 'stateless' | 'stateful', // we currently do not take this value into account and will always refresh the token internally
    access_token: string,
    refresh_token?: string,
    id_token?: string,
    expires_in?: number,
    token_type?: string
  }
}, '*');

Create interaction

iframe.contentWindow.postMessage({
  type: 'CORTI_EMBEDDED',
  version: 'v1',
  action: 'createInteraction',
  payload: {
    assignedUserId: null,
    encounter: {
      identifier: `encounter-${Date.now()}`,
      status: "planned",
      type: "first_consultation",
      period: {
        startedAt: new Date().toISOString(),
      },
      title: "Initial Consultation",
    },
    patient: {
      identifier: "brief-clinical-note-en",
    },
}, '*');

Add Facts

Add contextual facts to the current interaction:
iframe.contentWindow.postMessage({
  type: 'CORTI_EMBEDDED',
  version: 'v1',
  action: 'addFacts',
  requestId: 'unique-id',
  payload: {
    facts: [
      { text: "Chest pain", group: "other" },
      { text: "Shortness of breath", group: "other" },
      { text: "Fatigue", group: "other" },
      { text: "Dizziness", group: "other" },
      { text: "Nausea", group: "other" },
    ]
  }
}, '*');

Configure Session

Set session-level defaults and preferences:
iframe.contentWindow.postMessage({
  type: 'CORTI_EMBEDDED',
  version: 'v1',
  action: 'configureSession',
  requestId: 'unique-id',
  payload: {
    defaultLanguage: 'en',
    defaultOutputLanguage: 'en',
    defaultTemplateKey: 'soap_note',
    defaultMode: 'virtual'
  }
}, '*');
Navigate to a specific path within the embedded app:
iframe.contentWindow.postMessage({
  type: 'CORTI_EMBEDDED',
  version: 'v1',
  action: 'navigate',
  requestId: 'unique-id',
  payload: {
    path: '/session/interaction-123'
  }
}, '*');

Recording controls

Start and stop recording within the embedded session:
// Start recording
iframe.contentWindow.postMessage({
  type: 'CORTI_EMBEDDED',
  version: 'v1',
  action: 'startRecording',
  requestId: 'unique-id'
}, '*');

// Stop recording
iframe.contentWindow.postMessage({
  type: 'CORTI_EMBEDDED',
  version: 'v1',
  action: 'stopRecording',
  requestId: 'unique-id'
}, '*');

Events

The embedded app sends events to notify the parent application of important state changes:

Event Types

readyEmbedded app is loaded and ready
loadedNavigation to a specific path completed
recordingStartedRecording has started
recordingStoppedRecording has stopped
documentGeneratedA document has been generated
documentUpdated A document has been updated
documentSyncedA document has been synced to EHR

Listening for Events

Listening for Events
window.addEventListener('message', (event) => {
  if (event.data?.type === 'CORTI_EMBEDDED_EVENT') {
    switch (event.data.event) {
      case 'ready':
        console.log('Embedded app ready');
        break;
      case 'documentGenerated':
        console.log('Document generated:', event.data.payload.document);
        break;
      case 'recordingStarted':
        console.log('Recording started');
        break;
      // ... handle other events
    }
  }
});

Complete Integration Flow

Here’s a complete example showing the recommended integration steps:
Example Embedded Integration
// State management
let iframe = null;
let isReady = false;
let currentInteractionId = null;
let pendingRequests = new Map();

// Initialize the integration
function initializeCortiEmbeddedIntegration(iframeElement) {
  iframe = iframeElement;
  isReady = false;
  currentInteractionId = null;

  setupEventListeners();
}

function setupEventListeners() {
  window.addEventListener('message', (event) => {
    if (event.data?.type === 'CORTI_EMBEDDED_EVENT') {
      handleEvent(event.data);
    }
  });
}

function handleEvent(eventData) {
  switch (eventData.event) {
    case 'ready':
      isReady = true;
      startIntegrationFlow();
      break;
    case 'documentGenerated':
      onDocumentGenerated(eventData.payload.document);
      break;
    // ... handle other events
  }
}

async function startIntegrationFlow() {
  try {
    // 1. Authenticate
    await authenticate();

    // 2. Configure session
    await configureSession();

    // 3. Create interaction
    const interaction = await createInteraction();

    // 4. Add relevant facts
    await addFacts();

    // 5. Navigate to interaction UI
    await navigateToSession(interaction.id);

    console.log('Integration flow completed successfully');
  } catch (error) {
    console.error('Integration flow failed:', error);
  }
}

async function authenticate() {
  return new Promise((resolve, reject) => {
    const requestId = generateRequestId();

    pendingRequests.set(requestId, { resolve, reject });

    iframe.contentWindow.postMessage({
      type: 'CORTI_EMBEDDED',
      version: 'v1',
      action: 'auth',
      requestId,
      payload: {
        mode: 'stateful',
        accessToken: 'your-accesstoken',
        refreshToken: 'your-refreshtoken',
        ...
      }
    }, '*');
  });
}

// Usage example:
const iframeElement = document.getElementById('corti-iframe');
initializeCortiEmbeddedIntegration(iframeElement);

Error Handling

All API methods can throw errors. Always wrap calls in try-catch blocks:
Error Handling
try {
  const api = window.CortiEmbedded.v1;
  const user = await api.auth(authPayload);
  console.log('Authentication successful:', user);
} catch (error) {
  console.error('Authentication failed:', error.message);
  // Handle authentication failure
}

Please contact us for help or questions.
I