Expose your Open API specs with Azure API management
Tags: azure, api, bicep
Published: 2024-03-25 11:44:40

When deploying your API's to Azure API Management, you can have different logical API's that you want to have integrated by external applications or partners. 

For this, the API Developer portal can be deployed, but this could be somewhat tedious.  Another common approach is to expose the API's (only the ones you want to document publically!) specifications.  The Open API endpoint (or the Swagger endpoint as it used to be called). 

As documented in a previous post [Deploy multiple APIs in Azure API management, hosted in the same App service](https://dev.to/samvanhoutte/deploy-multiple-apis-in-azure-api-management-hosted-in-the-same-app-service-4159), you can easily have multiple API's deployed to Azure API management.

This post explains how you can expose the Open API spec endpoint for a logical API in Azure API Management. 

# Enable the Service Reader Role

The Azure API management service instance should be able to read its own definitions, in order to build the API spec.  For this, it is required we provide the Managed Identity of the Azure API management service with the `API Management Service Reader Role`.

This can be achieved with the following steps. 

## Enable managed identity 

Navigate to `Security` > `Managed Identities` in the configuration of your API Management instance. Make sure the status is set to `On`.  


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sryaxevdilj0yppysemf.png)

## Assign the required role

- After that , click the `Azure role assignments` button.  
- Click `Add role assignment (Preview)` button
- Select the resource group as scope, and search for the `API Management Service Reader role``


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0tfyye8mpgqgza445kr.png)

# Create the actual OpenAPI API definition

## Create the operation

- Create a new HTTP API (name: Swagger API) in Azure API management
- Add an operation manually that will download the API specification, by using the path parameter `api-id`: `/docs/{api-id}/openapi`.  


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ejktosg48nv919a0ibhp.png)


## Retrieve the OpenAPI spec from the management API

```
<policies>
    <inbound>
    <base />
   <!--Dynamically call the APIM Management API-->
   <send-request mode="new" response-variable-name="result" timeout="60" ignore-error="true">
      <set-url>@("https://management.azure.com/subscriptions/<subscriptionid>/resourceGroups/<resource-group>/providers/Microsoft.ApiManagement/service/<resourceid>"  + "/apis/" + context.Request.MatchedParameters.GetValueOrDefault("api-id","") + "?export=true&format=openapi&api-version=2021-01-01-preview")</set-url>
      <set-method>GET</set-method>
      <authentication-managed-identity resource="https://management.azure.com/" />
   </send-request>
   <!--Return the response-->
   <return-response>
      <set-status code="200" reason="OK" />
      <set-header name="Content-Type" exists-action="override">
         <value>application/yaml</value>
      </set-header>
      <set-body>@((string)(((IResponse)context.Variables["result"]).Body.As<JObject>()["value"]))</set-body>
   </return-response>
</inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>
```

This is the policy you can set on the operation.  With three replacements to make: 
- `<subscriptionid>`: the subscription id of the API management instance
- `<resource-group>`: the resource group name of the API management instance
- `<resourceid>`: the name of the API management instance.

# Testing the solution

Just calling the API endpoint will now return the actual Open API spec as yaml.  For this you need to provide the api-id value.  This is the system name of the API in your instance.  The field that is greyed out in the following screenshot: 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tj3pfc48v9igf7f1th00.png)