← Back to Guides

API Versioning, Revisions and Lifecycle

IntermediateAPI Management2026-03-14

Versions vs Revisions

Azure API Management distinguishes between two types of API changes:

📝

Revisions

Non-breaking changes — bug fixes, policy updates
VisibilityHidden until made current
URLSame URL (optional ;rev=N for testing)
Breaking changesNo
Parallel accessOnly current revision is live
🚀

Versions

Breaking changes — new schema, removed fields
VisibilityPublished as separate API
URLDifferent URL path, header, or query param
Breaking changesYes
Parallel accessMultiple versions live simultaneously

Microsoft Reference: Versions and revisions

Revisions

Creating a Revision

# Create a new revision
az apim api revision create \
  --resource-group rg-integration-prod \
  --service-name apim-enterprise-prod \
  --api-id orders-api \
  --api-revision 2 \
  --api-revision-description "Add pagination support to GET /orders"

Testing a Revision

Access a specific revision by appending ;rev=N to the API path:

# Test revision 2 (not yet live)
curl "https://apim-enterprise-prod.azure-api.net/orders;rev=2/orders" \
  -H "Ocp-Apim-Subscription-Key: your-key"

Making a Revision Current

# Make revision 2 the current (live) version
az apim api release create \
  --resource-group rg-integration-prod \
  --service-name apim-enterprise-prod \
  --api-id orders-api \
  --api-revision 2 \
  --notes "Released pagination support"

Revision Workflow

1. Create revision 2 from current revision
2. Make changes to revision 2 (policies, operations, schemas)
3. Test revision 2 using ;rev=2 in the URL
4. Create a release to make revision 2 current
5. Previous revision remains accessible for rollback

Bicep Configuration

resource ordersApiRevision 'Microsoft.ApiManagement/service/apis@2023-05-01-preview' = {
  parent: apim
  name: 'orders-api;rev=2'
  properties: {
    displayName: 'Orders API'
    path: 'orders'
    protocols: ['https']
    apiRevision: '2'
    apiRevisionDescription: 'Add pagination support'
    subscriptionRequired: true
    sourceApiId: ordersApi.id
  }
}

Versions

Versioning Schemes

Scheme Example Use Case
URL Path /v1/orders, /v2/orders Most common, explicit
Query String /orders?api-version=2024-01-01 Azure-style, flexible
Header Api-Version: v2 Clean URLs, more complex for consumers

Microsoft Reference: API versioning

Creating a Version Set

resource versionSet 'Microsoft.ApiManagement/service/apiVersionSets@2023-05-01-preview' = {
  parent: apim
  name: 'orders-api-version-set'
  properties: {
    displayName: 'Orders API'
    versioningScheme: 'Segment'  // URL path segment
    description: 'Version set for the Orders API'
  }
}

resource ordersApiV1 'Microsoft.ApiManagement/service/apis@2023-05-01-preview' = {
  parent: apim
  name: 'orders-api-v1'
  properties: {
    displayName: 'Orders API v1'
    path: 'orders'
    apiVersion: 'v1'
    apiVersionSetId: versionSet.id
    protocols: ['https']
    subscriptionRequired: true
    format: 'openapi+json'
    value: loadTextContent('api-specs/orders-v1.json')
  }
}

resource ordersApiV2 'Microsoft.ApiManagement/service/apis@2023-05-01-preview' = {
  parent: apim
  name: 'orders-api-v2'
  properties: {
    displayName: 'Orders API v2'
    path: 'orders'
    apiVersion: 'v2'
    apiVersionSetId: versionSet.id
    protocols: ['https']
    subscriptionRequired: true
    format: 'openapi+json'
    value: loadTextContent('api-specs/orders-v2.json')
  }
}

Resulting URLs

https://apim-enterprise-prod.azure-api.net/orders/v1/orders    → v1 backend
https://apim-enterprise-prod.azure-api.net/orders/v2/orders    → v2 backend

API Lifecycle Management

Lifecycle Stages

Draft → Published → Deprecated → Retired
Stage Description Consumer Impact
Draft Under development, not visible No access
Published Active and available Full access
Deprecated Still available but discouraged Sunset header returned
Retired Removed from service 410 Gone response

Deprecation Policy

Add sunset headers to deprecated API versions:

<outbound>
    <set-header name="Sunset" exists-action="override">
        <value>Sat, 01 Jun 2026 00:00:00 GMT</value>
    </set-header>
    <set-header name="Deprecation" exists-action="override">
        <value>true</value>
    </set-header>
    <set-header name="Link" exists-action="override">
        <value><https://api.example.com/v2/docs>; rel="successor-version"</value>
    </set-header>
