Azure API Management
Azure API Management (APIM) is a fully managed API gateway that sits in front of your backend APIs. It handles authentication, rate limiting, caching, transformation, monitoring, and developer documentation — so your backend services focus on business logic.
Why an API Gateway?
Section titled “Why an API Gateway?”Without a gateway, every backend service handles its own:
- Authentication and authorization
- Rate limiting and throttling
- Request/response transformation
- Monitoring and logging
- API versioning
An API gateway centralizes these concerns:
Clients (mobile, web, partners) │ ▼Azure API Management ├── Authentication (OAuth 2.0, API keys, JWT) ├── Rate limiting / throttling ├── Caching ├── Request transformation ├── Monitoring / analytics │ ├──► Backend: Order Service ├──► Backend: Product Service ├──► Backend: User Service └──► Backend: Azure FunctionAPIM Components
Section titled “APIM Components”| Component | What It Does |
|---|---|
| Gateway | Receives API calls, applies policies, routes to backends |
| Management plane | Configure APIs, products, policies (portal or ARM) |
| Developer portal | Auto-generated API documentation for consumers |
| Analytics | Usage metrics, error rates, latency |
Core Concepts
Section titled “Core Concepts”APIs, Operations, Products
Section titled “APIs, Operations, Products”Product: "Free Tier" (rate limit: 100 calls/min) └── API: Orders API (v1) ├── Operation: GET /orders ├── Operation: POST /orders └── Operation: GET /orders/{id}
Product: "Premium" (rate limit: 10,000 calls/min) ├── API: Orders API (v1) └── API: Analytics API (v2)| Concept | Description |
|---|---|
| API | A set of operations that map to a backend service |
| Operation | A single HTTP method + path (e.g. GET /orders) |
| Product | Groups APIs with usage policies (subscriptions, rate limits) |
| Subscription | An API key that grants access to a product |
| Policy | XML rules applied at various scopes (inbound, backend, outbound, on-error) |
Creating an APIM Instance
Section titled “Creating an APIM Instance”# Create an API Management instance (Developer tier for testing)az apim create \ --resource-group myapp-rg \ --name myapp-api \ --publisher-name "My Company" \ --sku-name Developer \ --location eastusAPIM Tiers
Section titled “APIM Tiers”| Tier | Use Case | SLA | Gateway Capacity | Cost |
|---|---|---|---|---|
| Consumption | Serverless, pay-per-call | 99.95% | Auto-scale | ~$3.50 per 10K calls |
| Developer | Testing and development | No SLA | 1 unit | ~$50/month |
| Basic | Small production | 99.95% | Up to 2 units | ~$150/month |
| Standard | Medium production | 99.95% | Up to 4 units | ~$700/month |
| Premium | Enterprise, multi-region | 99.99% | Up to 12+ units | ~$2,800/month |
Importing APIs
Section titled “Importing APIs”From OpenAPI Specification
Section titled “From OpenAPI Specification”# Import from an OpenAPI/Swagger fileaz apim api import \ --resource-group myapp-rg \ --service-name myapp-api \ --path "orders" \ --specification-format OpenApi \ --specification-url "https://myapp.azurewebsites.net/swagger/v1/swagger.json" \ --display-name "Orders API" \ --api-id "orders-api"From Azure Function App
Section titled “From Azure Function App”az apim api import \ --resource-group myapp-rg \ --service-name myapp-api \ --path "functions" \ --specification-format OpenApi \ --specification-url "https://my-func-app.azurewebsites.net/api/swagger.json" \ --display-name "Functions API"APIM can also import from Azure App Service, Logic Apps, or manually defined operations.
Policies
Section titled “Policies”Policies are XML rules that transform requests and responses at four stages:
<policies> <inbound> <!-- Applied before the request reaches the backend --> </inbound> <backend> <!-- Applied just before forwarding to the backend --> </backend> <outbound> <!-- Applied to the response before sending to the client --> </outbound> <on-error> <!-- Applied when an error occurs at any stage --> </on-error></policies>Common Policies
Section titled “Common Policies”Rate Limiting
Section titled “Rate Limiting”<inbound> <!-- 100 calls per 60 seconds per subscription key --> <rate-limit calls="100" renewal-period="60" />
<!-- Or by IP address --> <rate-limit-by-key calls="50" renewal-period="60" counter-key="@(context.Request.IpAddress)" /></inbound>JWT Validation
Section titled “JWT Validation”<inbound> <validate-jwt header-name="Authorization" require-scheme="Bearer" failed-validation-httpcode="401"> <openid-config url="https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration" /> <required-claims> <claim name="aud" match="all"> <value>{api-client-id}</value> </claim> </required-claims> </validate-jwt></inbound>Caching
Section titled “Caching”<inbound> <!-- Cache GET responses for 300 seconds --> <cache-lookup vary-by-developer="false" vary-by-developer-groups="false" downstream-caching-type="none" /></inbound><outbound> <cache-store duration="300" /></outbound>Request Transformation
Section titled “Request Transformation”<inbound> <!-- Add a header --> <set-header name="X-Request-Source" exists-action="override"> <value>api-gateway</value> </set-header>
<!-- Remove a header --> <set-header name="X-Internal-Token" exists-action="delete" />
<!-- Rewrite URL --> <rewrite-uri template="/api/v2/orders" /></inbound><inbound> <cors allow-credentials="true"> <allowed-origins> <origin>https://myapp.com</origin> <origin>https://admin.myapp.com</origin> </allowed-origins> <allowed-methods> <method>GET</method> <method>POST</method> <method>PUT</method> <method>DELETE</method> </allowed-methods> <allowed-headers> <header>Authorization</header> <header>Content-Type</header> </allowed-headers> </cors></inbound>Backend Circuit Breaker
Section titled “Backend Circuit Breaker”<backend> <forward-request timeout="30" /></backend><on-error> <return-response> <set-status code="503" reason="Service Unavailable" /> <set-body>{"error": "Backend temporarily unavailable"}</set-body> </return-response></on-error>Policy Scope
Section titled “Policy Scope”Policies can be applied at different scopes (inner scopes inherit outer):
Global (all APIs) └── Product (all APIs in a product) └── API (all operations in an API) └── Operation (single endpoint)Authentication Methods
Section titled “Authentication Methods”| Method | Use Case | Configuration |
|---|---|---|
| Subscription key | Simple API key in header or query | Built-in, per-product |
| OAuth 2.0 / JWT | Token-based auth (Entra ID) | validate-jwt policy |
| Client certificate | Mutual TLS | validate-client-certificate policy |
| Basic auth | Legacy systems | authentication-basic policy |
| Managed identity | Backend auth (APIM → backend) | authentication-managed-identity policy |
Subscription Keys
Section titled “Subscription Keys”# Clients include the key in the headercurl -H "Ocp-Apim-Subscription-Key: abc123..." \ https://myapp-api.azure-api.net/ordersAPI Versioning
Section titled “API Versioning”APIM supports multiple versioning schemes:
| Scheme | Example |
|---|---|
| URL path | /v1/orders, /v2/orders |
| Query string | /orders?api-version=2026-02-01 |
| Header | Api-Version: v2 |
# Create a version setaz apim api versionset create \ --resource-group myapp-rg \ --service-name myapp-api \ --display-name "Orders API" \ --versioning-scheme "Segment" \ --version-set-id "orders-versions"
# Create v2 of the APIaz apim api create \ --resource-group myapp-rg \ --service-name myapp-api \ --api-id "orders-v2" \ --display-name "Orders API v2" \ --path "orders" \ --api-version "v2" \ --api-version-set-id "orders-versions" \ --service-url "https://myapp-v2.azurewebsites.net"Developer Portal
Section titled “Developer Portal”APIM includes a self-service developer portal where API consumers can:
- Browse available APIs and operations.
- View request/response schemas and examples.
- Test APIs interactively (built-in test console).
- Sign up for products and get subscription keys.
- View usage analytics and quotas.
The portal is auto-generated from your API definitions and can be customized with branding.
Monitoring and Analytics
Section titled “Monitoring and Analytics”APIM provides built-in analytics:
| Metric | What It Shows |
|---|---|
| Requests | Total calls, success rate, error breakdown (4xx, 5xx) |
| Latency | Gateway processing time + backend response time |
| Capacity | Gateway resource utilization |
| Cache hit ratio | Percentage of requests served from cache |
Integrate with:
- Application Insights — Detailed request tracing, dependency maps.
- Azure Monitor — Alerts on error rates or latency.
- Event Hubs — Stream API logs for custom analytics.
APIM vs Application Gateway vs Azure Front Door
Section titled “APIM vs Application Gateway vs Azure Front Door”| APIM | Application Gateway | Azure Front Door | |
|---|---|---|---|
| Primary role | API gateway (L7 API management) | Load balancer (L7 web traffic) | Global CDN + load balancer |
| Policies | Rate limiting, JWT, caching, transformation | WAF, SSL, routing | WAF, caching, routing |
| Developer portal | Yes | No | No |
| API versioning | Yes | No | No |
| Best for | API consumers, partners, mobile backends | Web applications, WAF | Global web apps, CDN |
Key Takeaways
Section titled “Key Takeaways”- APIM centralizes authentication, rate limiting, caching, and monitoring for your APIs.
- Policies (XML) are the core mechanism — applied at inbound, backend, outbound, and on-error stages.
- Products group APIs with shared policies and subscription keys.
- JWT validation with Entra ID is the recommended auth method for modern APIs.
- The developer portal gives API consumers self-service documentation and testing.
- Consumption tier is serverless and cost-effective for low-traffic APIs; Standard/Premium for production.
- Use APIM for API management; use Application Gateway for web traffic and WAF.