Every response from Claude on Microsoft Foundry carries two correlation IDs in its headers: request-id and apim-request-id. Teams coming from the first-party Claude API recognize the first and ignore the second; teams coming from Azure recognize the second and ignore the first. On Foundry you need to capture both, because a single request lives in two systems and each ID only unlocks one of them.
Two IDs, two systems
A Claude call on Foundry goes to an Azure endpoint of the form https://<resource>.services.ai.azure.com/anthropic/v1/messages. Azure's front door — API Management, the gateway layer that handles routing, authentication, and metering for Foundry resources — processes it on the Azure side, and Anthropic's serving stack handles the model inference (Claude on Foundry is an Anthropic-operated service on both hosting options).
| Header | Issued by | Traces the request through |
|---|---|---|
request-id | Anthropic | Anthropic's serving systems — the same header the first-party Claude API returns (e.g. req_018EeWyXxfu5pfWkrYcMdjWG) |
apim-request-id | Azure API Management | Azure's gateway and the Azure-side infrastructure of your Foundry resource |
Anthropic's Foundry documentation is direct about why this matters: when contacting support, provide both IDs so support teams can trace the request across both Anthropic's systems and Azure's. Give Anthropic only an apim-request-id and they cannot find the inference; give Microsoft only a request-id and they cannot find the gateway transaction. A ticket with one ID often turns into a slow round-trip asking for the other — capturing both up front is the difference between a same-day answer and a week of back-and-forth.
Capturing both headers reliably
The mistake to avoid is logging response bodies and discarding headers. The Messages API response body contains an id field for the message, but the correlation headers live at the HTTP layer. If your logging wrapper deserializes the JSON and throws the rest away, you have lost the IDs precisely for the requests you will need them: failures, where there may be no body worth parsing at all.
At the REST layer the pattern is straightforward — read both headers off every response, success or error, and attach them to your structured logs:
import httpx
resp = httpx.post(
"https://example-resource.services.ai.azure.com/anthropic/v1/messages",
headers={"x-api-key": FOUNDRY_KEY, "anthropic-version": "2023-06-01"},
json={"model": "claude-sonnet-5", "max_tokens": 256,
"messages": [{"role": "user", "content": "Hello"}]},
)
log.info("claude_call",
request_id=resp.headers.get("request-id"),
apim_request_id=resp.headers.get("apim-request-id"),
status=resp.status_code)
If you use the AnthropicFoundry SDK client, the same principle applies: capture the headers from the raw HTTP response rather than only the parsed message object — the Anthropic SDKs expose raw-response access for exactly this purpose (check your SDK version's documentation for the specific helper). Whichever route you take, make header capture unconditional: wrap it in your client so no code path — streaming, retries, error handlers — can skip it.
request-id, and apim-request-id. Index all three.Fitting the IDs into your observability stack
Beyond support tickets, the dual IDs earn their keep in day-to-day debugging. Azure Monitor metrics and diagnostic logs describe your Foundry resource in aggregate; when a dashboard shows an error spike, the apim-request-id values from your application logs are how you connect specific failed calls to what Azure-side telemetry recorded (see Foundry diagnostic logs and Log Analytics for Claude). Meanwhile the request-id is your only handle into the Anthropic side of the stack, which you cannot observe directly.
One privacy note: correlation IDs are safe metadata — they identify requests without containing prompt content. That makes them the right thing to put in tickets and logs freely, unlike prompts and completions, which deserve the careful handling described in prompt-log content privacy.
Where to go next
Foundry's other observability gap — the missing anthropic-ratelimit-* headers — is covered in rate-limit visibility on Foundry. For the first-party equivalent of request-id, see Claude API error codes.