Azure API Management — Complete Guide
In this tutorial, you'll learn about Azure API Management. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Azure API Management is a hybrid, Multi-Cloud management platform for APIs, providing API Gateway, developer portal, management plane, and analytics in one service.
What You'll Learn
By the end of this lesson, you will import APIs, configure policies, manage products and subscriptions, use the developer portal, and set up version and revision management.
Why It Matters
Azure API Management provides a complete API lifecycle management solution with built-in developer portal, analytics, and policy engine, reducing the operational overhead of managing APIs.
Real-World Use
An enterprise imports a Swagger-defined API into Azure API Management, adds OAuth2 authentication via policy, publishes it as a product with subscription keys, and enables the developer portal for third-party developers.
Azure API Management Concepts
flowchart TD
Client --> APIM[Azure API Management]
APIM -->|Policies| Policies[Policy Engine]
APIM -->|Products| Products[Product Catalog]
APIM -->|Subscriptions| Sub[Subscription Mgmt]
APIM -->|Developer Portal| Portal[Developer Portal]
Policies --> Backend[Backend Service]
API Management Configuration
# azure_apim.py
from typing import Any, Dict, List, Optional
class AzureAPIMConfig:
def __init__(self, name: str, tier: str = "Developer"):
self.name = name
self.tier = tier
self.apis: List[Dict] = []
self.products: List[Dict] = []
self.policies: List[Dict] = []
def add_api(self, name: str, service_url: str,
openapi_spec: Optional[str] = None,
protocols: Optional[List[str]] = None):
self.apis.append({
"name": name,
"service_url": service_url,
"openapi_spec": openapi_spec,
"protocols": protocols or ["https"],
})
def add_product(self, name: str, display_name: str,
description: str, subscription_required: bool = True,
approval_required: bool = False,
state: str = "published"):
self.products.append({
"name": name,
"display_name": display_name,
"description": description,
"subscription_required": subscription_required,
"approval_required": approval_required,
"state": state,
})
def add_policy(self, scope: str, xml_content: str):
self.policies.append({
"scope": scope,
"xml": xml_content,
})
def summary(self) -> dict:
return {
"instance": self.name,
"tier": self.tier,
"apis": len(self.apis),
"products": len(self.products),
"policies": len(self.policies),
}
apim = AzureAPIMConfig("my-apim-instance", "Premium")
apim.add_api("Products API", "https://products-api.azurewebsites.net",
openapi_spec="products-swagger.json")
apim.add_api("Orders API", "https://orders-api.azurewebsites.net")
apim.add_product("starter", "Starter Tier",
"For evaluation and small projects",
subscription_required=True, state="published")
apim.add_product("enterprise", "Enterprise Tier",
"Full access with SLA support",
subscription_required=True, state="published")
print(f"APIM Instance: {apim.name} ({apim.tier})")
print(f"APIs: {len(apim.apis)}")
print(f"Products: {len(apim.products)}")
for p in apim.products:
print(f" {p['name']}: {p['display_name']} ({p['state']})")
Expected output:
APIM Instance: my-apim-instance (Premium)
APIs: 2
Products: 2
starter: Starter Tier (published)
enterprise: Enterprise Tier (published)
Policy Configuration
# apim_policies.py
from typing import Dict, List, Optional
class APIMPolicyBuilder:
def __init__(self):
self.policies: List[str] = []
def add_inbound(self, policy_xml: str):
self.policies.append(f"<inbound>{policy_xml}</inbound>")
def add_outbound(self, policy_xml: str):
self.policies.append(f"<outbound>{policy_xml}</outbound>")
def add_backend(self, policy_xml: str):
self.policies.append(f"<backend>{policy_xml}</backend>")
def add_on_error(self, policy_xml: str):
self.policies.append(f"<on-error>{policy_xml}</on-error>")
def add_rate_limit(self, calls: int = 100, renewal_period: int = 60):
self.add_inbound(
f'<rate-limit calls="{calls}" renewal-period="{renewal_period}" />'
)
def add_cors(self, origins: List[str] = None):
origins = origins or ["*"]
origins_xml = "\n".join(f"<origin>{o}</origin>" for o in origins)
self.add_inbound(
f"<cors allow-credentials=\"true\">\n"
f" <allowed-origins>\n{origins_xml}\n"
f" </allowed-origins>\n"
f" <allowed-methods>\n"
f" <method>GET</method><method>POST</method><method>PUT</method>\n"
f" <method>DELETE</method>\n"
f" </allowed-methods>\n"
f"</cors>"
)
def build(self) -> str:
return "<policies>\n" + "\n".join(self.policies) + "\n</policies>"
builder = APIMPolicyBuilder()
builder.add_rate_limit(calls=100, renewal_period=60)
builder.add_cors(origins=["https://app.example.com", "https://admin.example.com"])
print(builder.build())
Expected output shows XML policies with rate-limit and cors sections.
Common Mistakes
1. Not Using Products for Access Control
Without products, all APIs are accessible to all subscribers. Products group APIs and control access through subscriptions.
2. Overly Permissive CORS Policies
Using * for allowed origins opens the API to any website. Restrict to specific domains.
3. No Backend Circuit Breaking
Without retry and timeout policies, backend failures propagate to clients. Configure retry and circuit breaker policies.
4. Not Enabling Developer Portal
The developer portal is essential for third-party API consumers. Customize it with documentation, code samples, and interactive console.
5. Ignoring Version Management
Without versions, changing an API breaks existing consumers. Use versions and revisions for non-breaking changes.
Practice Questions
1. What is a product in Azure API Management?
A product groups one or more APIs and controls access through subscriptions. Products can have different access tiers (free, pro, enterprise).
2. How do policies work in Azure API Management?
Policies are XML snippets that execute in order: inbound (request), backend, outbound (response), and on-error. They can transform, validate, and secure API traffic.
3. What is the difference between versions and revisions?
Versions allow breaking changes with separate URL paths. Revisions are non-breaking changes that can be made current without changing the URL.
4. How does the developer portal benefit API consumers?
It provides interactive API documentation, code samples, API key management, and a test console for developers to explore the API.
Challenge
Configure an Azure API Management instance with three APIs, two products (free and pro), Rate Limiting policies (10 req/min free, 100 req/min pro), CORS restrictions, and OAuth2 JWT validation.
FAQ
Mini Project: APIM Configuration Generator
# apim_gen.py
import json
from typing import Dict, List, Optional
class APIMGenerator:
def __init__(self):
self.config = {"properties": {"publisherEmail": "admin@example.com",
"publisherName": "DodaTech"}}
def set_tier(self, tier: str):
self.config["sku"] = {"name": tier, "capacity": 1}
def add_api(self, name: str, service_url: str,
display_name: Optional[str] = None):
if "apis" not in self.config:
self.config["apis"] = []
self.config["apis"].append({
"name": name,
"properties": {
"displayName": display_name or name,
"serviceUrl": service_url,
"protocols": ["https"],
"subscriptionRequired": True,
},
})
gen = APIMGenerator()
gen.set_tier("Premium")
gen.add_api("products-api", "https://products.azurewebsites.net", "Products API")
gen.add_api("orders-api", "https://orders.azurewebsites.net", "Orders API")
print(f"Tier: {gen.config['sku']['name']}")
print(f"APIs: {len(gen.config.get('apis', []))}")
for api in gen.config.get("apis", []):
print(f" {api['name']}: {api['properties']['serviceUrl']}")
Expected output:
Tier: Premium
APIs: 2
products-api: https://products.azurewebsites.net
orders-api: https://orders.azurewebsites.net
What's Next
You understand Azure API Management. Next, learn about GraphQL gateway, then explore gateway monitoring.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro