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.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/completionsand/or/responses. This manual guide assumes OpenAI-shaped request and response bodies because the policy below reads OpenAI-specific fields such asmessages,input, andchoices[].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 readsevaluation.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 fromchoices[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’sRequestId 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, namedhiddenlayer-saas-auth) and referenced in any policy using:

