EHR/EMR-11 min read

CDS Hooks on Epic and Cerner: patient-view, order-select, order-sign

A playbook for CDS Hooks against Epic and Oracle Health (Cerner) — patient-view versus order-select versus order-sign, cards versus suggestions, prefetch, and de-identified fixtures.

Ala Ben Aicha

CDS Hooks on Epic and Cerner: patient-view, order-select, order-sign

Direct answer

patient-view, order-select and order-sign are different workflow points. A card is displayed guidance; a suggestion is an actionable FHIR change. Prefetch is data the EHR may send so the service stays fast.

Hook and card mapping

CDS Hooks is a JSON-over-HTTPS pattern: the EHR (CDS Client) POSTs to {baseUrl}/cds-services/{id} when a named workflow hook fires. Pin the CDS Hooks specification and the hook pages for patient-view, order-select and order-sign. Discovery is GET {baseUrl}/cds-services.

This is not the same article as AI in clinical workflows (model behaviour inside the EHR) or Epic vs Cerner (platform flavour). Both vendors expose CDS Hooks; the hook names and the card schema are the portable contract.

Hook When it fires Required context Typical response
patient-view User opens a patient's chart userId, patientId; encounterId often present Info / warning card, or a SMART link
order-select Clinician selects one or more orders, still draft userId, patientId, selections[], draftOrders Bundle Alternatives, coverage, interaction warnings while details are incomplete
order-sign Clinician is about to sign; last chance before draft leaves draft userId, patientId, full draftOrders Harder guidance; suggestions that create / update / delete draft resources

Card versus suggestion versus link:

Return What it is What it is not
Card summary (<140 chars), indicator (info | warning | critical), source, optional detail markdown Not a write. An empty cards: [] is a valid 200 — “no guidance”
Suggestion Labelled action set the user may accept; actions[] of FHIR create / update / delete Not auto-applied unless you also send systemActions and the EHR opts in. If suggestions exist, selectionBehavior is at-most-one or any
Link URL, optionally type: smart to launch a SMART app Not a substitute for a suggestion when you need a MedicationRequest change in-place
Prefetch Discovery-time FHIR read/search templates, filled by the EHR and POSTed as prefetch Not a guarantee. The client MAY honour zero, some, or all keys

Prefetch tokens are {{context.patientId}} (and other first-level primitive context fields). Example discovery fragment:

{
  "hook": "order-sign",
  "id": "example-pgx",
  "description": "Example pharmacogenomics check on sign (de-identified).",
  "prefetch": {
    "patient": "Patient/{{context.patientId}}",
    "medications": "MedicationRequest?patient={{context.patientId}}"
  }
}

If required data is in neither prefetch nor an authorized fhirServer, the service responds 412 Precondition Failed. Do not stall the EHR for seconds while you paginate the chart.

Identifier traps

Trap Symptom Fix
Treating context.patientId as a Patient URL Prefetch Patient/{{context.patientId}} vs Patient?identifier= confusion Hook context is a FHIR id, not an MRN. Map MRN in prefetch or via FHIR search
Using nested context as a prefetch token {{context.draftOrders.entry.0.resource.id}} is invalid Only first-level primitive context fields; hooks that need an order id expose it as a top-level field
Suggestions without selectionBehavior Client must treat the card as an error Always set at-most-one or any
Returning clinical advice as detail only Clinician never expands “view more” Put the decision in summary; keep detail for evidence
Prefetch from another service on the same hook Over-sharing Clients MUST only send keys this service registered
Oracle Health vs Epic draft resource shapes Suggestion update fails validation Fixture per EHR: same hook name, different MedicationRequest constraints. Do not assume one card JSON writes to both

CDS Hooks is decision support plumbing. It is not a licence to give treatment, dosing, or diagnosis. Model output that changes an order still needs a clinician and, where the software is a medical device, a regulatory owner — see the MDR software guide if that question is open.

Test fixtures

De-identified. The Patient id example-p is not a person.

