Skip to content

Azure API Management — Complete Guide

DodaTech Updated 2026-06-28 5 min read

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

Can Azure API Management handle GraphQL?

Yes. Azure API Management supports GraphQL APIs with schema validation, query complexity analysis, and resolver policies.

What tiers does Azure API Management offer?

Developer (dev/test), Basic (production with limited features), Standard, and Premium (multi-region, VNet, SLA).

How does Azure API Management handle caching?

It supports external Redis cache for response caching with configurable TTLs and cache key policies.

Can I import existing APIs?

Yes. You can import OpenAPI 2.0/3.0, WSDL, GraphQL schema, and SOAP APIs directly.

Does Azure API Management support WebSockets?

Yes. The Premium tier supports WebSocket APIs with rate limiting and authentication policies.

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