ScribeberryScribeberry Docs

Partner Widget

Embed Scribeberry in your product via iframe and postMessage.

Embed the Scribeberry app in an iframe. Each clinician uses their own Scribeberry account and subscription — they can create or link an account the first time they open the widget from your product.

Contact partnerships@scribeberry.com for a partner key and to register your allowed domains.

1. Mint a token

Server-side only. Never expose your partner key to the browser.

POST https://app.scribeberry.com/api/widget/token
X-Partner-Key: your-partner-id.your-secret
Content-Type: application/json
 
{
  "userEmail": "doctor@clinic.com",
  "emrUserId": "your-internal-user-id",
  "emrSessionId": "your-session-or-encounter-id"
}

Response: { "success": true, "data": { "token": "...", "expiresAt": "..." } }

FieldRequiredDescription
userEmailYesClinician email for account create/link
emrUserIdYesYour stable user id
emrSessionIdYesYour session/encounter id — opens the same scribe on relaunch; omit only if you want clinicians to pick scribes manually

2. Embed the iframe

<iframe
  id="scribeberry"
  src="https://app.scribeberry.com/widget?token=PASTE_TOKEN_HERE"
  allow="microphone"
  style="width: 420px; height: 700px; border: none;"
></iframe>

Tokens expire after 24 hours by default. First-time users complete signup inside the iframe; returning users are signed in via userEmail + emrUserId.

3. postMessage handler

Always check event.origin === 'https://app.scribeberry.com'.

const ORIGIN = 'https://app.scribeberry.com';
const iframe = document.getElementById('scribeberry');
 
window.addEventListener('message', (event) => {
  if (event.origin !== ORIGIN) return;
  const { type } = event.data;
 
  switch (type) {
    case 'WIDGET_READY':
      iframe.contentWindow.postMessage(
        {
          type: 'PATIENT_CONTEXT',
          patient: {
            id: 'patient-123',
            name: 'James Wilson',
            dob: '1985-03-15',
            gender: 'male',
          },
          context: {
            allergies: [{ name: 'Penicillin', severity: 'severe' }],
            medications: [{ name: 'Metformin', dosage: '500mg BID' }],
            diagnoses: [{ name: 'Type 2 Diabetes' }],
            chiefComplaint: 'Follow-up for blood sugar',
            medicalHistory: 'Hypertension, diagnosed 2019',
            labResults: [{ name: 'Hgb A1c', value: '7.2', unit: '%' }],
          },
          noteConfig: {
            sections: [
              { key: 'history', label: 'Subjective' },
              { key: 'examination', label: 'Objective' },
              { key: 'assessment', label: 'Assessment' },
              { key: 'plan', label: 'Plan' },
            ],
          },
        },
        ORIGIN,
      );
      break;
 
    case 'SESSION_STARTED':
      // sessionId = Scribeberry conversation id; store against your emrSessionId
      saveSessionMapping(currentEncounterId, event.data.sessionId);
      break;
 
    case 'PUSH_NOTE': {
      const { note, sections, sessionId, patientId } = event.data;
      // note — full text, always present
      // sections — keyed by noteConfig sections; "" if missing; only when noteConfig sent
      // sessionId — Scribeberry conversation id
      // patientId — your patient id from PATIENT_CONTEXT
      handleNote({ note, sections, sessionId, patientId });
      break;
    }
 
    case 'PUSH_DOCUMENT':
      handleDocument(event.data);
      break;
 
    case 'TOKEN_EXPIRING':
    case 'REQUEST_TOKEN_REFRESH':
      refreshTokenFromServer().then((token) => {
        iframe.contentWindow.postMessage({ type: 'TOKEN_REFRESH', token }, ORIGIN);
      });
      break;
 
    case 'TOKEN_EXPIRED':
      reloadIframeWithNewToken();
      break;
 
    case 'REQUEST_PATIENT_CONTEXT':
      sendCurrentPatientContext();
      break;
  }
});

Send PATIENT_CONTEXT again when the patient or chart changes. Clinicians can exclude individual context items in the widget UI before generating a note.

noteConfig

Add to PATIENT_CONTEXT to define note shape via ordered section labels. Scribeberry resolves an internal template from those labels and returns structured fields in PUSH_NOTE.sections.

FieldRequiredDescription
sectionsYesOrdered note sections. key values are returned on PUSH_NOTE.sections; label values drive generation headings and template resolution.

Do not send template UUIDs. Same ordered labels reuse the same resolved template. Classic SOAP labels (Subjective / Objective / Assessment / Plan) resolve to Scribeberry’s curated SOAP note. Other shapes get a synthetic heading-based template. If noteConfig is omitted, SOAP is used.

Template selection is locked when noteConfig is set.

Patient object

Send on PATIENT_CONTEXT.patient. id and name are required. If validation fails, the widget posts WIDGET_ERROR with code INVALID_PATIENT_DATA and field-level details.

FieldRequiredDescription
idYesYour stable patient identifier. Returned on PUSH_NOTE.patientId.
nameYesPatient full name
dobNoYYYY-MM-DD
genderNomale, female, other, or unknown (case-insensitive)
firstName, lastName, healthCardNumber, email, phoneNoOptional demographics

See Widget API Reference for complete schemas, types, enum values, and all postMessage payloads.

SET_CONTEXT

Append or overwrite free-text context:

iframe.contentWindow.postMessage(
  { type: 'SET_CONTEXT', context: 'Prior visit: started metformin.', mode: 'append' },
  ORIGIN,
);

Token refresh

On TOKEN_EXPIRING or REQUEST_TOKEN_REFRESH, mint a new token server-side and send TOKEN_REFRESH. On TOKEN_EXPIRED, reload the iframe with a new token.

Messages

You → Scribeberry

MessageWhen
PATIENT_CONTEXTChart open or patient change
SET_CONTEXTExtra text context
TOKEN_REFRESHNew token after refresh
CLOSE_WIDGETUser leaves chart

Scribeberry → you

MessageWhen
WIDGET_READYReady for PATIENT_CONTEXT
SESSION_STARTEDScribe opened (when emrSessionId used)
PUSH_NOTEClinician sent note
PUSH_DOCUMENTClinician sent document
TOKEN_EXPIRINGRefresh soon
TOKEN_EXPIREDReload iframe
REQUEST_PATIENT_CONTEXTWidget needs patient data
WIDGET_ERRORInvalid PATIENT_CONTEXT (see code + message)

On this page