Gestione delle risorse FHIR mediante i bundle FHIR

Questa pagina spiega come gestire le risorse FHIR eseguendo bundle FHIR, ovvero una raccolta di risorse e operazioni FHIR da eseguire su queste risorse.

Il metodo ExecuteBundle implementa l'interazione di batch/transazioni standard FHIR (DSTU2, STU3 e R4) e le operazioni della cronologia.

Bundle FHIR

Un bundle FHIR contiene un array di voci, ognuna delle quali rappresenta un'operazione, ad esempio creazione, aggiornamento o eliminazione, su una risorsa, ad esempio un'osservazione o un paziente. Consulta le descrizioni dettagliate degli elementi nella risorsa Bundle.

Quando esegui un bundle FHIR, il tipo di bundle determina il modo in cui vengono eseguite le operazioni al suo interno. Sono disponibili i seguenti tipi di pacchetti:

  • batch: esegue le operazioni come più richieste indipendenti.
  • transaction: esegue le operazioni come più richieste che dipendono l'una dall'altra.
  • history: inserisce le voci nella cronologia di una risorsa.

Ad esempio, supponiamo che un pacchetto di transazioni includa la creazione di una risorsa Patient e di una risorsa Observation. Se la richiesta di creazione della risorsa Patient non va a buon fine, la risorsa Observation non viene creata.

Se un'operazione non riesce quando il tipo di pacchetto è batch, l'API Cloud Healthcare esegue le operazioni rimanenti nel pacchetto. Se un'operazione non va a buon fine quando il tipo di pacchetto è transaction, l'API Cloud Healthcare interrompe l'esecuzione delle operazioni e esegue il rollback della transazione.

Cofanetti di film storici

I bundle di record storici sono estensioni personalizzate dello standard FHIR che supportano casi d'uso di backup e ripristino, come la sincronizzazione. Puoi utilizzare i bundle della cronologia per inserire o sostituire le versioni delle risorse nella cronologia di una risorsa FHIR. Puoi rimuovere le versioni delle risorse solo utilizzando il metodo Resource-purge. Il bundle history viene eseguito come una singola transazione con un limite di 100 voci per bundle. Se una versione della risorsa nel bundle history ha un timestamp maggiore rispetto alla versione più recente nel datastore FHIR, la versione più recente verrà aggiornata di conseguenza. Se il bundle history viene inserito correttamente, viene restituita una risposta vuota, altrimenti viene restituito un OperationOutcome che descrive l'errore.

Il supporto dei pacchetti di cronologia non è abilitato per impostazione predefinita. Un amministratore dell'archivio FHIR deve impostare enableHistoryModifications su true nella configurazione dell'archivio FHIR. Non puoi utilizzare i bundle della cronologia se disableResourceVersioning è impostato su true nella configurazione del datastore FHIR.

I bundle di cronologia vengono forniti nello stesso formato in cui vengono restituiti dal metodo fhir.history. Per essere valida, ogni voce del pacchetto richiede un ID risorsa, un timestamp di modifica e un stato. Inoltre, tutte le voci devono avere lo stesso ID risorsa. L'ID risorsa viene fornito con il campo resource.id o con il campo request.url. Se vengono forniti campi, l'ID risorsa fornito deve essere lo stesso. Il timestamp della risorsa viene fornito con il campo meta.lastUpdated nella risorsa o con il campo response.lastModified.

Concedere le autorizzazioni per l'esecuzione dei bundle

Il ruolo di autorizzazione datasets.fhirStores.fhir.executeBundle è necessario per eseguire i pacchetti. Per concedere questa autorizzazione, utilizza il ruolo healthcare.fhirResourceReader. Per la procedura per concedere questa autorizzazione, consulta Modificare un criterio.

Per eseguire i bundle di cronologia, è necessario anche il ruolo di autorizzazione datasets.fhirStores.fhir.import.

L'API Cloud Healthcare controlla le autorizzazioni per ogni operazione nel bundle. Se disponi dell'autorizzazione healthcare.fhirResources.create, ma non dell'autorizzazione healthcare.fhirResources.update, puoi eseguire solo bundle contenenti operazioni healthcare.fhirResources.create.

