The azapi provider is a thin Terraform provider maintained by Microsoft that calls the Azure Resource Manager REST API directly — giving it the same day-0 coverage as ARM Templates and Bicep.
The azurerm provider (by HashiCorp) wraps the Azure API behind its own HCL-friendly field names and abstractions. That abstraction is convenient but introduces a lag: a new Azure feature has to be implemented in the provider before you can use it in Terraform. azapi skips that layer entirely.
azurerm vs azapi
azurerm
azapi
Maintained by
HashiCorp
Microsoft
Day-0 coverage
No — provider lag possible
Yes — same API as ARM/Bicep
Field names
Custom HCL-friendly names
Mirror ARM/Bicep API names
Abstraction level
High — opinionated resource blocks
Low — body is raw JSON/YAML
Maturity
Very mature
Generally Available (GA)
Best for
Stable, well-supported resources
New/preview services, Azure-native teams
How It Works
azapi has three core resource types:
azapi_resource — create, update, and delete any Azure resource via the ARM REST API.
azapi_update_resource — patch properties of an existing resource (even one managed by azurerm).
azapi_resource_action — invoke arbitrary ARM actions (e.g. listKeys, restart).
Because the body is passed as structured data (HCL object → JSON), it mirrors Bicep’s properties block almost exactly, making Bicep docs directly applicable.
Notice how the field names (minimumTlsVersion, allowBlobPublicAccess, supportsHttpsTrafficOnly) match the ARM/Bicep API exactly — the same names you’d use in a .bicep file.
Using azapi Alongside azurerm
The recommended pattern:
Use azurerm for stable, well-supported resources where its abstractions save time.
Use azapi for new/preview features not yet in azurerm, or when you need exact API control.
Use azapi_update_resource to set properties on an azurerm-managed resource that azurerm doesn’t expose yet.
Patching an azurerm Resource
# Core resource via azurermresource"azurerm_storage_account""main"{name=var.storage_account_nameresource_group_name=var.resource_group_namelocation=var.locationaccount_tier="Standard"account_replication_type="LRS"}# Patch a property azurerm doesn't expose yetresource"azapi_update_resource""dns_endpoint_type"{type="Microsoft.Storage/storageAccounts@2023-01-01"resource_id=azurerm_storage_account.main.idbody={properties={dnsEndpointType="AzureDnsZone"}}}
Bicep Alignment
Bicep
azapi body
sku: { name: 'Standard_LRS' }
sku = { name = "Standard_LRS" }
properties: { minimumTlsVersion: 'TLS1_2' }
properties = { minimumTlsVersion = "TLS1_2" }
kind: 'StorageV2'
kind = "StorageV2"
The main difference is syntax (Bicep’s : vs HCL’s =) — the structure and names are identical.
Cons
Verbosity for common resources — azurerm provides much shorter, more readable blocks for well-supported resources.
No provider-level validations — azurerm catches many mistakes at plan time; azapi passes the body straight to ARM, so errors surface at apply time.
Less community content — fewer examples, blog posts, and Stack Overflow answers compared to azurerm.