Launch PopApp¶
Open the PopApp with patient context.
Integration Flow¶
- User opens a patient in your system
- If patient doesn't exist in Unomed yet, your backend creates the patient via API (see Send Patient Data)
- Your frontend loads the PopApp iframe with our Patient UUID as parameter and the requested module
- Iframe sends
UNOMED_READY, your frontend responds withUNOMED_AUTHcontaining the OAuth2 token - User sees PopApp with the patient pre-selected, already authenticated
Authentication¶
- Backend (API calls): Your backend uses OAuth2 to get tokens and sync data (see Authentication)
- Frontend (iframe): Your frontend passes the OAuth2 token to the iframe via postMessage (see PostMessage Authentication below)
URL Format¶
The app uses hash-based routing. The URL format is:
With patient context:
Without patient (organization only):
Embed as iframe¶
The PopApp must be integrated as an iframe in your application.
<iframe
id="unomed-popapp"
src="https://app.dev.unomed.ch/#/radiology/ORG_UUID?patientId=PATIENT_UUID"
width="100%"
height="800"
frameborder="0"
allow="camera; microphone"
></iframe>
Dynamic Loading¶
function loadPopApp(organizationId, patientId) {
const baseUrl = 'https://app.dev.unomed.ch/';
let url;
if (patientId) {
url = `${baseUrl}#/radiology/${organizationId}?patientId=${patientId}`;
} else {
url = `${baseUrl}#/radiology/${organizationId}`;
}
document.getElementById('unomed-popapp').src = url;
}
// Usage
loadPopApp('org-uuid-here', 'patient-uuid-here');
Handling Close Events¶
The PopApp provides a close button that users can click to indicate they want to close the iframe. When clicked, the PopApp sends a postMessage event to the parent window.
Listening for Close Events¶
window.addEventListener('message', (event) => {
// Verify origin for security
if (event.origin !== 'https://app.dev.unomed.ch') return;
if (event.data?.type === 'close-popapp') {
// User clicked close button - hide or remove the iframe
document.getElementById('unomed-popapp').style.display = 'none';
// Or remove from DOM, close modal, etc.
}
});
Message Format¶
| Property | Value | Description |
|---|---|---|
type |
'close-popapp' |
Event identifier |
Note: The iframe cannot close itself due to browser security restrictions. Your application must handle this event and close/hide the iframe accordingly.
PostMessage Authentication¶
After your backend obtains an OAuth2 token (see Authentication), your frontend passes it to the iframe via postMessage. This enables seamless single sign-on - users don't need to log in again.
Protocol Flow¶
| Step | Direction | Message | Description |
|---|---|---|---|
| 1 | iframe → PIS | UNOMED_READY |
Iframe ready for auth |
| 2 | PIS → iframe | UNOMED_AUTH |
Send OAuth2 token |
| 3 | iframe → PIS | UNOMED_AUTH_ACK |
Success |
| 3 | iframe → PIS | UNOMED_AUTH_ERROR |
Failure |
Note: UNOMED_READY is always sent when the iframe loads - even if a user session is cached in localStorage. This allows your PIS to send fresh tokens at any time. If you don't send a token (no UNOMED_AUTH response), the iframe continues with the cached session.
Message Formats¶
UNOMED_READY (iframe → PIS):
UNOMED_AUTH (PIS → iframe):
| Field | Required | Description |
|---|---|---|
type |
Yes | Must be "UNOMED_AUTH" |
version |
Yes | Must be 1 |
token |
Yes | OAuth2 access token |
expires_in |
No | Token expiry in seconds (from OAuth2 token response). Used for local cache. Default: 43200 (12 hours) |
Note: Patient context is passed via the URL query parameter (?patientId=...), not in the auth message.
UNOMED_AUTH_ACK (iframe → PIS):
UNOMED_AUTH_ERROR (iframe → PIS):
Error Codes¶
| Error | Description |
|---|---|
TOKEN_INVALID |
Token rejected by server |
TOKEN_EXPIRED |
Token has expired |
TIMEOUT |
No auth message within 10 seconds |
VALIDATION_FAILED |
Server error during validation |
Important: Your origin must be allowlisted by Unomed. If your origin is not allowlisted, UNOMED_AUTH messages are silently ignored and you will receive a TIMEOUT error.
Implementation Example¶
const iframe = document.getElementById('unomed-popapp');
const UNOMED_ORIGIN = 'https://app.dev.unomed.ch';
window.addEventListener('message', (event) => {
if (event.origin !== UNOMED_ORIGIN) return;
if (event.data.type === 'UNOMED_READY') {
iframe.contentWindow.postMessage({
type: 'UNOMED_AUTH',
version: 1,
token: 'YOUR_OAUTH2_ACCESS_TOKEN',
expires_in: 43200 // Optional: token expiry in seconds
}, UNOMED_ORIGIN);
}
if (event.data.type === 'UNOMED_AUTH_ACK') {
console.log('User authenticated');
}
if (event.data.type === 'UNOMED_AUTH_ERROR') {
console.error('Auth failed:', event.data.error);
}
});
Requirements¶
- Your domain must be allowlisted (contact info@unomed.ch)
- Send
UNOMED_AUTHwithin 10 seconds of receivingUNOMED_READY - Token must be a valid OAuth2 access token from Unomed