---
title: Enabling App and API Protection for Azure API Management
description: >-
  Add threat detection and blocking to your Azure API Management gateway with
  the App and API Protection callout service.
breadcrumbs: >-
  Docs > Datadog Security > App and API Protection > Enabling App and API
  Protection > Enabling App and API Protection for Azure API Management
---

> For the complete documentation index, see [llms.txt](https://docs.datadoghq.com/llms.txt).

# Enabling App and API Protection for Azure API Management

{% callout %}
# Important note for users on the following Datadog sites: us2.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

{% callout %}
# Important note for users on the following Datadog sites: app.datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, app.datadoghq.eu, ap1.datadoghq.com, ap2.datadoghq.com, uk1.datadoghq.com, app.ddog-gov.com

{% callout %}
##### App and API Protection for Azure API Management is in Preview

To try the preview of App and API Protection for Azure API Management, use the following setup instructions.
{% /callout %}

{% /callout %}

App and API Protection for Azure API Management (APIM) adds threat detection and blocking to your APIM gateway without requiring changes to your backend code. APIM is a managed service, so it cannot run an in-process tracer. Instead, Datadog provides an HTTP callout service that the gateway invokes from an APIM policy. For each request, the service runs the Datadog Web Application Firewall (WAF) and returns a decision: continue or block.

Protection applies at the gateway, so it covers every API behind the gateway, regardless of language. This includes third-party and legacy APIs you do not own.

## How it works{% #how-it-works %}

Azure API Management evaluates policies on the way in and on the way out. The Datadog policy adds a [`send-request`](https://learn.microsoft.com/en-us/azure/api-management/send-request-policy) callout to the Datadog callout service at each stage, then reads the decision from a policy variable.

The exchange uses four calls:

1. **Inbound, request headers.** The service returns a request ID, Datadog trace propagation headers, and, when body inspection applies, the number of body bytes it accepts.
1. **Inbound, request body.** Runs only when the previous phase asked for the body.
1. **Outbound, response headers.**
1. **Outbound, response body.** Runs only when the previous phase asked for the body.

The request ID ties all four phases to a single WAF evaluation context. If an inbound phase returns a block decision, APIM returns the block response to the client and never calls your backend. If an outbound phase returns a block decision, the backend has already run, and APIM replaces its response with the block response. If the decision is continue, APIM injects Datadog trace-context headers and forwards the request as usual.

The integration is fail-open at every stage. Each callout sets `ignore-error="true"`, so if the callout service is unreachable, times out, or answers with anything other than `200`, traffic proceeds unmodified. A misconfiguration shows up as missing security data rather than as broken traffic.

For the policy internals, see [Azure API Management policies for App and API Protection](https://docs.datadoghq.com/security/application_security/setup/azure/api-management/policies.md).

## Prerequisites{% #prerequisites %}

- An Azure subscription.
- An existing Azure API Management instance on the **Developer**, **Standard v2**, or **Premium** tier. This integration places the callout service inside a virtual network and requires APIM virtual network integration, so the **Consumption** tier is not supported.
- A [Datadog API key](https://app.datadoghq.com/organization-settings/api-keys).
- Permission to deploy ARM or Bicep templates into the target resource group, and to edit APIM policies.
- `Microsoft.Authorization/roleAssignments/write` on the APIM resource. The template grants the **API Management Service Contributor** role to a managed identity so it can configure virtual network integration. This role assignment is created on every deployment, including when `deployPolicy` is `false`.
- Optional: an existing Log Analytics workspace to collect Container Apps logs.

## Deploy the callout service{% #deploy-the-callout-service %}

Click **Deploy to Azure** and fill in the form in the Azure portal:

[](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FDataDog%2Fdd-trace-go%2Fmain%2Fcontrib%2Fazure%2Fapim-callout%2Fdeploy%2Fazure%2Fazuredeploy.json)

Two parameters are required:

| Parameter         | Value                                                                                                                   |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `datadogApiKey`   | Your Datadog API key. In the Azure portal, select **Reference a Key Vault secret** to use an existing Key Vault secret. |
| `apimServiceName` | The name of the existing APIM instance to protect.                                                                      |

The template provisions:

- A virtual network with separate subnets for APIM, the callout service, and the Datadog Agent. The template also creates network security groups and a NAT gateway for egress.
- The callout service on Azure Container Apps with KEDA HTTP autoscaling. Ingress is on port `8080`, the health probe on port `8081`, and the service scales from 1 to 10 replicas at 20 concurrent requests per replica.
- The Datadog Agent on Azure Container Instances in a private subnet. The callout service sends traces and security events to the Agent.
- A private DNS zone and virtual network link so APIM can resolve the internal Container Apps hostname.
- Virtual network integration on the existing APIM instance and, optionally, the Datadog policy itself.

Every other parameter has a default. Useful defaults include:

| Parameter                     | Default                                           |
| ----------------------------- | ------------------------------------------------- |
| `namePrefix`                  | `dd-apim`                                         |
| `datadogSite`                 | <YOUR_DATADOG_SITE>                               |
| `deployPolicy`                | `false`                                           |
| `enableHttps`                 | `false`                                           |
| `containerImage`              | `ghcr.io/datadog/dd-trace-go/apim-callout:latest` |
| `vnetAddressPrefix`           | `10.0.0.0/16`                                     |
| `minReplicas` / `maxReplicas` | `1` / `10`                                        |
| `concurrentRequestsThreshold` | `20`                                              |
| `targetApiIds`                | Empty, which applies to all APIs                  |

To deploy from the command line or from your own infrastructure-as-code instead, see [Configuring the Azure API Management callout](https://docs.datadoghq.com/security/application_security/setup/azure/api-management/configuration.md).

## Apply the Datadog policy{% #apply-the-datadog-policy %}

The callout service only inspects traffic that the gateway sends to it, so attach the Datadog policy to the APIs you want to protect.

You have two options:

- Set `deployPolicy` to `true` and let the deployment inject the policy. The `targetApiIds` parameter selects which APIs receive the policy and defaults to all APIs.
- Apply the provided policy XML yourself in the APIM policy editor. Replace every occurrence of the placeholder URL `https://<dd-apim-callout-host>:8080` with the `calloutBaseUrl` output of the deployment, not the hostname alone. The output is `http://<ACA-FQDN>` unless you set `enableHttps` to `true`, and it does not include a port. Leaving the `https` scheme or `:8080` suffix in place causes the policy to miss the service and fail open.

{% alert level="warning" %}
Setting `deployPolicy` to `true` **replaces** the policy at each selected scope. It does not merge with what is already there, so any existing rules at that scope are lost. Apply the policy yourself when the APIs you are protecting already have policy content, and merge the Datadog inbound and outbound fragments into your existing sections.
{% /alert %}

For the policy contents, attachment scopes, and how a block becomes a client response, see [Azure API Management policies for App and API Protection](https://docs.datadoghq.com/security/application_security/setup/azure/api-management/policies.md).

## Validate the deployment{% #validate-the-deployment %}

Send a normal request, then a simulated attack:

```shell
# Normal request: passes through to your backend
curl -v https://<apim-gateway-host>/<api-path>

# Simulated attack: returns 403
curl -v -A dd-test-scanner-log-block "https://<apim-gateway-host>/<api-path>"
```

Verify the results in Datadog:

1. Open [Security > App and API Protection](https://app.datadoghq.com/security/appsec) and confirm that the simulated attack appears as a signal.
1. Open the [App and API Protection Service Inventory](https://app.datadoghq.com/security/appsec/inventory/services) and confirm that the `apim-callout` service appears. Its spans have the tag `component:apim-callout`. To use a different service name, set `DD_SERVICE` on the callout container.

The callout service also exposes a health endpoint on port `8081`. Container Apps ingress publishes only port `8080`, so the health endpoint is reachable only from within the container. Azure Container Apps uses it for liveness and readiness probes. To check its status, review replica health in the Azure portal.

## Performance{% #performance %}

Measured on a 0.5 vCPU, 1 GiB Azure Container Apps deployment:

| Phase                                                       | Processing time |
| ----------------------------------------------------------- | --------------- |
| Request headers                                             | ~2.4 ms         |
| Response headers                                            | ~2.4 ms         |
| Full APIM pipeline, including both callouts and the backend | ~9.7 ms         |

Body phases run only when body inspection is enabled and the previous phase requested the body. To minimize network round-trip time, deploy the callout service in the same Azure region as your APIM instance.

## Compatibility{% #compatibility %}

For the capabilities this integration supports and the versions that introduced them, see the [App and API Protection compatibility requirements](https://docs.datadoghq.com/security/application_security/setup/compatibility.md).

## Further reading{% #further-reading %}

Additional helpful documentation, links, and articles:

- [Configuring the Azure API Management callout](https://docs.datadoghq.com/security/application_security/setup/azure/api-management/configuration.md)
- [Azure API Management policies for App and API Protection](https://docs.datadoghq.com/security/application_security/setup/azure/api-management/policies.md)
- [App and API Protection Azure API Management callout source code](https://github.com/DataDog/dd-trace-go/tree/main/contrib/azure/apim-callout)
- [OOTB App and API Protection Rules](https://docs.datadoghq.com/security/default_rules.md?category=cat-application-security)
- [Troubleshooting App and API Protection](https://docs.datadoghq.com/security/application_security/troubleshooting.md)
