Iframe Integration Guide
This document provides comprehensive instructions for embedding the RADPAIR application within your own application as an iframe.
🎉 Welcome to Our Documentation 🎉
🛠 Gold Standard Integration (Recommended)
To ensure optimal performance and the smoothest user experience, we recommend:
Embedding RADPAIR as an iframe in your application using the Credentialless parameter.
Pre-caching Reports— create and store reports in advance (with all required metadata) so they load instantly when opened, avoiding real-time creation delays
Listening for reporting events via iframe events — a fast and responsive alternative to webhooks.
This approach ensures near-instant load times, reliable ownership assignment, and real-time, low-latency event sync.
You can reference the high-level workflow of the process below as you go over the rest of the document:

Initial Configuration
Before integrating RADPAIR, a few preliminary steps are necessary to set up your environment and user permissions correctly.
Organization Setup
Organization Creation: Initially, RADPAIR will establish an organization specifically for your team.
User Registration: You will need to sign up with RADPAIR as a member of this organization. A unique organization code will be provided to you for this purpose.
Admin Assignment: Once your account is verified, RADPAIR will grant you admin privileges within your organization.
Authentication
To facilitate a secure environment, RADPAIR utilizes a straightforward authentication workflow. By doing so, admins can manage user access securely and efficiently.
API Key-based Authentication
RADPAIR is migrating to a more secure and flexible API Key-based authentication system. We strongly recommend transitioning from admin credential-based authentication to API keys, as this approach simplifies integration and provides better security controls for your application.
Benefits of API Key Authentication
Enhanced Security: No need to share admin credentials across systems
Simplified Integration: Streamlined authentication flow
Fine-grained Access Control: API keys can be scoped to specific organizations
Obtaining an API Key
You can create an API key from your org admin's account:
Navigate to the organization's page
Select the organization you wish to create the API key for
Click on the options button for the org (⋮) and click on the "API Keys" option
Click "Create New API Key"
Copy and securely store the generated API key - it will only be shown once
Note: API keys should be treated as sensitive credentials and stored securely. Never share or commit API keys to version control.
Security Best Practices
Store API Keys Securely: Never expose your API key in client-side code or public repositories
Use HTTPS: Always make API requests over HTTPS
Implement Token Rotation: Periodically generate new tokens for long-lived sessions
Revoke Unused Tokens: Revoke tokens when they're no longer needed
This API Key authentication method provides a more secure and flexible way to integrate with RADPAIR while maintaining full control over user access and report management.
Creating a Token
Endpoint
URL:
https://api.radpair.com/integrations/auth/tokenMethod:
POST
This endpoint can also be used to change a user's first_name, last_name, and role
Request Body
{
"user_email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"user_role": "attending_radiologist",
"org_path": ["Clinic West", "Radiology"],
"auto_create_suborgs": true
}user_email
string
✅
Email of the user
first_name
string
❌
User's first name
last_name
string
❌
User's last name
org_path
array
❌
Path to sub-organization
auto_create_suborgs
boolean
❌
Auto-create sub-orgs if they don't exist
Note: org_path is optional. You only need to specify it if you intend to create the user in a sub-organization. If you wish to create the user under the main organization associated with your API key, you should skip this parameter.
Organization Management
The API Key system supports hierarchical organization structures. You can specify an organization path when creating users or reports to target specific sub-organizations:
{
"user_email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"org_path": ["West Coast", "San Francisco", "Radiology"]
}If the auto_create_suborgs flag is set to true, any missing organizations in the path will be automatically created. Otherwise, the API will return an error if the specified organization doesn't exist.
Important Note on API Keys and Organization Paths
When using API keys with organization paths, keep these key points in mind:
API Key Context Matters: The
org_pathparameter creates sub-organizations relative to the organization from which your API key was createdUsing Sub-Org API Keys: If your API key was created from the specific sub-organization you're targeting, you can omit the
org_pathparameter entirelyUsing Parent-Org API Keys: If your API key was created from a parent organization, you must provide the complete path to your target sub-organization:
"org_path": ["SubOrg1", "SubOrg2"] // Creates/targets Parent → SubOrg1 → SubOrg2Creating Missing Orgs: Set
auto_create_suborgs: trueif your path includes organizations that don't exist yet
This hierarchical approach gives you flexibility while maintaining proper organizational boundaries.
Response
Success (200)
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Error Responses
400: Bad Request - Invalid request format or parameters.401: Unauthorized - Invalid API key.500: Internal Server Error.Example request:
fetch("https://api.radpair.com/integrations/auth/token", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer your-api-key-here",
},
body: JSON.stringify({
user_email: "[email protected]",
first_name: "John",
last_name: "Doe",
org_path: ["Clinic West", "Radiology"],
}),
})
.then((response) => response.json())
.then((data) => {
const accessToken = data.access_token;
// Use this token for iframe authentication
});Revoking a Token
Endpoint
URL:
https://api.radpair.com/integrations/auth/token/revokeMethod:
POST
Request Body
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}access_token
string
✅
JWT access token to revoke
Response
Success (200)
{
"message": "Token revoked"
}Error Responses
400: Bad Request - Invalid request format or parameters.401: Unauthorized - Invalid API key.500: Internal Server Error.
Using the Access Token with the iframe
Once you've obtained an access token you can use it with the iframe:
iframe.postMessage({ authentication: `Bearer ${accessToken}` }, RADPAIR_URL);Token Expiration
RADPAIR access tokens expire after 24 hours.
Iframe
Embedding the iframe
Embed the within your application by adding the following component:
<iframe
allow="microphone; hid"
src={"<RADPAIR_URL>"}
style={{ width: "100%", height: "600px" }}
/>A few notes:
The
RADPAIR_URLis https://external.radpair.comThe
allowattribute needs both permissions:microphone: Required for dictation through RADPAIR🎉 Recent update🎉
hid: Required for accessing HID (Human Interface Device) devices like dictation hardware (e.g., SpeechMike)
The width and height can be customized based on how RADPAIR will fit within your application
Optional: Credentialless mode (experimental)
When multiple RADPAIR iframe instances are open (e.g., one inside your integration and another in a separate browser tab), browser storage and tokens can conflict. For example:
A user logs into RADPAIR in one tab as User A.
In a second tab or integration, they try to log in as User B.
Because tokens/cookies are shared across iframes by default, the session from User A is reused. This can cause confusion and prevent correct access to reports tied to the intended user.
To avoid this, you can enable credentialless mode. This isolates each iframe in its own isolated context, so tokens and storage are not shared between instances.
<iframe
allow="microphone; hid"
credentialless
src={"<RADPAIR_URL>"}
style={{ width: "100%", height: "600px" }}
/>Credentialless iframes do not retain session state. If the iframe is closed or left idle in the background (Radpair tokens expire after 24 hours), re-authentication will be required when it is reopened.
This attribute is experimental and browser support is limited. See MDN: IFrame credentialless for details.
Iframe interactions

We support interactions with the iframe through messages (postMessage). See the below for a comprehensive list of all the interactions we support:
Authentication: You can send a request to authenticate the user by passing the previously acquired
access_tokento the iframe using:iframe.postMessage({ authentication: 'Bearer <ACCESS_TOKEN>' }, <RADPAIR_URL>);Headless Mode: To enable a 'headless' version of the app, which hides the sidebar, appbar, and other components that are may not be necessary when displayed in an iframe, you can do that as follows:
iframe.postMessage({ headless: <true|false> });You can also enable the headless by default by appending a query parameter to the RADPAIR URL:
https://external.radpair.com/?headless=trueOpening a RADPAIR report: To update the report RADPAIR has open:
iframe.postMessage({ report_id: "<REPORT_ID>" });If a report_id of
nullis sent it closes the report. For more on thereport_id, see the next section.Logging Out: To trigger a logout from the embedded iframe:
iframe.postMessage({ logout: true });
Further Iframe Interactions during Reporting
We support further fine-grained interactions with the iframe during reporting, such as stopping and starting the recording (dictation), processing a transcript, signing a report, and so on. These can be useful if you plan on mapping controls of devices like a SpeechMike to RADPAIR events. Find the list of actions we support below.
Starting or stopping the recorder:
iframe.postMessage({ report_action: 'start_recording|stop_recording' }, <RADPAIR_URL>);You can also target a specific field when interacting with the recorder:
iframe.postMessage({ report_action: 'start_recording_transcript|stop_recording_transcript' }, <RADPAIR_URL>);And:
iframe.postMessage({ report_action: 'start_recording_final_report|stop_recording_final_report' }, <RADPAIR_URL>);Processing a report:
iframe.postMessage({ report_action: 'process_report' }, <RADPAIR_URL>);Signing a report:
iframe.postMessage({ report_action: 'sign_report' }, <RADPAIR_URL>);When multiple sign options are available (e.g., "sign prelim" and "sign final"), this action will automatically select the primary sign type. For example, if both options are available, the system will default to "sign final" as the primary type.
After successful signing, the system will automatically send the signed report data back to the parent window with the following payload:
{ "final_report_signed": { "signType": "[PRIMARY_SIGN_TYPE_USED]", "html_final_report": "<HTML_FINAL_REPORT>", "final_report": "<FINAL_REPORT>" } }Field Reporting: If you have fields (e.g.
[Placeholder]) in your template (in the final report box), these can be navigated via these actions:iframe.postMessage({ report_action: 'next_final_report_field|prev_final_report_field' }, <RADPAIR_URL>);Receiving Signed Report Event: You can send the finalized report data back to the parent window using the following command:
iframe.postMessage({ report_action: 'send_report_to_parent_window' }, <RADPAIR_URL>);The parent window will receive the following payload:
{ "final_report_signed": { "signType": "manually_triggered", "html_final_report": "<HTML_FINAL_REPORT>", "final_report": "<FINAL_REPORT>" } }Creating Impressions:
iframe.postMessage({ report_action: 'create_impression' }, <RADPAIR_URL>);Triggers the creation of impressions in the report based on the current content.
Adding an Addendum:
iframe.postMessage({ report_action: 'add_addendum' }, <RADPAIR_URL>);Appends an addendum section to the existing report (This will be added only to the final report box).

