Skip to main content
This guide walks through inserting HiddenLayer AI Runtime Security into an Azure API Management (APIM) pipeline to scan and act on both user inputs and model outputs (including blocking unsafe content and redacting PII) before they reach the LLM or are returned to the user.
CLI recommended for most deploymentsFor repeatable APIM setup, use the hiddenlayer-apim CLI. The CLI deploys HiddenLayer APIM policy fragments, applies them to APIs, and preserves unrelated APIM policy rules. Use this manual policy guide when you need to inspect or customize the underlying XML directly.
Use this manual guide if you cannot run the CLI in your environment, need to understand the XML that APIM executes, or want to build a custom policy by hand.
Scope of this manual policy guideThe XML in this guide is OpenAI / Azure OpenAI chat-completions shaped. It parses OpenAI request and response fields directly and calls HiddenLayer’s /detection/v1/interactions endpoint. For providers that are not Azure OpenAI (Anthropic, Bedrock, Vertex, etc.), use the CLI’s v2-request-evals and v2-response-evals packages instead — they pass the original provider payload to HiddenLayer’s /detection/v2/request-evaluations and /detection/v2/response-evaluations endpoints and rely on HiddenLayer for provider parsing. See Fragment packages for per-package provider support.

Prerequisites

Azure

  • An Azure APIM instance.
  • An API in that APIM instance that proxies an Azure OpenAI resource and exposes /chat/completions and/or /responses. This manual guide assumes OpenAI-shaped request and response bodies because the policy below reads OpenAI-specific fields such as messages, input, and choices[].message.

HiddenLayer

  • Access to a HiddenLayer SaaS or containerized (hybrid) instance
  • A policy configured with the following:
    • Prompt Injection: Block
    • Code: Block (output at minimum; input optional)
    • PII: Redact
  • A project with that policy attached
Note on PII redactionThis guide demonstrates redaction for custom PII entities, which can only be added to a policy via API. If you haven’t done that yet, standard entity redaction (e.g., <PHONE_NUMBER>) will still work. See Runtime Security Policy to learn how to configure custom entities.

Background: How APIM Policy Works

Azure APIM policy is written in a combination of XML and C#. Full documentation on policy options is available in the Microsoft APIM policy reference. To edit policy from the Azure portal, navigate to the operation you want to moderate, then click the angle-bracket icon (</>) in either the Inbound Processing or Outbound Processing pane. Policy is organized into four sections:
  • <inbound>: Runs before the request is forwarded to the backend (LLM). Use this to scan user inputs.
  • <backend>: Controls how requests are forwarded.
  • <outbound>: Runs after the backend responds. Use this to scan model outputs.
  • <on-error>: Handles exceptions.

Complete Policy

The policy example below obtains a SaaS auth token, scans input with HiddenLayer in <inbound> (including optional block/redact), forwards the request to Azure OpenAI, then scans the model output in <outbound>. It supports both /chat/completions-style bodies (with system-role messages filtered out before scanning) and /responses-style bodies. The full policy can be copied into your APIM instance and assumes SaaS detection (https://api.hiddenlayer.ai). Replace placeholder named values ({{hiddenlayer-client-id}}, {{hiddenlayer-client-secret}}, {{hiddenlayer-project-id}}, {{aoai-api-key}}) before deploying. You can define these as named variables in Azure API Management and reference them with {{ }} as shown. The sections that follow explain each piece in detail.

How It Works: Section by Section

Calling HiddenLayer Inbound (User Input)

The inbound section intercepts the user’s request before it reaches the LLM and POSTs to HiddenLayer’s /detection/v1/interactions endpoint. For /chat/completions requests, the policy builds a filtered copy of messages that omits system role entries (so the system prompt is never sent to HiddenLayer). It scans the latest user message content. For /responses-style bodies, it reads the input field (string or message array) instead. Requests to HiddenLayer include Authorization (Bearer token from SaaS OAuth), HL-Project-Id, X-Correlation-ID (APIM RequestId), and X-Requester-Id (first hop from X-Forwarded-For, else client IP).

Responding Based on the HiddenLayer Evaluation

The policy reads evaluation.action from the JSON response (Block, Redact, or allow). If HiddenLayer returns a non-2xx status or times out, the policy fails open: it traces the failure and forwards the original request to Azure OpenAI. If the evaluation action is Block, the caller receives 403 with a JSON error body that includes correlation and event metadata. If the evaluation action is Redact, the inbound body is rewritten using modified_data.input.messages[0].content (for chat completions, the last user message is updated; for /responses, the input field is updated accordingly). After the HiddenLayer inbound check completes, the policy sets the Azure OpenAI Authorization header ({{aoai-api-key}}), removes Ocp-Apim-Subscription-Key and X-Requester-Id, and records timing for the backend call.

Calling HiddenLayer Outbound (Model Output)

The outbound section reads the assistant turn from choices[0].message (chat completions shape), sends only that normalized message to /detection/v1/interactions, and applies the same Block (403) / Redact / fail-open behavior. Redaction merges modified_data.output.messages back into choices[0].message. Timing / correlation headers (X-Correlation-ID, X-HiddenLayer-*-Ms, etc.) are added on the response for observability.

Appendix

Correlating HiddenLayer Logs with APIM Logs

The complete policy above already stores APIM’s RequestId as correlation_id and sends X-Correlation-ID on HiddenLayer requests and on the client response. That matches gateway logs without extra steps. If you are building a smaller policy or fragment by hand, you can add the same pattern explicitly:

APIM Policy Fragments

Policy fragments are centrally managed, reusable XML code snippets that can enable consistent integration with AI Runtime across the APIM environment. For more information from Microsoft, see Reuse Policy Configurations in API Management. It is common to maintain the inbound HiddenLayer logic (OAuth, input scan, Azure OpenAI headers) and the outbound HiddenLayer logic (output scan, timing headers) as separate fragments. That lets you reuse the HiddenLayer pieces across APIs while composing them with unrelated APIM policy (rate limiting, caching, JWT validation, transformation steps, or other backends) in the order your operation requires. The OAuth token cache logic shown in the inbound section above can be extracted into a fragment (for example, named hiddenlayer-saas-auth) and referenced in any policy using:
Example usage in a policy: