
When using Terraform to import an OpenAPI/Swagger definition into Azure API Management (APIM), the API and its operations are created successfully. However, one subtle behavior can cause confusion when trying to manage operation-level policies declaratively.
This post explains the issue and a simple workaround.
The Scenario
I was importing my API using Terraform:
Swagger/OpenAPI definition imported into APIM
API created successfully
All operations appeared correctly in Azure
Later, I wanted to attach operation-level policies using Terraform using azurerm_api_management_api_operation_policy
At this point I ran into a problem: Terraform had no record of the operations in its state file.
Why This Happens
This behavior is expected once you understand how Terraform works. Terraform only tracks resources explicitly declared in configuration, or
resources manually imported into state
When Swagger is imported via azurerm_api_management_api the operations are created inside Azure, but they are not separate Terraform-managed resources unless you explicitly declare using azurerm_api_management_api_operation
Effectively — API is created in Azure and tracked in Terraform while
API Operations (via Swagger import) are created in Azure but NOT tracked in Terraform
This makes it unclear how to attach policies to those operations without creating the operations explicitly — a nightmare if you have hundreds of operations
The Simple Workaround
You do not need a Terraform resource reference to the operation for you to create an operation policy and attach it. Instead, you can attach the policy directly using azurerm_api_management_api_operation_policy resource and referencing the Swagger operationId.
Example:
resource “azurerm_api_management_api_operation_policy” “my_op_policy” {
provider = «provider»
api_name = “
api_management_name = data.azurerm_api_management.apim.name
resource_group_name = data.azurerm_api_management.apim.resource_group_name
operation_id = “
xml_content = templatefile("
backend_name = “
method = “
})
}
As long as the API exists in APIM and the operation exists and operation_id exactly matches the Swagger operationId — Terraform can apply and update the policy successfully. No explicit Terraform operation resource is required.
Notes
1. Use the Swagger operationId, not the display name. Terraform identifies the operation strictly by operationId.
2. Treat operationId as a stable contract. If you later rename the operationId or remove an endpoint or restructure the Swagger Terraform may fail because the referenced operation no longer exists.
3. Importing operations individually is possible but rarely worth it. You can define azurerm_api_management_api_operation and import each operation manually into Terraform state. However, it requires one resource per operation. Also, manual imports are tedious and scales poorly for large APIs thus defeating the benefit of Swagger-driven API definition
For most setups, referencing operationId directly in the policy resource is simpler.
Takeaway
When importing Swagger into APIM using Terraform:
Operations are created in Azure
Terraform does not automatically track them
Operation policies can still be managed declaratively by simply referencing the Swagger/OpenAPI Spec operationId
Understanding this distinction can save significant time when automating API Management deployments.