CDS Hooks In
Inbound trigger for a CDS Hooks invocation from the EHR — fires when the EHR calls this connection's
invocation URL for the selected hook (patient-view, order-select or
order-sign).
Details
This node registers with the global CDS Hooks Router on deploy. The EHR's request is authenticated by validating its signed JWT against the connection's trusted JWKS URL before this node ever sees it — invalid/unsigned requests are rejected upstream and never reach the flow.
A hook can only be bound to one CDS Hooks In node per connection, workspace-wide (not just within this flow). Already-claimed hooks show disabled in the dropdown above; deploying a second node for an already-claimed hook fails with an error status instead of silently overriding the first.
The Invocation URL field shows the exact URL to give the EHR when registering this CDS Hooks
service — the CDS Hooks spec's standard convention (/api/integrations/<connectionId>/
cds-services/<hookId>), derived from the connection and hook only, never from this flow
or node, so it doesn't change if the node is moved. A spec-compliant client auto-derives this same
URL from discovery; EHRs that need the URL registered by hand are given this exact string.
Outputs
Output 2 — Feedback
Fires when the EHR reports what the clinician did with a card this hook returned (sent to the
Invocation URL + /feedback). msg.payload.feedback is an array of
{ card, outcome: "accepted" | "overridden", outcomeTimestamp, acceptedSuggestions?, overrideReasons? },
where card is the card's uuid. Don't wire it to a CDS Hooks Response node — the EHR
has already been answered. overrideReasons.userComment is free text and may contain PHI.
Typical Flow
┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐
│ CDS Hooks In │──▶│ Your Logic │──▶│ CDS Hooks Response │
└──────────────┘ └──────────────┘ └──────────────────────┘
Best Practices
- Always wire a CDS Hooks Response node at the end — even to return an empty card list.
- Keep flow logic fast — the EHR expects a synchronous reply; a flow that takes longer than 8 seconds gets an empty response sent on its behalf.
- Never log
payload.context/payload.prefetchdirectly — they may contain PHI. Use ids/references in debug/audit output, not full resource content. - Never log or forward
payload.fhirAuthorization— it is a live EHR access token. - Prefer
payload.prefetchover a FHIR call; fall back tofhirServer+fhirAuthorization(or the connection's own FHIR Request node) only when a key is missing.