

# Managing FHIR resources in AWS HealthLake
<a name="managing-fhir-resources"></a>

Use FHIR R4 RESTful API interactions to manage FHIR resources in a HealthLake data store. The following sections describe all HealthLake-supported FHIR R4 RESTful API interactions available for FHIR resource management. For information about HealthLake data store capabilities and which portions of the FHIR specification it supports, see [FHIR R4 Capability Statement for AWS HealthLake](reference-fhir-capability-statement.md).

**Note**  
The FHIR interactions listed in this chapter are built in conformance to the HL7 FHIR R4 standard for health care data exchange. Because they are representations of HL7 FHIR services, they are not offered through AWS CLI and AWS SDKs. For more information, see [RESTful API](https://hl7.org/fhir/R4/http.html) in the **FHIR R4 RESTful API documentation**.

The following table lists FHIR R4 interactions supported by AWS HealthLake. For information about FHIR *resource types* supported by HealthLake, see [Resource types](reference-fhir-resource-types.md).




**FHIR R4 interactions supported by AWS HealthLake**  
<a name="supported-fhir-interactions"></a>[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/healthlake/latest/devguide/managing-fhir-resources.html)

**Topics**
+ [

# Creating a FHIR resource
](managing-fhir-resources-create.md)
+ [

# Reading a FHIR resource
](managing-fhir-resources-read.md)
+ [

# Reading FHIR resource history
](managing-fhir-resources-read-history.md)
+ [

# Updating a FHIR resource
](managing-fhir-resources-update.md)
+ [

# Modifying Resources with PATCH Operation
](managing-fhir-resources-patch.md)
+ [

# Bundling FHIR resources
](managing-fhir-resources-bundle.md)
+ [

# Deleting a FHIR resource
](managing-fhir-resources-delete.md)
+ [

# Idempotency and Concurrency
](managing-fhir-resources-idempotency.md)

# Creating a FHIR resource
<a name="managing-fhir-resources-create"></a>

The FHIR `create` interaction creates a new FHIR resource in a HealthLake data store. For additional information, see [https://hl7.org/fhir/R4/http.html#create](https://hl7.org/fhir/R4/http.html#create) in the **FHIR R4 RESTful API documentation**.

**To create a FHIR resource**  


1. Collect HealthLake `region` and `datastoreId` values. For more information, see [Getting data store properties](managing-data-stores-describe.md).

1. Determine the type of FHIR `Resource` to create. For more information, see [Resource types](reference-fhir-resource-types.md).

1. Construct a URL for the request using the collected values for HealthLake `region` and `datastoreId`. Also include the FHIR `Resource` type to create. To view the entire URL path in the following example, scroll over the **Copy** button.

   ```
   POST https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Resource
   ```

1. Construct a JSON body for the request, specifying the FHIR data for the new resource. For the purpose of this procedure, we are using a FHIR `Patient` resource, so save the file as `create-patient.json`.

   ```
   {
       "resourceType": "Patient",
       "identifier": [
           {
               "system": "urn:oid:1.2.36.146.595.217.0.1",
               "value": "12345"
           }
       ],
       "name": [
           {
               "family": "Silva",
               "given": [
                   "Ana",
                   "Carolina"
               ]
           }
       ],
       "gender": "female",
       "birthDate": "1992-02-10"
   }
   ```

1. Send the request. The FHIR `create` interaction uses a `POST` request with either [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) or SMART on FHIR authorization. The following examples create a FHIR `Patient` resource in HealthLake using either curl or the HealthLake Console. To view an entire example, scroll over the **Copy** button.

------
#### [ SigV4 ]

   SigV4 authorization

   ```
   curl --request POST \
     'https://healthlake.region.amazonaws.com/datastore/datastore-id/r4/Patient' \
     --aws-sigv4 'aws:amz:region:healthlake' \
     --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
     --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
     --header 'Accept: application/json' \
     --data @create-patient.json
   ```

------
#### [ SMART on FHIR ]

   SMART on FHIR authorization example for the [https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html](https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html) data type.

   ```
   {
       "AuthorizationStrategy": "SMART_ON_FHIR",
       "FineGrainedAuthorizationEnabled": true,
       "IdpLambdaArn": "arn:aws:lambda:your-region:your-account-id:function:your-lambda-name",
       "Metadata": "{\"issuer\":\"https://ehr.example.com\", \"jwks_uri\":\"https://ehr.example.com/.well-known/jwks.json\",\"authorization_endpoint\":\"https://ehr.example.com/auth/authorize\",\"token_endpoint\":\"https://ehr.token.com/auth/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"foo\"],\"grant_types_supported\":[\"client_credential\",\"foo\"],\"registration_endpoint\":\"https://ehr.example.com/auth/register\",\"scopes_supported\":[\"openId\",\"profile\",\"launch\"],\"response_types_supported\":[\"code\"],\"management_endpoint\":\"https://ehr.example.com/user/manage\",\"introspection_endpoint\":\"https://ehr.example.com/user/introspect\",\"revocation_endpoint\":\"https://ehr.example.com/user/revoke\",\"code_challenge_methods_supported\":[\"S256\"],\"capabilities\":[\"launch-ehr\",\"sso-openid-connect\",\"client-public\",\"permission-v2\"]}"
   }
   ```

   The caller can assign permissions in the authorization lambda. For more information, see [OAuth 2.0 scopes](reference-smart-on-fhir-oauth-scopes.md).

------
#### [ AWS Console ]

**Note**  
The HealthLake Console supports only [AWS SigV4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) authorization.

   1. Sign in to the [Run query](https://console.aws.amazon.com/healthlake/home#/crud) page on the HealthLake Console.

   2. Under the **Query settings** section, make the following selections.
   + **Data Store ID** — choose a data store ID to generate a query string.
   + **Query type** — choose `Create`.
   + **Resource type** — choose the FHIR [resource type](reference-fhir-resource-types.md) to create.
   + **Request body** — construct a JSON body for the request, specifying the FHIR data for the new resource.

   3. Choose **Run query**.

------

**Configuring validation level for resource creation**  


When creating a FHIR resource, you can optionally specify an `x-amzn-healthlake-fhir-validation-level` HTTP header to configure a validation level for the resource. AWS HealthLake currently supports the following validation levels:
+ `strict`: Resources are validated according to the profile element of the resource, or the R4 specification if no profile is present. This is the default validation level for AWS HealthLake.
+ `structure-only`: Resources are validated against R4, ignoring any referenced profiles.
+ `minimal`: Resources are validated minimally, ignoring certain R4 rules. Resources that fail structure checks required for search/analytics will be updated to include a warning for audit.

Resources created with the minimal validation level may be ingested into a Datastore despite failing validation required for search indexing. In this case, resources will be updated to include a Healthlake specific extension to document said failures:

```
{
    "url": "http://healthlake.amazonaws.com/fhir/StructureDefinition/validation-issue",
    "valueString": "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"error\",\"code\":\"processing\",\"details\":{\"text\":\"FHIR resource in payload failed FHIR validation rules.\"},\"diagnostics\":\"FHIR resource in payload failed FHIR validation rules.\"}]}"
}
```

Additionally, the following HTTP response header will be included with a value of "true":

```
x-amzn-healthlake-validation-issues : true
```

**Note**  
The data ingested that is malformed according the R4 specification may not be searchable as expected if these errors are present.

# Reading a FHIR resource
<a name="managing-fhir-resources-read"></a>

The FHIR `read` interaction reads the current state of a resource in a HealthLake data store. For additional information, see [https://hl7.org/fhir/R4/http.html#read](https://hl7.org/fhir/R4/http.html#read) in the **FHIR R4 RESTful API documentation**.

**To read a FHIR resource**  


1. Collect HealthLake `region` and `datastoreId` values. For more information, see [Getting data store properties](managing-data-stores-describe.md).

1. Determine the type of FHIR `Resource` to read and collect the associated `id` value. For more information, see [Resource types](reference-fhir-resource-types.md). 

1. Construct a URL for the request using the collected values for HealthLake `region` and `datastoreId`. Also include the FHIR `Resource` type and its associated `id`. To view the entire URL path in the following example, scroll over the **Copy** button.

   ```
   GET https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Resource/id
   ```

1. Send the request. The FHIR `read` interaction uses a `GET` request with either [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) or SMART on FHIR authorization. The following `curl` example reads the current state of a FHIR `Patient` resource in HealthLake. To view the entire example, scroll over the **Copy** button.

------
#### [ SigV4 ]

   SigV4 authorization

   ```
   curl --request GET \
     'https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Patient/id' \
     --aws-sigv4 'aws:amz:region:healthlake' \
     --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
     --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
     --header 'Accept: application/json'
   ```

------
#### [ SMART on FHIR ]

   SMART on FHIR authorization example for the [https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html](https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html) data type.

   ```
   {
       "AuthorizationStrategy": "SMART_ON_FHIR",
       "FineGrainedAuthorizationEnabled": true,
       "IdpLambdaArn": "arn:aws:lambda:your-region:your-account-id:function:your-lambda-name",
       "Metadata": "{\"issuer\":\"https://ehr.example.com\", \"jwks_uri\":\"https://ehr.example.com/.well-known/jwks.json\",\"authorization_endpoint\":\"https://ehr.example.com/auth/authorize\",\"token_endpoint\":\"https://ehr.token.com/auth/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"foo\"],\"grant_types_supported\":[\"client_credential\",\"foo\"],\"registration_endpoint\":\"https://ehr.example.com/auth/register\",\"scopes_supported\":[\"openId\",\"profile\",\"launch\"],\"response_types_supported\":[\"code\"],\"management_endpoint\":\"https://ehr.example.com/user/manage\",\"introspection_endpoint\":\"https://ehr.example.com/user/introspect\",\"revocation_endpoint\":\"https://ehr.example.com/user/revoke\",\"code_challenge_methods_supported\":[\"S256\"],\"capabilities\":[\"launch-ehr\",\"sso-openid-connect\",\"client-public\",\"permission-v2\"]}"
   }
   ```

   The caller can assign permissions in the authorization lambda. For more information, see [OAuth 2.0 scopes](reference-smart-on-fhir-oauth-scopes.md).

------
#### [ AWS Console ]

   1. Sign in to the [Run query](https://console.aws.amazon.com/healthlake/home#/crud) page on the HealthLake Console.

   2. Under the **Query settings** section, make the following selections.
   + **Data Store ID** — choose a data store ID to generate a query string.
   + **Query type** — choose `Read`.
   + **Resource type** — choose the FHIR [resource type](reference-fhir-resource-types.md) to read.
   + **Resource ID** — enter the FHIR resource ID.

   3. Choose **Run query**.

------

# Reading FHIR resource history
<a name="managing-fhir-resources-read-history"></a>

The FHIR `history` interaction retrieves the history of a particular FHIR resource in a HealthLake data store. Using this interaction, you can determine how the contents of a FHIR resource have changed over time. It is also useful in coordination with audit logs to see the state of a resource before and after modification. The FHIR interactions `create`, `update`, and `delete` result in a historical version of the resource to be saved. For additional information, see [https://hl7.org/fhir/R4/http.html#history](https://hl7.org/fhir/R4/http.html#history) in the **FHIR R4 RESTful API documentation**.

**Note**  
You can opt out of `history` for specific FHIR resource types. To opt out, create a case using [AWS Support Center Console](https://console.aws.amazon.com/support/home#/). To create your case, log in to your AWS account and choose **Create case**.

**To read FHIR resource history**  


1. Collect HealthLake `region` and `datastoreId` values. For more information, see [Getting data store properties](managing-data-stores-describe.md).

1. Determine the type of FHIR `Resource` to read and collect the associated `id` value. For more information, see [Resource types](reference-fhir-resource-types.md). 

1. Construct a URL for the request using the collected values for HealthLake `region` and `datastoreId`. Also include the FHIR `Resource` type, its associated `id`, and optional search parameters. To view the entire URL path in the following example, scroll over the **Copy** button.

   ```
   GET https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Resource/id/_history{?[parameters]}
   ```  
**HealthLake supported search parameters for FHIR `history` interaction**    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/healthlake/latest/devguide/managing-fhir-resources-read-history.html)

1. Send the request. The FHIR `history` interaction uses a `GET` request with either [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) or SMART on FHIR authorization. The following `curl` example uses the `_count` search parameter to return 100 historical search results per page for a FHIR `Patient` resource in HealthLake. To view the entire example, scroll over the **Copy** button.

------
#### [ SigV4 ]

   SigV4 authorization

   ```
   curl --request GET \
     'https://healthlake.region.amazonaws.com/datastore/datastore-id/r4/Patient/id/_history?_count=100' \
     --aws-sigv4 'aws:amz:region:healthlake' \
     --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
     --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
     --header 'Accept: application/json'
   ```

------
#### [ SMART on FHIR ]

   SMART on FHIR authorization example for the [https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html](https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html) data type.

   ```
   {
       "AuthorizationStrategy": "SMART_ON_FHIR",
       "FineGrainedAuthorizationEnabled": true,
       "IdpLambdaArn": "arn:aws:lambda:your-region:your-account-id:function:your-lambda-name",
       "Metadata": "{\"issuer\":\"https://ehr.example.com\", \"jwks_uri\":\"https://ehr.example.com/.well-known/jwks.json\",\"authorization_endpoint\":\"https://ehr.example.com/auth/authorize\",\"token_endpoint\":\"https://ehr.token.com/auth/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"foo\"],\"grant_types_supported\":[\"client_credential\",\"foo\"],\"registration_endpoint\":\"https://ehr.example.com/auth/register\",\"scopes_supported\":[\"openId\",\"profile\",\"launch\"],\"response_types_supported\":[\"code\"],\"management_endpoint\":\"https://ehr.example.com/user/manage\",\"introspection_endpoint\":\"https://ehr.example.com/user/introspect\",\"revocation_endpoint\":\"https://ehr.example.com/user/revoke\",\"code_challenge_methods_supported\":[\"S256\"],\"capabilities\":[\"launch-ehr\",\"sso-openid-connect\",\"client-public\",\"permission-v2\"]}"
   }
   ```

   The caller can assign permissions in the authorization lambda. For more information, see [OAuth 2.0 scopes](reference-smart-on-fhir-oauth-scopes.md).

------

   The return content of a `history` interaction is contained in a FHIR resource `Bundle`, with type set to `history`. It contains the specified version history, sorted with oldest versions last, and includes deleted resources. For more information, see [https://hl7.org/fhir/R4/bundle.html](https://hl7.org/fhir/R4/bundle.html) in the **FHIR R4 documentation**.

## Reading version-specific FHIR resource history
<a name="managing-fhir-data-get-version-specific-resource"></a>

The FHIR `vread` interaction performs a version-specific read of a resource in a HealthLake data store. Using this interaction, you can view the contents of a FHIR resource as it was at a particular time in the past.

**Note**  
If you use FHIR `history` interaction *without* `vread`, HealthLake always returns the latest version of the resource's metadata.

HealthLake declares it support for versioning in [https://hl7.org/fhir/R4/capabilitystatement-definitions.html#CapabilityStatement.rest.resource.versioning](https://hl7.org/fhir/R4/capabilitystatement-definitions.html#CapabilityStatement.rest.resource.versioning) for each supported resource. All HealthLake data stores include `Resource.meta.versionId` (`vid`) on all resources.

When FHIR `history` interaction is enabled (by default for data stores created after 10/25/2024 or by request for older data stores), the `Bundle` response includes the `vid` as part of the [https://hl7.org/fhir/R4/bundle-definitions.html#Bundle.entry.response.location](https://hl7.org/fhir/R4/bundle-definitions.html#Bundle.entry.response.location) element. In the following example, the `vid` displays as the number `1`. To view the full example, see [Example Bundle/bundle-response (JSON)](https://build.fhir.org/bundle-response.json.html).

```
"response" : {
    "status" : "201 Created",
    "location" : "Patient/12423/_history/1",
    ...}
```

**To read version-specific FHIR resource history**  


1. Collect HealthLake `region` and `datastoreId` values. For more information, see [Getting data store properties](managing-data-stores-describe.md).

1. Determine the FHIR `Resource` type to read and collect associated `id` and `vid` values. For more information, see [Resource types](reference-fhir-resource-types.md).

1. Construct a URL for the request using the values collected for HealthLake and FHIR. To view the entire URL path in the following example, scroll over the **Copy** button.

   ```
   GET https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Resource/id/_history/vid
   ```

1. Send the request. The FHIR `history` interaction uses a `GET` request with either [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) or SMART on FHIR authorization. The following `vread` interaction returns a single instance with the content specified for the FHIR `Patient` resource for the version of the resource metadata specified by the `vid`. To view the entire URL path in the following example, scroll over the **Copy** button.

------
#### [ SigV4 ]

   SigV4 authorization

   ```
   curl --request GET \
     'https://healthlake.region.amazonaws.com/datastore/datastore-id/r4/Patient/id/_history/vid' \
     --aws-sigv4 'aws:amz:region:healthlake' \
     --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
     --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
     --header 'Accept: application/json'
   ```

------
#### [ SMART on FHIR ]

   SMART on FHIR authorization example for the [https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html](https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html) data type.

   ```
   {
       "AuthorizationStrategy": "SMART_ON_FHIR",
       "FineGrainedAuthorizationEnabled": true,
       "IdpLambdaArn": "arn:aws:lambda:your-region:your-account-id:function:your-lambda-name",
       "Metadata": "{\"issuer\":\"https://ehr.example.com\", \"jwks_uri\":\"https://ehr.example.com/.well-known/jwks.json\",\"authorization_endpoint\":\"https://ehr.example.com/auth/authorize\",\"token_endpoint\":\"https://ehr.token.com/auth/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"foo\"],\"grant_types_supported\":[\"client_credential\",\"foo\"],\"registration_endpoint\":\"https://ehr.example.com/auth/register\",\"scopes_supported\":[\"openId\",\"profile\",\"launch\"],\"response_types_supported\":[\"code\"],\"management_endpoint\":\"https://ehr.example.com/user/manage\",\"introspection_endpoint\":\"https://ehr.example.com/user/introspect\",\"revocation_endpoint\":\"https://ehr.example.com/user/revoke\",\"code_challenge_methods_supported\":[\"S256\"],\"capabilities\":[\"launch-ehr\",\"sso-openid-connect\",\"client-public\",\"permission-v2\"]}"
   }
   ```

   The caller can assign permissions in the authorization lambda. For more information, see [OAuth 2.0 scopes](reference-smart-on-fhir-oauth-scopes.md).

------

# Updating a FHIR resource
<a name="managing-fhir-resources-update"></a>

The FHIR `update` interaction creates a new current version for an existing resource or creates an initial version if no resource already exists for the given `id`. For additional information, see [https://hl7.org/fhir/R4/http.html#update](https://hl7.org/fhir/R4/http.html#update) in the **FHIR R4 RESTful API documentation**.

**To update a FHIR resource**  


1. Collect HealthLake `region` and `datastoreId` values. For more information, see [Getting data store properties](managing-data-stores-describe.md).

1. Determine the type of FHIR `Resource` to update and collect the associated `id` value. For more information, see [Resource types](reference-fhir-resource-types.md). 

1. Construct a URL for the request using the collected values for HealthLake `region` and `datastoreId`. Also include the FHIR `Resource` type and its associated `id`. To view the entire URL path in the following example, scroll over the **Copy** button.

   ```
   PUT https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Resource/id
   ```

1. Construct a `JSON` body for the request, specifying the FHIR data updates to be made. For the purpose of this procedure, save the file as `update-patient.json`.

   ```
   {
       "id": "2de04858-ba65-44c1-8af1-f2fe69a977d9",
       "resourceType": "Patient",
       "active": true,
       "name": [
           {
               "use": "official",
               "family": "Doe",
               "given": [
                   "Jane"
               ]
           },
           {
               "use": "usual",
               "given": [
                   "Jane"
               ]
           }
       ],
       "gender": "female",
       "birthDate": "1985-12-31"
   }
   ```

1. Send the request. The FHIR `update` interaction uses a `PUT` request with either [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) or SMART on FHIR authorization. The following `curl` example updates a `Patient` resource in HealthLake. To view the entire example, scroll over the **Copy** button.

------
#### [ SigV4 ]

   SigV4 authorization

   ```
   curl --request PUT \
     'https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Patient/id' \
     --aws-sigv4 'aws:amz:region:healthlake' \
     --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
     --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
     --header 'Accept: application/json' \
     --data @update-patient.json
   ```

   Your request will return a `200` HTTP status code if an existing resource is *updated* or a `201` HTTP status code if a new resource is created.

------
#### [ SMART on FHIR ]

   SMART on FHIR authorization example for the [https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html](https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html) data type.

   ```
   {
       "AuthorizationStrategy": "SMART_ON_FHIR",
       "FineGrainedAuthorizationEnabled": true,
       "IdpLambdaArn": "arn:aws:lambda:your-region:your-account-id:function:your-lambda-name",
       "Metadata": "{\"issuer\":\"https://ehr.example.com\", \"jwks_uri\":\"https://ehr.example.com/.well-known/jwks.json\",\"authorization_endpoint\":\"https://ehr.example.com/auth/authorize\",\"token_endpoint\":\"https://ehr.token.com/auth/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"foo\"],\"grant_types_supported\":[\"client_credential\",\"foo\"],\"registration_endpoint\":\"https://ehr.example.com/auth/register\",\"scopes_supported\":[\"openId\",\"profile\",\"launch\"],\"response_types_supported\":[\"code\"],\"management_endpoint\":\"https://ehr.example.com/user/manage\",\"introspection_endpoint\":\"https://ehr.example.com/user/introspect\",\"revocation_endpoint\":\"https://ehr.example.com/user/revoke\",\"code_challenge_methods_supported\":[\"S256\"],\"capabilities\":[\"launch-ehr\",\"sso-openid-connect\",\"client-public\",\"permission-v2\"]}"
   }
   ```

   The caller can assign permissions in the authorization lambda. For more information, see [OAuth 2.0 scopes](reference-smart-on-fhir-oauth-scopes.md).

------
#### [ AWS Console ]

   1. Sign in to the [Run query](https://console.aws.amazon.com/healthlake/home#/crud) page on the HealthLake Console.

   2. Under the **Query settings** section, make the following selections.
   + **Data Store ID** — choose a data store ID to generate a query string.
   + **Query type** — choose `Update (PUT)`.
   + **Resource type** — choose the FHIR [resource type](reference-fhir-resource-types.md) to update or create.
   + **Request body** — construct a JSON body for the request, specifying the FHIR data to update the resource with.

   3. Choose **Run query**.

------

## Updating FHIR resources based on conditions
<a name="managing-fhir-resources-update-conditional"></a>

Conditional update allows you to update an existing resource based on some identification search criteria, rather than by logical FHIR `id`. When the server processes the update, it performs a search using its standard search capabilities for the resource type, with the goal of resolving a single logical `id` for the request.

The action the server takes depends on how many matches it finds:
+ **No matches, no `id` provided in the request body**: The server creates the FHIR resource.
+ **No matches, `id` provided and resource doesn't already exist with the `id`**: The server treats the interaction as an Update as Create interaction.
+ **No matches, `id` provided and already exist**: The server rejects the update with a `409 Conflict` error.
+ **One Match, no resource `id` provided OR (resource `id` provided and it matches the found resource)**: The server performs the update against the matching resource as above where, if the resource was updated, the server SHALL return a `200 OK`.
+ **One Match, resource `id` provided but does not match resource found**: The server returns a `409 Conflict` error indicating the client id specification was a problem preferably with an `OperationOutcome`
+ **Multiple matches**: The server returns a `412 Precondition Failed` error indicating the client's criteria were not selective enough preferably with an OperationOutcome

The following example updates a `Patient` resource whose name is peter, birthdate is 1st Jan 2000, and phone number is 1234567890.

```
PUT https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Patient?name=peter&birthdate=2000-01-01&phone=1234567890
```

## Configuring validation level for resource updates
<a name="validation-level-resource-updates"></a>

When updating a FHIR resource, you can optionally specify an `x-amzn-healthlake-fhir-validation-level` HTTP header to configure a validation level for the resource. AWS HealthLake currently supports the following validation levels:
+ `strict`: Resources are validated according to the profile element of the resource, or the R4 specification if no profile is present. This is the default validation level for AWS HealthLake.
+ `structure-only`: Resources are validated against R4, ignoring any referenced profiles.
+ `minimal`: Resources are validated minimally, ignoring certain R4 rules. Resources that fail structure checks required for search/analytics will be updated to include a warning for audit.

Resources updated with the minimal validation level may be ingested into a Datastore despite failing validation required for search indexing. In this case, resources will be updated to include a Healthlake specific extension to document said failures:

```
{
    "url": "http://healthlake.amazonaws.com/fhir/StructureDefinition/validation-issue",
    "valueString": "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"error\",\"code\":\"processing\",\"details\":{\"text\":\"FHIR resource in payload failed FHIR validation rules.\"},\"diagnostics\":\"FHIR resource in payload failed FHIR validation rules.\"}]}"
}
```

Additionally, the following HTTP response header will be included with a value of "true":

```
x-amzn-healthlake-validation-issues : true
```

**Note**  
Note that data ingested that is malformed according the R4 specification may not be searchable as expected if these errors are present.

# Modifying Resources with PATCH Operation
<a name="managing-fhir-resources-patch"></a>

AWS HealthLake supports the PATCH operation for FHIR resources, enabling you to modify resources by targeting specific elements to add, replace, or delete without updating the entire resource. This operation is particularly useful when you need to:
+ Make targeted updates to large resources
+ Reduce network bandwidth usage
+ Perform atomic modifications on specific resource elements
+ Minimize the risk of overwriting concurrent changes
+ Update resources as part of batch and transaction workflows

## Supported PATCH Formats
<a name="patch-supported-formats"></a>

AWS HealthLake supports two standard PATCH formats:

### JSON Patch (RFC 6902)
<a name="patch-format-json"></a>

Uses JSON Pointer syntax to target elements by their position in the resource structure.

**Content-Type:** `application/json-patch+json`

### FHIRPath Patch (FHIR R4 Specification)
<a name="patch-format-fhirpath"></a>

Uses FHIRPath expressions to target elements by their content and relationships, providing a FHIR-native approach to patching.

**Content-Type:** `application/fhir+json`

## Usage
<a name="patch-usage"></a>

### Direct PATCH Operations
<a name="patch-usage-direct"></a>

The PATCH operation can be invoked directly on FHIR resources using the PATCH HTTP method:

```
PATCH [base]/[resource-type]/[id]{?_format=[mime-type]}
```

### PATCH in Bundles
<a name="patch-usage-bundles"></a>

PATCH operations can be included as entries within FHIR Bundles of type `batch` or `transaction`, enabling you to combine patch operations with other FHIR interactions (create, read, update, delete) in a single request.
+ **Transaction bundles**: All entries succeed or fail atomically
+ **Batch bundles**: Each entry is processed independently

## JSON Patch Format
<a name="patch-json-format"></a>

### Supported Operations
<a name="patch-json-supported-operations"></a>


| Operation | Description | 
| --- | --- | 
| add | Add a new value to the resource | 
| remove | Remove a value from the resource | 
| replace | Replace an existing value in the resource | 
| move | Remove a value from one location and add it to another | 
| copy | Copy a value from one location to another | 
| test | Test that a value at the target location equals a specified value | 

### Path Syntax
<a name="patch-json-path-syntax"></a>

JSON Patch uses JSON Pointer syntax (RFC 6901):


| Path Example | Description | 
| --- | --- | 
| /name/0/family | First name's family element | 
| /telecom/- | Append to telecom array | 
| /active | Root-level active element | 
| /address/0/line/1 | Second line of first address | 

### Examples
<a name="patch-json-examples"></a>

**Direct JSON Patch Request with Multiple Operations**  


```
PATCH [base]/Patient/example
Content-Type: application/json-patch+json
If-Match: W/"1"

[
  {
    "op": "replace",
    "path": "/name/0/family",
    "value": "Smith"
  },
  {
    "op": "add",
    "path": "/telecom/-",
    "value": {
      "system": "phone",
      "value": "555-555-5555",
      "use": "home"
    }
  },
  {
    "op": "remove",
    "path": "/address/0"
  },
  {
    "op": "move",
    "from": "/name/0/family",
    "path": "/name/1/family"
  },
  {
    "op": "test",
    "path": "/gender",
    "value": "male"
  },
  {
    "op": "copy",
    "from": "/name/0",
    "path": "/name/1"
  }
]
```

**Direct JSON Patch Request with Single Operation**  


```
PATCH [base]/Patient/example
Content-Type: application/json-patch+json

[
  {
    "op": "replace",
    "path": "/active",
    "value": false
  }
]
```

**JSON Patch in Bundle**  
Use a Binary resource containing the base64-encoded JSON Patch payload:

```
{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [{
    "resource": {
      "resourceType": "Binary",
      "contentType": "application/json-patch+json",
      "data": "W3sib3AiOiJhZGQiLCJwYXRoIjoiL2JpcnRoRGF0ZSIsInZhbHVlIjoiMTk5MC0wMS0wMSJ9XQ=="
    },
    "request": {
      "method": "PATCH",
      "url": "Patient/123"
    }
  }]
}
```

## FHIRPath Patch Format
<a name="patch-fhirpath-format"></a>

### Supported Operations
<a name="patch-fhirpath-supported-operations"></a>


| Operation | Description | 
| --- | --- | 
| add | Add a new element to a resource | 
| insert | Insert an element at a specific position in a list | 
| delete | Remove an element from a resource | 
| replace | Replace the value of an existing element | 
| move | Reorder elements within a list | 

### Path Syntax
<a name="patch-fhirpath-path-syntax"></a>

FHIRPath Patch uses FHIRPath expressions, supporting:
+ **Index-based access**: `Patient.name[0]`
+ **Filtering with `where()`**: `Patient.name.where(use = 'official')`
+ **Boolean logic**: `Patient.telecom.where(system = 'phone' and use = 'work')`
+ **Subsetting functions**: `first()`, `last()`
+ **Existence checks**: `exists()`, `count()`
+ **Polymorphic navigation**: `Observation.value`

### Examples
<a name="patch-fhirpath-examples"></a>

**Direct FHIRPath Patch Request**  


```
PATCH [base]/Patient/123
Content-Type: application/fhir+json
Authorization: ...

{
  "resourceType": "Parameters",
  "parameter": [{
    "name": "operation",
    "part": [
      { "name": "type", "valueCode": "add" },
      { "name": "path", "valueString": "Patient" },
      { "name": "name", "valueString": "birthDate" },
      { "name": "value", "valueDate": "1990-01-01" }
    ]
  }]
}
```

**FHIRPath Patch in Bundle**  
Use a Parameters resource as the entry resource with `method: PATCH`:

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

## Request Headers
<a name="patch-request-headers"></a>


| Header | Required | Description | 
| --- | --- | --- | 
| Content-Type | Yes | application/json-patch\$1json for JSON Patch or application/fhir\$1json for FHIRPath Patch | 
| If-Match | No | Version-specific conditional update using ETag | 

## Sample Response
<a name="patch-sample-response"></a>

The operation returns the updated resource with new version information:

```
HTTP/1.1 200 OK
Content-Type: application/fhir+json
ETag: W/"2"
Last-Modified: Mon, 05 May 2025 10:10:10 GMT

{
  "resourceType": "Patient",
  "id": "example",
  "active": true,
  "name": [
    {
      "family": "Smith",
      "given": ["John"]
    }
  ],
  "telecom": [
    {
      "system": "phone",
      "value": "555-555-5555",
      "use": "home"
    }
  ],
  "meta": {
    "versionId": "2",
    "lastUpdated": "2025-05-05T10:10:10Z"
  }
}
```

## Behavior
<a name="patch-behavior"></a>

The PATCH operation:
+ Validates the patch syntax according to the appropriate specification (RFC 6902 for JSON Patch, FHIR R4 for FHIRPath Patch)
+ Applies operations atomically - all operations succeed or all fail
+ Updates the resource version ID and creates a new history entry
+ Preserves the original resource in history before applying changes
+ Validates FHIR resource constraints after applying patches
+ Supports conditional updates using If-Match header with ETag

## Error Handling
<a name="patch-error-handling"></a>

The operation handles the following error conditions:
+ **400 Bad Request**: Invalid patch syntax (non-conformant request or malformed patch document)
+ **404 Not Found**: Resource not found (specified ID does not exist)
+ **409 Conflict**: Version conflict (concurrent updates or non-current version ID provided)
+ **422 Unprocessable Entity**: Patch operations cannot be applied to the specified resource elements

## Summary of Capabilities
<a name="patch-summary-of-capabilities"></a>


| Capability | JSON Patch | FHIRPath Patch | 
| --- | --- | --- | 
| Content Type | application/json-patch\$1json | application/fhir\$1json | 
| Path Format | JSON Pointer (RFC 6901) | FHIRPath expressions | 
| Direct PATCH API | Supported | Supported | 
| Bundle Batch | Supported (via Binary) | Supported (via Parameters) | 
| Bundle Transaction | Supported (via Binary) | Supported (via Parameters) | 
| Operations | add, remove, replace, move, copy, test | add, insert, delete, replace, move | 

## Limitations
<a name="patch-limitations"></a>
+ Conditional PATCH operations using search conditions are not supported
+ JSON Patch in bundles must use Binary resources with base64-encoded content
+ FHIRPath Patch in bundles must use Parameters resources

## Additional Resources
<a name="patch-additional-resources"></a>

For more information about PATCH operations, see:
+ [FHIR R4 PATCH Documentation](https://hl7.org/fhir/http.html#patch)
+ [FHIR R4 FHIRPath Patch Specification](https://hl7.org/fhir/fhirpatch.html)
+ [RFC 6902 - JSON Patch](https://datatracker.ietf.org/doc/html/rfc6902#section-4)
+ [RFC 6901 - JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901)

# Bundling FHIR resources
<a name="managing-fhir-resources-bundle"></a>

A FHIR `Bundle` is a container for a collection of FHIR resources in AWS HealthLake. AWS HealthLake supports two types of bundles with different processing behaviors.

[https://hl7.org/fhir/R4/http.html#transaction](https://hl7.org/fhir/R4/http.html#transaction) bundles process each resource independently. If one resource fails, the remaining resources can still succeed. Each operation is processed individually, and processing continues even when some operations fail. Use batch bundles for bulk operations where partial success is acceptable, such as uploading multiple unrelated patient records.

[https://hl7.org/fhir/R4/http.html#transaction](https://hl7.org/fhir/R4/http.html#transaction) bundles process all resources atomically as a single unit. Either all resource operations succeed, or AWS HealthLake commits none of them. Use transaction bundles when you need guaranteed referential integrity across related resources, such as creating a patient with related observations and conditions where all data must be recorded together.


**Differences between batch and transaction bundles**  

| Feature | Batch | Transaction | 
| --- | --- | --- | 
| Processing model | Each operation succeeds or fails independently. | All operations succeed or fail as a single atomic unit. | 
| Failure handling | Processing continues even if individual operations fail. | The entire bundle fails if any single operation fails. | 
| Execution order | Execution order is not guaranteed. | Operations are processed in the order specified. | 
| Referential integrity | Not enforced across operations. | Enforced for locally referenced resources within the bundle. | 
| Best used for | Bulk operations where partial success is acceptable. | Related resources that must be created or updated together. | 

You can bundle FHIR resources of the same or different types, and they can include a mix of FHIR operations, such as `create`, `read`, `update`, `delete`, and `patch`. For additional information, see [Resource Bundle](https://hl7.org/fhir/R4/Bundle) in the **FHIR R4 documentation**.

The following are example use cases for each bundle type.

Batch bundles  
+ Upload multiple unrelated patient records from different facilities during nightly data synchronization.
+ Bulk upload historical medication records where some records might have validation issues.
+ Load reference data, such as organizations and practitioners, where individual failures don't affect other entries.

Transaction bundles  
+ Create a patient with related observations and conditions during an emergency department admission where all data must be recorded together.
+ Update a patient's medication list and related allergy information that must remain consistent.
+ Record a complete encounter with the patient, observations, procedures, and billing information as a single atomic unit.

**Important**  
Both batch and transaction bundles use the same `Bundle` resource structure. The only difference is the value of the `type` field.

The following example shows a transaction bundle with multiple resource types and operations.

```
{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "fullUrl": "urn:uuid:4f6a30fb-cd3c-4ab6-8757-532101f72065",
      "resource": {
        "resourceType": "Patient",
        "id": "new-patient",
        "active": true,
        "name": [
          {
            "family": "Johnson",
            "given": [
              "Sarah"
            ]
          }
        ],
        "gender": "female",
        "birthDate": "1985-08-12",
        "telecom": [
          {
            "system": "phone",
            "value": "555-123-4567",
            "use": "home"
          }
        ]
      },
      "request": {
        "method": "POST",
        "url": "Patient"
      }
    },
    {
      "fullUrl": "urn:uuid:7f83f473-d8cc-4a8d-86d3-9d9876a3248b",
      "resource": {
        "resourceType": "Observation",
        "id": "blood-pressure",
        "status": "final",
        "code": {
          "coding": [
            {
              "system": "http://loinc.org",
              "code": "85354-9",
              "display": "Blood pressure panel"
            }
          ],
          "text": "Blood pressure panel"
        },
        "subject": {
          "reference": "urn:uuid:4f6a30fb-cd3c-4ab6-8757-532101f72065"
        },
        "effectiveDateTime": "2023-10-15T09:30:00Z",
        "component": [
          {
            "code": {
              "coding": [
                {
                  "system": "http://loinc.org",
                  "code": "8480-6",
                  "display": "Systolic blood pressure"
                }
              ]
            },
            "valueQuantity": {
              "value": 120,
              "unit": "mmHg",
              "system": "http://unitsofmeasure.org",
              "code": "mm[Hg]"
            }
          },
          {
            "code": {
              "coding": [
                {
                  "system": "http://loinc.org",
                  "code": "8462-4",
                  "display": "Diastolic blood pressure"
                }
              ]
            },
            "valueQuantity": {
              "value": 80,
              "unit": "mmHg",
              "system": "http://unitsofmeasure.org",
              "code": "mm[Hg]"
            }
          }
        ]
      },
      "request": {
        "method": "POST",
        "url": "Observation"
      }
    },
    {
      "resource": {
        "resourceType": "Appointment",
        "id": "appointment-123",
        "status": "booked",
        "description": "Annual physical examination",
        "start": "2023-11-15T09:00:00Z",
        "end": "2023-11-15T09:30:00Z",
        "participant": [
          {
            "actor": {
              "reference": "urn:uuid:4f6a30fb-cd3c-4ab6-8757-532101f72065"
            },
            "status": "accepted"
          }
        ]
      },
      "request": {
        "method": "PUT",
        "url": "Appointment/appointment-123"
      }
    },
    {
      "request": {
        "method": "DELETE",
        "url": "MedicationRequest/med-request-456"
      }
    }
  ]
}
```

## Bundling FHIR resources as independent entities
<a name="bundle-fhir-resources-batch-type"></a>

**To bundle FHIR resources as independent entities**  


1. Collect HealthLake `region` and `datastoreId` values. For more information, see [Getting data store properties](managing-data-stores-describe.md).

1. Construct a URL for the request using the collected values for HealthLake `region` and `datastoreId`. Do *not* specify a FHIR resource type in the URL. To view the entire URL path in the following example, scroll over the **Copy** button.

   ```
   POST https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/
   ```

1. Construct a JSON body for the request, specifying each HTTP verb as part of the `method` elements. The following example uses a `batch` type interaction with the `Bundle` resource to create new `Patient` and `Medication` resources. All required sections are commented accordingly. For the purpose of this procedure, save the file as `batch-independent.json`.

   ```
   {
       "resourceType": "Bundle",
       "id": "bundle-batch",
       "meta": {
           "lastUpdated": "2014-08-18T01:43:30Z"
       },
       "type": "batch",
       "entry": [
           {
               "resource": {
                   "resourceType": "Patient",
                   "meta": {
                       "lastUpdated": "2022-06-03T17:53:36.724Z"
                   },
                   "text": {
                       "status": "generated",
                       "div": "Some narrative"
                   },
                   "active": true,
                   "name": [
                       {
                           "use": "official",
                           "family": "Jackson",
                           "given": [
                               "Mateo",
                               "James"
                           ]
                       }
                   ],
                   "gender": "male",
                   "birthDate": "1974-12-25"
               },
               "request": {
                   "method": "POST",
                   "url": "Patient"
               }
           },
           {
               "resource": {
                   "resourceType": "Medication",
                   "id": "med0310",
                   "contained": [
                       {
                           "resourceType": "Substance",
                           "id": "sub03",
                           "code": {
                               "coding": [
                                   {
                                       "system": "http://snomed.info/sct",
                                       "code": "55452001",
                                       "display": "Oxycodone (substance)"
                                   }
                               ]
                           }
                       }
                   ],
                   "code": {
                       "coding": [
                           {
                               "system": "http://snomed.info/sct",
                               "code": "430127000",
                               "display": "Oral Form Oxycodone (product)"
                           }
                       ]
                   },
                   "form": {
                       "coding": [
                           {
                               "system": "http://snomed.info/sct",
                               "code": "385055001",
                               "display": "Tablet dose form (qualifier value)"
                           }
                       ]
                   },
                   "ingredient": [
                       {
                           "itemReference": {
                               "reference": "#sub03"
                           },
                           "strength": {
                               "numerator": {
                                   "value": 5,
                                   "system": "http://unitsofmeasure.org",
                                   "code": "mg"
                               },
                               "denominator": {
                                   "value": 1,
                                   "system": "http://terminology.hl7.org/CodeSystem/v3-orderableDrugForm",
                                   "code": "TAB"
                               }
                           }
                       }
                   ]
               },
               "request": {
                   "method": "POST",
                   "url": "Medication"
               }
           }
       ]
   }
   ```

1. Send the request. The FHIR `Bundle` batch type uses a `POST` request with either [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) or SMART on FHIR authorization. The following code example uses the `curl` command line tool for demonstration purposes.

------
#### [ SigV4 ]

   SigV4 authorization

   ```
   curl --request POST \
     'https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/' \
     --aws-sigv4 'aws:amz:region:healthlake' \
     --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
     --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
     --header 'Accept: application/json' \
     --data @batch-type.json
   ```

------
#### [ SMART on FHIR ]

   SMART on FHIR authorization example for the [https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html](https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html) data type.

   ```
   {
       "AuthorizationStrategy": "SMART_ON_FHIR",
       "FineGrainedAuthorizationEnabled": true,
       "IdpLambdaArn": "arn:aws:lambda:your-region:your-account-id:function:your-lambda-name",
       "Metadata": "{\"issuer\":\"https://ehr.example.com\", \"jwks_uri\":\"https://ehr.example.com/.well-known/jwks.json\",\"authorization_endpoint\":\"https://ehr.example.com/auth/authorize\",\"token_endpoint\":\"https://ehr.token.com/auth/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"foo\"],\"grant_types_supported\":[\"client_credential\",\"foo\"],\"registration_endpoint\":\"https://ehr.example.com/auth/register\",\"scopes_supported\":[\"openId\",\"profile\",\"launch\"],\"response_types_supported\":[\"code\"],\"management_endpoint\":\"https://ehr.example.com/user/manage\",\"introspection_endpoint\":\"https://ehr.example.com/user/introspect\",\"revocation_endpoint\":\"https://ehr.example.com/user/revoke\",\"code_challenge_methods_supported\":[\"S256\"],\"capabilities\":[\"launch-ehr\",\"sso-openid-connect\",\"client-public\",\"permission-v2\"]}"
   }
   ```

   The caller can assign permissions in the authorization lambda. For more information, see [OAuth 2.0 scopes](reference-smart-on-fhir-oauth-scopes.md).

------

   The server returns a response showing the `Patient` and `Medication` resources created as a result of the `Bundle` batch type request.

## Conditional PUTs in bundles
<a name="bundle-conditional-PUTs"></a>

AWS HealthLake supports conditional updates within bundles using the following query parameters:
+ `_id` (standalone)
+ `_id` in combination with one of the following:
  + `_tag`
  + `_createdAt`
  + `_lastUpdated`

When you use conditional PUTs in bundles, AWS HealthLake evaluates the query parameters against existing resources and takes action based on the match results.


**Conditional update behavior**  

| Scenario | HTTP status | Action taken | 
| --- | --- | --- | 
| Resource without ID provided | 201 Created | Always creates a new resource. | 
| Resource with new ID (no match) | 201 Created | Creates a new resource with the specified ID. | 
| Resource with existing ID (single match) | 200 OK | Updates the matching resource. | 
| Resource with existing ID (conflict detected) | 409 Conflict | Returns an error. No changes are made. | 
| Resource with existing ID (ID mismatch) | 400 Bad Request | Returns an error. No changes are made. | 
| Multiple resources match conditions | 412 Precondition Failed | Returns an error. No changes are made. | 

In the following example bundle with a conditional update, the `Patient` resource with FHIR ID `476` updates only if the condition `_lastUpdated=lt2025-04-20` is met.

```
{
    "resourceType": "Bundle",
    "id": "bundle-batch",
    "meta": {
        "lastUpdated": "2014-08-18T01:43:30Z"
    },
    "type": "batch",
    "entry": [
        {
            "resource": {
                "resourceType": "Patient",
                "id": "476",
                "meta": {
                    "lastUpdated": "2022-06-03T17:53:36.724Z"
                },
                "active": true,
                "name": [
                    {
                        "use": "official",
                        "family": "Jackson",
                        "given": [
                            "Mateo",
                            "James"
                        ]
                    }
                ],
                "gender": "male",
                "birthDate": "1974-12-25"
            },
            "request": {
                "method": "PUT",
                "url": "Patient?_id=476&_lastUpdated=lt2025-04-20"
            }
        },
        {
            "resource": {
                "resourceType": "Medication",
                "id": "med0310",
                "contained": [
                    {
                        "resourceType": "Substance",
                        "id": "sub03",
                        "code": {
                            "coding": [
                                {
                                    "system": "http://snomed.info/sct",
                                    "code": "55452001",
                                    "display": "Oxycodone (substance)"
                                }
                            ]
                        }
                    }
                ],
                "code": {
                    "coding": [
                        {
                            "system": "http://snomed.info/sct",
                            "code": "430127000",
                            "display": "Oral Form Oxycodone (product)"
                        }
                    ]
                },
                "form": {
                    "coding": [
                        {
                            "system": "http://snomed.info/sct",
                            "code": "385055001",
                            "display": "Tablet dose form (qualifier value)"
                        }
                    ]
                },
                "ingredient": [
                    {
                        "itemReference": {
                            "reference": "#sub03"
                        },
                        "strength": {
                            "numerator": {
                                "value": 5,
                                "system": "http://unitsofmeasure.org",
                                "code": "mg"
                            },
                            "denominator": {
                                "value": 1,
                                "system": "http://terminology.hl7.org/CodeSystem/v3-orderableDrugForm",
                                "code": "TAB"
                            }
                        }
                    }
                ]
            },
            "request": {
                "method": "POST",
                "url": "Medication"
            }
        }
    ]
}
```

## Bundling FHIR resources as a single entity
<a name="bundle-fhir-resources-document-type"></a>

**To bundle FHIR resources as a single entity**  


1. Collect HealthLake `region` and `datastoreId` values. For more information, see [Getting data store properties](managing-data-stores-describe.md).

1. Construct a URL for the request using the collected values for HealthLake `region` and `datastoreId`. Include the FHIR resource type `Bundle` as part of the URL. To view the entire URL path in the following example, scroll over the **Copy** button.

   ```
   POST https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Bundle
   ```

1. Construct a JSON body for the request, specifying the FHIR resources to group together. The following example groups two `Patient` resources in HealthLake. For the purpose of this procedure, save the file as `batch-single.json`.

   ```
   {
       "resourceType": "Bundle",
       "id": "bundle-minimal",
       "language": "en-US",
       "identifier": {
           "system": "urn:oid:1.2.3.4.5",
           "value": "28b95815-76ce-457b-b7ae-a972e527db4f"
       },
       "type": "document",
       "timestamp": "2020-12-11T14:30:00+01:00",
       "entry": [
           {
               "fullUrl": "urn:uuid:f40b07e3-37e8-48c3-bf1c-ae70fe12dabf",
               "resource": {
                   "resourceType": "Composition",
                   "id": "f40b07e3-37e8-48c3-bf1c-ae70fe12dabf",
                   "status": "final",
                   "type": {
                       "coding": [
                           {
                               "system": "http://loinc.org",
                               "code": "60591-5",
                               "display": "Patient summary Document"
                           }
                       ]
                   },
                   "date": "2020-12-11T14:30:00+01:00",
                   "author": [
                       {
                           "reference": "urn:uuid:45271f7f-63ab-4946-970f-3daaaa0663ff"
                       }
                   ],
                   "title": "Patient Summary as of December 7, 2020 14:30"
               }
           },
           {
               "fullUrl": "urn:uuid:45271f7f-63ab-4946-970f-3daaaa0663ff",
               "resource": {
                   "resourceType": "Practitioner",
                   "id": "45271f7f-63ab-4946-970f-3daaaa0663ff",
                   
                   "active": true,
                   "name": [
                       {
                           "family": "Doe",
                           "given": [
                               "John"
                           ]
                       }
                   ]                
               }
           }
       ]
   }
   ```

1. Send the request. The FHIR `Bundle` document type uses a `POST` request with [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) signing protocol. The following code example uses the `curl` command line tool for demonstration purposes.

------
#### [ SigV4 ]

   SigV4 authorization

   ```
   curl --request POST \
     'https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Bundle' \
     --aws-sigv4 'aws:amz:region:healthlake' \
     --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
     --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
     --header 'Accept: application/json' \
     --data @document-type.json
   ```

------
#### [ SMART on FHIR ]

   SMART on FHIR authorization example for the [https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html](https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html) data type.

   ```
   {
       "AuthorizationStrategy": "SMART_ON_FHIR",
       "FineGrainedAuthorizationEnabled": true,
       "IdpLambdaArn": "arn:aws:lambda:your-region:your-account-id:function:your-lambda-name",
       "Metadata": "{\"issuer\":\"https://ehr.example.com\", \"jwks_uri\":\"https://ehr.example.com/.well-known/jwks.json\",\"authorization_endpoint\":\"https://ehr.example.com/auth/authorize\",\"token_endpoint\":\"https://ehr.token.com/auth/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"foo\"],\"grant_types_supported\":[\"client_credential\",\"foo\"],\"registration_endpoint\":\"https://ehr.example.com/auth/register\",\"scopes_supported\":[\"openId\",\"profile\",\"launch\"],\"response_types_supported\":[\"code\"],\"management_endpoint\":\"https://ehr.example.com/user/manage\",\"introspection_endpoint\":\"https://ehr.example.com/user/introspect\",\"revocation_endpoint\":\"https://ehr.example.com/user/revoke\",\"code_challenge_methods_supported\":[\"S256\"],\"capabilities\":[\"launch-ehr\",\"sso-openid-connect\",\"client-public\",\"permission-v2\"]}"
   }
   ```

   The caller can assign permissions in the authorization lambda. For more information, see [OAuth 2.0 scopes](reference-smart-on-fhir-oauth-scopes.md).

------

   The server returns a response showing two `Patient` resources created as a result of the `Bundle` document type request.

## Configuring validation level for bundles
<a name="validation-level-bundles"></a>

When bundling FHIR resources, you can optionally specify an `x-amzn-healthlake-fhir-validation-level` HTTP header to configure a validation level for the resource. This validation level will be set for all create and update requests within the bundle. AWS HealthLake currently supports the following validation levels:
+ `strict`: Resources are validated according to the profile element of the resource, or the R4 specification if no profile is present. This is the default validation level for AWS HealthLake.
+ `structure-only`: Resources are validated against R4, ignoring any referenced profiles.
+ `minimal`: Resources are validated minimally, ignoring certain R4 rules. Resources that fail structure checks required for search/analytics will be updated to include a warning for audit.

Resources bundled with the minimal validation level may be ingested into a Datastore despite failing validation required for search indexing. In this case, resources will be updated to include a Healthlake specific extension to document said failures, and the entries within the Bundle response will include OperationOutcome resources as follows:

```
{
    "resourceType": "Bundle",
    "type": "batch-response",
    "timestamp": "2025-08-25T22:58:48.846287342Z",
    "entry": [
        {
            "response": {
                "status": "201",
                "location": "Patient/195abc49-ba8e-4c8b-95c2-abc88fef7544/_history/1",
                "etag": "W/\"1\"",
                "lastModified": "2025-08-25T22:58:48.801245445Z",
                "outcome": {
                    "resourceType": "OperationOutcome",
                    "issue": [
                        {
                            "severity": "error",
                            "code": "processing",
                            "details": {
                                "text": "FHIR resource in payload failed FHIR validation rules."
                            },
                            "diagnostics": "FHIR resource in payload failed FHIR validation rules."
                        }
                    ]
                }
            }
        }
    ]
}
```

Additionally, the following HTTP response header will be included with a value of "true":

```
x-amzn-healthlake-validation-issues : true
```

**Note**  
Note that data ingested that is malformed according the R4 specification may not be searchable as expected if these errors are present.

## Limited support for Bundle type "message"
<a name="bundle-message-type-limited-support"></a>

HealthLake provides limited support for FHIR Bundle type `message` through an internal conversion process. This support is designed for scenarios where message bundles cannot be reformatted at the source, such as ingesting ADT (Admission, Discharge, Transfer) feeds from legacy hospital systems.

**Warning**  
This feature requires explicit AWS account allowlisting and does not enforce FHIR R4 message semantics or referential integrity. Contact AWS Support to request enablement for your account before using message bundles.

### Key differences from standard message processing
<a name="bundle-message-key-differences"></a>
+ **Message Bundles** (FHIR specification): First entry must be a `MessageHeader` that references other resources. Resources lack individual `request` objects, and the MessageHeader event determines processing actions.
+ **HealthLake Processing**: Converts message Bundles to batch Bundles by automatically assigning PUT operations to each resource entry. Resources are processed independently without enforcing message semantics or referential integrity.

### Important limitations
<a name="bundle-message-limitations"></a>
+ FHIR R4 Message-specific processing rules are not enforced
+ No transactional integrity across resources
+ Inter-resource references are not validated
+ Requires explicit account allowlisting

### Example message Bundle structure
<a name="bundle-message-example"></a>

```
{
              "resourceType": "Bundle",
              "type": "message",
              "entry": [
                {
                  "resource": {
                    "resourceType": "MessageHeader",
                    "eventCoding": {
                      "system": "http://hl7.org/fhir/us/davinci-alerts/CodeSystem/notification-event",
                      "code": "notification-admit"
                    },
                    "focus": [{"reference": "Encounter/example-id"}]
                  }
                },
                {
                  "resource": {"resourceType": "Patient", "id": "example-id"}
                },
                {
                  "resource": {"resourceType": "Encounter", "id": "example-id"}
                }
              ]
            }
```

**Note**  
Each resource is stored independently as if submitted via individual PUT operations. If full FHIR messaging semantics or referential integrity validation are required, pre-process message Bundles or implement application-level validation before submission.

## Asynchronous bundle transactions
<a name="managing-fhir-resources-async-transactions"></a>

AWS HealthLake supports asynchronous `Bundle` type `transaction` that allows you to submit transactions with up to 500 resources. When you submit an asynchronous transaction, HealthLake queues it for processing and immediately returns a polling URL. You can use this URL to check the status and retrieve the response. This follows the [FHIR async bundle pattern](https://hl7.org/fhir/async-bundle.html). 

**When to use asynchronous transactions**  

+ You need to submit more than 100 resources (synchronous limit) in a single transaction.
+ You want to avoid blocking your application while waiting for transaction processing to complete.
+ You need to process high volumes of related resources with better throughput.

**Important**  
Polling results are available for 90 days after the transaction is completed. After this 90-day period, the polling URL no longer returns results. Design your integration to retrieve and store results within this window.

**Note**  
Synchronous `Bundle` type `transaction` continues to support up to 100 resources and is the default processing mode. If you submit a `Bundle` type `transaction` with more than 100 resources without the `Prefer: respond-async` header, HealthLake returns a `422 Unprocessable Entity` error. Bundles with type `batch` are not supported for asynchronous processing—only `Bundle` type `transaction` can be submitted asynchronously (with up to 500 operations).

### Submitting an asynchronous transaction
<a name="async-transactions-submitting"></a>

To submit an asynchronous transaction, send a `POST` request to the data store endpoint with the `Prefer: respond-async` header. The bundle must have type `transaction`. Bundles with type `batch` are not supported for asynchronous bundle processing.

HealthLake does initial validations for the bundle at submission time. If validation succeeds, HealthLake returns HTTP 202 Accepted with a `content-location` response header that contains the polling URL.

**To submit an asynchronous `Bundle` type `transaction`**  


1. Send a `POST` request to the HealthLake data store endpoint.

   ```
   POST https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/
   ```

1. Construct a JSON body for the request with bundle type `transaction`. For the purpose of this procedure, save the file as `async-transaction.json`.

   ```
   {
       "resourceType": "Bundle",
       "type": "transaction",
       "entry": [
           {
               "resource": {
                   "resourceType": "Patient",
                   "active": true,
                   "name": [
                       {
                           "use": "official",
                           "family": "Smith",
                           "given": ["Jane"]
                       }
                   ],
                   "gender": "female",
                   "birthDate": "1990-01-15"
               },
               "request": {
                   "method": "POST",
                   "url": "Patient"
               }
           },
           {
               "resource": {
                   "resourceType": "Observation",
                   "status": "final",
                   "code": {
                       "coding": [
                           {
                               "system": "http://loinc.org",
                               "code": "85354-9",
                               "display": "Blood pressure panel"
                           }
                       ]
                   },
                   "subject": {
                       "reference": "urn:uuid:example-patient-id"
                   }
               },
               "request": {
                   "method": "POST",
                   "url": "Observation"
               }
           }
       ]
   }
   ```

1. Send the request with the `Prefer: respond-async` header. The FHIR `Bundle` transaction type uses a `POST` request with either [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) or SMART on FHIR authorization. The following code example uses the `curl` command line tool for demonstration purposes.

------
#### [ SigV4 ]

   SigV4 authorization

   ```
   curl --request POST \
     'https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/' \
     --aws-sigv4 'aws:amz:region:healthlake' \
     --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
     --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
     --header 'Accept: application/json' \
     --header 'Prefer: respond-async' \
     --data @async-transaction.json
   ```

------
#### [ SMART on FHIR ]

   SMART on FHIR authorization example for the [https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html](https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html) data type.

   ```
   {
       "AuthorizationStrategy": "SMART_ON_FHIR",
       "FineGrainedAuthorizationEnabled": true,
       "IdpLambdaArn": "arn:aws:lambda:your-region:your-account-id:function:your-lambda-name",
       "Metadata": "{\"issuer\":\"https://ehr.example.com\", \"jwks_uri\":\"https://ehr.example.com/.well-known/jwks.json\",\"authorization_endpoint\":\"https://ehr.example.com/auth/authorize\",\"token_endpoint\":\"https://ehr.token.com/auth/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"foo\"],\"grant_types_supported\":[\"client_credential\",\"foo\"],\"registration_endpoint\":\"https://ehr.example.com/auth/register\",\"scopes_supported\":[\"openId\",\"profile\",\"launch\"],\"response_types_supported\":[\"code\"],\"management_endpoint\":\"https://ehr.example.com/user/manage\",\"introspection_endpoint\":\"https://ehr.example.com/user/introspect\",\"revocation_endpoint\":\"https://ehr.example.com/user/revoke\",\"code_challenge_methods_supported\":[\"S256\"],\"capabilities\":[\"launch-ehr\",\"sso-openid-connect\",\"client-public\",\"permission-v2\"]}"
   }
   ```

   The caller can assign permissions in the authorization lambda. For more information, see [OAuth 2.0 scopes](reference-smart-on-fhir-oauth-scopes.md).

------

1. On successful submission, the server returns HTTP 202 Accepted. The `content-location` response header contains the polling URL. The response body is an `OperationOutcome` resource.

   ```
   HTTP/1.1 202 Accepted
   content-location: https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Transaction/transactionId
   ```

   ```
   {
       "resourceType": "OperationOutcome",
       "issue": [
           {
               "severity": "information",
               "code": "informational",
               "diagnostics": "Submitted Asynchronous Bundle Transaction",
               "location": [
                   "https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Transaction/transactionId"
               ]
           }
       ]
   }
   ```

### Polling for transaction status
<a name="async-transactions-polling"></a>

After you submit an asynchronous transaction, use the polling URL from the `content-location` response header to check the transaction status. Send a `GET` request to the polling URL.

**Note**  
For SMART on FHIR enabled data stores, the authorization token must include `read` permissions on the `Transaction` resource type to poll for transaction status. For more information about SMART on FHIR scopes, see [SMART on FHIR OAuth 2.0 scopes supported by HealthLake](reference-smart-on-fhir-oauth-scopes.md).

Send a `GET` request to the polling URL. The following example uses the `curl` command line tool.

------
#### [ SigV4 ]

SigV4 authorization

```
curl --request GET \
  'https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Transaction/transactionId' \
  --aws-sigv4 'aws:amz:region:healthlake' \
  --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
  --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
  --header 'Accept: application/json'
```

------
#### [ SMART on FHIR ]

SMART on FHIR authorization. The authorization token must include `read` permissions on the `Transaction` resource type.

```
curl --request GET \
  'https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Transaction/transactionId' \
  --header 'Authorization: Bearer $SMART_ACCESS_TOKEN' \
  --header 'Accept: application/json'
```

------

The following table describes the possible responses.


**Polling response codes**  

| HTTP status | Meaning | Response body | 
| --- | --- | --- | 
| 202 Accepted | Transaction is queued | OperationOutcome with diagnostics "SUBMITTED" | 
| 202 Accepted | Transaction is being processed | OperationOutcome with diagnostics "IN\$1PROGRESS" | 
| 200 OK | Transaction completed successfully | Bundle with type transaction-response | 
| 4xx/5xx | Transaction failed | OperationOutcome with error details | 

The following examples show each response type.

**Transaction queued (202)**  


```
{
    "resourceType": "OperationOutcome",
    "id": "transactionId",
    "issue": [
        {
            "severity": "information",
            "code": "informational",
            "diagnostics": "SUBMITTED"
        }
    ]
}
```

**Transaction processing (202)**  


```
{
    "resourceType": "OperationOutcome",
    "id": "transactionId",
    "issue": [
        {
            "severity": "information",
            "code": "informational",
            "diagnostics": "IN_PROGRESS"
        }
    ]
}
```

**Transaction completed (200)**  


```
{
    "resourceType": "Bundle",
    "type": "transaction-response",
    "entry": [
        {
            "response": {
                "status": "201",
                "location": "Patient/example-id/_history/1",
                "etag": "W/\"1\"",
                "lastModified": "2024-01-15T10:30:00.000Z"
            }
        },
        {
            "response": {
                "status": "201",
                "location": "Observation/example-id/_history/1",
                "etag": "W/\"1\"",
                "lastModified": "2024-01-15T10:30:00.000Z"
            }
        }
    ]
}
```

**Transaction failed (4xx/5xx)**  


```
{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "error",
            "code": "exception",
            "diagnostics": "Transaction failed: conflict detected on resource Patient/example-id"
        }
    ]
}
```

### Processing order
<a name="async-transactions-processing-order"></a>

Asynchronous bundles of type `transaction` are queued but are not processed in strict submission order. HealthLake optimizes processing based on available capacity and system load.

**Important**  
Do not depend on transactions being processed in the order they were submitted. For example, if you submit Transaction A at 10:00 AM and Transaction B at 10:01 AM, Transaction B might complete before Transaction A. Design your application to:  
Handle out-of-order completion.
Use the polling URL to track each transaction independently.
Implement application-level sequencing if order matters for your use case.

### Quotas and throttling
<a name="async-transactions-quotas"></a>

The following quotas and rate limits apply to asynchronous transactions.


**Asynchronous transaction quotas**  

| Quota | Value | Adjustable | 
| --- | --- | --- | 
| Maximum operations per asynchronous transaction | 500 | No | 
| Maximum pending transactions per data store | 500 | Yes | 
+ Asynchronous transactions share the same API rate limits defined under [Service quotas](reference-healthlake-endpoints-quotas.md#reference-healthlake-quotas).
+ Polling for transaction status shares the same API rate limits as read (`GET`) operations on FHIR resources.
+ If the pending transaction limit is reached, subsequent submissions return an error until existing transactions complete.

### Error handling
<a name="async-transactions-error-handling"></a>

For a 'transaction' bundle, all FHIR resources contained in the bundle are processed as an atomic operation. All the resources in the operation must succeed, or no operations in the bundle are processed. 

Errors fall into two categories: submission errors that HealthLake returns synchronously, and processing errors that you retrieve through polling.

**Submission errors**  


HealthLake validates the bundle at submission time and returns errors synchronously before the transaction is queued. Submission errors include invalid FHIR resource validation errors, unsupported resource types, exceeding the 500 operations limit, and using the `Prefer: respond-async` header with batch bundles. If the pending transaction limit for the data store has been reached, HealthLake returns a `ThrottlingException`. When a submission error occurs, the transaction will not be queued.

**Processing errors**  


Processing errors occur after the transaction has been queued and are returned through the polling URL. These include transaction conflicts, where another operation modified a resource that is part of the transaction, and server errors during processing. When a processing error occurs, no resource mutations are done for resources in the transaction. The polling URL will return an `OperationOutcome` with the error details.

# Deleting a FHIR resource
<a name="managing-fhir-resources-delete"></a>

The FHIR `delete` interaction removes an existing FHIR resource from a HealthLake data store. For additional information, see [https://hl7.org/fhir/R4/http.html#delete](https://hl7.org/fhir/R4/http.html#delete) in the **FHIR R4 RESTful API documentation**.

**To delete a FHIR resource**  


1. Collect HealthLake `region` and `datastoreId` values. For more information, see [Getting data store properties](managing-data-stores-describe.md).

1. Determine the type of FHIR `Resource` to delete and collect the associated `id` value. For more information, see [Resource types](reference-fhir-resource-types.md).

1. Construct a URL for the request using the collected values for HealthLake `region` and `datastoreId`. Also include the FHIR `Resource` type and its associated `id`. To view the entire URL path in the following example, scroll over the **Copy** button.

   ```
   DELETE https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Resource/id
   ```

1. Send the request. The FHIR `delete` interaction uses a `DELETE` request with either [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) or SMART on FHIR authorization. The following `curl` example removes an existing FHIR `Patient` resource from a HealthLake data store. To view the entire example, scroll over the **Copy** button.

------
#### [ SigV4 ]

   SigV4 authorization

   ```
   curl --request DELETE \
     'https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Patient/id' \
     --aws-sigv4 'aws:amz:region:healthlake' \
     --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
     --header "x-amz-security-token:$AWS_SESSION_TOKEN" \
     --header 'Accept: application/json'
   ```

   The server returns a `204` HTTP status code confirming the resource has been removed from the HealthLake data store. If a delete request fails, you will receive a `400` series HTTP status code indicating why the request failed.

------
#### [ SMART on FHIR ]

   SMART on FHIR authorization example for the [https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html](https://docs.aws.amazon.com/healthlake/latest/APIReference/API_IdentityProviderConfiguration.html) data type.

   ```
   {
       "AuthorizationStrategy": "SMART_ON_FHIR",
       "FineGrainedAuthorizationEnabled": true,
       "IdpLambdaArn": "arn:aws:lambda:your-region:your-account-id:function:your-lambda-name",
       "Metadata": "{\"issuer\":\"https://ehr.example.com\", \"jwks_uri\":\"https://ehr.example.com/.well-known/jwks.json\",\"authorization_endpoint\":\"https://ehr.example.com/auth/authorize\",\"token_endpoint\":\"https://ehr.token.com/auth/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"foo\"],\"grant_types_supported\":[\"client_credential\",\"foo\"],\"registration_endpoint\":\"https://ehr.example.com/auth/register\",\"scopes_supported\":[\"openId\",\"profile\",\"launch\"],\"response_types_supported\":[\"code\"],\"management_endpoint\":\"https://ehr.example.com/user/manage\",\"introspection_endpoint\":\"https://ehr.example.com/user/introspect\",\"revocation_endpoint\":\"https://ehr.example.com/user/revoke\",\"code_challenge_methods_supported\":[\"S256\"],\"capabilities\":[\"launch-ehr\",\"sso-openid-connect\",\"client-public\",\"permission-v2\"]}"
   }
   ```

   The caller can assign permissions in the authorization lambda. For more information, see [OAuth 2.0 scopes](reference-smart-on-fhir-oauth-scopes.md).

------
#### [ AWS Console ]

   1. Sign in to the [Run query](https://console.aws.amazon.com/healthlake/home#/crud) page on the HealthLake Console.

   2. Under the **Query settings** section, make the following selections.
   + **Data Store ID** — choose a data store ID to generate a query string.
   + **Query type** — choose `Delete`.
   + **Resource type** — choose the FHIR [resource type](reference-fhir-resource-types.md) to delete.
   + **Resource ID** — enter the FHIR resource ID.

   3. Choose **Run query**.

------

## Deleting FHIR resources based on conditions
<a name="conditional-delete-fhir"></a>

Conditional delete is particularly useful when you don't know the specific FHIR resource ID but have other identifying information about the resource you want to delete.

Conditional delete allows you to delete an existing resource based on search criteria rather than by logical FHIR ID. When the server processes the delete request, it performs a search using standard search capabilities for the resource type to resolve a single logical ID for the request.

### How conditional delete works
<a name="conditional-delete-works"></a>

**The server's action depends on how many matches it finds:**  


1. **No matches**: The server attempts an ordinary delete and responds appropriately (404 Not Found for non-existent resource, 204 No Content for already deleted resource)

1. **One match**: The server performs an ordinary delete on the matching resource

1. **Multiple matches**: Returns a 412 Precondition Failed error indicating the client's criteria were not selective enough

### Response scenarios
<a name="response-scenerios"></a>

AWS HealthLake handles conditional delete operations with the following response patterns:

**Successful Operations**  

+ When your search criteria successfully identify a single active resource, the system returns **204 No Content** after completing the deletion, just like standard delete operations.

**ID-Based Conditional Delete**  
When performing conditional delete based on `id` with additional parameters (`createdAt`, `tag`, or `_lastUpdated`):
+ **204 No Content**: Resource was already deleted
+ **404 Not Found**: Resource doesn't exist
+ **409 Conflict**: ID matches but other parameters don't match

**Non-ID-Based Conditional Delete**  
When `id` is not provided or when using parameters other than `createdAt`, `tag`, or `_lastUpdated`:
+ **404 Not Found**: No matches found

**Conflict Situations**  
Several scenarios result in 412 Precondition Failed responses:
+ Multiple resources match your search criteria (criteria not specific enough)
+ Version conflicts when using ETag headers with `If-Match`
+ Resource updates occurring between search and delete operations

**Example of a Successful Conditional Delete**  
The following example deletes a Patient resource based on specific criteria:

```
DELETE https://healthlake.region.amazonaws.com/datastore/datastoreId/r4/Patient?name=peter&birthdate=2000-01-01&phone=1234567890
```

This request deletes a Patient resource where:
+ Name is "peter"
+ Birth date is January 1, 2000
+ Phone number is 1234567890

**Best Practices**  


1. Use specific search criteria to avoid multiple matches and prevent 412 errors.

1. Consider ETag headers for version control when needed to handle concurrent modifications.

1. Handle error responses appropriately:
   + For 404: Refine your search criteria
   + For 412: Make criteria more specific or resolve version conflicts

1. Prepare for timing conflicts in high-concurrency environments where resources may be modified between search and delete operations.

# Idempotency and Concurrency
<a name="managing-fhir-resources-idempotency"></a>

## Idempotency Keys
<a name="idempotency-keys"></a>

AWS HealthLake supports idempotency keys for FHIR `POST` operations, providing a robust mechanism to ensure data integrity during resource creation. By including a unique UUID as an idempotency key in the request header, healthcare applications can guarantee that each FHIR resource is created exactly once, even in scenarios involving network instability or automatic retries.

This feature is particularly crucial for healthcare systems where duplicate medical records could have serious consequences. When a request is received with the same idempotency key as a previous request, HealthLake will return the original resource instead of creating a duplicate. For example, this could occur during a retry loop or due to redundant request pipelines. Using the idempotency key allows HealthLake to maintain data consistency while providing a seamless experience for client applications handling intermittent connectivity issues.

### Implementation
<a name="implementation"></a>

```
POST /<baseURL>/Patient
x-amz-fhir-idempotency-key: 123e4567-e89b-12d3-a456-426614174000
{
    "resourceType": "Patient",
    "name": [...]
}
```

### Response Scenarios
<a name="response-scenarios"></a>

First Request (201 Created)  
+ New resource created successfully
+ Response includes resource ID

Duplicate Request (409 Conflict)  
+ Same idempotency key detected
+ Original resource returned
+ No new resource created

Invalid Request (400 Bad Request)  
+ Malformed UUID
+ Missing required fields

### Best Practices
<a name="best-practices"></a>
+ Generate unique UUID for each new resource creation
+ Store idempotency keys for retry logic
+ Use consistent key format: UUID v4 recommended
+ Implement in client applications handling resource creation

**Note**  
This feature is particularly valuable for healthcare systems requiring strict data accuracy and preventing duplicate medical records.

## ETag in AWS HealthLake
<a name="healthlake-etag"></a>

AWS HealthLake uses ETags for optimistic concurrency control in FHIR resources, providing a reliable mechanism to manage concurrent modifications and maintain data consistency. An ETag is a unique identifier that represents a specific version of a resource, functioning as a version control system through HTTP headers. When reading or modifying resources, applications can use ETags to prevent unintended overwrites and ensure data integrity, particularly in scenarios with potential concurrent updates.

### Implementation Example
<a name="healthlake-etag-implementation"></a>

```
// Initial Read
GET /fhir/Patient/123
Response: 
ETag: W/"1"

// Update with If-Match
PUT /fhir/Patient/123
If-Match: W/"1"
{resource content}

// Create with If-None-Match
PUT /fhir/Patient/123
If-None-Match: *
{resource content}
// Succeeds only if resource doesn't exist
// Fails with 412 if resource exists
```

### Response Scenarios
<a name="healthlake-etag-scenarios"></a>

Successful Operation (200 OK or 204 No Content)  
+ ETag matches current version
+ Operation proceeds as intended

Version Conflict (412 Precondition Failed)  
+ ETag doesn't match current version
+ Update rejected to prevent data loss

### Best Practices
<a name="healthlake-etag-practices"></a>
+ Include ETags in all update and delete operations
+ Implement retry logic for handling version conflicts
+ Use If-None-Match: \$1 for create-if-not-exists scenarios
+ Always verify ETag freshness before modifications

This concurrency control system is essential for maintaining the integrity of healthcare data, especially in environments with multiple users or systems accessing and modifying the same resources.