The azure-native:healthcareapis:Service resource, part of the Pulumi Azure Native provider, provisions Azure Healthcare APIs FHIR services that store and serve health data using the FHIR standard. This guide focuses on three capabilities: FHIR R4 deployment with access control, OAuth authentication and CORS policies, and customer-managed encryption for data sovereignty.
FHIR services require Azure AD identities for access policies and may reference Key Vaults, storage accounts, and private endpoints. The examples are intentionally small. Combine them with your own identity management, networking, and compliance infrastructure.
Create a FHIR service with basic access control
Most healthcare API deployments start with a minimal FHIR service that grants access to specific Azure AD identities, establishing the foundation for storing and querying health data.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const service = new azure_native.healthcareapis.Service("service", {
kind: azure_native.healthcareapis.Kind.Fhir_R4,
location: "westus2",
properties: {
accessPolicies: [{
objectId: "c487e7d1-3210-41a3-8ccc-e9372b78da47",
}],
},
resourceGroupName: "rg1",
resourceName: "service2",
tags: {},
});
import pulumi
import pulumi_azure_native as azure_native
service = azure_native.healthcareapis.Service("service",
kind=azure_native.healthcareapis.Kind.FHIR_R4,
location="westus2",
properties={
"access_policies": [{
"object_id": "c487e7d1-3210-41a3-8ccc-e9372b78da47",
}],
},
resource_group_name="rg1",
resource_name_="service2",
tags={})
package main
import (
healthcareapis "github.com/pulumi/pulumi-azure-native-sdk/healthcareapis/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := healthcareapis.NewService(ctx, "service", &healthcareapis.ServiceArgs{
Kind: healthcareapis.Kind_Fhir_R4,
Location: pulumi.String("westus2"),
Properties: &healthcareapis.ServicesPropertiesArgs{
AccessPolicies: healthcareapis.ServiceAccessPolicyEntryArray{
&healthcareapis.ServiceAccessPolicyEntryArgs{
ObjectId: pulumi.String("c487e7d1-3210-41a3-8ccc-e9372b78da47"),
},
},
},
ResourceGroupName: pulumi.String("rg1"),
ResourceName: pulumi.String("service2"),
Tags: pulumi.StringMap{},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var service = new AzureNative.HealthcareApis.Service("service", new()
{
Kind = AzureNative.HealthcareApis.Kind.Fhir_R4,
Location = "westus2",
Properties = new AzureNative.HealthcareApis.Inputs.ServicesPropertiesArgs
{
AccessPolicies = new[]
{
new AzureNative.HealthcareApis.Inputs.ServiceAccessPolicyEntryArgs
{
ObjectId = "c487e7d1-3210-41a3-8ccc-e9372b78da47",
},
},
},
ResourceGroupName = "rg1",
ResourceName = "service2",
Tags = null,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.healthcareapis.Service;
import com.pulumi.azurenative.healthcareapis.ServiceArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServicesPropertiesArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var service = new Service("service", ServiceArgs.builder()
.kind("fhir-R4")
.location("westus2")
.properties(ServicesPropertiesArgs.builder()
.accessPolicies(ServiceAccessPolicyEntryArgs.builder()
.objectId("c487e7d1-3210-41a3-8ccc-e9372b78da47")
.build())
.build())
.resourceGroupName("rg1")
.resourceName("service2")
.tags(Map.ofEntries(
))
.build());
}
}
resources:
service:
type: azure-native:healthcareapis:Service
properties:
kind: fhir-R4
location: westus2
properties:
accessPolicies:
- objectId: c487e7d1-3210-41a3-8ccc-e9372b78da47
resourceGroupName: rg1
resourceName: service2
tags: {}
The kind property sets the FHIR version (fhir-R4 for FHIR Release 4). The accessPolicies array lists Azure AD object IDs that can access the service. Each objectId corresponds to a user, group, or service principal in your tenant. Without additional configuration, the service uses Azure-managed encryption and allows public network access.
Configure authentication, CORS, and private networking
Production FHIR services typically require OAuth authentication, cross-origin resource sharing for web clients, and private network access to protect health data.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const service = new azure_native.healthcareapis.Service("service", {
identity: {
type: azure_native.healthcareapis.ManagedServiceIdentityType.SystemAssigned,
},
kind: azure_native.healthcareapis.Kind.Fhir_R4,
location: "westus2",
properties: {
accessPolicies: [
{
objectId: "c487e7d1-3210-41a3-8ccc-e9372b78da47",
},
{
objectId: "5b307da8-43d4-492b-8b66-b0294ade872f",
},
],
authenticationConfiguration: {
audience: "https://azurehealthcareapis.com",
authority: "https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc",
smartProxyEnabled: true,
},
corsConfiguration: {
allowCredentials: false,
headers: ["*"],
maxAge: 1440,
methods: [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
],
origins: ["*"],
},
cosmosDbConfiguration: {
keyVaultKeyUri: "https://my-vault.vault.azure.net/keys/my-key",
offerThroughput: 1000,
},
exportConfiguration: {
storageAccountName: "existingStorageAccount",
},
privateEndpointConnections: [],
publicNetworkAccess: azure_native.healthcareapis.PublicNetworkAccess.Disabled,
},
resourceGroupName: "rg1",
resourceName: "service1",
tags: {},
});
import pulumi
import pulumi_azure_native as azure_native
service = azure_native.healthcareapis.Service("service",
identity={
"type": azure_native.healthcareapis.ManagedServiceIdentityType.SYSTEM_ASSIGNED,
},
kind=azure_native.healthcareapis.Kind.FHIR_R4,
location="westus2",
properties={
"access_policies": [
{
"object_id": "c487e7d1-3210-41a3-8ccc-e9372b78da47",
},
{
"object_id": "5b307da8-43d4-492b-8b66-b0294ade872f",
},
],
"authentication_configuration": {
"audience": "https://azurehealthcareapis.com",
"authority": "https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc",
"smart_proxy_enabled": True,
},
"cors_configuration": {
"allow_credentials": False,
"headers": ["*"],
"max_age": 1440,
"methods": [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
],
"origins": ["*"],
},
"cosmos_db_configuration": {
"key_vault_key_uri": "https://my-vault.vault.azure.net/keys/my-key",
"offer_throughput": 1000,
},
"export_configuration": {
"storage_account_name": "existingStorageAccount",
},
"private_endpoint_connections": [],
"public_network_access": azure_native.healthcareapis.PublicNetworkAccess.DISABLED,
},
resource_group_name="rg1",
resource_name_="service1",
tags={})
package main
import (
healthcareapis "github.com/pulumi/pulumi-azure-native-sdk/healthcareapis/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := healthcareapis.NewService(ctx, "service", &healthcareapis.ServiceArgs{
Identity: &healthcareapis.ServicesResourceIdentityArgs{
Type: pulumi.String(healthcareapis.ManagedServiceIdentityTypeSystemAssigned),
},
Kind: healthcareapis.Kind_Fhir_R4,
Location: pulumi.String("westus2"),
Properties: &healthcareapis.ServicesPropertiesArgs{
AccessPolicies: healthcareapis.ServiceAccessPolicyEntryArray{
&healthcareapis.ServiceAccessPolicyEntryArgs{
ObjectId: pulumi.String("c487e7d1-3210-41a3-8ccc-e9372b78da47"),
},
&healthcareapis.ServiceAccessPolicyEntryArgs{
ObjectId: pulumi.String("5b307da8-43d4-492b-8b66-b0294ade872f"),
},
},
AuthenticationConfiguration: &healthcareapis.ServiceAuthenticationConfigurationInfoArgs{
Audience: pulumi.String("https://azurehealthcareapis.com"),
Authority: pulumi.String("https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc"),
SmartProxyEnabled: pulumi.Bool(true),
},
CorsConfiguration: &healthcareapis.ServiceCorsConfigurationInfoArgs{
AllowCredentials: pulumi.Bool(false),
Headers: pulumi.StringArray{
pulumi.String("*"),
},
MaxAge: pulumi.Int(1440),
Methods: pulumi.StringArray{
pulumi.String("DELETE"),
pulumi.String("GET"),
pulumi.String("OPTIONS"),
pulumi.String("PATCH"),
pulumi.String("POST"),
pulumi.String("PUT"),
},
Origins: pulumi.StringArray{
pulumi.String("*"),
},
},
CosmosDbConfiguration: &healthcareapis.ServiceCosmosDbConfigurationInfoArgs{
KeyVaultKeyUri: pulumi.String("https://my-vault.vault.azure.net/keys/my-key"),
OfferThroughput: pulumi.Int(1000),
},
ExportConfiguration: &healthcareapis.ServiceExportConfigurationInfoArgs{
StorageAccountName: pulumi.String("existingStorageAccount"),
},
PrivateEndpointConnections: healthcareapis.PrivateEndpointConnectionTypeArray{},
PublicNetworkAccess: pulumi.String(healthcareapis.PublicNetworkAccessDisabled),
},
ResourceGroupName: pulumi.String("rg1"),
ResourceName: pulumi.String("service1"),
Tags: pulumi.StringMap{},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var service = new AzureNative.HealthcareApis.Service("service", new()
{
Identity = new AzureNative.HealthcareApis.Inputs.ServicesResourceIdentityArgs
{
Type = AzureNative.HealthcareApis.ManagedServiceIdentityType.SystemAssigned,
},
Kind = AzureNative.HealthcareApis.Kind.Fhir_R4,
Location = "westus2",
Properties = new AzureNative.HealthcareApis.Inputs.ServicesPropertiesArgs
{
AccessPolicies = new[]
{
new AzureNative.HealthcareApis.Inputs.ServiceAccessPolicyEntryArgs
{
ObjectId = "c487e7d1-3210-41a3-8ccc-e9372b78da47",
},
new AzureNative.HealthcareApis.Inputs.ServiceAccessPolicyEntryArgs
{
ObjectId = "5b307da8-43d4-492b-8b66-b0294ade872f",
},
},
AuthenticationConfiguration = new AzureNative.HealthcareApis.Inputs.ServiceAuthenticationConfigurationInfoArgs
{
Audience = "https://azurehealthcareapis.com",
Authority = "https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc",
SmartProxyEnabled = true,
},
CorsConfiguration = new AzureNative.HealthcareApis.Inputs.ServiceCorsConfigurationInfoArgs
{
AllowCredentials = false,
Headers = new[]
{
"*",
},
MaxAge = 1440,
Methods = new[]
{
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
},
Origins = new[]
{
"*",
},
},
CosmosDbConfiguration = new AzureNative.HealthcareApis.Inputs.ServiceCosmosDbConfigurationInfoArgs
{
KeyVaultKeyUri = "https://my-vault.vault.azure.net/keys/my-key",
OfferThroughput = 1000,
},
ExportConfiguration = new AzureNative.HealthcareApis.Inputs.ServiceExportConfigurationInfoArgs
{
StorageAccountName = "existingStorageAccount",
},
PrivateEndpointConnections = new() { },
PublicNetworkAccess = AzureNative.HealthcareApis.PublicNetworkAccess.Disabled,
},
ResourceGroupName = "rg1",
ResourceName = "service1",
Tags = null,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.healthcareapis.Service;
import com.pulumi.azurenative.healthcareapis.ServiceArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServicesResourceIdentityArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServicesPropertiesArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServiceAuthenticationConfigurationInfoArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServiceCorsConfigurationInfoArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServiceCosmosDbConfigurationInfoArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServiceExportConfigurationInfoArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var service = new Service("service", ServiceArgs.builder()
.identity(ServicesResourceIdentityArgs.builder()
.type("SystemAssigned")
.build())
.kind("fhir-R4")
.location("westus2")
.properties(ServicesPropertiesArgs.builder()
.accessPolicies(
ServiceAccessPolicyEntryArgs.builder()
.objectId("c487e7d1-3210-41a3-8ccc-e9372b78da47")
.build(),
ServiceAccessPolicyEntryArgs.builder()
.objectId("5b307da8-43d4-492b-8b66-b0294ade872f")
.build())
.authenticationConfiguration(ServiceAuthenticationConfigurationInfoArgs.builder()
.audience("https://azurehealthcareapis.com")
.authority("https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc")
.smartProxyEnabled(true)
.build())
.corsConfiguration(ServiceCorsConfigurationInfoArgs.builder()
.allowCredentials(false)
.headers("*")
.maxAge(1440)
.methods(
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT")
.origins("*")
.build())
.cosmosDbConfiguration(ServiceCosmosDbConfigurationInfoArgs.builder()
.keyVaultKeyUri("https://my-vault.vault.azure.net/keys/my-key")
.offerThroughput(1000)
.build())
.exportConfiguration(ServiceExportConfigurationInfoArgs.builder()
.storageAccountName("existingStorageAccount")
.build())
.privateEndpointConnections()
.publicNetworkAccess("Disabled")
.build())
.resourceGroupName("rg1")
.resourceName("service1")
.tags(Map.ofEntries(
))
.build());
}
}
resources:
service:
type: azure-native:healthcareapis:Service
properties:
identity:
type: SystemAssigned
kind: fhir-R4
location: westus2
properties:
accessPolicies:
- objectId: c487e7d1-3210-41a3-8ccc-e9372b78da47
- objectId: 5b307da8-43d4-492b-8b66-b0294ade872f
authenticationConfiguration:
audience: https://azurehealthcareapis.com
authority: https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc
smartProxyEnabled: true
corsConfiguration:
allowCredentials: false
headers:
- '*'
maxAge: 1440
methods:
- DELETE
- GET
- OPTIONS
- PATCH
- POST
- PUT
origins:
- '*'
cosmosDbConfiguration:
keyVaultKeyUri: https://my-vault.vault.azure.net/keys/my-key
offerThroughput: 1000
exportConfiguration:
storageAccountName: existingStorageAccount
privateEndpointConnections: []
publicNetworkAccess: Disabled
resourceGroupName: rg1
resourceName: service1
tags: {}
The authenticationConfiguration block defines OAuth settings: audience specifies the expected token audience (typically the Healthcare APIs endpoint), and authority points to your Azure AD tenant’s OAuth endpoint. The corsConfiguration block controls browser-based access, listing allowed origins, methods, and headers. Setting publicNetworkAccess to Disabled requires clients to connect through private endpoints, which you configure separately via the privateEndpointConnections property.
Enable customer-managed encryption for data sovereignty
Healthcare organizations in regulated regions often need customer-managed keys to maintain control over encryption and meet data residency requirements.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const service = new azure_native.healthcareapis.Service("service", {
identity: {
type: azure_native.healthcareapis.ManagedServiceIdentityType.SystemAssigned,
},
kind: azure_native.healthcareapis.Kind.Fhir_R4,
location: "Southeast Asia",
properties: {
accessPolicies: [
{
objectId: "c487e7d1-3210-41a3-8ccc-e9372b78da47",
},
{
objectId: "5b307da8-43d4-492b-8b66-b0294ade872f",
},
],
authenticationConfiguration: {
audience: "https://azurehealthcareapis.com",
authority: "https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc",
smartProxyEnabled: true,
},
corsConfiguration: {
allowCredentials: false,
headers: ["*"],
maxAge: 1440,
methods: [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
],
origins: ["*"],
},
cosmosDbConfiguration: {
crossTenantCmkApplicationId: "de3fbeef-8c3a-428e-8b9f-4d229c8a85f4",
keyVaultKeyUri: "https://my-vault.vault.azure.net/keys/my-key",
offerThroughput: 1000,
},
exportConfiguration: {
storageAccountName: "existingStorageAccount",
},
privateEndpointConnections: [],
publicNetworkAccess: azure_native.healthcareapis.PublicNetworkAccess.Disabled,
},
resourceGroupName: "rg1",
resourceName: "service1",
tags: {},
});
import pulumi
import pulumi_azure_native as azure_native
service = azure_native.healthcareapis.Service("service",
identity={
"type": azure_native.healthcareapis.ManagedServiceIdentityType.SYSTEM_ASSIGNED,
},
kind=azure_native.healthcareapis.Kind.FHIR_R4,
location="Southeast Asia",
properties={
"access_policies": [
{
"object_id": "c487e7d1-3210-41a3-8ccc-e9372b78da47",
},
{
"object_id": "5b307da8-43d4-492b-8b66-b0294ade872f",
},
],
"authentication_configuration": {
"audience": "https://azurehealthcareapis.com",
"authority": "https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc",
"smart_proxy_enabled": True,
},
"cors_configuration": {
"allow_credentials": False,
"headers": ["*"],
"max_age": 1440,
"methods": [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
],
"origins": ["*"],
},
"cosmos_db_configuration": {
"cross_tenant_cmk_application_id": "de3fbeef-8c3a-428e-8b9f-4d229c8a85f4",
"key_vault_key_uri": "https://my-vault.vault.azure.net/keys/my-key",
"offer_throughput": 1000,
},
"export_configuration": {
"storage_account_name": "existingStorageAccount",
},
"private_endpoint_connections": [],
"public_network_access": azure_native.healthcareapis.PublicNetworkAccess.DISABLED,
},
resource_group_name="rg1",
resource_name_="service1",
tags={})
package main
import (
healthcareapis "github.com/pulumi/pulumi-azure-native-sdk/healthcareapis/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := healthcareapis.NewService(ctx, "service", &healthcareapis.ServiceArgs{
Identity: &healthcareapis.ServicesResourceIdentityArgs{
Type: pulumi.String(healthcareapis.ManagedServiceIdentityTypeSystemAssigned),
},
Kind: healthcareapis.Kind_Fhir_R4,
Location: pulumi.String("Southeast Asia"),
Properties: &healthcareapis.ServicesPropertiesArgs{
AccessPolicies: healthcareapis.ServiceAccessPolicyEntryArray{
&healthcareapis.ServiceAccessPolicyEntryArgs{
ObjectId: pulumi.String("c487e7d1-3210-41a3-8ccc-e9372b78da47"),
},
&healthcareapis.ServiceAccessPolicyEntryArgs{
ObjectId: pulumi.String("5b307da8-43d4-492b-8b66-b0294ade872f"),
},
},
AuthenticationConfiguration: &healthcareapis.ServiceAuthenticationConfigurationInfoArgs{
Audience: pulumi.String("https://azurehealthcareapis.com"),
Authority: pulumi.String("https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc"),
SmartProxyEnabled: pulumi.Bool(true),
},
CorsConfiguration: &healthcareapis.ServiceCorsConfigurationInfoArgs{
AllowCredentials: pulumi.Bool(false),
Headers: pulumi.StringArray{
pulumi.String("*"),
},
MaxAge: pulumi.Int(1440),
Methods: pulumi.StringArray{
pulumi.String("DELETE"),
pulumi.String("GET"),
pulumi.String("OPTIONS"),
pulumi.String("PATCH"),
pulumi.String("POST"),
pulumi.String("PUT"),
},
Origins: pulumi.StringArray{
pulumi.String("*"),
},
},
CosmosDbConfiguration: &healthcareapis.ServiceCosmosDbConfigurationInfoArgs{
CrossTenantCmkApplicationId: pulumi.String("de3fbeef-8c3a-428e-8b9f-4d229c8a85f4"),
KeyVaultKeyUri: pulumi.String("https://my-vault.vault.azure.net/keys/my-key"),
OfferThroughput: pulumi.Int(1000),
},
ExportConfiguration: &healthcareapis.ServiceExportConfigurationInfoArgs{
StorageAccountName: pulumi.String("existingStorageAccount"),
},
PrivateEndpointConnections: healthcareapis.PrivateEndpointConnectionTypeArray{},
PublicNetworkAccess: pulumi.String(healthcareapis.PublicNetworkAccessDisabled),
},
ResourceGroupName: pulumi.String("rg1"),
ResourceName: pulumi.String("service1"),
Tags: pulumi.StringMap{},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var service = new AzureNative.HealthcareApis.Service("service", new()
{
Identity = new AzureNative.HealthcareApis.Inputs.ServicesResourceIdentityArgs
{
Type = AzureNative.HealthcareApis.ManagedServiceIdentityType.SystemAssigned,
},
Kind = AzureNative.HealthcareApis.Kind.Fhir_R4,
Location = "Southeast Asia",
Properties = new AzureNative.HealthcareApis.Inputs.ServicesPropertiesArgs
{
AccessPolicies = new[]
{
new AzureNative.HealthcareApis.Inputs.ServiceAccessPolicyEntryArgs
{
ObjectId = "c487e7d1-3210-41a3-8ccc-e9372b78da47",
},
new AzureNative.HealthcareApis.Inputs.ServiceAccessPolicyEntryArgs
{
ObjectId = "5b307da8-43d4-492b-8b66-b0294ade872f",
},
},
AuthenticationConfiguration = new AzureNative.HealthcareApis.Inputs.ServiceAuthenticationConfigurationInfoArgs
{
Audience = "https://azurehealthcareapis.com",
Authority = "https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc",
SmartProxyEnabled = true,
},
CorsConfiguration = new AzureNative.HealthcareApis.Inputs.ServiceCorsConfigurationInfoArgs
{
AllowCredentials = false,
Headers = new[]
{
"*",
},
MaxAge = 1440,
Methods = new[]
{
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
},
Origins = new[]
{
"*",
},
},
CosmosDbConfiguration = new AzureNative.HealthcareApis.Inputs.ServiceCosmosDbConfigurationInfoArgs
{
CrossTenantCmkApplicationId = "de3fbeef-8c3a-428e-8b9f-4d229c8a85f4",
KeyVaultKeyUri = "https://my-vault.vault.azure.net/keys/my-key",
OfferThroughput = 1000,
},
ExportConfiguration = new AzureNative.HealthcareApis.Inputs.ServiceExportConfigurationInfoArgs
{
StorageAccountName = "existingStorageAccount",
},
PrivateEndpointConnections = new() { },
PublicNetworkAccess = AzureNative.HealthcareApis.PublicNetworkAccess.Disabled,
},
ResourceGroupName = "rg1",
ResourceName = "service1",
Tags = null,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.healthcareapis.Service;
import com.pulumi.azurenative.healthcareapis.ServiceArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServicesResourceIdentityArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServicesPropertiesArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServiceAuthenticationConfigurationInfoArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServiceCorsConfigurationInfoArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServiceCosmosDbConfigurationInfoArgs;
import com.pulumi.azurenative.healthcareapis.inputs.ServiceExportConfigurationInfoArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var service = new Service("service", ServiceArgs.builder()
.identity(ServicesResourceIdentityArgs.builder()
.type("SystemAssigned")
.build())
.kind("fhir-R4")
.location("Southeast Asia")
.properties(ServicesPropertiesArgs.builder()
.accessPolicies(
ServiceAccessPolicyEntryArgs.builder()
.objectId("c487e7d1-3210-41a3-8ccc-e9372b78da47")
.build(),
ServiceAccessPolicyEntryArgs.builder()
.objectId("5b307da8-43d4-492b-8b66-b0294ade872f")
.build())
.authenticationConfiguration(ServiceAuthenticationConfigurationInfoArgs.builder()
.audience("https://azurehealthcareapis.com")
.authority("https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc")
.smartProxyEnabled(true)
.build())
.corsConfiguration(ServiceCorsConfigurationInfoArgs.builder()
.allowCredentials(false)
.headers("*")
.maxAge(1440)
.methods(
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT")
.origins("*")
.build())
.cosmosDbConfiguration(ServiceCosmosDbConfigurationInfoArgs.builder()
.crossTenantCmkApplicationId("de3fbeef-8c3a-428e-8b9f-4d229c8a85f4")
.keyVaultKeyUri("https://my-vault.vault.azure.net/keys/my-key")
.offerThroughput(1000)
.build())
.exportConfiguration(ServiceExportConfigurationInfoArgs.builder()
.storageAccountName("existingStorageAccount")
.build())
.privateEndpointConnections()
.publicNetworkAccess("Disabled")
.build())
.resourceGroupName("rg1")
.resourceName("service1")
.tags(Map.ofEntries(
))
.build());
}
}
resources:
service:
type: azure-native:healthcareapis:Service
properties:
identity:
type: SystemAssigned
kind: fhir-R4
location: Southeast Asia
properties:
accessPolicies:
- objectId: c487e7d1-3210-41a3-8ccc-e9372b78da47
- objectId: 5b307da8-43d4-492b-8b66-b0294ade872f
authenticationConfiguration:
audience: https://azurehealthcareapis.com
authority: https://login.microsoftonline.com/abfde7b2-df0f-47e6-aabf-2462b07508dc
smartProxyEnabled: true
corsConfiguration:
allowCredentials: false
headers:
- '*'
maxAge: 1440
methods:
- DELETE
- GET
- OPTIONS
- PATCH
- POST
- PUT
origins:
- '*'
cosmosDbConfiguration:
crossTenantCmkApplicationId: de3fbeef-8c3a-428e-8b9f-4d229c8a85f4
keyVaultKeyUri: https://my-vault.vault.azure.net/keys/my-key
offerThroughput: 1000
exportConfiguration:
storageAccountName: existingStorageAccount
privateEndpointConnections: []
publicNetworkAccess: Disabled
resourceGroupName: rg1
resourceName: service1
tags: {}
The cosmosDbConfiguration block controls the underlying Cosmos DB storage. The keyVaultKeyUri points to your encryption key in Azure Key Vault, enabling customer-managed key (CMK) encryption. The crossTenantCmkApplicationId is required when using CMK in data sovereign regions like Southeast Asia, allowing the Healthcare APIs service to access your key across tenant boundaries. The offerThroughput sets provisioned throughput in request units per second.
Beyond these examples
These snippets focus on specific FHIR service features: FHIR R4 deployment and access control, OAuth authentication and CORS configuration, and customer-managed encryption and data sovereignty. They’re intentionally minimal rather than full healthcare data platforms.
The examples reference pre-existing infrastructure such as Azure AD tenant and object IDs for access policies, resource groups and Azure regions, Key Vault with encryption keys for CMK scenarios, and storage accounts for export configuration. They focus on configuring the FHIR service rather than provisioning everything around it.
To keep things focused, common FHIR service patterns are omitted, including:
- Managed identity configuration beyond SystemAssigned
- SMART on FHIR proxy settings (smartProxyEnabled details)
- Cosmos DB throughput tuning and performance optimization
- Import configuration for bulk data loading
- Diagnostic settings and monitoring integration
- Private endpoint DNS configuration
These omissions are intentional: the goal is to illustrate how each FHIR service feature is wired, not provide drop-in healthcare platforms. See the Healthcare APIs Service resource reference for all available configuration options.
Let's deploy Azure Healthcare APIs Services
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration Basics
kind (e.g., fhir-R4), location, and at least one access policy with an objectId in the accessPolicies array.location, resourceGroupName, and resourceName properties are immutable and cannot be changed after creation.accessPolicies array, each with a different objectId representing a user or application.Security & Authentication
authenticationConfiguration with audience (your API audience URL), authority (your Azure AD tenant URL), and optionally enable smartProxyEnabled for SMART on FHIR support.publicNetworkAccess to Disabled and configure privateEndpointConnections to allow access only through private endpoints.SystemAssigned managed identity, which can be configured through the identity property.Data Storage & Encryption
cosmosDbConfiguration.keyVaultKeyUri with your Azure Key Vault key URI. You can also set offerThroughput to control CosmosDB throughput.exportConfiguration with the storageAccountName of an existing Azure Storage account where exported data will be stored.CORS & Integration
corsConfiguration with headers, methods, origins, maxAge (in seconds), and allowCredentials. Use ["*"] for wildcard access or specify exact values for stricter control.Using a different cloud?
Explore integration guides for other cloud providers: