This product is not supported for your selected Datadog site. ().
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.

This page describes how to deploy and configure the App and API Protection callout service for Azure API Management (APIM) without using the one-click template. If you have not deployed the integration yet, start with Enabling App and API Protection for Azure API Management.

The callout service ships as the container image ghcr.io/datadog/dd-trace-go/apim-callout:latest. It listens on two ports:

  • 8080 serves the callout endpoint, POST /, which handles all request and response phases.
  • 8081 serves the health endpoint, GET /.

Deployment options

The deploy/azure/deploy.sh script wraps az deployment group create.

It first verifies that the Azure CLI is installed and authenticated, Bicep is available, the resource group exists, and the APIM tier is not Consumption. It then runs az deployment group what-if so you can preview the changes before applying them.

DD_API_KEY=<your-datadog-api-key> \
  ./deploy/azure/deploy.sh \
  --resource-group <rg-name> \
  --apim-name <apim-service-name>

On success, the script prints the callout URL, the Container Apps hostname, the Datadog Agent IP address, and whether the policy was deployed.

This example omits both --deploy-policy and --no-deploy-policy, which makes the script choose for you. It reads the existing policy at the target scope and then:

  • Deploys the policy when the scope has no policy, or only the default skeleton.
  • Skips deployment when it finds the Datadog callout already in place, or any custom policy content.

This differs from the Bicep module, where deployPolicy defaults to false. The command above can therefore write an APIM policy. To guarantee that no policy is written, pass --no-deploy-policy.

Available flags:

FlagDescription
--resource-group, -gResource group for the deployment.
--apim-nameName of the APIM instance to protect.
--apim-resource-groupResource group containing the APIM instance, if different from the deployment resource group. You also need permission to create resources in that resource group. The deployment creates a managed identity, a role assignment, and a deployment script there.
--api-idsRestrict the policy to specific API IDs.
--deploy-policyInject the Datadog policy.
--no-deploy-policySkip policy injection.
--what-ifPreview the deployment without applying it.
--name-prefixPrefix for created resource names.
--container-imageOverride the callout container image.
--dd-siteDatadog site.
--log-analytics-workspace-idID of an existing Log Analytics workspace for logs.
--vnet-address-prefixAddress space for the created virtual network. The subnet prefixes are fixed, so this value must contain them. See Address ranges.
--existing-vnet-idID of an existing virtual network to use. See Using an existing virtual network for the required subnets and their prerequisites.
--existing-aca-subnet-idID of an existing subnet for the callout service. Required with --existing-vnet-id.
--existing-aci-subnet-idID of an existing subnet for the Datadog Agent. Required with --existing-vnet-id.
--enable-httpsServe the callout endpoint over HTTPS.
--no-locksSkip resource locks.
--min-replicasMinimum number of callout replicas.
--max-replicasMaximum number of callout replicas.
--concurrent-requestsConcurrent requests per replica before scaling out.

The script reads DD_API_KEY and DD_SITE from the environment.

Reference the Bicep module directly from your own infrastructure-as-code:

module apimCallout 'path/to/contrib/azure/apim-callout/deploy/azure/main.bicep' = {
  name: 'dd-apim-callout'
  params: {
    datadogApiKey: keyVault.getSecret('dd-api-key')
    apimServiceName: 'my-apim'
    logAnalyticsWorkspaceId: logAnalytics.id
    // every other parameter has a default
  }
}

datadogApiKey and apimServiceName are required. The remaining parameters are optional: apimResourceGroup, targetApiIds, logAnalyticsWorkspaceId, namePrefix, location, datadogSite, deployPolicy, enableHttps, containerImage, vnetAddressPrefix, existingVnetId, existingAcaSubnetId, existingAciSubnetId, enableLocks, minReplicas, maxReplicas, concurrentRequestsThreshold, and customTags.

Setting existingVnetId makes existingAcaSubnetId and existingAciSubnetId required, and adds prerequisites on those subnets. Setting vnetAddressPrefix does not move the subnets. For both, see Networking.

Defaults:

ParameterDefault
namePrefixdd-apim
datadogSitedatadoghq.com
deployPolicyfalse
enableHttpsfalse
containerImageghcr.io/datadog/dd-trace-go/apim-callout:latest
vnetAddressPrefix10.0.0.0/16
minReplicas / maxReplicas1 / 10
concurrentRequestsThreshold20
targetApiIdsempty, which applies to all APIs

Accepted datadogSite values are datadoghq.com, us3.datadoghq.com, us5.datadoghq.com, datadoghq.eu, ap1.datadoghq.com, ap2.datadoghq.com, and ddog-gov.com. Your site is .

For local testing or for hosting outside Azure, run the image directly:

docker run -d \
  -p 8080:8080 \
  -p 8081:8081 \
  -e DD_AGENT_HOST=datadog-agent \
  ghcr.io/datadog/dd-trace-go/apim-callout:latest

Confirm the service is running:

curl -s http://localhost:8081/
# {"status":"ok","library":{"language":"golang","version":"2.x.x"}}

A container hosted this way still needs network reachability from the APIM gateway and a Datadog Agent to receive traces and security events.

Networking

Address ranges

vnetAddressPrefix and --vnet-address-prefix set the address space of the virtual network, but the subnet prefixes inside it are fixed:

SubnetPrefix
Callout service10.0.1.0/27
Datadog Agent10.0.2.0/24
APIM10.0.3.0/27

Because the deployment does not derive the subnets from the address space, any value you set must contain these three prefixes. The default 10.0.0.0/16 does. A value such as 10.1.0.0/16 leaves the subnets outside the virtual network, and the deployment fails.

To place the callout service in a different address range, supply your own network with existingVnetId instead.

Using an existing virtual network

Setting existingVnetId makes the deployment skip the virtual network, subnets, network security groups, and NAT gateway. You supply those instead, so existingAcaSubnetId and existingAciSubnetId become required, and each subnet must meet the requirements the deployment would otherwise have set up:

  • The callout subnet needs a Microsoft.App/environments delegation, and enough addresses for the Container Apps environment.
  • The Agent subnet needs a Microsoft.ContainerInstance/containerGroups delegation, and outbound connectivity so the Agent can reach Datadog.
  • The callout service must reach the Agent on port 8126.

The deployment also creates no APIM subnet in this mode, so the APIM instance must already be integrated with the same virtual network. Otherwise the APIM configuration step can fail, or APIM cannot resolve the callout service.

Configuration

The callout service enables the Datadog Web Application Firewall (WAF) itself at startup, so you do not need to set DD_APPSEC_ENABLED.

The service supports the following settings:

Environment variableDefault valueDescription
DD_APIM_CALLOUT_HOST0.0.0.0Address on which the callout service listens.
DD_APIM_CALLOUT_PORT8080Port for the callout endpoint (POST /).
DD_APIM_CALLOUT_HEALTHCHECK_PORT8081Port for the health endpoint (GET /).
DD_APPSEC_BODY_PARSING_SIZE_LIMIT10485760Maximum number of body bytes analyzed, in bytes (10 MB). Set to 0 to skip body analysis, which reduces the exchange to two calls.
DD_APIM_CALLOUT_REQUEST_TIMEOUT30sTime-to-live for cached per-request state. Orphaned state is released after this duration.
DD_APIM_CALLOUT_TLSfalseServe HTTPS instead of HTTP.
DD_APIM_CALLOUT_TLS_CERT_FILE(empty)Path to the TLS certificate. Required when TLS is enabled.
DD_APIM_CALLOUT_TLS_KEY_FILE(empty)Path to the TLS private key. Required when TLS is enabled.

Automatic defaults

If the following variables are unset, the service assigns them at startup:

Environment variableValueDescription
DD_APM_TRACING_ENABLEDfalseWhether to send APM traces for the callout service itself.
DD_APPSEC_WAF_TIMEOUT10msPer-request WAF evaluation budget.
DD_TRACE_PROPAGATION_STYLEdatadogFormat of the trace-context headers injected into requests.

If a single WAF evaluation exceeds its budget, the request is allowed rather than delayed.

Datadog Agent connection

The callout service does not send data directly to Datadog. It sends traces and security events to a Datadog Agent, which forwards them to Datadog. The callout service and Agent run in separate containers, and each has its own environment variables.

On the callout container:

Environment variableDefault valueDescription
DD_AGENT_HOSTlocalhostHostname or IP of your Datadog Agent.

On the Datadog Agent container:

Environment variableDefault valueDescription
DD_API_KEY(required)Your Datadog API key.
DD_SITEdatadoghq.comYour Datadog site.
DD_APM_ENABLEDfalseSet to true. The Agent does not accept traces otherwise.
DD_APM_NON_LOCAL_TRAFFICfalseSet to true. The callout runs in a separate container, so its traffic is not local to the Agent.
DD_APM_RECEIVER_PORT8126Port the Agent accepts traces on. The callout must be able to reach it.

Because the callout runs in its own container, DD_APM_ENABLED and DD_APM_NON_LOCAL_TRAFFIC are both required. Without them the Agent drops the spans and security events this integration produces. The one-click deployment sets all of these on the Agent container for you.

Do not set DD_API_KEY on the callout container. The one-click deployment sets DD_AGENT_HOST on the callout container and maps datadogApiKey and datadogSite to DD_API_KEY and DD_SITE on the Agent container.

Your site is .

Encrypting the callout endpoint

To serve the callout endpoint over HTTPS, set DD_APIM_CALLOUT_TLS to true and provide both DD_APIM_CALLOUT_TLS_CERT_FILE and DD_APIM_CALLOUT_TLS_KEY_FILE. If TLS is enabled and either file is missing, the service does not start. The minimum accepted TLS version is 1.2.

When TLS is enabled, the APIM policy must call the service over https://.

Health check

Check the health endpoint on port 8081:

curl -s http://localhost:8081/
# {"status":"ok","library":{"language":"golang","version":"2.x.x"}}

A 200 response indicates that the service is running, but does not indicate the state of the WAF. To confirm that security data is arriving, use the Datadog UI checks described in Enabling App and API Protection for Azure API Management.

Sizing and performance

On a 0.5 vCPU, 1 GiB Azure Container Apps deployment, the request-headers and response-headers phases each take about 2.4 ms. The full APIM pipeline, including both callouts and the backend, takes about 9.7 ms.

Body phases run only when body inspection is enabled and the previous phase requested the body. The gateway maintains a connection pool to the callout service, which can reduce latency in production.

To minimize network round-trip time, deploy the callout service in the same Azure region as your APIM instance, and keep APIM close to your API consumers. By default, the service scales from 1 to 10 replicas and scales out at 20 concurrent requests per replica.

Further reading