Esecuzione di un bundle

Per eseguire un bundle FHIR, utilizza il metodo projects.locations.datasets.fhirStores.fhir.executeBundle.

Nei seguenti esempi, BUNDLE.json è il percorso e il nome file di un bundle FHIR codificato in JSON. Puoi anche includere il bundle nel corpo della richiesta.

Il seguente Bundle di esempio crea una risorsa Patient ed elimina un'altra risorsa Patient:

{
  "resourceType": "Bundle",
  "id": "bundle-transaction",
  "meta": {
    "lastUpdated": "2018-03-11T11:22:16Z"
  },
  "type": "transaction",
  "entry": [
    {
      "resource": {
        "resourceType": "Patient",
        "name": [
          {
            "family": "Smith",
            "given": [
              "Darcy"
            ]
          }
        ],
        "gender": "female",
        "address": [
          {
            "line": [
              "123 Main St."
            ],
            "city": "Anycity",
            "state": "CA",
            "postalCode": "12345"
          }
        ]
      },
      "request": {
        "method": "POST",
        "url": "Patient"
      }
    },
    {
      "request": {
        "method": "DELETE",
        "url": "Patient/1234567890"
      }
    }
  ]
}

Gli esempi riportati di seguito mostrano come eseguire un bundle.

curl

Per eseguire un bundle, effettua una richiesta POST e specifica le seguenti informazioni:

  • Il nome e la posizione del set di dati padre e dell'archivio FHIR
  • La posizione del file del bundle sulla tua macchina locale
  • Un token di accesso

Il seguente esempio mostra una richiesta POST che utilizza curl:

curl -X POST \
    -H "Content-Type: application/fhir+json; charset=utf-8" \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    --data @BUNDLE_FILE.json \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir"

Indipendentemente dall'esito delle singole operazioni, dopo aver eseguito un batch bundle, il server restituisce una rappresentazione codificata in JSON di una risorsa Bundle di tipo batch-response. La risorsa Bundle contiene una voce per ogni voce della richiesta con il risultato dell'elaborazione della voce, che può essere un insieme di risultati di successo ed errore.

Se un pacchetto di transazioni è andato a buon fine, il server restituisce una rappresentazione codificata in JSON di una risorsa Bundle di tipo transaction-response contenente una voce per ogni voce nella richiesta con il risultato positivo dell'operazione.

Se si verifica un errore durante l'esecuzione di un pacchetto di transazioni, il corpo della risposta non contiene un pacchetto. ma contiene una risorsa OperationOutcome codificata in JSON che descrive il motivo dell'errore. Le operazioni riuscite di cui è stato eseguito il rollback non vengono riportate nella risposta.

Il seguente bundle di esempio è l'output dell'esecuzione corretta dell'esempio precedente. La prima voce indica il buon esito dell'operazione di creazione di un paziente e include l'ID della nuova risorsa. La seconda voce indica il buon esito dell'operazione di eliminazione.

{
  "entry": [
    {
      "response": {
        "location": projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/RESOURCE/RESOURCE_ID,
        "status": "201 Created"
      }
    },
    {
      "response": {
        "status": "200 OK"
      }
    }
  ],
  "resourceType": "Bundle",
  "type": "transaction-response"
}

PowerShell

Per eseguire un bundle, effettua una richiesta POST e specifica le seguenti informazioni:

  • Il nome e la posizione del set di dati padre e dell'archivio FHIR
  • La posizione del file del bundle sulla tua macchina locale
  • Un token di accesso

Il seguente esempio mostra una richiesta POST mediante Windows PowerShell:

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred" }

