Launch DN Viewer from your teleradiology website.
DN Viewer can be opened from an external webpage using the dnviewer:// protocol. Providers can pass a DICOMweb study directly, or send a short-lived manifest URL when credentials and launch policy should stay server-side.
DN Viewer speaks the full DICOMweb standard — QIDO-RS for study search and WADO-RS for retrieval — and connects to any compliant server: Orthanc, DCM4CHEE, Google Cloud Healthcare API, AWS HealthLake Imaging, and most commercial PACS systems. On-premise deployments on private networks are supported over plain HTTP.
Open one study with a direct URL
Use this format when your web application can safely generate the launch URL and the DICOMweb endpoint is reachable from the workstation.
dnviewer://dicomweb?baseUrl=https%3A%2F%2Fpacs.example.com%2Fdicom-web&studyUid=1.2.840.113619.2.55.3.604688435.781.1712859156.467
Supported query parameters
baseUrl- URL-encoded DICOMweb service root, without/studies.studyUid- StudyInstanceUID to retrieve.providerorlabel- Optional display name shown while loading.replaceWorkspace- Optional. Defaults totrue. Set tofalseto add the study alongside whatever is already open — useful for comparison workflows where the radiologist should keep the prior study visible.
Bearer token example
dnviewer://dicomweb?baseUrl=https%3A%2F%2Fpacs.example.com%2Fdicom-web&studyUid=1.2.840...&auth=bearer&token=SHORT_LIVED_TOKEN
Both token and bearerToken are accepted as the parameter name.
Custom header example
dnviewer://dicomweb?baseUrl=https%3A%2F%2Fpacs.example.com%2Fdicom-web&studyUid=1.2.840...&auth=header&headerName=Authorization&headerValue=Bearer%20SHORT_LIVED_TOKEN
Direct URLs use headerName / headerValue. In a manifest JSON (see below), the same fields are named name / value.
Open a study from a launch manifest
Use a manifest when the provider portal should issue a short-lived launch ticket and keep auth details under server control.
dnviewer://open?manifest=https%3A%2F%2Fprovider.example.com%2Fdnviewer%2Flaunch%2Fabc123
Manifest JSON
{
"type": "dicomweb-study",
"baseUrl": "https://pacs.example.com/dicom-web",
"studyUid": "1.2.840.113619.2.55.3.604688435.781.1712859156.467",
"provider": "Provider Name",
"replaceWorkspace": true,
"auth": {
"type": "bearer",
"token": "short-lived-token"
}
}
Custom header manifest auth
{
"type": "dicomweb-study",
"baseUrl": "https://pacs.example.com/dicom-web",
"studyUid": "1.2.840...",
"auth": {
"type": "header",
"name": "Authorization",
"value": "Bearer short-lived-token"
}
}
Your manifest endpoint must respond with Content-Type: application/json and return the JSON body within 20 seconds. Respond with a non-2xx status to signal an invalid or expired ticket — DN Viewer will surface the HTTP status to the user.
Example launch link
In your provider portal, render a normal link or button. Browsers will ask the user to open DN Viewer when the protocol handler is installed.
<a href="dnviewer://open?manifest=https%3A%2F%2Fprovider.example.com%2Fdnviewer%2Flaunch%2Fabc123">
Open in DN Viewer
</a>
If the app is not installed, show a fallback link to download DN Viewer.
Implementing a manifest endpoint
A manifest is a small JSON document your server generates per launch request. DN Viewer fetches it once, opens the study, then discards it. Your endpoint can stay completely private — the short-lived ticket URL is the only secret that needs to reach the browser.
What DN Viewer does
- User clicks a link in your portal — the browser hands the
dnviewer://open?manifest=…URL to DN Viewer. - DN Viewer issues a plain GET request to the manifest URL with a 20-second timeout. No special request headers are sent — your server just needs to be reachable from the workstation.
- A 2xx response with a valid JSON body opens the study. Any non-2xx response surfaces the HTTP status to the user as an error (use
404for expired or unknown tickets,403for access denied). - DN Viewer retrieves the DICOM study from the
baseUrlusing the auth config in the manifest, then displays it.
Top-level fields
| Field | Description | |
|---|---|---|
baseUrl |
Required | DICOMweb service root. HTTPS required for remote hosts; HTTP allowed for localhost, RFC 1918, and .local names. |
studyUid |
Required | StudyInstanceUID. Must contain only digits and dots. |
type |
Optional | If present, must be "dicomweb-study". Safe to omit. |
provideralias: label |
Optional | Display name shown to the user while the study loads. |
replaceWorkspace |
Optional | Boolean. Default: true. Set to false to add the study alongside whatever the user already has open. |
firstParty |
Optional | Boolean. Default: false. Set to true if you operate the DICOMweb server — enables metadata-first retrieval, which is more efficient than the whole-study multipart fallback used for third-party servers. |
auth |
Optional | Authentication object for the DICOMweb endpoint. Omit entirely for unauthenticated endpoints. See auth fields below. |
Auth fields
| Field | Description | |
|---|---|---|
type |
Required | "none" — no auth (same as omitting the auth object)"bearer" — Authorization: Bearer token"header" — arbitrary custom HTTP header |
tokenalias: bearerToken |
If bearer | The bearer token value. Must be non-empty. |
namealias: headerName |
If header | HTTP header name, e.g. "Authorization". |
valuealias: headerValue |
If header | HTTP header value, e.g. "Bearer short-lived-token". |
Minimal manifest (no auth)
{
"baseUrl": "https://pacs.example.com/dicom-web",
"studyUid": "1.2.840.113619.2.55.3.604688435.781.1712859156.467"
}
Recommended ticket pattern
Your portal generates a short-lived ticket when the user requests a study, stores the launch parameters server-side, and hands the ticket URL to the browser. The manifest endpoint exchanges the ticket for the JSON — once.
# 1. Authenticated portal endpoint — called from your frontend
POST /api/launch/ticket
→ generate ticket_id (cryptographically random, e.g. UUID v4)
→ store { ticket_id, base_url, study_uid, auth_token, expires_at: now + 60s }
→ return { "manifestUrl": "https://yourhost/dnviewer/launch/" + ticket_id }
# 2. Public manifest endpoint — called by DN Viewer from the workstation
GET /dnviewer/launch/:ticket_id
→ look up ticket
→ if not found or expired → 404 Not Found
→ delete ticket ← single-use: prevent replay
→ respond 200 with Content-Type: application/json:
{
"baseUrl": "<stored base_url>",
"studyUid": "<stored study_uid>",
"firstParty": true,
"auth": { "type": "bearer", "token": "<stored auth_token>" }
}
- Use a cryptographically random ticket ID (UUID v4 or equivalent) — never sequential integers.
- Set a short TTL on the ticket — 60 seconds is sufficient; 5 minutes is a reasonable upper bound.
- Delete the ticket after it is fetched (single-use). Reuse opens a replay window.
- The manifest endpoint itself does not need authentication — the unguessable ticket ID is the credential.
- Never embed auth tokens in the
dnviewer://URL directly — it appears in browser history and server access logs. - Keep the manifest TTL short enough that a stolen URL is useless by the time it could be replayed.