# Azure API Management

- Canonical URL: https://docs.fairvisor.com/docs/gateway/azure-apim/
- Section: docs
- Last updated: n/a
> Integrating Fairvisor Edge with Azure APIM using inbound policy decision checks.


For Azure, the canonical managed-gateway pattern is APIM inbound policy calling Fairvisor decision endpoint before backend forwarding.

## Architecture

```text
Client -> Azure APIM inbound policy -> Fairvisor /v1/decision
                                  | allow -> backend service
                                  | reject -> 429 response
```

## APIM policy sketch

Use inbound policy to call Fairvisor and branch on status:

```xml
<policies>
  <inbound>
    <base />

    <send-request mode="new" response-variable-name="fvDecision" timeout="0.3" ignore-error="false">
      <set-url>{{fairvisor-edge-url}}/v1/decision</set-url>
      <set-method>POST</set-method>
      <set-header name="X-Original-Method" exists-action="override">
        <value>@(context.Request.Method)</value>
      </set-header>
      <set-header name="X-Original-URI" exists-action="override">
        <value>@(context.Request.OriginalUrl.Path + context.Request.OriginalUrl.QueryString)</value>
      </set-header>
      <set-header name="Authorization" exists-action="override">
        <value>@(context.Request.Headers.GetValueOrDefault("Authorization", ""))</value>
      </set-header>
      <set-header name="X-Forwarded-For" exists-action="override">
        <value>@(context.Request.IpAddress)</value>
      </set-header>
    </send-request>

    <choose>
      <when condition="@( ((IResponse)context.Variables[\"fvDecision\"]).StatusCode == 429 )">
        <return-response>
          <set-status code="429" reason="Too Many Requests" />
          <set-header name="Retry-After" exists-action="override">
            <value>@(((IResponse)context.Variables["fvDecision"]).Headers.GetValueOrDefault("Retry-After", "1"))</value>
          </set-header>
          <set-header name="X-Fairvisor-Reason" exists-action="override">
            <value>@(((IResponse)context.Variables["fvDecision"]).Headers.GetValueOrDefault("X-Fairvisor-Reason", "rate_limited"))</value>
          </set-header>
        </return-response>
      </when>
    </choose>
  </inbound>
  <backend><base /></backend>
  <outbound><base /></outbound>
  <on-error><base /></on-error>
</policies>
```

Adjust policy syntax for your APIM tier/runtime version.

## Failure policy

Decide behavior when Fairvisor is unavailable:

- fail-closed: return 503/deny from policy
- fail-open: skip deny and continue to backend

Use route-based split from [Gateway Failure Policy](/docs/reference/gateway-failure-policy/).

## Timeout guidance

- keep decision timeout low (200-500 ms budget)
- avoid retries in inbound policy hot path
- alert on timeout spikes and downstream dependency errors

## Security notes

- Keep Fairvisor on private network path (VNet/private endpoint where possible)
- Limit callers to APIM boundary only
- Do not trust external `X-Original-*` headers from clients

## Verification checklist

1. Allowed request reaches backend
2. Limited request returns `429` with `Retry-After`
3. `X-Fairvisor-Reason` visible in logs and response
4. Outage drill validates chosen fail-open/closed behavior

See [Decision API](/docs/reference/api/) for canonical header contract.