Invoke-RestMethod `
  -Method Post `
  -Headers $headers `
  -ContentType: "application/fhir+json" `
  -InFile BUNDLE_FILE.json `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir" | ConvertTo-Json

Indipendentemente dall'esito delle singole operazioni, dopo l'esecuzione di un batch bundle, il server restituisce una rappresentazione codificata in JSON di una risorsa Bundle di tipo batch-response. La risorsa Bundle contiene una voce per ogni voce della richiesta con il risultato dell'elaborazione della voce, che può essere un insieme di risultati di successo ed errore.

Se un pacchetto di transazioni è andato a buon fine, il server restituisce una rappresentazione codificata in JSON di una risorsa Bundle di tipo transaction-response contenente una voce per ogni voce nella richiesta con il risultato positivo dell'operazione.

Se si verifica un errore durante l'esecuzione di un pacchetto di transazioni, il corpo della risposta non contiene un pacchetto. ma contiene una risorsa OperationOutcome codificata in JSON che descrive il motivo dell'errore. Le operazioni riuscite di cui è stato eseguito il rollback non vengono riportate nella risposta.

Il seguente bundle di esempio è l'output dell'esecuzione corretta dell'esempio precedente. La prima voce indica il buon esito dell'operazione di creazione di un paziente e include l'ID della nuova risorsa. La seconda voce indica l'esito dell'operazione di eliminazione.

{
  "entry": [
    {
      "response": {
        "etag": "ETAG",
        "lastModified": "2020-08-03T04:12:47.312669+00:00",
        "location": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/RESOURCE/RESOURCE_ID",
        "status": "201 Created"
      }
    },
    {
      "response": {
        "etag": "ETAG",
        "lastModified": "2020-08-03T04:12:47.312669+00:00",
        "status": "200 OK"
      }
    }
  ],
  "resourceType": "Bundle",
  "type": "transaction-response"
}

Go

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"

	healthcare "google.golang.org/api/healthcare/v1"
)

// fhirExecuteBundle executes an FHIR bundle.
func fhirExecuteBundle(w io.Writer, projectID, location, datasetID, fhirStoreID string) error {
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %w", err)
	}

	fhirService := healthcareService.Projects.Locations.Datasets.FhirStores.Fhir

	payload := map[string]interface{}{
		"resourceType": "Bundle",
		"type":         "transaction",
		"entry": []map[string]interface{}{
			{
				"resource": map[string]interface{}{
					"resourceType": "Patient",
					"active":       true,
				},
				"request": map[string]interface{}{
					"method": "POST",
					"url":    "Patient",
				},
			},
		},
	}
	jsonPayload, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("json.Encode: %w", err)
	}

	parent := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/fhirStores/%s", projectID, location, datasetID, fhirStoreID)

	call := fhirService.ExecuteBundle(parent, bytes.NewReader(jsonPayload))
	call.Header().Set("Content-Type", "application/fhir+json;charset=utf-8")
	resp, err := call.Do()
	if err != nil {
		return fmt.Errorf("executeBundle: %w", err)
	}
	defer resp.Body.Close()

	respBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("could not read response: %w", err)
	}

	if resp.StatusCode > 299 {
		return fmt.Errorf("create: status %d %s: %s", resp.StatusCode, resp.Status, respBytes)
	}
	fmt.Fprintf(w, "%s", respBytes)

	return nil
}

Java

import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collections;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;

public class FhirStoreExecuteBundle {
  private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void fhirStoreExecuteBundle(String fhirStoreName, String data)
      throws IOException, URISyntaxException {
    // String fhirStoreName =
    //    String.format(
    //        FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id");
    // String data = "{\"resourceType\": \"Bundle\",\"type\": \"batch\",\"entry\": []}"

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();
    HttpClient httpClient = HttpClients.createDefault();
    String baseUri = String.format("%sv1/%s/fhir", client.getRootUrl(), fhirStoreName);
    URIBuilder uriBuilder = new URIBuilder(baseUri).setParameter("access_token", getAccessToken());
    StringEntity requestEntity = new StringEntity(data);

    HttpUriRequest request =
        RequestBuilder.post()
            .setUri(uriBuilder.build())
            .setEntity(requestEntity)
            .addHeader("Content-Type", "application/fhir+json")
            .addHeader("Accept-Charset", "utf-8")
            .addHeader("Accept", "application/fhir+json; charset=utf-8")
            .build();

    // Execute the request and process the results.
    HttpResponse response = httpClient.execute(request);
    HttpEntity responseEntity = response.getEntity();
    if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
      System.err.print(
          String.format(
              "Exception executing FHIR bundle: %s\n", response.getStatusLine().toString()));
      responseEntity.writeTo(System.err);
      throw new RuntimeException();
    }
    System.out.print("FHIR bundle executed: ");
    responseEntity.writeTo(System.out);
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }

  private static String getAccessToken() throws IOException {
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    return credential.refreshAccessToken().getTokenValue();
  }
}

Node.js

Un file del bundle di esempio è disponibile nel repository GitHub del esempio di codice.

const google = require('@googleapis/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
  headers: {'Content-Type': 'application/fhir+json'},
});
const fs = require('fs');

async function executeFhirBundle() {
  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const fhirStoreId = 'my-fhir-store';
  // const bundleFile = 'bundle.json';
  const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}`;

  const bundle = JSON.parse(fs.readFileSync(bundleFile));

  const request = {parent, requestBody: bundle};
  const resource =
    await healthcare.projects.locations.datasets.fhirStores.fhir.executeBundle(
      request
    );
  console.log('FHIR bundle executed');
  console.log(resource.data);
}

