Azure API Management (APIM) is not just a gateway; it’s the gatekeeper, the transformer, and the analyst for your backend services, making them discoverable, secure, and consumable by developers.

Let’s see APIM in action. Imagine you have a simple backend API running on Azure Functions, exposed via HTTP.

// Azure Function: MyHttpTriggerFunction
{
  "type": "Microsoft.Web/sites/functions",
  "apiVersion": "2021-01-01",
  "name": "my-function-app/MyHttpTriggerFunction",
  "properties": {
    "functionAppId": "/subscriptions/YOUR_SUB_ID/resourceGroups/my-rg/providers/Microsoft.Web/sites/my-function-app",
    "scriptRootPath": "...",
    "entryPoint": "...",
    "scriptFileName": "...",
    "runtime": "...",
    "disabled": false,
    "config": {
      "bindings": [
        {
          "type": "httpTrigger",
          "direction": "in",
          "name": "req",
          "methods": [
            "get",
            "post"
          ],
          "authLevel": "anonymous"
        },
        {
          "type": "http",
          "direction": "out",
          "name": "res"
        }
      ]
    }
  }
}

This function is accessible directly via its HTTP endpoint, something like https://my-function-app.azurewebsites.net/api/MyHttpTriggerFunction. Now, let’s put APIM in front of it.

First, you create an APIM instance:

az apim create \
  --name my-apim-service \
  --resource-group my-rg \
  --location eastus \
  --publisher-name "My Company" \
  --publisher-email "admin@mycompany.com" \
  --sku-name Developer_1 # Developer tier for testing

This creates a gateway URL, e.g., https://my-apim-service.azure-api.net. Next, you define an API within APIM that represents your backend.

az apim api create \
  --resource-group my-rg \
  --service-name my-apim-service \
  --api-type http \
  --name my-backend-api \
  --display-name "My Backend API" \
  --path "backend" \
  --protocols "https" \
  --import '{"value": {"serviceUrl": "https://my-function-app.azurewebsites.net"}}'

Here, serviceUrl points to your actual backend. APIM now knows about your API, but it needs operations. You’d typically import an OpenAPI (Swagger) specification, but for a simple case, you can define one operation:

az apim api operation create \
  --resource-group my-rg \
  --service-name my-apim-service \
  --api-name my-backend-api \
  --operation-id "get-items" \
  --display-name "Get Items" \
  --method "GET" \
  --url "/api/MyHttpTriggerFunction"

Now, if you call https://my-apim-service.azure-api.net/backend/api/MyHttpTriggerFunction (the APIM gateway URL, with the API’s path prefix), APIM will forward the request to your Azure Function.

The real power comes with policies. Let’s add a simple authentication policy to require a subscription key.

First, create a product to group your APIs and associate policies:

az apim product create \
  --resource-group my-rg \
  --service-name my-apim-service \
  --product-id "unlimited" \
  --display-name "Unlimited Access" \
  --description "For testing" \
  --subscription-required true

Then, link your API to this product:

az apim api product link create \
  --resource-group my-rg \
  --service-name my-apim-service \
  --api-name my-backend-api \
  --product-id "unlimited"

Now, when you try to access the API via APIM without a subscription key, you’ll get a 401 Unauthorized. You can create a subscription for a user:

az apim subscription create \
  --resource-group my-rg \
  --service-name my-apim-service \
  --user-id "test-user" \
  --display-name "Test Subscription" \
  --scope "global" # Or specify a product

This subscription will have a primary key. You can then pass this key in the Ocp-Apim-Subscription-Key header.

The APIM gateway is a sophisticated proxy. It intercepts requests, applies policies (like authentication, rate limiting, transformation), and then forwards them to your backend. The response from the backend is similarly processed by APIM before being returned to the client. This allows you to abstract away backend complexities, manage access, and gain insights without modifying your backend code.

The serviceUrl in the API definition is not just a destination; it’s the base URL that APIM uses when rewriting the request’s URL before sending it to the backend. If your backend API expects a specific host header, you can explicitly set it using a set-header policy within APIM to ensure the backend receives the request correctly.

The next hurdle is usually understanding how to leverage APIM’s transformation capabilities to modify requests or responses on the fly, like converting XML to JSON or adding/removing headers.

Want structured learning?

Take the full Azure course →