Discovery (truncated):

{
  "services": [
    {
      "hook": "patient-view",
      "id": "static-patient-greeter",
      "title": "Static example",
      "description": "Returns a static info card.",
      "prefetch": {
        "patientToGreet": "Patient/{{context.patientId}}"
      }
    }
  ]
}

patient-view request (truncated):

{
  "hookInstance": "d1577c69-dfbe-44ad-ba6d-3e05e953b2ea",
  "hook": "patient-view",
  "fhirServer": "https://ehr.example.org/fhir",
  "context": {
    "userId": "Practitioner/example-pract",
    "patientId": "example-p",
    "encounterId": "example-enc"
  },
  "prefetch": {
    "patientToGreet": {
      "resourceType": "Patient",
      "id": "example-p",
      "gender": "female",
      "birthDate": "1977-04-12",
      "active": true
    }
  }
}

Info card (no suggestion):

{
  "cards": [
    {
      "summary": "Example info card — not clinical advice.",
      "indicator": "info",
      "source": { "label": "Example CDS Service" },
      "links": [
        {
          "label": "Open example SMART app",
          "url": "https://app.example.org/launch",
          "type": "smart"
        }
      ]
    }
  ]
}

Suggestion shape on order-sign (resource truncated, not a real medication order):

{
  "cards": [
    {
      "summary": "Example: replace the draft order (fixture).",
      "indicator": "warning",
      "source": { "label": "Example CDS Service" },
      "selectionBehavior": "at-most-one",
      "suggestions": [
        {
          "label": "Apply example update",
          "actions": [
            {
              "type": "update",
              "description": "Update the draft ServiceRequest identifier only.",
              "resource": {
                "resourceType": "ServiceRequest",
                "id": "draft-order-1",
                "status": "draft",
                "intent": "order",
                "subject": { "reference": "Patient/example-p" }
              }
            }
          ]
        }
      ]
    }
  ]
}

Minimum tests:

  1. patient-view with prefetch present — 200, ≤1 info card, latency budget the EHR actually enforces.
  2. patient-view with prefetch key omitted — either 200 with a narrower card or 412; never hang.
  3. order-select with two selections — card talks about the selected drafts only.
  4. order-sign suggestion accepted vs dismissed (feedback API if the EHR sends it).
  5. Same service registered on Epic sandbox and an Oracle Health sandbox — compare draft MedicationRequest required fields.

Failure modes and rollback

Failure Detection Rollback
Slow service Chart open blocked Time out; return cards: []; never block sign on a dead callback
Stale cards order-select cards still showing at sign Clients should drop previous cards from the same id when a new hook fires
Suggestion writes the wrong resource Identifier / id mismatch on update Suggestions MUST send the full updated resource; disable auto-apply (systemActions) until fixtures pass
Token leakage via fhirAuthorization Long-lived bearer in logs Treat the token as transient; EHR should revoke after the hook; do not persist
Dual-EHR JSON assumed portable Production 400 from one vendor Per-EHR schema tests; shared hook names, not shared resource payloads

Turn a dangerous service off at discovery (remove it from {baseUrl}/cds-services) rather than returning critical cards you cannot support. Rollback is: unregister the hook, keep the EHR workflow native, replay nothing — CDS Hooks is advisory unless you opted into systemActions.

Related service

If you need CDS Hooks wired into Oracle Health / Cerner (and the same cards tested against Epic), that is Cerner integration. For a scoped hook spike, use contact with project intent.

This page is not clinical advice, not a CDS Hooks certification, and not an EHR vendor partnership. Empty cards are a successful response.

CDS HooksEpicCernerOracle HealthClinical Decision SupportFHIRprefetchEHR

Related reading and services

Let's Continue the Conversation

Have questions about this topic? I'd love to hear from you.

Get in Touch

🍪 Do you like cookies?

Allow analytics cookies to help understand site visits and enquiries? Optional analytics stays off until you accept.

Learn More