executeFhirBundle();

Python

Un file bundle di esempio è disponibile nel repository GitHub del esempio di codice.

def execute_bundle(
    project_id,
    location,
    dataset_id,
    fhir_store_id,
    bundle,
):
    """Executes the operations in the given bundle.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/fhir
    before running the sample."""
    # Imports Python's built-in "os" module
    import os

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using a service account
    from google.oauth2 import service_account

    # Gets credentials from the environment.
    credentials = service_account.Credentials.from_service_account_file(
        os.environ["GOOGLE_APPLICATION_CREDENTIALS"]
    )
    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # fhir_store_id = 'my-fhir-store' # replace with the FHIR store ID
    # bundle = 'bundle.json'  # replace with the bundle file
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    resource_path = "{}/datasets/{}/fhirStores/{}/fhir".format(
        url, dataset_id, fhir_store_id
    )

    headers = {"Content-Type": "application/fhir+json;charset=utf-8"}

    with open(bundle) as bundle_file:
        bundle_file_content = bundle_file.read()

    response = session.post(resource_path, headers=headers, data=bundle_file_content)
    response.raise_for_status()

    resource = response.json()

    print(f"Executed bundle from file: {bundle}")
    print(json.dumps(resource, indent=2))

    return resource

Fai una richiesta PATCH

Puoi utilizzare i bundle FHIR per effettuare richieste JSON PATCH alle risorse FHIR. Per ulteriori informazioni, consulta Eseguire una richiesta PATCH in un bundle FHIR.

Risolvere i riferimenti alle risorse create in un pacchetto

Le risorse in un pacchetto di transazioni possono contenere riferimenti a risorse che non esistono nel sistema di destinazione, ma che vengono create durante l'esecuzione del pacchetto. L'API Cloud Healthcare risolve l'associazione tra le risorse utilizzando il campo entry.fullUrl. I riferimenti corrispondenti al valore entry.fullUrl di un'altra risorsa nel pacchetto vengono riscritti con l'ID della risorsa corrispondente nello store. L'operazione va a buon fine indipendentemente dall'ordine delle operazioni nel bundle.

L'API Cloud Healthcare accetta fullUrl nei seguenti formati:

  • urn:uuid:UUID
  • urn:oid:OID
  • qualsiasi URL
  • un nome risorsa nel formato RESOURCE_TYPE/RESOURCE_ID, ad esempio Patient/123. L'utilizzo di questo formato non è consigliato perché fullUrl è un segnaposto locale del bundle. Ciò può creare confusione se una risorsa nel magazzino ha lo stesso nome, ma la risorsa nel bundle risolve un nome diverso a seguito di un'operazione di creazione.

Il seguente bundle di esempio crea una risorsa Patient e una risorsa Observation che fa riferimento alla risorsa Patient.

