TTA Workflow
Version 0.6
Introduction
This Technical Agreement (TA) specifies a standards-based mechanism for exchanging clinical workflow status — referrals, orders, and transfers — between a Placer and a Fulfiller. It is built on COW IG and TTA Notifications, and brings existing, separately-developed Dutch agreements for this same problem together under a single, shared specification.
Context
Dutch healthcare organizations already exchange referrals, orders, and transfers between systems today, but they do so using at least two separately developed, incompatible mechanisms, and neither fully supports exchanging the status of that work once it is underway. The Technical Agreement Exchanging FHIR Data using a generic Notified Pull mechanism (TA NP) specifies one such mechanism, built for the exchange of the BgZ during a patient referral. The Nuts eOverdracht Bolt specifies another, built independently, on a similar timeline, for the nursing handoff referral.
Two national specifications, developed independently for closely related problems, cannot both remain the reference every new implementer is pointed to — harmonizing them is worthwhile. Doing so depends on two things being settled at the technical level:
-
TTA Notifications specifies the standardized Subscription and notification mechanism by which a party learns that a resource it does not own has changed.
-
The forthcoming TA I&A&A specifies how the parties to an exchange identify, authenticate, and authorize one another.
Together, these give a harmonized specification the technical building blocks that neither TA NP nor eOverdracht had available when each defined its own mechanism.
These two agreements are not enough on their own. TA NP and eOverdracht each model the clinical workflow itself in its own way: a system built to one specification still cannot exchange a referral with a system built to the other, and a healthcare organization operating across both domains still needs two separate implementations to do what is, underneath, the same kind of work. Left alone, this divergence would only widen as each specification continues to evolve independently. Harmonizing the workflow model itself — not just the transport it travels over — is what allows an organization to build and maintain one implementation instead of two.
It also does something neither original specification could, precisely because each was written for one use case at a time: a harmonized model is general enough that referral, order, and transfer are simply particular instances of it, so that the next use case this ecosystem needs is described as a profile of something that already exists, rather than specified again from first principles.
This Technical Agreement is that model. It specifies, in one place, a standards-based way to exchange clinical workflow status for orders, referrals, and transfers, so that the agreements currently expressed via TA NP and via eOverdracht can each be specified and implemented as a profile of it.
Scope
In scope
-
Exchanging clinical workflow status between a Placer and a Fulfiller.
-
Hosting, creating, and updating a Coordination Task at the Placer, and the FHIR profile constraining it.
-
The standing Subscription and notification mechanism informing a Fulfiller of relevant Task changes.
-
The Multiple Fulfillers pattern, and the simpler case of a single, already-known Fulfiller.
-
Conformance to TA Routing.
-
Conformance to GF Addressing, independently of TA Routing.
Out of scope
-
Identification, authentication, and authorization of the parties — the subject of the forthcoming TA I&A&A.
-
How a Placer decides which candidate to select among multiple Fulfillers.
-
The placement of patient-identifying information on the Coordination Task (see Open Questions).
-
Which notification payload mode applies (see Subscription).
-
Sharing content beyond the standard dataset (see Open Questions).
Vocabulary
|
Term |
Definition |
|---|---|
|
Placer |
The party that authorizes and initiates a Request. |
|
Fulfiller |
The party expected to carry out the Request. |
|
Request |
The FHIR resource representing what is being asked for (e.g. ServiceRequest). |
|
Standard dataset |
The baseline set of information a referral requires, as identified by the Request (see Resource Definitions → Request). |
|
Coordination Task |
The Task profile tracking one Fulfiller's progress against one Request. |
|
Cancellation Request Task |
The Task profile used to request cancellation of a Coordination Task. |
|
Notified Pull |
Delivery via notification, followed by the Fulfiller retrieving the Task itself. |
|
Direct Write |
A Fulfiller's authenticated write to the Placer-hosted Coordination Task, observed synchronously by the Placer. |
|
HealthcareService |
The FHIR resource Task.owner resolves to, per TA Routing. |
|
Location |
The FHIR resource Task.location resolves to, per TA Routing. |
Base Specifications
|
Specification |
Role |
|---|---|
|
COW IG |
Base resource and workflow model. |
|
TTA Notifications |
Base notification mechanism. |
|
TA Routing |
Conformance target: internal routing of a referral once received. |
|
GF Addressing (forthcoming) (no canonical URL available) |
Conformance target: registration and discovery of HealthcareService/Location. In scope independently of TA Routing. |
|
TA I&A&A (forthcoming) (no canonical URL available) |
Out of scope of this TA; covers identification, authentication, authorization. |
|
TA NP |
Evidence for design choices (e.g. Task at Placer); not a base specification. |
|
eOverdracht (no canonical URL available) |
Evidence for design choices (e.g. Multiple Fulfillers); not a base specification. |
Relationship to COW IG
COW IG was chosen as the base resource and workflow model for four reasons: it is generic enough to cover order, referral, and transfer workflows alike, rather than one at a time; complete enough that this TA needs no invented extension to address the core problem; pitched at the right level of detail to be profiled rather than rebuilt; and an international standard, keeping this TA aligned with an ecosystem wider than the Netherlands alone.
COW IG cannot serve as a technical agreement on its own. Its generality is deliberate: it leaves open many of the choices two systems must agree on to actually interoperate, and implementers left free to make those choices differently produce systems that are each individually COW-conformant yet unable to exchange anything with one another.
This TA is a profile of COW IG, not an extension of it. It makes binding choices among the options COW IG already permits — which hosting pattern applies, which values Task.code takes, how cancellation is realized — so that independently-built systems converge on one behavior. It does not add resource types, elements, or mechanisms beyond what COW IG itself defines. Where this TA is silent, COW IG's own guidance applies unmodified.
Design Choices
This section states, for each major choice this TA makes within COW IG's model, why it was made this way rather than left to individual implementers.
-
Task at Placer, not Task at Fulfiller. COW IG names two patterns for where the Coordination Task is hosted. This TA fixes the Placer. TA NP's own persistent, status-bearing resource (the Workflow Task) is already hosted at the Sending System — the Placer, in COW IG's terms — eOverdracht's Task is likewise hosted at the bronhouder, for the same reason its own specification gives: keeping data at the source. Both existing agreements, developed independently of each other and of COW IG, already converge on this hosting choice.
-
The Multiple Fulfillers pattern is adopted, not only the simpler single-performer case. eOverdracht already supports offering one patient to several candidate organizations in parallel; a harmonized specification should not drop that capability simply because it is now expressed in COW IG's own terms. Beyond that precedent, the same mechanism is worth having available generally: a genuine negotiation before a referral is finalized can be useful even with exactly one Fulfiller under consideration, though many single-Fulfiller referrals need no negotiation at all (see Single Fulfiller Pattern).
-
Task.owner and Task.location resolve to HealthcareService and Location, not Organization. This follows TA Routing, which itself exists because addressing a notification at the level of a healthcare organization is not granular enough for the people who must act on it. Filtering the Subscription at the same granularity (see Subscription) keeps the notification layer consistent with what the Task already expresses, and lets a Fulfiller with multiple healthcare services register one narrowly-scoped Subscription per service rather than one for the whole organization.
-
The SubscriptionTopic triggers on create and update, not create alone. eOverdracht notifies on every Task change without exception, and TA NP's own mechanisms for both dataset updates and cancellation are update-triggered, not creation events. A topic that only covered create could not be specified as a profile of either.
-
Task.groupIdentifier is not used. TA NP and eOverdracht each assign it a different, incompatible meaning. Since Task.focus is mandatory in this TA's profile, Coordination Tasks competing for the same Request are already identifiable by that shared reference; a second, conflicting correlation field would be redundant as well as incompatible.
Actors
Placer
The Placer:
-
SHALL create the Request, hosted on its own FHIR server. (COW IG)
-
SHALL create the Coordination Task on its own FHIR server, referencing the Request. (this TA — COW IG permits either hosting pattern; see Design Choices)
-
SHALL establish a standing, out-of-band Subscription with each Fulfiller relationship (see Subscription). (TTA Notifications, mechanism; this TA, requiring it)
-
SHALL grant the Fulfiller write access to the Coordination Task on which it is Task.owner. (this TA)
-
SHALL act on Request.status when the Coordination Task reaches completed. (COW IG)
Fulfiller
The Fulfiller:
-
SHALL authenticate to the Placer on every read or write of the Coordination Task. (this TA)
-
SHALL update Task.status, Task.businessStatus, and Task.output directly, as a Direct Write. (COW IG, elements; this TA, the Direct Write pattern)
-
SHALL accept or reject a Cancellation Request Task. (COW IG)
-
MAY reject the Coordination Task with a statusReason. (COW IG)
Resource Definitions
Request
The standard dataset for a referral is the baseline set of information a Fulfiller needs to carry it out — what would otherwise have to be negotiated case by case. This TA has the Request identify it directly, rather than leaving it to be inferred or agreed separately.
-
A Request resource SHALL exist for every Coordination Task. (COW IG)
-
ServiceRequest.code SHALL identify the standard dataset for the referral. (this TA)
-
ServiceRequest.instantiatesCanonical MAY additionally reference an ActivityDefinition or a PlanDefinition, where a bare code is not precise enough. A PlanDefinition is a composite of ActivityDefinitions; the same rules apply to both. (TA Routing)
-
Where a directory defines an ActivityDefinition or PlanDefinition for a service, a receiving server MAY decline a Request that does not reference it via instantiatesCanonical, or that does not adhere to its requirements. (TA Routing)
-
ServiceRequest.performer SHALL remain unset while more than one Fulfiller is under consideration (see Multiple Fulfillers Pattern). (COW IG)
Coordination Task
A Coordination Task:
-
MUST be created by the Placer, on its own FHIR server, via create. (this TA)
-
Task.identifier MUST be present (min 1). (COW IG)
-
Task.focus MUST be present (min 1) and reference the Request. (COW IG)
-
Task.code MUST be present (min 1) (COW IG, the requirement; this TA, the two values):
-
request-fulfillment — while more than one candidate Fulfiller is under consideration;
-
fulfill — otherwise, including once a candidate has been selected.
-
-
Task.status MUST NOT be constrained beyond the full base FHIR Task state machine (draft, requested, received, accepted, rejected, ready, cancelled, in-progress, on-hold, failed, completed, entered-in-error). At creation, Task.status MUST be requested. (COW IG leaves the range unconstrained; this TA declines to narrow it further)
-
Task.businessStatus SHOULD be populated whenever more specific progress information is known, bound to COW IG's business-status ValueSet at example strength. selected MAY additionally be used, per COW IG's own worked example, though it is not among the five codes currently published in that ValueSet. (COW IG)
-
Task.requester MUST identify the Placer. (this TA)
-
Task.owner MUST identify the Fulfiller, resolving to a HealthcareService — TA Routing's own profile of the base FHIR R4 resource (required .providedBy, value-set-bound .type, an extension for supported ActivityDefinitions) — not merely an Organization. (COW IG requires Task.owner; TA Routing requires the HealthcareService resolution)
-
Task.location SHOULD be supported, resolving to a Location conforming to the existing Dutch HCIM-based profile (not separately profiled by TA Routing). (TA Routing)
-
Task.output SHOULD be supported, for the Fulfiller to record the result of its work. (COW IG)
-
Task.statusReason SHOULD be populated whenever Task.status moves to rejected or cancelled, as a CodeableConcept. (COW IG — inherited from base FHIR Task)
-
not selected MUST be used when cancelling a non-selected candidate in the Multiple Fulfillers Pattern (see Multiple Fulfillers Pattern). (this TA)
-
-
Task.groupIdentifier MUST NOT be used. Because Task.focus is mandatory, Coordination Tasks competing for the same Request are already identifiable by that shared reference. (this TA)
-
Task.for is not specified by this TA. Whether and how it should identify the patient is open — see Open Questions → Patient Identification. (this TA, unresolved)
Write access:
-
The Fulfiller MUST authenticate on every read or write; access is verified per interaction. (this TA)
-
The Placer MUST grant the Fulfiller write access, scoped to Coordination Task(s) on which it is Task.owner, to update status, businessStatus, output, and other progress-reflecting elements. (this TA)
-
focus, requester, and owner MUST NOT be writable by the Fulfiller: the Placer sets these once, at creation. (this TA)
Cancellation Request Task
A Cancellation Request Task:
-
MUST be created by the Placer, on its own FHIR server, when Task.status has already reached in-progress on the Coordination Task it targets. (COW IG)
-
Task.status MUST be requested at creation. (COW IG)
-
Task.code MUST be abort. (COW IG)
-
Task.focus MUST reference the Coordination Task being cancelled. (COW IG)
-
Task.status MUST be updated to accepted or rejected by the Fulfiller, as a Direct Write. (COW IG)
-
The Fulfiller MAY additionally update the Coordination Task's own status to cancelled. (COW IG)
SubscriptionTopic
A SubscriptionTopic under this TA:
-
SubscriptionTopic.url MUST be
https://landelijkafsprakenstelsel.nl/fhir/SubscriptionTopic/zorgaanbieder-verwijzing. (this TA) -
SubscriptionTopic.resource and resourceTrigger.resource MUST both be Task. (this TA, the choice of resource type; TTA Notifications, the requirement that a topic name exactly one)
-
resourceTrigger.supportedInteraction MUST include create and update. create alone is not sufficient: both TA NP and eOverdracht rely on update-triggered notifications (dataset updates, cancellation), so this topic must support both to be specifiable as a profile of either. (this TA)
-
canFilterBy MUST include Task.owner. (this TA)
-
queryCriteria MAY further narrow the topic per workflow type. (TTA Notifications)
Because a Subscription fires on any matching interaction regardless of who performed it, including update means the Fulfiller is also notified of its own Direct Writes to the Coordination Task — the same self-notification behaviour eOverdracht itself exhibits. A Fulfiller MAY disregard a notification it recognizes as reporting its own prior write. (this TA)
Subscription
A Subscription under this TA:
-
MUST be established out-of-band: because the Fulfiller does not create the Coordination Task, it has no Task identifier to filter on at the point an in-band Subscription would otherwise be created. (TTA Notifications, the out-of-band mechanism; this TA, requiring it here)
-
MUST be established once, as part of onboarding a Placer–Fulfiller relationship — not per Task — filtered broadly to the Fulfiller as a whole, and remain in place across every subsequently created Task. (this TA)
-
MUST be created by the Placer, as Subscription Server, on its own server, addressed to the Fulfiller's notification endpoint. How that endpoint is discovered is the responsibility of GF Addressing. (this TA, placer-as-server; GF Addressing, endpoint discovery)
-
Subscription.criteria MUST carry the SubscriptionTopic canonical, via extension backport-topic-canonical. (TTA Notifications)
-
Extension backport-filter-criteria MUST carry
Task?owner=HealthcareService/{id}— notOrganization/{id}— matching the granularity Task.owner already requires (Resource Definitions → Coordination Task), and TA Routing's own premise that organization-level addressing is not sufficient. (TTA Notifications, the extension; this TA, the filter value) -
channel.type MUST be rest-hook. (TTA Notifications)
-
channel.payload MUST be application/fhir+json, with extension backport-payload-content set to the agreed payload mode (empty, id-only, or full-resource). Which mode applies is not yet fixed by this TA. (TTA Notifications)
Transactions
Task Creation
-
Trigger: the Placer has authorized a Request and identified one or more candidate Fulfillers.
-
Exchange: POST on the Placer's own Task endpoint (Resource Definitions → Coordination Task).
-
Rules: delivered as Notified Pull, via the standing Subscription (Resource Definitions → Subscription). (this TA)
Task Update by Fulfiller
-
Trigger: the Fulfiller updates Task.status, Task.businessStatus, Task.output, or any other progress-reflecting element.
-
Exchange: PUT/PATCH by the Fulfiller on the Placer-hosted Coordination Task.
-
Rules: Direct Write; covers every such change over the Request's lifecycle. (this TA)
Task Update by Placer
-
Trigger: the Placer updates an element of the Coordination Task on its own initiative — for example, cancelling it before in-progress (see Cancellation, below) by setting Task.status, or updating any other element.
-
Exchange: local PUT/PATCH by the Placer on its own Coordination Task.
-
Rules: delivered as Notified Pull: the Fulfiller did not make this change itself and has no synchronous way to observe it. (this TA)
Multiple Fulfillers Pattern
A Placer facing more than one reasonable candidate solicits several at once, lets each respond, and commits to one, without having authorized the Request to any other in the meantime. (COW IG, the pattern; eOverdracht, its adoption here — see Design Choices)
-
One Request MUST be shared by every candidate under consideration. (COW IG)
-
One Coordination Task MUST be created per candidate, each referencing the same Request via Task.focus. (COW IG)
-
ServiceRequest.performer MUST remain unset while solicitation is open. (COW IG)
-
Each candidate MAY accept, by updating its own Task.status to accepted, as a Task Update by Fulfiller (see Transactions). Acceptance does not imply selection. (COW IG)
-
When a candidate is chosen, the Placer MUST set that candidate's Task.businessStatus to selected, and MUST set every other candidate's Task.status to cancelled with statusReason set to not selected. (COW IG)
-
ServiceRequest.performer MAY be set to the selected candidate once chosen; Task.owner on the selected Task remains authoritative regardless. (COW IG)
How the Placer decides which candidate to select is out of scope of this TA. This TA specifies only how the decision is recorded and communicated once made.
Nothing in this pattern gives a candidate Fulfiller a way to learn, from its own Task alone, that it is one of several under consideration. Whether a not-yet-selected candidate may access the shared Request's content is an access-control question, out of scope of this TA.
Nothing in this pattern depends on the referral use case that motivated it: the same structure applies to any workflow type this TA covers, wherever a Placer might solicit more than one Fulfiller for the same piece of work.
Single Fulfiller Pattern
Where a Placer already knows, at the moment the Request is authorized, which single Fulfiller should carry out the work, the Multiple Fulfillers Pattern does not apply. (this TA)
-
Task.code MUST be fulfill from creation. (this TA)
-
Task.owner MUST identify the one Fulfiller directly. (COW IG)
-
accepted MUST NOT be used: the Fulfiller MAY move directly from requested to in-progress. (this TA)
-
Declining is likewise direct: the Fulfiller MAY move Task.status from requested straight to rejected, with statusReason. (this TA)
This pattern applies only where the Placer and the sole Fulfiller have nothing to negotiate. Where negotiation is wanted — a proposed timing, a different scope, a request for more information — even with only one candidate, the Multiple Fulfillers Pattern applies instead, treating the referral as a solicitation of exactly one.
Cancellation (Before in-progress)
An instance of Task Update by Placer, above, specifically setting Task.status to cancelled.
-
Trigger: the Placer wishes to withdraw the Request; Task.status has not reached in-progress.
-
Exchange: local PUT/PATCH by the Placer on its own Coordination Task, status → cancelled.
-
Rules: delivered as Notified Pull; requires no cross-organization write access. (COW IG, the cancellation mechanism; this TA, the notification)
Cancellation Request (After in-progress)
-
Trigger: the Placer wishes to withdraw the Request; Task.status has reached in-progress.
-
Exchange: POST by the Placer, on its own server, creating a Cancellation Request Task.
-
Rules: delivered as Notified Pull. (COW IG, the mechanism; this TA, the notification)
Cancellation Request Response
-
Trigger: the Fulfiller has read a Cancellation Request Task.
-
Exchange: PUT/PATCH by the Fulfiller, updating the Cancellation Request Task's status, and optionally the Coordination Task's own status.
-
Rules: Direct Write. (COW IG)
Open Questions
Patient Identification
Whether this TA should specify how the patient is identified on the Coordination Task at all is open.
-
If specified: Task.for.identifier SHALL carry the patient's BSN. It is NOT required while Task.status is requested or accepted. It MUST be populated no later than the point Task.status reaches in-progress. (this TA, proposed, unresolved)
-
Since the Fulfiller, not the Placer, drives the transition to in-progress (Task Update by Fulfiller), the Placer MUST add Task.for.identifier, if not already present, as part of processing that same write — atomically, within the same operation the Fulfiller's status update triggers, not as a separate round trip. (this TA, proposed, unresolved)
Sharing Additional Content
Whether and how to share content beyond the standard dataset (Resource Definitions → Request) is open.
-
Task.input is not the right fit: COW IG associates it with fulfillment-relevant content specifically, and using it for arbitrary extra content would conflate it with the standard dataset the Request already determines.
-
If specified, it should be through new properties added to the Coordination Task profile, rather than repurposing an existing COW IG element. Specifying it at the Task level keeps it inside the existing Notified Pull mechanism: any new property, populated via update, reaches the Fulfiller through the SubscriptionTopic already defined, without further mechanism. (this TA, proposed, unresolved)