SMART on FHIR

Updating Data

Note: Opala’s publicly documented APIs are read-only. The guidance and examples on this page describe standard FHIR behavior on a Firely-based server for reference. Write operations and administrative server behaviors are not available on public endpoints.

Patching Data

Important! Patching requires write permissions in the target environment and resources. Opala’s public APIs do not expose write operations. This information is for-reference only.

Often you want to make a small change to a resource without needing to re-upload the entire content. For example, a resource status field might be changed by an app with no other changes needed.

This type of scenario is a good candidate for the FHIR patch operation. Opala supports three syntaxes for patching:

  • FHIR Patch: This is the most expressive syntax for patching and is recommended for use unless you have a specific reason to need one of the other options. It uses a format described in the FHIR specification as FHIR Patch.
  • JSON Patch: This syntax expresses a changeset in JSON using RFC 6902.
  • XML Patch: This syntax expresses a changeset in XML using RFC 5261.

Availability of JSON Patch and XML Patch is environment-dependent; FHIR Patch is the recommended and most portable option on Firely-based servers.

Patch Using FHIR Patch

The FHIR Patch format is very powerful and can be used to specify very precise rules for inserting, modifying, and removing data from FHIR resources. See FHIR Patch for details about the format.

In FHIR environments that expose it, the $diff operation (see Reading Data in this documentation set) can be used to generate patches, which can be helpful when trying to design a patch for a specific scenario.

The following example shows a FHIR Patch being used to update a Patient status:

PATCH https://{baseurl}/Patient/123
Content-Type: application/fhir+json
                        
{
    "resourceType": "Parameters",
    "parameter": [
	{
	    "name": "operation",
	    "part": [
		{ "name": "type", "valueCode": "replace" },
		{ "name": "path", "valueString": "Patient.birthDate" },
		{ "name": "value", "valueDate": "1930-01-01" }
	    ]
	}
    ]
}

Patch Using FHIR Patch (Transaction)

A FHIR Patch may also be submitted as a part of a FHIR transaction.

{
    "resourceType": "Bundle",
    "type": "transaction",
    "entry": [
	{
	    "request": { "method": "PATCH", "url": "Patient/123" },
	    "resource": {
		"resourceType": "Parameters",
		"parameter": [
			{
			    "name": "operation",
			    "part": [
				"name": "type", "valueCode": "replace" },
				"name": "path", "valueString": "Patient.birthDate" },
				"name": "value", "valueDate": "1930-01-01" }
			    ]
			}
		    ]
		}
	   }
    ]
}

Patch Using JSONPatch

Note: JSON Patch support (application/json-patch+json) may be disabled in some environments; check the server CapabilityStatement..

The following example shows a JSONPatch being used to update an Observation status:

PATCH Observation/123
Content-Type: application/json-patch+json
                            
    [
        {"op": "replace", "path": "/status", "value": "in-progress"}
    ]

Patch Using JSONPatch (Transaction)

Reference-only: Some servers wrap a JSON Patch payload in a Binary within a transaction.

A JSONPatch may also be submitted as a part of a FHIR transaction using a Binary resource as the payload in order to hold the contents.

{
    "resourceType": "Bundle",
    "type": "transaction",
    "entry": [
	{
	    "request": { "method": "PATCH", "url": "Patient/1" },
	    "resource": {
		"resourceType": "Binary",
		"contentType": "application/json-patch+json",
		"data":
	         "WyB7ICJvcCI6InJlcGxhY2UiLCAicGF0aCI6Ii9hY3RpdmUiLCAidmFsdWUiOmZhbHNlIH0gXQ=="
			}
		}
	]
}
Note: Opala’s publicly documented APIs are read-only. The guidance and examples on this page describe standard FHIR behavior on a Firely-based server for reference. Write operations and administrative server behaviors are not available on public endpoints.

Tag Retention

According to the FHIR rules on updating resources, by default when a resource is updated, any tags and security labels will be carried forward even if they are not explicitly listed in the new version.

FHIR Meta Snapshot Mode Example

For example, suppose a resource is created by a client, and in that resource a tag "foo" is listed in Resource.meta.tag. Then an update is performed by a client but this update does not contain a value in Resource.meta.

According to the FHIR rules, in this case the tag will be copied to the new version of the resource even though it was not explicitly requested. This is consistent with how tags are expected to be used.

If you want to override this behavior, use the X-Meta-Snapshot-Mode header. This header indicates that Tags and/or Security Labels and/or Profile Declarations should be treated as snapshots — meaning that any values not already present should be removed.

Snapshot headers such as X-Meta-Snapshot-Mode are not used in Opala’s Firely-based environments. To remove or add tags/security labels/profiles, edit meta explicitly in your PUT/PATCH.

An example of removing a tag via FHIR Patch is shown below:

{
    "resourceType": "Parameters",
    "parameter": [
	{
	    "name": "operation",
	    "part": [
		{ "name": "type", "valueCode": "delete" },
		{ "name": "path", "valueString":
		    "Patient.meta.tag[system='https://example.org/tags' and code='foo']" }
			]
		}
	]
}

Concurrent Write Errors

If a server is serving multiple concurrent requests against the same resource, an HTTP 409 Version Conflict may be returned to the client. For example, if two client requests attempt to update the same resource at the exact same time, this error will be returned for one of the requests. This error is not a bug in the server itself, but instead is a defense against client updates accidentally being lost because of concurrency issues. When this occurs, it is important to consider what the root cause might be since concurrent writes against the same resource are often indicative of a deeper application design issue.

Use HTTP ETags with If-Match to prevent lost updates.

Example:

PUT https://{baseurl}/Patient/123
If-Match: W/"3"
Content-Type: application/fhir+json

{
	"resourceType": "Patient",
	"id": "123",
	"meta": { "versionId": "3" },
	"name": [ { "family": "Smith" } ]
}