{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry":[
    {
      "request": {
        "method":"POST",
        "url":"Patient"
      },
      "fullUrl": "urn:uuid:05efabf0-4be2-4561-91ce-51548425acb9",
      "resource": {
        "resourceType":"Patient",
        "gender":"male"
      }
    },
    {
      "request": {
        "method":"POST",
        "url":"Observation"
      },
      "resource": {
        "resourceType":"Observation",
        "subject": {
          "reference": "urn:uuid:05efabf0-4be2-4561-91ce-51548425acb9"
        },
        "status":"preliminary",
        "code": {
          "text":"heart rate"
        }
      }
    }
  ]
}

Gli esempi riportati di seguito mostrano come eseguire un bundle.

curl

Un file del bundle di esempio è disponibile nel repository GitHub del esempio di codice.

Per eseguire un bundle, effettua una richiesta POST e specifica le seguenti informazioni:

  • Il nome e la posizione del set di dati padre e dell'archivio FHIR
  • La posizione del file del pacchetto in Cloud Storage
  • Un token di accesso

Il seguente esempio mostra una richiesta POST che utilizza curl:

curl -X POST \
    -H "Content-Type: application/fhir+json; charset=utf-8" \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    --data @BUNDLE_FILE.json \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir"

Il seguente bundle di esempio è l'output dell'esecuzione corretta dell'esempio precedente. La prima voce indica il buon esito dell'operazione di creazione di un paziente e include l'ID della nuova risorsa. La seconda voce indica il buon esito dell'operazione di creazione dell'osservazione e include l'ID della nuova risorsa.

{
  "entry": [
    {
      "response": {
        "etag": "ETAG1",
        "lastModified": "2020-08-04T16:14:14.273976+00:00",
        "location": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/REGION/datasets/REGION/fhirStores/FHIR_STORE_ID/fhir/Patient/PATIENT_ID/_history/HISTORY_ID",
        "status": "201 Created"
      }
    },
    {
      "response": {
        "etag": "ETAG",
        "lastModified": "2020-08-04T16:14:14.273976+00:00",
        "location": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/REGION/datasets/REGION/fhirStores/FHIR_STORE_ID/fhir/Observation/OBSERVATION_ID/_history/HISTORY_ID",
        "status": "201 Created"
      }
    }
  ],
  "resourceType": "Bundle",
  "type": "transaction-response"
}

PowerShell

Un file del bundle di esempio è disponibile nel repository GitHub del esempio di codice.

Per eseguire un bundle, effettua una richiesta POST e specifica le seguenti informazioni:

  • Il nome e la posizione del set di dati padre e dell'archivio FHIR
  • La posizione del file del pacchetto in Cloud Storage
  • Un token di accesso

Il seguente esempio mostra una richiesta POST mediante Windows PowerShell:

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred" }

Invoke-RestMethod `
  -Method Post `
  -Headers $headers `
  -ContentType: "application/fhir+json" `
  -InFile BUNDLE_FILE.json `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir" | ConvertTo-Json

Il seguente bundle di esempio è l'output dell'esecuzione corretta dell'esempio precedente. La prima voce indica il buon esito dell'operazione di creazione di un paziente e include l'ID della nuova risorsa. La seconda voce indica il buon esito dell'operazione di creazione dell'osservazione e include l'ID della nuova risorsa.

{
  "entry": [
    {
      "response": {
        "etag": "ETAG1",
        "lastModified": "2020-08-04T16:14:14.273976+00:00",
        "location": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/REGION/datasets/REGION/fhirStores/FHIR_STORE_ID/fhir/Patient/PATIENT_ID/_history/HISTORY_ID",
        "status": "201 Created"
      }
    },
    {
      "response": {
        "etag": "ETAG",
        "lastModified": "2020-08-04T16:14:14.273976+00:00",
        "location": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/REGION/datasets/REGION/fhirStores/FHIR_STORE_ID/fhir/Observation/OBSERVATION_ID/_history/HISTORY_ID",
        "status": "201 Created"
      }
    }
  ],
  "resourceType": "Bundle",
  "type": "transaction-response"
}