Unmerge operation
The $unmerge operation reverses a previous $merge by executing a
client-provided FHIR transaction Bundle. The client decides exactly how to
restore resources; MDMbox validates the referenced merge Task, adds audit
resources, flips the original merge Task to unmerged, and executes everything
atomically.
Use $unmerge when a merge was accepted by mistake and the affected resources
must be restored or reassigned.
How it works
- The client finds the original merge
Task. - The client reads the merge audit trail, usually the
Provenancereferenced byTask.relevantHistory, and builds a reverse transaction Bundle. - The client calls
$unmergewith the merge Task reference and the reverse plan. - MDMbox adds an unmerge
Task, addsProvenance, updates the original merge Task tobusinessStatus=unmerged, and executes the Bundle as one transaction. - If anything fails, the entire transaction rolls back, including audit records and the merge Task status update.
Request
POST https://<mdmbox-host>/api/fhir/$unmerge
Content-Type: application/json
{
"resourceType": "Parameters",
"parameter": [
{"name": "task", "valueReference": {"reference": "Task/merge-task-123"}},
{"name": "preview", "valueBoolean": false},
{
"name": "plan",
"resource": {
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"request": {"method": "PUT", "url": "Patient/primary-456", "ifMatch": "W/\"4\""},
"resource": {
"resourceType": "Patient",
"id": "primary-456",
"name": [{"given": ["John"], "family": "Smith"}]
}
},
{
"request": {"method": "PUT", "url": "Patient/duplicate-123"},
"resource": {
"resourceType": "Patient",
"id": "duplicate-123",
"name": [{"given": ["Jon"], "family": "Smyth"}]
}
},
{
"request": {"method": "PUT", "url": "Encounter/enc-789", "ifMatch": "W/\"2\""},
"resource": {
"resourceType": "Encounter",
"id": "enc-789",
"subject": {"reference": "Patient/duplicate-123"}
}
}
]
}
}
]
}
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
task | valueReference | Yes | Reference to the original merge Task |
preview | valueBoolean | No | If true, return the assembled Bundle without executing (default: false) |
plan | resource (Bundle) | Yes | FHIR transaction Bundle with the reverse changes |
Plan Bundle
The plan is a standard FHIR transaction Bundle. It commonly contains:
PUTentries that restore the target and related resources to the desired post-unmerge statePUTentries that recreate resources deleted by the mergePUTentries that reassign related resources back to the restored source- optional
POSTorDELETEentries if the client policy requires them
Allowed plan methods are PUT, POST, and DELETE. The plan must not contain
duplicate PUT or DELETE URLs.
Use ifMatch for optimistic locking when updating live resources. If a resource
changed after the client built the reverse plan, the FHIR transaction rolls back
and $unmerge returns 422 Unprocessable Entity with an OperationOutcome
code such as conflict.
Preview mode
Set preview to true to validate the request and inspect the assembled
transaction without writing anything:
{
"resourceType": "Parameters",
"parameter": [
{"name": "task", "valueReference": {"reference": "Task/merge-task-123"}},
{"name": "preview", "valueBoolean": true},
{
"name": "plan",
"resource": {
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{"request": {"method": "PUT", "url": "Patient/duplicate-123"}}
]
}
}
]
}
Preview response:
{
"resourceType": "Parameters",
"parameter": [
{
"name": "outcome",
"resource": {
"resourceType": "OperationOutcome",
"issue": [{"severity": "information", "code": "informational"}]
}
},
{
"name": "bundle",
"resource": {
"resourceType": "Bundle",
"type": "transaction",
"entry": ["... assembled entries including audit resources ..."]
}
}
]
}
Response
On success, the response is a Parameters resource containing:
{
"resourceType": "Parameters",
"parameter": [
{
"name": "outcome",
"resource": {
"resourceType": "OperationOutcome",
"issue": [{"severity": "information", "code": "informational"}]
}
},
{
"name": "input-parameters",
"resource": {
"resourceType": "Parameters",
"parameter": [
{"name": "task", "valueReference": {"reference": "Task/merge-task-123"}},
{"name": "preview", "valueBoolean": false}
]
}
},
{
"name": "task",
"resource": {
"resourceType": "Task",
"id": "generated-unmerge-task-id",
"status": "completed",
"intent": "order",
"code": {"coding": [{"code": "unmerge"}]},
"businessStatus": {"coding": [{"code": "completed"}]},
"basedOn": [{"reference": "Task/merge-task-123"}]
}
}
]
}
The input-parameters echo omits the potentially large plan parameter.
Audit trail
Every executed unmerge creates or updates these resources in the same transaction:
Unmerge Task
code-unmergebusinessStatus-completedbasedOn- the original merge Taskforandfocus- copied from the original merge Task when present
Original merge Task
businessStatuschanges frommergedtounmerged- updated with
ifMatchusing the Task version read during validation
Provenance
activity-unmergefromhttp://terminology.hl7.org/CodeSystem/iso-21089-lifecycletarget- every reverse-plan target plus the unmerge Taskentity[]- versioned references to pre-unmerge revisions when availableagent-Device/mdmbox
After a successful unmerge, the original source can be merged again because the previous merge Task is no longer active.
Validation
MDMbox validates the unmerge request before execution:
Structural validation (400 Bad Request):
- Request body must be a FHIR
Parametersresource taskis requiredplanmust be a transaction Bundle with at least one entry- Plan methods must be
PUT,POST, orDELETE - No duplicate
PUTorDELETEURLs in the plan
State validation (422 Unprocessable Entity):
- The referenced Task must exist
- The Task must be a merge Task (
code=merge) - The merge Task must still be active (
businessStatus=merged)
FHIR transaction validation (422 or 500):
- If any transaction entry fails validation or optimistic locking, the whole transaction rolls back
- Client-side transaction failures return
422with anOperationOutcome - Server-side transaction failures return
500