Skip to content

Scribe Embedding

HAMI Scribe listens to the clinician–patient consultation and drafts the clinical documentation: SOAP note, ICD/CPT codes, and after-visit summary. With Scribe embedding, the clinician opens Scribe inside your EHR for the appointment you have just sent to HAMI, instead of switching to a separate app.

The launch link comes back as scribeLaunchUrl in the response of the Universal Ingestion API. When the clinician finishes, HAMI pushes the completed note to your Scribe Webhook.

Before go-live, the HAMI team configures the following for your group:

ItemDetails
Scribe embedding enabledSwitches on scribeLaunchUrl in ingestion responses.
Allowed originThe origin of the EHR page that hosts the Scribe iframe (e.g. https://ehr.yourclinic.com). HAMI sends postMessage events containing encounter or patient identifiers only to this origin.
Clinician accountsEvery clinician who will use Scribe needs a HAMI account that is a member of your group. Otherwise they see an error screen at sign-in (see Error codes).
Launch link lifetime (optional)Defaults to 120 minutes and can be adjusted per group.
Scribe webhook (optional)Your HTTPS endpoint and API key, if you want the finished note pushed back. See Scribe Webhook.
  1. Ingest. Your system POSTs the FHIR bundle to the Universal Ingestion API. The response includes scribeLaunchUrl (https://hamiapp.bostonhealth.ai/scribe/launch?launch_code=...; the host is the HAMI app for your environment).
  2. Open. When the clinician opens the appointment in your EHR, load scribeLaunchUrl in an iframe (or a new window).
  3. Validate. HAMI checks the launch code without using it up and shows your group’s branding.
  4. Sign in. The clinician enters their phone number, then a one-time code or their password. A clinician who signed in to an embedded Scribe session recently in the same browser may be recognised automatically. HAMI checks that they belong to your group before using up the launch code, so a clinician who isn’t authorised yet can be added to the group and retry with the same link.
  5. Start the session. HAMI uses up the single-use launch code, links the session to the appointment’s encounter, and opens the consultation. Your page receives HAMI_CONSULTATION_LAUNCHED.
  6. Document. The clinician starts Scribe. Once the recording connection is up, your page receives HAMI_SCRIBE_READY. When the clinician chooses Save & Complete, Scribe saves the transcript and draft note and your page receives HAMI_SCRIBE_COMPLETE.
  7. Sign off. The clinician signs off the SOAP note and HAMI generates the after-visit summary. Your page receives HAMI_SOAP_LOCKED.
  8. Deliver. If the Scribe webhook is configured, HAMI POSTs the full clinical note to your endpoint. This happens once per encounter, on the first sign-off.
<iframe
src="{scribeLaunchUrl}"
title="HAMI Scribe"
width="100%"
height="800"
style="border:0; display:block;"
referrerpolicy="strict-origin-when-cross-origin"
allow="microphone; autoplay; clipboard-write"
></iframe>
PermissionRequiredDescription
microphoneYesScribe captures the consultation audio
autoplayYesAudio feedback and playback
clipboard-writeRecommendedLets the clinician copy note sections into your EHR

The network requirements are the same as for intake. See Iframe Embedding → Network Connectivity.

The Scribe iframe tells the host page about progress through window.parent.postMessage. Every message has a type. All messages except the session-timeout form of HAMI_SCRIBE_EXPIRED (see below) also carry source: "hami-scribe".

typeWhen it is sentPayload fields
HAMI_CONSULTATION_LAUNCHEDThe consultation screen has loaded for this appointmentencounterId, patientId, groupSlug
HAMI_SCRIBE_READYThe clinician started Scribe and the recording connection is upencounterId, patientId, groupSlug
HAMI_SCRIBE_COMPLETEThe clinician chose Save & Complete on the Scribe recordingencounterId, patientId
HAMI_SOAP_LOCKEDThe clinician signed off the SOAP noteencounterId, patientId
HAMI_SCRIBE_EXPIREDThe launch link has expired or was already used (on the launch screen), or the active session ended because of inactivity or an expired sign-inOn the launch screen: source, code, message. On session timeout: no other fields (just { "type": "HAMI_SCRIBE_EXPIRED" })
HAMI_SCRIBE_ERRORThe launch failed for another reasoncode, message

Events that carry encounterId or patientId are sent only to your registered origin. If HAMI does not yet know your origin (for example, the launch code itself was invalid), error and expiry events may be sent without an origin restriction. They never contain patient data.

codeMeaningSuggested action
TOKEN_EXPIREDThe launch link has expired or was already usedRequest a new scribeLaunchUrl by ingesting the appointment again
SESSION_EXPIREDThe clinician’s embedded session has expiredOpen Scribe again with a fresh scribeLaunchUrl
NOT_REGISTEREDNo HAMI account exists for the phone number enteredAsk the HAMI team to create the clinician’s account
WRONG_PASSWORDThe password was incorrectThe clinician retries
NOT_AUTHORIZEDThe clinician’s account is not a member of your groupAdd the clinician to the group, then reload with the same link
GENERICUnexpected errorReload and try again. Contact support if it persists
// The HAMI app origin for your environment (the host of scribeLaunchUrl)
const HAMI_ORIGIN = 'https://hamiapp.bostonhealth.ai';
window.addEventListener('message', (event) => {
// Only trust messages from the HAMI iframe. Filter on origin and type, not on `source`,
// because the session-timeout HAMI_SCRIBE_EXPIRED message has no `source` field.
if (event.origin !== HAMI_ORIGIN || typeof event.data?.type !== 'string') return;
switch (event.data.type) {
case 'HAMI_SCRIBE_READY':
showRecordingIndicator(event.data.encounterId);
break;
case 'HAMI_SOAP_LOCKED':
// The note is final: expect the Scribe webhook shortly
markNotePending(event.data.encounterId);
break;
case 'HAMI_SCRIBE_EXPIRED':
// Session over: ingest again (or reuse a still-unused link) to get a fresh scribeLaunchUrl
showScribeExpired(event.data.code ?? 'SESSION_EXPIRED');
break;
case 'HAMI_SCRIBE_ERROR':
showScribeError(event.data.code, event.data.message);
break;
}
});
  • scribeLaunchUrl is a bearer link for one appointment. Render it only for authorised clinicians, and never log it or put it in analytics.
  • Always check event.origin before acting on a postMessage event.
  • The clinician always has to sign in with their own HAMI account. The launch link on its own doesn’t give access to patient data.