Hiding Multi-Author UI Elements:
iframe.postMessage({ hide_multi_author_actions: { signButton: true, actionsButton: true, addAddendumButton: true, completeDiscardButton: false, } }, <RADPAIR_URL>);
Controls the visibility of specific UI elements in multi-author scenarios. Set individual properties to true to hide the corresponding buttons, or false to show them.
The completeDiscardButton is disabled by default and must be explicitly enabled via iframe by setting it to false (to show the button) in the hide_multi_author_actions configuration.
What does completeDiscardButton do?: This button allows users to fully discard all changes in a report, restoring it back to its original state, and automatically unlocks and unassigns the report from the current user. This is different from regular discard which only reverts recent changes - complete discard performs a full restoration and releases the report entirely.

Discard and Close Report:
iframe.postMessage({ report_action: 'discard_and_close_report' }, <RADPAIR_URL>);Discards any unsaved changes in the current report and closes it, returning to the previous screen.
Complete Discard and Close Report:
iframe.postMessage({ report_action: 'complete_discard_and_close_report' }, <RADPAIR_URL>);Completely discards and unassigns the entire report (restoring it back to original state) and closes it, returning to the previous screen.
11. Save and Close Report:
iframe.postMessage({ report_action: 'save_and_close_report' }, <RADPAIR_URL>);Saves the current state of the report and closes it, returning to the previous screen.
12. Save Report:
iframe.postMessage({ report_action: 'save_report' }, <RADPAIR_URL>);Saves the current state of the report but does not close it.
13. Unlock Report:
iframe.postMessage({ report_action: 'unlock_report' }, <RADPAIR_URL>);Unlocks a report that has been previously signed or locked, allowing it to be edited again.
14. Configure Toast Notifications:
iframe.postMessage({
configure_toasts: {
success: { enabled: false },
// info, warning, and error are also supported
}
}, '*');Configures the visibility of toast notifications by type. Set enabled to false to disable a specific type of toast notification, or true to enable it. Supported toast types are success, info, warning, and error.
Events from the RADPAIR Iframe
RADPAIR sends events to the parent window to notify it of various actions and state changes. These events can be used to track user interactions and update your application's UI accordingly.
🎉 Recent update🎉 Listening for events can also be an alternative to webhooks:
As an alternative to subscribing to webhooks or socket events, RADPAIR supports real-time reporting event delivery via postMessage events emitted from the iframe. These are particularly useful for integrations that want to avoid server-side webhook complexity or need immediate client-side awareness of report actions like signing, saving, or discarding.
To receive events from the RADPAIR iframe, add an event listener to your parent window:
window.addEventListener('message', function(event) {
// Verify the origin for security
if (event.origin !== "<RADPAIR_URL>") return;
// Check if this is a reporting event
if (event.data && event.data.type === "reporting_event") {
const reportingEvent = event.data.event;
const payload = event.data.payload;
console.log(`Received reporting event: ${reportingEvent}`, payload);
// Handle different event types
switch (reportingEvent) {
case "report_opened":
// Handle report opened event
break;
case "transcript_focused":
// Handle transcript focused event
break;
// Handle other events...
}
}
});Base payload fields (always included)
{
"type": "reporting_event",
"event": "report.signed",
"payload": {
"timestamp": 1743518340903,
"user_info": { "id": "user_1", "email": "[email protected]", "full_name": "Jane Doe", "role": "radiologist" },
"report_id": "12345",
"report_info": {
"report_id": "12345",
"report_label": "XR Chest",
"report_status": "drafting",
"is_drafting": true,
"metadata": {},
"linked_reports": [],
"accession_number": "ACC-001",
"mrn": "MRN-001",
"order_id": "ORD-001",
"site_id": "SITE-001",
"assigning_authority": "HOSP",
"native_id": "NATIVE-001"
}
}
}Available Events
RADPAIR sends the following events to the parent window:
Report Lifecycle Events:
{
"type": "reporting_event",
"event": "report_opened",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903
}
}{
"type": "reporting_event",
"event": "report_closed",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903
}
}{
"type": "reporting_event",
"event": "report.signed",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903,
"user_info": {
"id": "user_123",
"email": "[email protected]",
"full_name": "Dr. John Smith",
"role": "attending_radiologist"
},
"report_info": {
"report_id": "12345",
"report_label": "XR Chest",
"report_status": "signed",
"is_drafting": false,
"metadata": {},
"linked_reports": [],
"accession_number": "ACC-001",
"mrn": "MRN-001",
"order_id": "ORD-001",
"site_id": "SITE-001",
"assigning_authority": "HOSP",
"native_id": "NATIVE-001"
},
"sign_type": "sign",
"html_final_report": "<HTML_FINAL_REPORT>",
"final_report": "<FINAL_REPORT>"
}
}{
"type": "reporting_event",
"event": "report_saved",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903
}
}{
"type": "reporting_event",
"event": "report_unlocked",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903
}
}{
"type": "reporting_event",
"event": "report_discarded",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903
}
}{
"type": "reporting_event",
"event": "report.discarded_completely",
"payload": {
"report_id": "12345", "timestamp": 1743518340903
}
}{
"type": "reporting_event",
"event": "report_discarded_and_closed",
"payload": {
"final_report": "This report was discarded.",
"html_final_report": "<p>This report was discarded.</p>"
}
}{
"type": "reporting_event",
"event": "report_updated",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903,
"final_report": "Updated content.",
"html_final_report": "<p>Updated content.</p>"
}
}{
"type": "reporting_event",
"event": "report_processed",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903,
"final_report": "Processed text.",
"html_final_report": "<p>Processed text.</p>"
}
}{
"type": "reporting_event",
"event": "report_impressions_processed",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903
}
}{
"type": "reporting_event",
"event": "report_dictated",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903
}
}{
"type": "reporting_event",
"event": "report_saved_and_closed",
"payload": {
"final_report": "Patient has pneumonia.",
"html_final_report": "<p>Patient has pneumonia.</p>"
}
}{
"type": "reporting_event",
"event": "final_report_updated",
"payload": {
"final_report": "Updated content.",
"html_final_report": "<p>Updated content.</p>"
}
}{
"type": "reporting_event",
"event": "report.linked",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903,
"linked_reports": [
{
"report_id": "67890",
"accession_number": "ACC002",
"mrn": "MRN123"
}
]
}
}{
"type": "reporting_event",
"event": "report.unlinked",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903,
"unlinked_reports": [
{
"report_id": "67890",
"accession_number": "ACC002",
"mrn": "MRN123"
}
]
}
}The two new events (report.linked and report.unlinked) are sent when users link or unlink reports using the report linking feature in the RADPAIR UI or via the API. These events notify the parent window/iframe about changes to report groupings, including which specific reports were linked or unlinked via their identifiers (report_id, accession_number, MRN, etc.).
Editor Focus Events:
{
"type": "reporting_event",
"event": "transcript_focused",
"payload": {
"report_id": "12345",
"timestamp": 1743518340893
}
}{
"type": "reporting_event",
"event": "transcript_blurred",
"payload": {
"report_id": "12345",
"timestamp": 1743518340893
}
}{
"type": "reporting_event",
"event": "final_report_focused",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903
}
}{
"type": "reporting_event",
"event": "final_report_blurred",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903
}
}Multi Author (Reject):
{
"type": "reporting_event",
"event": "report.changes_rejected",
"payload": {
"report_id": "12345",
"timestamp": 1743518340903,
"user_info": {
"id": "user_123",
"email": "[email protected]",
"full_name": "Dr. Jane Reviewer",
"role": "attending_radiologist"
},
"report_info": {
"report_id": "12345",
"report_label": "XR Chest",
"report_status": "unread",
"is_drafting": false,
"metadata": {},
"linked_reports": [],
"accession_number": "ACC-001",
"mrn": "MRN-001",
"order_id": "ORD-001",
"site_id": "SITE-001",
"assigning_authority": "HOSP",
"native_id": "NATIVE-001"
},
"new_status": "unread",
"previous_status": "pending_approval",
"new_owner_details": {
"id": "user_456",
"email": "[email protected]",
"full_name": "Dr. Sarah Resident",
"role": "resident"
},
"previous_owner_details": {
"id": "user_123",
"email": "[email protected]",
"full_name": "Dr. Jane Reviewer",
"role": "attending_radiologist"
}
}
}When using multi-author workflows, reviewers (typically attending radiologists) can reject changes made to a report and return it to the previous owner for revisions. This triggers a specific event that includes ownership transfer details and status changes.
When it's triggered:
A reviewer rejects changes made to a report
The report is automatically transferred back to the previous owner
Use Cases
These events can be used for various purposes:
UI Updates: Update your application's UI based on which editor is currently focused
Tracking: Monitor user interactions with the report for analytics or auditing
Integration with External Devices: Synchronize external devices (like dictation hardware) with the current state of the RADPAIR interface
Workflow Automation: Trigger automated actions when reports are opened, closed, or signed
Theme Customization
The app's appearance can be customized through a theme configuration message. The theme system handles certain properties specially while allowing direct palette customization for others.
Send a theme configuration message to customize the app's appearance:
window.postMessage({
theme: {
// Properties with special handling
recordButtonColor: "#212132", // Maps to record.main
diffCheckColor: "#9894f9", // Direct palette property
fontFamilyName: "inter", // Font configuration
logoWideUrl: "/logo.png", // Full logo for regular display
logoIconUrl: "/mini_logo.png", // Square logo for small screens
// Direct palette properties
background: {
default: "#212132", // Main app background
paper: "#1E1E2E", // Cards/surfaces background
medium: "#1A1A28", // Medium shade for layering
dark: "#181829", // Darker shade for depth
extraDark: "#181829" // Maximum contrast areas
},
primary: {
main: "#9894f9", // Primary brand color
dark: "#09144f", // Hover states
light: "#c4ccff" // Highlights
},
secondary: {
main: "#3B967D" // Some input box strokes/borders
},
text: {
primary: "#ffffff", // Main text color
secondary: "#999999" // Secondary text color
},
error: {
main: "#fff", // Main error color
light: "#ff3333", // Warning variant
dark: "#cc0000", // Critical variant
extraLight: "#ff6666" // Error backgrounds
},
success: {
main: "#31C48D" // Checkmark icons
},
alert: {
info: "#9894f9" // Info alert color (maps to info.main)
},
divider: "#373745" // Dividing lines color
}
}, "*")window.postMessage({
theme: {
// Properties with special handling
recordButtonColor: "rgb(33, 33, 50)", // Maps to record.main
diffCheckColor: "rgb(152, 148, 249)", // Direct palette property
fontFamilyName: "inter", // Font configuration
logoWideUrl: "/logo.png", // Full logo for regular display
logoIconUrl: "/mini_logo.png", // Square logo for small screens
// Direct palette properties
background: {
default: "rgb(33, 33, 50)", // Main app background
paper: "rgb(30, 30, 46)", // Cards/surfaces background
medium: "rgb(26, 26, 40)", // Medium shade for layering
dark: "rgb(24, 24, 41)", // Darker shade for depth
extraDark: "rgb(24, 24, 41)" // Maximum contrast areas
},
primary: {
main: "rgb(152, 148, 249)", // Primary brand color
dark: "rgb(9, 20, 79)", // Hover states
light: "rgb(196, 204, 255)" // Highlights
},
secondary: {
main: "rgb(59, 150, 125)" // Some input box strokes/borders
},
text: {
primary: "rgb(255, 255, 255)", // Main text color
secondary: "rgb(153, 153, 153)" // Secondary text color
},
error: {
main: "rgb(255, 255, 255)", // Main error color
light: "rgb(255, 51, 51)", // Warning variant
dark: "rgb(204, 0, 0)", // Critical variant
extraLight: "rgb(255, 102, 102)" // Error backgrounds
},
success: {
main: "rgb(49, 196, 141)" // Checkmark icons
},
alert: {
info: "rgb(152, 148, 249)" // Info alert color (maps to info.main)
},
divider: "rgb(55, 55, 69)" // Dividing lines color
}
}, "*")Special Handling Properties
These properties receive special treatment in the theme system:
recordButtonColor: Maps to record.main in the palettediffCheckColor: Direct palette property for diff highlightingfontFamilyName: Configures the application fontlogoWideUrl: Full logo for regular displaylogoIconUrl: Square/icon logo for small screens
Direct Palette Properties
These properties are applied directly to the theme palette:
Background Colors
background.default: Main application backgroundbackground.paper: Cards and surfacesbackground.medium: Layering elementsbackground.dark: Depth elementsbackground.extraDark: Maximum contrast areas
Brand Colors
primary.main: Primary brand colorprimary.dark: Hover statesprimary.light: Highlights
UI Element Colors
secondary.main: Controls input box strokes and borderssuccess.main: Used for checkmark icons
Text Colors
text.primary: Main text colortext.secondary: Secondary text color
Status Colors
error.main: Main error colorerror.light: Warning varianterror.dark: Critical varianterror.extraLight: Error backgrounds
Component Colors
alert.info: Info alert color (automatically maps to info.main)divider: Dividing lines
Notes
All color values should be provided in hexadecimal format (e.g.,
#FF0000for red)Both logo URLs should be provided together for proper responsive behavior
The alert.info color is automatically mapped to info.main in the palette
Font configuration requires a valid font family name that is available in the application
Application Usage
Integrating RADPAIR's functionalities involves creating a report via REST API and receiving events via webhooks.
Workflow to initialize the iframe
Once you have established the webhook connection and have the iframe embedded as in the steps shown above, you would follow the workflow below:
Embed the iframe as above
Establish the webhook endpoint
Register your webhook
Add a listener callback to receive messages from the RADPAIR iframe event. The RADPAIR iframe sends events to the parent component in two different instances: when the app is ready to receive messages (as the app may take a short amount of time to start), and when the app successfully signs in (using the access token obtained from earlier). Below, you'll find JavaScript code defining the types of events, and how to set the listener.
const IFRAME_PARENT_EVENT_TYPES = { SIGN_IN_SUCCESSFUL: "sign_in_successful", APP_READY: "app_ready", }; const receiveMessage = (message) => { const event = message.data?.event; switch (event) { case IFRAME_PARENT_EVENT_TYPES.APP_READY: // RADPAIR is now ready to receive events break; case IFRAME_PARENT_EVENT_TYPES.SIGN_IN_SUCCESSFUL: // RADPAIR has now authenticated the user break; default: console.log("Unknown event received from iframe:", event); } }; window.addEventListener("message", receiveMessage);Await the
IFRAME_PARENT_EVENT_TYPES.APP_READYevent.Upon receiving the event above, send in the Authentication request
Await the
IFRAME_PARENT_EVENT_TYPES.SIGN_IN_SUCCESScFULevent.RADPAIR is now authenticated and can receive other events like
report_id,themeetc., as above.We will assume you have a database model for saving your reports in your own database. You will need to add a field to your schema to associate your own report ID with a RADPAIR report ID. Therefore, you will need to add a field such as
radpair_report_id. This is essential for the next step.When a user needs to start a new report on your app, you will follow the pre-caching workflow as follows:
Create the Report Ahead of Time Use the
POST /integrations/reports/createendpoint with all required metadata fields. The report will be saved with a status ofunread.Find the Report When User Is Ready Just before the user needs to open the report (e.g., after clicking on it), use the
/integrations/reports/findendpoint to retrieve thereport_id.Open the Report in the Iframe Pass the
report_idinto the embedded RADPAIR iframe:iframe.postMessage({ report_id: "<REPORT_ID_FROM_FIND>" }, RADPAIR_URL);The report will open instantly, and the user will be assigned as the owner automatically since the report is still in
unreadstatus.Fallback (only if no
report_id): POST /integrations/reports/create
When the user is done dictation, the user can click on the "Process Transcript" button.
After the report is processed, the user can make any final changes to the report before signing or saving the report.
After the user signs or saves the report a webhook event will be sent. See webhooks section below for more details.
Creating Reports with Pre-Caching
RADPAIR allows partners to pre-create ("pre-cache") reports in advance of user interaction to reduce perceived latency and improve user experience. Rather than creating the report at the moment a user clicks to open it, which may involve time-consuming metadata processing, the system supports creating reports ahead of time, storing them in an "unread" state.
Pre-caching is the recommended default integration method for creating reports. Creating reports on-the-fly when the user opens them should only be used as a fallback in rare failure cases.
Why Pre-Caching Matters
Creating reports in real time can take varying amounts of time depending on system load and metadata complexity. By pre-caching, all of that work is already completed by the time the user interacts with the report, resulting in an immediate load and a smoother experience.
Full Pre-Caching Workflow
Create the Report Ahead of Time Use the
POST /integrations/reports/createendpoint with all required metadata fields. The report will be saved with a status ofunread.
Endpoint:
POST https://api.radpair.com/integrations/reports/create
{
"accession_number": "ACC12345",
"metadata": {
"studyDescription": "Chest X-ray",
"clinical_notes": "Shortness of breath",
"laterality": "bilateral",
"views": "2",
"comparison": "None",
"symptom": "Dyspnea",
"patient_age": "42",
"patient_gender": "M",
"pre_findings": "", // DIACOM SR DATA goes here
},
"metadata_source": "yourIntegrationSystem",
"org_path": ["Your Clinic", "Radiology"]
}Find the Report When User Is Ready Just before the user needs to open the report (e.g., after clicking on it), use the
/integrations/reports/findendpoint to retrieve thereport_id.
Endpoint:
POST https://api.radpair.com/integrations/reports/find
{
"accession_number": "ACC12345",
// Any other identifier used when report was created, e.g. mrn, native_id, etc
"org_path": ["Your Clinic", "Radiology"]
}When to use this endpoint:
If you didn’t store the report_id after pre-caching, use this endpoint to fetch it dynamically using identifiers like accession_number.
Open the Report in the Iframe Pass the
report_idinto the embedded RADPAIR iframe:iframe.postMessage({ report_id: "<REPORT_ID_FROM_FIND>" }, RADPAIR_URL);The report will open instantly, and the user will be assigned as the owner automatically since the report is still in
unreadstatus.
Summary
Pre-caching allows you to:
Eliminate slow load times for report creation
Ensure users can interact with reports instantly
Maintain full control over report lifecycle and ownership
For maximum performance and reliability, always pre-cache reports in advance. On-demand creation should be considered a last resort fallback.
Ownership Behavior
Unread Status: The first user to open the report becomes the owner.
Assigned Reports: If a report already has an owner or is not in
unreadstatus, use thetransfer-ownershipAPI to assign it.
Important Note on Ownership Transfer
Reports with an "unread" status are automatically assigned to the first user who opens them. Subsequent transfers will still be handled through the transfer ownership API.
Flow:
Report Created (Unread Status)
↓
User Opens Report
↓
Ownership Automatically Assigned to First User
↓
Subsequent Ownership Transfers (via Transfer Ownership API)For API-created reports:
If the report has "unread" status: The first user who opens it will automatically become the owner.
If the report has any other status: You’ll still need to use the API.
Endpoints
Creating & Updating Reports
This endpoint serves as an upsert function. It will create a new report if one doesn't exist with the provided identifiers or update an existing one if the metadata payload changes.
Only reports that are "unread" can be updated via the upserting functionality.
Endpoint:
POST https://api.radpair.com/integrations/reports/create
Request Body
{
"accession_number": "string",
"metadata": {
"studyDescription": "string",
"clinical_notes": "string",
"laterality": "string",
"views": "string",
"comparison": "string",
"symptom": "string",
"modality": "string",
"contrast": "string",
"patient_age": "string",
"patient_gender": "string",
"pre_findings": "", // DIACOM SR DATA goes here
},
"metadata_source": "string",
"native_id": "string",
"assigning_authority": "string",
"order_id": "string",
"site_id": "string",
"mrn": "string",
"org_path": ["Clinic A", "Department B"],
"auto_create_suborgs": true,
"process_normal": false
}accession_number
string
✅
Unique ID
metadata
object
❌
Study metadata
metadata_source
string
❌
Identifies the source system of the metadata, enabling RADPAIR to apply processing rules for your specific integration. For example, if your organization has custom field mappings or specialized processing needs, providing this parameter allows RADPAIR to handle your metadata appropriately. Contact us during integration if you have custom metadata handling requirements.
native_id
string
❌
A flexible identifier that links your system to ours. Unlike accession_number, which is required, native_id is optional and can be any string you choose, allowing you to store a unique
reference from your system for easier tracking.
assigning_authority
string
❌
Assigning authority
order_id
string
❌
Order ID
site_id
string
❌
Site ID
mrn
string
❌
Patient MRN
draft_report
string
❌
A pre-generated report draft that will be loaded into the report. This parameter is used within metadata object.
org_path
array
❌
Org path
auto_create_suborgs
boolean
❌
Auto-create sub-orgs
process_normal
boolean
❌
When true, RADPAIR will attempt to process the report as “normal” upon creation according to your organization’s processing rules. Default: false.
pre_findings
object
❌
Structured measurement data (typically from DICOM SR) that RADPAIR will process through an LLM to generate a formatted clinical summary. The formatted text is inserted into the transcript for radiologist review and editing. This parameter is used within the metadata object.
Example Metadata Structure:
Schema
{
metadata: <METADATA>,
metadata_source: <METADATA_SOURCE> // Optional - Identifies the origin of the metadata (typically organization or sub-organization name, but can be any value you choose)
accession_number: <ACCESSION_NUMBER>, // Optional - Unique identifier for the report
native_id: <NATIVE_ID>, // Optional
assigning_authority: <ASSIGNING_AUTHORITY>, // Optional
order_id: <ORDER_ID>, // Optional
site_id: <SITE_ID>, // Optional
mrn: <MRN>, // Optional
org_path: <ORG_PATH>, // Optional - A unique identifier for sub-organizations or specific departments within an organization
process_normal: // Optional - Process as normal on creation (default: false)
}Note: Each report is attached to a set of IDs which would be the accession_number plus any of the following IDs: native_id, assigning_authority, order_id, site_id, and mrn. Each report can only be updated/referenced with the exact same set of IDs that were used when creating it. The accession_number is required, while the other identifiers are optional but recommended for more precise report identification.
Detailed payload structure
{
"metadata": {
"studyDescription": "X-ray of the hand metatarsal",
"clinical_notes": "fractured left hand",
"laterality": "left",
"views": "2",
"comparison": "feb 22 2023",
"symptom": "Pain",
"patient_age": "45",
"patient_gender": "M",
"draft_report": "xyz"// Optional "Patient presents with left hand pain and suspected fracture."
},
"metadata_source": "xyzCorp" // Optional - Identifies the origin of the metadata (typically organization or sub-organization name, but can be any value you choose)
"accession_number": "ACC12345", // Optional - Unique identifier for the report
"native_id": "NAT98765", // Optional
"mrn": "MRN123456", // Optional
"org_path": "Clinic_123" // Optional - Unique identifier for a sub-organization or department within an organization
"process_normal": true // Optional - Process as normal on creation
}Response:
{ "report_id": <REPORT_ID> }Receiving Report Updates: you can configure this via webhooks in the section below.
Sample response:
Note: If process_normal is true, you may receive a report.processed update shortly after creation.
{
// plain text version of the report
final_report: <PLAIN_TEXT_REPORT>,
report_id: <REPORT_ID>,
// if the "Sign" button is clicked, the update_type
// will be "sign". In the case of "Approve", it will be "approve"
// After the report gets processed, this event will be emitted
// with "mark_processed" update_type
update_type: 'report.updated|report.signed|report.approved|report.processed'
// HTML version of the report
final_report_html: <HTML_REPORT>,
accession_number: <ACCESSION_NUMBER>,
native_id: <NATIVE_ID>,
assigning_authority: <ASSIGNING_AUTHORITY>,
order_id: <ORDER_ID>,
site_id: <SITE_ID>,
mrn: <MRN>,
org_path: <ORG_PATH>
}Response
{ "report_id": 12345, "error": null }A Deeper Dive into Metadata and Its Role in Integration
Metadata plays a critical role in ensuring accurate preprocessing and template selection within RADPAIR. By structuring metadata correctly, integrators can enhance reporting accuracy and streamline workflows.
Key Metadata Fields
studyDescription (Highly Recommended) The
studyDescriptionfield is crucial for accurate preprocessing and template selection. It ensures that the correct study type and template are applied when creating a report.Flexible Structure Metadata in RADPAIR is designed to be flexible, allowing users to include additional fields relevant to their workflow. While some fields influence system behavior, others can be customized to store structured data.
Metadata Fields Displayed in the UI
The following metadata fields are prominently displayed in the UI:
Clinical History
Comparison
Laterality
Views
These fields help provide context for reports and enhance usability for radiologists and other users.
Optional but Useful Metadata Fields
modality (e.g.,
"XR","CT","US") Helps refine template selection based on the imaging modality.contrast (e.g.,
"IV contrast") Indicates whether contrast was used in the imaging study.
Metadata Flexibility and Customization
While certain metadata fields directly impact reporting accuracy and workflow efficiency, integrators can store additional structured data tailored to their needs. This flexibility allows for seamless adaptation to different radiology environments and organizational requirements.
Pre-Findings Processing
Overview
Pre-findings is a feature that automatically converts structured measurement data (typically from DICOM SR) into human-readable clinical summaries. When a study includes structured measurements in the pre_findings metadata field, RADPAIR processes this data through an LLM and inserts the formatted text into the transcript for radiologist review and editing.
API Payload Structure
{
"metadata": {
"pre_findings": {
"report_info": { ... },
"anatomical_findings": [ ... ]
}
}
}Configuration
Admins can customize the processing prompt per organization via Organization Settings → Pre-findings.
Default System Prompt:
You are preparing data for incorporation into a radiology report. Please take the extracted DICOM SR data and format it concisely into a summary with one line per organ with a description of the organ, followed by the measurement. Where measurements are taken in 3 planes, format it as length × width × height. Any measurements should be rounded to one decimal place.
Example Output
Aorta – proximal 1.7 cm, mid 1.9 cm, distal 1.9 cm
Pancreas – head 1.3 cm, body 1.5 cm, tail 2.4 cm
Right kidney – 5.6 × 5.8 × 3.1 cm (vol 51.7 ml)Finding a Report
Endpoint:
POST https://api.radpair.com/integrations/reports/find
Request Body
{
"accession_number": "string",
"native_id": "string",
"assigning_authority": "string",
"order_id": "string",
"site_id": "string",
"mrn": "string",
"org_path": ["Clinic A", "Department B"]
}accession_number
string
✅
Unique Accession number
native_id
string
❌
Additional ID
assigning_authority
string
❌
Additional ID
order_id
string
❌
Additional ID
site_id
string
❌
Additional ID
mrn
string
❌
Additional ID
org_path
array
❌
Organizational path
Response
{
"report": {
"accession_number": "A12345",
"events": [
{
"event_data": {
"data": { "timestamp": 1741809758130 },
"user_info": {
"email": "[email protected]",
"full_name": "Jane Doe",
"id": 37,
"role": "attending_radiologist"
}
},
"event_type": "report.opened",
"id": "8193e680-c743-4b82-882e-ae56c4f63afe",
"report_id": 4152,
"timestamp": 1741809758
},
{
"event_data": {
"data": { "timestamp": 1741809758131 },
"user_info": {
"email": "[email protected]",
"full_name": "Jane Doe",
"id": 37,
"role": "attending_radiologist"
}
},
"event_type": "report.closed",
"id": "b33df3a3-c410-4a6a-a716-ce5639aaee17",
"report_id": 4152,
"timestamp": 1741809758
},
{
"event_data": {
"data": {},
"user_info": {
"email": "[email protected]",
"full_name": "John Doe",
"id": 38,
"role": "attending_radiologist"
}
},
"event_type": "report.discarded",
"id": "c3d767b0-24f3-48b9-857a-883b48a52e59",
"report_id": 4152,
"timestamp": 1741813477
},
{
"event_data": {
"data": { "timestamp": 1741898217 },
"user_info": {
"email": "[email protected]",
"full_name": "John Doe",
"id": 38,
"role": "attending_radiologist"
}
},
"event_type": "report.processed",
"id": "7614c949-2ea0-4033-b001-678d0912574c",
"report_id": 4152,
"timestamp": 1741898217
}
],
"final_report": "EXAM:\nXR Left Hand, 2 Views.\n\nCLINICAL HISTORY:\nPain. Fractured left hand, suspected. \n\nCOMPARISON:\n02/22/2023.\n\nFINDINGS:\n\nBONES:\nNo acute fracture or focal osseous lesion.\n\nJOINTS:\nNo dislocation. The joint spaces are normal. \n\nSOFT TISSUES:\nThe soft tissues are unremarkable.\n\nIMPRESSION:\n1. No acute osseous abnormality or displaced fracture identified.\n2. Consider MRI for further characterization of soft tissue injuries or disruption in the setting of ongoing pain.",
"meta": {
"clinical_history": "Pain\nfractured left hand, suspected",
"clinical_notes": "fractured left hand",
"comparison": "02/22/2023",
"laterality": "left",
"studyDescription": "X-ray of the hand metatarsal",
"symptom": "Pain",
"views": "2"
},
"is_drafting": true, // Whether the report is currently in draft mode for that user
"mrn": "12345",
"order_id": "ORDER950",
"owner": "[email protected]",
"report_id": 12345,
"status": "addendum_signed"
},
"report_id": 12345
}Notes
The response includes a full report object, including metadata, history of events, and the final report content.
The
eventsarray records interactions such as report opened, closed, discarded, and processed.The
metasection contains structured metadata fields relevant to the report.
Transferring Report Ownership
Endpoint:
POST https://api.radpair.com/integrations/reports/transfer-ownership
Request Body
{
"accession_number": "string",
"email": "[email protected]",
// Any other identifier used when report was created, e.g. mrn, native_id, etc
"native_id": "string",
"assigning_authority": "string",
"order_id": "string",
"site_id": "string",
"mrn": "string",
"org_path": ["Clinic A", "Department B"],
"force": true
}If email is left blank and report is assigned to a user, it will be unassigned from that user.
accession_number
string
✅
Report ID
string
✅
New owner
native_id
string
❌
Additional ID
assigning_authority
string
❌
Additional ID
order_id
string
❌
Additional ID
site_id
string
❌
Additional ID
mrn
string
❌
Additional ID
org_path
array
❌
[ ]
Org path
force
boolean
❌
false
When set to true, forces ownership transfer even if the report is currently locked or being
Notes
The
forceparameter allows administrators to transfer ownership regardless of the report's current stateUse with caution as it may interrupt another user's active editing session
When
forceis true, the current owner will receive a notification that ownership has been transferred\
Response
{ "report_id": 12345, "new_owner_email": "[email protected]" }Transferring a Report to another Organization
This endpoint transfers a report from one organization to another within the system. It locates a report using provided identifiers (like accession number or MRN) within a source organization and moves it to a target organization specified by their respective org paths.
Endpoint:
POST https://api.radpair.com/integrations/reports/transfer-org
Request Body:
{
"report_identifiers": {
"accession_number": "string",
"native_id": "string",
"assigning_authority": "string",
"order_id": "string",
"site_id": "string",
"mrn": "string"
},
"source_org_path": ["Clinic A", "Department B"],
"target_org_path": ["Clinic C", "Department D"]
}Parameters
report_identifiers
object
✅
Object containing report identifiers (at least one required)
source_org_path
array
✅
Source organization path where report currently exists
target_org_path
array
✅
Target organization path where report will be transferred
Report Identifiers (at least one required)
accession_number
string
❌
Unique Accession number
native_id
string
❌
Additional ID
assigning_authority
string
❌
Additional ID
order_id
string
❌
Additional ID
site_id
string
❌
Additional ID
mrn
string
❌
Additional ID
At least one report identifier must be provided to locate the report.
Both source and target organization paths must be valid and accessible.
The report will be moved from the source organization to the target organization.
This operation cannot be undone — use with caution.
Response
{
"report_id": 12345,
"report": {
// Full report object with updated organization
}
}Error Responses
403
(varies)
ReportingService exception (insufficient permissions, etc.)
500
TRANSFER_REPORT_ORG_ERROR
Unexpected error during transfer
Canceling a Report
Endpoint:
POST https://api.radpair.com/integrations/reports/cancel
Request Body
{
"accession_number": "string",
"org_path": ["Clinic A", "Department B"]
}accession_number
string
✅
Report ID
org_path
array
❌
Org path
Response
{ "status": "success" }Checking Report Access
Endpoint:
POST https://api.radpair.com/integrations/reports/<REPORT_ID>/can-access
Request Body
{
"email": "[email protected]",
"accession_number": "string",
"org_path": ["Clinic A", "Department B"]
}string
✅
User email
accession_number
string
✅
Report ID
org_path
array
❌
Org path
Response
{ "can_access": true, "reason": null }Deleting a Report
Endpoint:
POST https://api.radpair.com/integrations/reports/delete
Request Body
{
"accession_number": "string",
"native_id": "string",
"assigning_authority": "string",
"order_id": "string",
"site_id": "string",
"mrn": "string",
"org_path": ["Clinic A", "Department B"]
}accession_number
string
✅
Unique Accession number
native_id
string
❌
Additional ID
assigning_authority
string
❌
Additional ID
order_id
string
❌
Additional ID
site_id
string
❌
Additional ID
mrn
string
❌
Additional ID
org_path
array
❌
Organizational path
Response
{ "status": "success" }Update Report Status Endpoint
Endpoint:POST https://api.radpair.com/integrations/reports/status-update
Request Body
{
"status": "DRAFT",
"accession_number": "ABC12345",
"org_path": ["Clinic A", "Department B"]
}status
string
✅
New status for the report (DRAFT or CANCELLED)
accession_number
string
✅
Report identifier (required if no other ID is present)
native_id
string
❌
Alternate identifier for the report
assigning_authority
string
❌
Alternate identifier for the report
order_id
string
❌
Optional report ID from order system
site_id
string
❌
Optional site ID for additional context
mrn
string
❌
Medical record number
org_path
array
❌
Organizational hierarchy path
* At least one identifying field (accession_number, native_id, order_id, etc.) is required to locate the report.
Allowed Status Values:
DRAFTCANCELLED
Response
{
"report_id": "a1b2c3",
"report": { /* report metadata */ },
"new_status": "DRAFT"
}Errors
STATUS_REQUIRED: Ifstatusis missing from the requestINVALID_STATUS: If the provided status is not one of the allowed valuesUPDATE_REPORT_STATUS_ERROR: If an error occurs during database update
Notes:
This is a temporary implementation. A more robust and traceable event-handling system is planned.
Make sure the report being updated is accessible to the authenticated organization context.
Linking Reports
This endpoint links multiple reports together, creating a group. Reports in a group share content (transcript, final report, and metadata) while maintaining individual identity (label, id).
Endpoint:POST https://api.radpair.com/integrations/reports/link
Request Body
{
"reports": [
{
"accession_number": "ACC001",
"native_id": "NAT001",
"order_id": "ORD001"
},
{
"accession_number": "ACC002",
"native_id": "NAT002",
"order_id": "ORD002"
}
],
"org_path": ["Clinic A", "Department B"]
}reports
array
✅
Array of report identifiers (at least 2 reports needed)
org_path
array
❌
Organization path
Notes
Each report in the array needs at least one identifier (accession_number, native_id, etc.)
Reports must have the same MRN to be linked
Only reports with "unread" or "draft" status can be linked
The first report becomes the default report for the group
Response
{ "status": "success" }Error Responses
400: Bad Request - Invalid request format or parameters (e.g., INVALID_REPORTS if fewer than 2 reports provided)500: REPORT_LINKING_ERROR - Error occurred during linking with detailed error message
Unlinking Reports
This endpoint removes reports from a group. When a report is unlinked, it returns to its original state.
Endpoint:POST https://api.radpair.com/integrations/reports/unlink
Request Body
{
"reports": [
{
"accession_number": "ACC001",
"native_id": "NAT001",
"order_id": "ORD001"
}
],
"org_path": ["Clinic A", "Department B"]
}reports
array
✅
Array of report identifiers to unlink
org_path
array
❌
Organization path
Notes
Only reports with "unread" or "draft" status can be unlinked
Unlinking restores the report to its original state (before it was linked)
Other reports in the group remain linked
Response
{ "status": "success" }Error Responses
400: Bad Request - Invalid request format or parameters (e.g., MISSING_REPORTS if no reports provided)500: REPORT_UNLINKING_ERROR - Error occurred during unlinking with detailed error message
Update Identifiers
Update report identifiers. Useful for synchronizing changes in accession numbers, order IDs, or MRNs across reports.
Endpoint:POST https://api.radpair.com/integrations/reports/update-identifiers
Request Body
{
{
"source_identifiers": {
"accession_number": "MOUADACCD1",
"order_id": "MOUADORDERD1",
"mrn": "XXXXXX"
},
"target_identifiers": {
"accession_number": "MOUADACCD1U",
"order_id": "MOUADORDERD1U",
"mrn": "XXXXXX"
}
}source_identifiers
object
✅
Original set of identifiers for each report.
target_identifiers
object
✅
New set of identifiers to apply.
accession_number
string
✅
Report accession number.
order_id
string
✅
Report order ID.
mrn
string
✅
Medical record number.
Response
{
"status": "success",
"updated_report": [
{
"accession_number": "MOUADACCD1U",
"order_id": "MOUADORDERD1U",
"mrn": "XXXXXX"
/* other public fields */
},
{
"accession_number": "MOUADACCD2U",
"order_id": "MOUADORDERD2U",
"mrn": "XXXXXX"
}
],
}status
string
"success" if changes applied without error.
updated_report
array
List of public report objects reflecting new identifiers.
Copying Reports
This endpoint copies specified fields from a source report to a target report. Both reports must exist and be accessible within the organization.
Endpoint: POST https://api.radpair.com/integrations/reports/copy
Request Body
{
"source_identifiers": {
"accession_number": "ACC001",
"native_id": "NAT001"
},
"target_identifiers": {
"accession_number": "ACC002",
"native_id": "NAT002"
},
"fields": ["transcript", "final_report", "meta"],
"org_path": ["Clinic A", "Department B"]
}source_identifiers
object
✅
Identifiers for the source report to copy from
target_identifiers
object
✅
Identifiers for the target report to copy to
fields
array
❌
Array of field names to copy (defaults to all copyable fields)
org_path
array
❌
Organization path for target organization
Available Fields to Copy
transcript- Report transcript contentfinal_report- Final report contentmeta- Report metadatastatus- Report statusis_drafting- Drafting statetemplate- Template IDstudy- Study ID
Notes
Both source and target reports must exist and be accessible
If no fields are specified, all copyable fields are copied
Invalid field names will result in a 400 error
Copy operation is atomic - either all fields copy successfully or none do
Target report fields are overwritten with source report values
Response
{
"status": "success",
"report": {
"id": "report_id",
"accession_number": "ACC002",
"transcript": "copied transcript content",
"final_report": "copied final report content",
"meta": {...},
"status": "copied_status"
}
}Error Responses
400: Bad Request - Invalid field names or copy operation failed404: Report not found - Source or target report not found500: COPY_REPORT_ERROR - Database error during copy operation
Integration Preview

Webhooks
We have transitioned from using Socket.IO for event communication to a webhook-based system. This change improves scalability, reliability, and flexibility in delivering events to your systems.
Until Socket.IO support is depreciated we will be sending all of the reporting events to reporting_events
What You Need to Do
To continue receiving events, you must migrate to webhooks by following these steps:
1. Set Up Your Webhook Endpoint
Create a publicly accessible HTTP endpoint (must support HTTPS).
Ensure the endpoint can handle POST requests with JSON payloads.
2. Register Your Webhook
Use our portal to register your webhook URL and specify the events you want to subscribe to.
Navigate to the Organizations page
Click on the "⋮" button for your organization (or any sub-organization) and hit "Setup webhooks":

Here, you'll be able to create, edit and view all your webhook configurations for the given organization:

Click on "Create New" to setup a new webhook. Specify the URL, the event types you want to listen to and submit the form:

Once created, you'll get a "Signing Secret." Keep that somewhere safe!
Verifying Webhook Messages
To ensure the integrity of the messages your application receives, you should validate the webhook signature included in the message. This prevents unauthorized access and ensures the message was sent by us.
Signature Details
Algorithm: HMAC-SHA256
Header:
X-Webhook-SignatureSigning Secret: Your secret key (provided in your account settings)
Payload Canonicalization: JSON payload is canonicalized before signing by:
Sorting all keys alphabetically.
Using
,as the separator for array elements and:for key-value pairs.Removing unnecessary spaces.
Sample Code
SECRET = "your-secret-key"
def verify_signature(request):
received_signature = request.headers.get("X-Webhook-Signature")
if not received_signature:
raise ValueError("Missing X-Webhook-Signature header")
# Get the raw request payload
payload = request.data
# Compute the expected signature
expected_signature = hmac.new(
SECRET_KEY.encode("utf-8"),
payload,
hashlib.sha256
).hexdigest()
# Use a timing-safe comparison
return hmac.compare_digest(received_signature, expected_signature):
raise ValueError("Invalid signature")
return Trueconst crypto = require("crypto");
const encoder = new TextEncoder();
const SECRET_KEY = "your-secret-key";
async function verifySignature(secret, receivedSignature, payload) {
if (!receivedSignature) return false; // Ensure the signature exists
const keyBytes = encoder.encode(secret);
const dataBytes = encoder.encode(
typeof payload === "string" ? payload : payload.toString("utf8")
);
const algorithm = { name: "HMAC", hash: { name: "SHA-256" } };
const key = await crypto.subtle.importKey("raw", keyBytes, algorithm, false, [
"sign",
"verify",
]);
const sigBytes = hexToBytes(receivedSignature);
return await crypto.subtle.verify(algorithm.name, key, sigBytes, dataBytes);
}
function hexToBytes(hex) {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return bytes;
}
// Sample usage
const receivedSignature = req.headers["X-Webhook-Signature"];
const payload = req.body;
// Validate the webhook signature
if (!verifySignature(SECRET_KEY, receivedSignature, payload)) {
console.warn("Invalid webhook signature:", receivedSignature);
return res.status(400).json({ error: "INVALID_WEBHOOK_SIGNATURE" });
}
console.log("✅ Webhook signature validated successfully");
// Do something with the webhook payload
// ...
});Webhook Events
RADPAIR sends webhook events for various report actions. All webhook events follow this general structure:
{
"event": "event.name",
"timestamp": "ISO-8601 timestamp",
"payload": {
"data": {
"timestamp": 1742577136992
},
"user_info": {
"id": 123,
"email": "[email protected]",
"full_name": "User Name",
"role": "user_role"
},
"report_info": {
"report_id": 456,
"report_label": null,
"report_status": "status",
"order_id": "ORDER_ID",
"accession_number": "ACCESSION_NUMBER",
// The metadata is only provided in sign events
"metadata": {
"studyDescription": "X-ray of the hand metatarsal",
"clinical_notes": "fractured left hand",
"laterality": "left",
"views": "4",
"comparison": "feb 22 2023",
"symptom": "Pain"
// And any other custom or additional fields provided
// when creating the report
}
}
},
"webhook_version": "1.0"
}Available Events
report.created
New report was created
Report creation details
report.opened
Report was opened
timestamp: Unix timestamp in ms
report.closed
Report was closed
timestamp: Unix timestamp in ms
report.dictated
Dictation occurred
dictation_start_time_ms, dictation_stop_time_ms
report.saved
Report was saved
Varies based on save type
report.processed
Report was processed
timestamp: Unix timestamp in ms
report.impressions_processed
Impressions were processed
Varies
report.discarded
Report was discarded
Varies
report.discarded_completely
Report was completely discarded
Varies
report.unlocked
Report was unlocked
Varies
report.prelim_signed
Report was signed by a resident
html_final_report & final_report HTML and plain text version of the report
report.signed
Report was signed by an attending
html_final_report & final_report HTML and plain text version of the report
report.addendum_prelim_signed
Addendum was signed by a resident
html_final_report & final_report HTML and plain text version of the report
report.addendum_signed
Addendum was signed by an attending
html_final_report & final_report HTML and plain text version of the report
report.approved
Legacy event, equivalent to signed
html_final_report & final_report HTML and plain text version of the report
report.updated
Report content was updated
final_report: Plain text version of the report
report.mark_processed
Report was marked as processed
final_report, html_final_report, timestamp: Unix timestamp in ms
report.owner_changed
Report ownership changed
New owner information
report.status_changed
Report status changed
Previous and new status information
report.linked
Reports were linked together
identifiers_list, group_id, report_ids
report.unlinked
Reports were unlinked
identifiers_list, group_id, report_ids
report.identifiers_updated
Report identifiers were updated
Updated identifier information
report.published
Report was published to RIS/PACS
sign_context, publish_context, idempotency_key
report.published_cancelled
Scheduled publication was cancelled
cancelled_at, remaining_seconds, reason
Example: Report Opened Event
{
"event": "report.opened",
"timestamp": "2025-03-17T19:06:34.289782+00:00",
"payload": {
"data": {
"timestamp": 1742238394168
},
"user_info": {
"id": 29,
"email": "[email protected]",
"full_name": "User Name",
"role": "radiologist_admin"
},
"report_info": {
"report_id": 456,
"report_label": null,
"report_status": "status",
"order_id": "ORDER_ID",
"accession_number": "ACCESSION_NUMBER",
},
},
"webhook_version": "1.0"
}Example: Report Dictated Event
{
"event": "report.dictated",
"timestamp": "2025-03-17T16:15:34.868720+00:00",
"payload": {
"data": {
"dictation_start_time_ms": 1742228120497,
"dictation_stop_time_ms": 1742228134628
},
"user_info": {
"id": 37,
"email": "[email protected]",
"full_name": "User Name",
"role": "resident"
},
"report_info": {
"report_id": 456,
"report_label": null,
"report_status": "status",
"order_id": "ORDER_ID",
"accession_number": "ACCESSION_NUMBER",
},
},
"webhook_version": "1.0"
}Example: Report Preliminary Signed Event
{
"event": "report.prelim_signed",
"timestamp": "2025-03-17T16:19:52.633577+00:00",
"payload": {
"data": {
"html_final_report": "<HTML_FINAL_REPORT>",
"final_report": "<FINAL_REPORT>",
// All sign events for mammo studies will include the below
"exam_specific_data": {
"breast_imaging_mammo": {
"birads_category": "3",
"breast_density": "Heterogeneously dense'",
"follow_up_interval_type": "6 month",
"laterality": "Bilateral"
}
}
},
"user_info": {
"id": 38,
"email": "[email protected]",
"full_name": "User Name",
"role": "resident"
},
"report_info": {
"report_id": 4173,
"report_label": null,
"report_status": "prelim_signed",
"order_id": "ORDER_ID_123",
"accession_number": "ACC_456"
// All sign events include an aggregate of the metadata provided
// during creating and updating the report
"metadata": {
"studyDescription": "X-ray of the hand metatarsal",
"clinical_notes": "fractured left hand",
"laterality": "left",
"views": "4",
"comparison": "feb 22 2023",
"symptom": "Pain"
}
},
"webhook_version": "1.0"
}Example: Report Processed Event
For more examples of payloads from sign events for mammo studies please see go Mammo Specific Sign Events
{
"event": "report.processed",
"timestamp": "2025-03-17T19:23:32.153561+00:00",
"payload": {
"data": {
"timestamp": 1742239412
},
"user_info": {
"id": 29,
"email": "[email protected]",
"full_name": "User Name",
"role": "radiologist_admin"
},
},
"webhook_version": "1.0"
}Report Recall Webhook Integration
Audience: Integration partners, RIS/PACS vendors, and webhook consumers
Overview
When Report Recall (Oops Factor) is enabled, the publication workflow changes from a single signed event to a two-stage process:
Why This Matters for Your Integration
Report Recall requires webhook integration to function properly. Unlike simpler features that rely solely on the user interface, Report Recall introduces a two-stage publication workflow that your integration must handle correctly.
The Problem with Traditional Integrations
Traditional integrations listen only to the signed event to know when a report is complete. However, with Report Recall enabled:
The signed event fires immediately when the radiologist clicks Sign, but the report is not yet finalized
A countdown timer begins (configurable delay, typically 20–120 seconds)
The report may be recalled and edited during this window
The published event fires only when the timer expires OR the user clicks "Publish Now"
What This Means for You
Your integration must distinguish between:
Reports that are signed but still in the recall window (potentially subject to changes)
Reports that are truly finalized and ready to commit to your RIS/PACS system
Without proper handling, you risk:
Committing reports that are later recalled and modified
Missing user-expedited publications ("Publish Now" button clicks)
Receiving delayed published events for previous reports while working on new ones
Poor user experience (iframe not closing at the right time)
This guide provides two robust integration patterns to handle Report Recall correctly, along with edge case handling, migration guidance, and testing procedures.
Integration Requirements
To properly support Report Recall, your integration should listen to both events:
report.signed
User completed signing
Close iframe, move to next report, update UI
report.published
Report finalized for RIS/PACS
Commit final report to your system, close pending workflows
Report Recall Event Payloads
report.signed Event
Fires immediately when user clicks Sign (any variant: prelim, final, addendum).
{
"event": "report.signed",
"payload": {
"data": {
"sign_context": {
"sign_type": "sign",
"new_status": "signed",
"signed_at": "2025-10-22T15:30:00Z",
"sign_payload": { }
}
},
"user_info": {
"id": 123,
"email": "[email protected]",
"full_name": "Dr. Jane Smith",
"role": "radiologist"
},
"report_info": {
"report_id": 12345,
"accession_number": "ACC123456",
"mrn": "MRN789",
"study_id": "STU456",
"report_status": "signed",
"is_drafting": false,
"metadata": { },
"events": [ ]
}
}
}report.published Event
Fires when report is finalized (either timer expiration or user-expedited).
{
"event": "report.published",
"payload": {
"data": {
"sign_context": {
"sign_type": "sign",
"new_status": "signed",
"signed_at": "2025-10-22T15:30:00Z",
"sign_payload": { }
},
"publish_context": {
"trigger": "timer_expired",
"delay_seconds": 60,
"published_at": "2025-10-22T15:31:00Z"
},
"idempotency_key": "report_12345_sign"
},
"user_info": {
"id": 123,
"email": "[email protected]",
"full_name": "Dr. Jane Smith",
"role": "radiologist"
},
"report_info": {
"report_id": 12345,
"accession_number": "ACC123456",
"mrn": "MRN789",
"study_id": "STU456",
"report_status": "signed",
"is_drafting": false,
"metadata": { }
}
}
}Key Field: publish_context.trigger
This is the critical field for handling Report Recall correctly.
The trigger field indicates why the report was published:
timer_expired
Countdown timer reached zero
⚠️ Verify this is the expected report (check accession_number or report_id) before closing workflows
user_overridden
User clicked "Publish Now"
✅ Safe to immediately close iframe/workflow for this report
recall_disabled
Organization has recall disabled
✅ Treat as immediate publish (no delay occurred)
Why trigger Matters:
Scenario: A radiologist signs Report A, moves to Report B, and then the timer expires for Report A.
Without checking trigger:
Your integration receives published for Report A
Blindly closes the current iframe
User could be kicked out of Report B unexpectedly
With trigger checking:
Receives published with trigger: "timer_expired" for Report A
Checks if Report A is still the active report (via
accession_numberorreport_id)If not, commits to RIS but doesn't close iframe
User continues working on Report B without interruption
Migration Guide
If You Currently Listen to signed Only
Problem: You'll miss user-expedited publications ("Publish Now" button clicks).
Solution:
Add report.published webhook listener
Check trigger field:
user_overridden: Commit to RIS immediatelytimer_expired: Verify it's expected, then commitrecall_disabled: Commit immediately (no delay)
Keep existing signed listener for iframe navigation
Testing Your Integration
Test Scenarios
Normal flow
Sign → wait for timer → observe
published received with trigger: "timer_expired"
Expedited
Sign → click "Publish Now" → observe
published received with trigger: "user_overridden"
Cancelled
Sign → click "Cancel" → observe
publish_cancelled received, no published
Multiple reports
Sign Report A → move to Report B → sign Report B
Correct pairing of events, no race conditions
Recall disabled
Sign with recall disabled org
published fires immediately with trigger: "recall_disabled"
Frequently Asked Questions
User Roles and Statuses
User Roles
When creating users or generating tokens, you can specify a user role that determines what actions they can perform. If not specified, users are assigned the attending_radiologist role by default.
attending_radiologist
Default role with full access to signing reports
resident
Can sign preliminary reports but not final reports
report_drafter_two
Can edit both transcript and final report
report_drafter_one
Can only edit transcript
radiologist_admin
Administrative role with all attending radiologist permissions
To specify a role when creating a user or token, include the user_role parameter:
{
"user_email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"user_role": "resident",
"org_path": ["Clinic West", "Radiology"]
}Role Permissions
Roles follow an inheritance hierarchy where higher-level roles inherit all permissions from lower-level roles:
radiologist_admin
↑
attending_radiologist
↑
resident
↑
report_drafter_two
↑
report_drafter_onereport_drafter_one
Edit transcript
None
report_drafter_two
Edit final report
report_drafter_one
resident
Sign preliminary reports, Sign preliminary addendums
report_drafter_two
attending_radiologist
Sign final reports, Sign addendums
resident
radiologist_admin
Administrative functions
attending_radiologist
Report Statuses
Reports can have the following statuses:
unread
Default status for new reports
draft
Report is in progress
prelim_signed
Report has been signed by a resident
signed
Report has been signed by an attending radiologist
addendum_prelim_signed
Addendum has been signed by a resident
addendum_signed
Addendum has been signed by an attending radiologist
cancelled
Report has been cancelled
approved
Legacy status, equivalent to signed
Clinical Validation Process
Before transitioning from the staging environment to production, all integrations with RADPAIR must undergo a clinical validation process conducted by RADPAIR's internal radiologists and QA specialists. This ensures that the integration meets clinical safety, accuracy, and workflow requirements before being deployed in a live setting.
Purpose of Clinical Validation
Clinical Accuracy: Verify that reports generated through the integration are complete, properly structured, and clinically sound.
Workflow Compliance: Ensure that the integration aligns with expected radiology reporting workflows and does not introduce errors or inefficiencies.
System Integrity: Confirm that data is processed correctly, with no unintended modifications to medical content.
What the Validation Process Involves
Test Cases in Staging RADPAIR's clinical team will generate, review, and process sample reports using your integration.
Detailed QA Review Our radiologists and QA specialists will assess the reports for formatting, accuracy, and compliance with standard reporting practices.
Issue Resolution If any discrepancies or issues are found, RADPAIR will work with you to address them before approval.
Steps to Approval
RADPAIR Conducts Clinical Testing Our team will test your integration using real-world scenarios to ensure it functions correctly.
Validation Report & Feedback You will receive a summary of the validation results, including any necessary adjustments.
Final Sign-Off Once all criteria are met, RADPAIR will approve the transition to the external environment.
This clinical validation is a critical step to ensure that all integrations with RADPAIR maintain the highest standards of accuracy, reliability, and clinical usability.
Miscellaneous
Mammo Specific Sign Events
These are specialized metadata structures extracted during the signing of mammography reports, ultrasound reports with "Breast" in the name, and MRI studies with "Breast" in the name. This section outlines how metadata is extracted, valid options, and example payloads for each study type.
Report Metadata Extraction Rules
Study Type Conditions
The system extracts metadata based on the following study types:
Mammogram (MG)
Ultrasound (US) with "Breast" in the study name (case-insensitive)
MRI (MR) with "Breast" in the study name (case-insensitive)
Metadata Categories
1. Lung Cancer Screening Reports
{
"lung_cancer_screening": {
"lung_rads_category": "<LUNG_RADS_CATEGORY>",
"incomplete_reason": "<INCOMPLETE_REASON>",
"modifier": "<MODIFIER>",
"follow_up_recommendations": "<FOLLOW_UP_RECOMMENDATION>"
}
}Valid Options:
lung_rads_category:"0","1","2","3","4A","4B","4X","0S","1S","2S","3S","4AS","4BS","4XS"incomplete_reason:"Prior comparison needed","Part of lungs cannot be evaluated","Inflammatory or Infectious process"modifier:"N","S"follow_up_recommendations:"1-3 month LDCT","12-month screening","6-month LDCT","3-month LDCT or PET","Referral","Diagnostic CT or PET/Bx"
2. Breast Imaging Mammogram Reports
{
"breast_imaging_mammo": {
"breast_density": "<BREAST_DENSITY>",
"birads_category": "<BIRADS_CATEGORY>",
"follow_up_interval_type": "<FOLLOW_UP_INTERVAL_TYPE>",
"laterality": "<LATERALITY>"
}
}Valid Options:
breast_density:"Fatty","Scattered","Heterogenous","Very Dense"birads_category:"0","1","2","3","4","4A","4B","4C","5","6","Post Procedure"follow_up_interval_type:"12 month","18 month","2 year","3 month","6 month","Addtl Imaging","Age 35-40","Bx","Galactogram","Immediate","No follow-up","US","Diagnostic Priors","US Bx","Stereotactic Bx"laterality:"Bilateral","Left","Right"
3. Breast Imaging MRI Reports
{
"breast_imaging_mri": {
"birads_category": "<BIRADS_CATEGORY>",
"follow_up_interval_type": "<FOLLOW_UP_INTERVAL_TYPE>"
}
}Valid Options:
birads_category:"0","1","2","3","4","4A","4B","4C","5","6"follow_up_interval_type:"Other","Addtl Imaging","Routine MRI","6-month","Surgical","Bx"
4. Breast Imaging Ultrasound Reports
{
"breast_imaging_us": {
"birads_category": "<BIRADS_CATEGORY>"
}
}Valid Options:
birads_category:"0","1","2","3","4","4A","4B","4C","5","6"
Example Payloads
Mammogram Report Example
{
"html_final_report": "...",
"final_report": "...",
"timestamp": 1743796612114,
"exam_specific_data": {
"breast_imaging_mammo": {
"breast_density": "Heterogeneously",
"birads_category": "3",
"follow_up_interval_type": "No follow-up",
"laterality": "Bilateral"
}
}
}Ultrasound Report Example
{
"html_final_report": "...",
"final_report": "...",
"timestamp": 1743796988602,
"exam_specific_data": {
"breast_imaging_us": {
"birads_category": "1"
}
}
}MRI Report Example
{
"html_final_report": "...",
"final_report": "...",
"timestamp": 1743797202435,
"exam_specific_data": {
"breast_imaging_mri": {
"birads_category": "1",
"follow_up_interval_type": "Routine MRI"
}
}
}Draft Report
A pre-generated report draft that will be loaded into the report. If you have a report that you want to drop into RADPAIR you can use this parameter. This bypasses ai layers for extracting metadata and normal processing. This is ideal for if you have a pregenerated report and you want to drop it into the final report box.
{
"accession_number": "string",
"metadata": {
"studyDescription": "string",
"clinical_notes": "string",
"draft_report": "string",
},
}
Legacy Authentication and Endpoints
Creating a Token
Admin Authentication Request: Admins authenticate themselves using their own username and password and send a POST request to RADPAIR to generate an access token for a specific user:
url: https://api.radpair.com/users/orgs/sign_in requestKind: POST headers: basicAuth: type: http scheme: basic description: The admin username and password bodyContentType: JSON bodyProperties: user_email: type: string description: The email of the user for whom the access token is being generated. first_name: type: string description: The user's first name, used during the registration step last_name: type: string description: The user's last name, used during the registration step user_role: type: string description: (Optional) The user's role. Valid values are "attending_radiologist" (default), "resident", "report_drafter_one", "report_drafter_two", or "radiologist_admin". internal_org_id: type: string description: (Optional) This field is not required. However, use it to specify a unique ID (name) for sub-organizations or sub-practices, if applicable. responses: "200": bodyContentType: JSON bodyProperties: access_token: type: string description: the access token used to authenicate a user "400": description: Bad Request - Invalid request format or parameters "401": description: Unauthorized "500": description: Internal Server Error
Admin Authentication Request
POST /users/orgs/sign_in HTTP/1.1 Host: api.radpair.com Authorization: Basic YWRtaW5fdXNlcm5hbWU6YWRtaW5fcGFzc3dvcmQ= Content-Type: application/json { "user_email": "[email protected]", "first_name": "John", "last_name": "Doe", "user_role": "resident", "internal_org_id": "clinic_1" }
Note: YWRtaW5fdXNlcm5hbWU6YWRtaW5fcGFzc3dvcmQ= is just an example, replace with the Base64-encoded string of admin_username:admin_password.
Using the Access Token:
This
access_tokenis essential for authenticating subsequent user sessions and actions.
Creating Report
url: https://api.radpair.com/reports/intgt/create
requestKind: POST
headers:
basicAuth:
type: http
scheme: basic
description: The admin username and password
bodyContentType: JSON
bodyProperties:
metadata:
type: object
description: (Optional)
metadata_source:
type: string
description: (Optional) e.g. name of your org or sub-org.
Note: For best results, please communicate with us what metadata you can provide
and the value of this field in advance so we can process it accordingly.
accession_number:
type: string
description: (Required)
native_id:
type: string
description: (Optional) A flexible identifier that links your system to ours.
Unlike `accession_number`, which is required, `native_id` is optional and can be any string you choose, allowing you to store a unique
reference from your system for easier tracking.
assigning_authority:
type: string
description: (Optional) The assigning authority is a unique name of the system (or organization or agency or department) that creates the data.
order_id:
type: string
description: (Optional) A unique order reference number.
site_id:
type: string
description: (Optional) Identifier for the reporting site or facility.
mrn:
type: string
description: (Optional) MRN is encrypted on our end.
internal_org_id:
type: string
description: (Optional) This field is not required. However, use it to specify a unique ID (name) for sub-organizations or sub-practices, if applicable.
responses:
"200":
bodyContentType: JSON
bodyProperties:
report_id:
type: number
description: the ID for the report created
error:
type: string
description: any errors that occurred during the report creation
description: Report successfully created
"400":
description: Bad Request - Invalid request format or parameters
"401":
description: Unauthorized
"500":
description: Internal Server ErrorReport Ownership Transfer
Reports created via the accession_number are tied to the user that invoked the create_report mentioned above. If there's a need to transfer the ownership of the report, you can invoke the endpoint below:
url: https://api.radpair.com/reports/intgt/transfer-ownership
requestKind: POST
headers:
basicAuth:
type: http
scheme: basic
description: The admin username and password
bodyContentType: JSON
bodyProperties:
accession_number:
type: string
description: (Required)
native_id:
type: string
description: (Optional) A flexible identifier that links your system to ours.
Unlike `accession_number`, which is required, `native_id` is optional and can be any string you choose, allowing you to store a unique
reference from your system for easier tracking.
assigning_authority:
type: string
description: (Optional) TThe assigning authority is a unique name of the system (or organization or agency or department) that creates the data.
order_id:
type: string
description: (Optional) A unique order reference number.
site_id:
type: string
description: (Optional) Identifier for the reporting site or facility.
mrn:
type: string
description: (Optional) MRN is encrypted on our end.
internal_org_id:
type: string
description: (Optional) This field is not required. However, use it to specify a unique ID (name) for sub-organizations or sub-practices, if applicable.
email:
type: string
description: The email address of the new owner. If blank, the report will be reset/transferred back to the admin user.
responses:
"200":
bodyContentType: JSON
bodyProperties:
report_id:
type: number
description: the ID for the report created
error:
type: string
description: any errors that occurred during the report creation
description: Report successfully created
"400":
description: Bad Request - Invalid request format or parameters
"401":
description: Unauthorized
"500":
description: Internal Server ErrorChecking for Access
You can check if a given user has access to a given report using the endpoint below:
url: https://api.radpair.com/reports/intgt/<RADPAIR_REPORT_ID>/can-access
requestKind: POST
headers:
basicAuth:
type: http
scheme: basic
description: The admin username and password
bodyContentType: JSON
bodyProperties:
email:
type: string
description: the user email we want to check report access for
accession_number:
type: string
description: (Required)
native_id:
type: string
description: (Optional) A flexible identifier that links your system to ours.
Unlike `accession_number`, which is required, `native_id` is optional and can be any string you choose, allowing you to store a unique
reference from your system for easier tracking.
assigning_authority:
type: string
description: (Optional) TThe assigning authority is a unique name of the system (or organization or agency or department) that creates the data.
order_id:
type: string
description: (Optional) A unique order reference number.
site_id:
type: string
description: (Optional) Identifier for the reporting site or facility.
mrn:
type: string
description: (Optional) MRN is encrypted on our end.
internal_org_id:
type: string
description: (Optional) This field is not required. However, use it to specify a unique ID (name) for sub-organizations or sub-practices, if applicable.
responses:
"200":
bodyContentType: JSON
bodyProperties:
can_access:
type: boolean
description: whether or not the given user email has access to this report
reason:
type: string
description: if can_access is false, this can provide an explanation when applicable
"400":
description: Bad Request - Invalid request format or parameters
"401":
description: Unauthorized
"500":
description: Internal Server ErrorFeedback & Support
This guide outlines the essential steps for integrating RADPAIR into your application, from initial setup to leveraging the application’s full capabilities. For further assistance or clarification, please contact RADPAIR support.
Last updated