</outbound>

Retirement Policy (Return 410 Gone)

<inbound>
    <return-response>
        <set-status code="410" reason="Gone" />
        <set-header name="Content-Type" exists-action="override">
            <value>application/json</value>
        </set-header>
        <set-body>{
            "error": "API_RETIRED",
            "message": "This API version has been retired. Please migrate to v2.",
            "migrationGuide": "https://docs.example.com/migration/v1-to-v2",
            "newEndpoint": "https://api.example.com/v2"
        }</set-body>
    </return-response>
</inbound>

API Governance

Products for Access Control

Use Products to control which API versions are available to which consumers:

resource internalProduct 'Microsoft.ApiManagement/service/products@2023-05-01-preview' = {
  parent: apim
  name: 'internal-apis'
  properties: {
    displayName: 'Internal APIs'
    description: 'APIs for internal services'
    subscriptionRequired: true
    approvalRequired: false
    state: 'published'
  }
}

resource externalProduct 'Microsoft.ApiManagement/service/products@2023-05-01-preview' = {
  parent: apim
  name: 'external-apis'
  properties: {
    displayName: 'External Partner APIs'
    description: 'APIs for external partners'
    subscriptionRequired: true
    approvalRequired: true  // Manual approval required
    state: 'published'
    terms: 'By subscribing, you agree to our API Terms of Service.'
  }
}

API Change Log

Maintain a change log for consumers using the revision description:

Revision 5 (2026-03-14): Added pagination support to GET /orders
Revision 4 (2026-02-28): Fixed response schema for GET /orders/{id}
Revision 3 (2026-02-15): Added rate limiting policy (100 req/min)
Revision 2 (2026-02-01): Added X-Correlation-Id header to responses
Revision 1 (2026-01-15): Initial release

OpenAPI Specification Management

Exporting API Definitions

# Export OpenAPI 3.0 specification
az apim api export \
  --resource-group rg-integration-prod \
  --service-name apim-enterprise-prod \
  --api-id orders-api \
  --export-format openapi-link

# Export WSDL
az apim api export \
  --resource-group rg-integration-prod \
  --service-name apim-enterprise-prod \
  --api-id legacy-soap-api \
  --export-format wsdl-link

API-First Design

1. Design API in OpenAPI (Swagger Editor / Stoplight / SwaggerHub)
2. Review with stakeholders
3. Import to APIM as a new version
4. Apply policies (security, rate limiting, transformation)
5. Publish to Developer Portal
6. Generate client SDKs from OpenAPI spec

Microsoft Reference: API design best practices

CI/CD for API Lifecycle

Azure DevOps Pipeline for API Deployment

trigger:
  branches:
    include:
      - main
  paths:
    include:
      - apis/*

variables:
  - group: apim-settings

stages:
  - stage: ValidateAPIs
    jobs:
      - job: Validate
        steps:
          - task: UsePythonVersion@0
            inputs:
              versionSpec: '3.x'

          - script: |
              pip install openapi-spec-validator
              python -c "from openapi_spec_validator import validate_spec; import json; validate_spec(json.load(open('apis/orders-v2.json')))"
            displayName: 'Validate OpenAPI Spec'

  - stage: DeployAPIs
    dependsOn: ValidateAPIs
    jobs:
      - deployment: DeployToAPIM
        environment: 'apim-production'
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self

                - task: AzureCLI@2
                  displayName: 'Import API to APIM'
                  inputs:
                    azureSubscription: 'prod-service-connection'
                    scriptType: 'bash'
                    scriptLocation: 'inlineScript'
                    inlineScript: |
                      az apim api import \
                        --resource-group $(resourceGroup) \
                        --service-name $(apimName) \
                        --api-id orders-api-v2 \
                        --path orders \
                        --api-version v2 \
                        --api-version-set-id orders-api-version-set \
                        --specification-format OpenApiJson \
                        --specification-path apis/orders-v2.json \
                        --display-name "Orders API v2"

Best Practices

  1. Use URL path versioning for public APIs — it's the most explicit and discoverable
  2. Create revisions for non-breaking changes — avoid creating unnecessary versions
  3. Document all changes with revision descriptions
  4. Set sunset dates well in advance (minimum 6 months for external APIs)
  5. Use Products to control version access per consumer group
  6. Validate OpenAPI specs in CI/CD before importing to APIM
  7. Maintain backward compatibility within a version — use revisions for fixes
  8. Monitor version usage to identify when old versions can be retired
  9. Provide migration guides when deprecating versions
  10. Use semantic versioning (v1, v2) for clarity

Official Microsoft Resources