Skip to content

API Documentation

Chris Martinez edited this page Feb 23, 2026 · 20 revisions

Adding documentation is often the final, pivotal step in making your versioned services available to clients and fosters their utilization. While there are many approaches to documenting your services, OpenAPI (formerly Swagger) has quickly become the de facto method for describing REST services.

The ASP.NET API versioning project provides several new API explorer implementations that make it easy to add versioning into your OpenAPI configurations. Each of these API explorers do all of the heavy lifting to discover and collate your REST services by API version. They do not directly rely on nor use any external OpenAPI libraries so that you can use them for other scenarios as well.

Any OpenAPI generator such as Microsoft, Swashbuckle, or NSwag that leverage the API Explorer can be used.

ASP.NET Web API NuGet Package

Everything you need to add versioned documentation to your API controllers using API Explorer extensions with Swashbuckle.

config.AddApiVersioning();

// (optional) format the version as "'v'major[.minor][-status]"
var apiExplorer = config.AddVersionedApiExplorer( o => o.GroupNameFormat = "'v'VVV" );

config.EnableSwagger(
    "{apiVersion}/swagger",
    swagger =>
    {
        swagger.MultipleApiVersions(
            ( apiDescription, version ) => apiDescription.GetGroupName() == version,
            info =>
            {
                foreach ( var group in apiExplorer.ApiDescriptions )
                {
                    info.Version( group.Name, $"Example API {group.ApiVersion}" );
                }
            } );
    } )
 .EnableSwaggerUi( swagger => swagger.EnableDiscoveryUrlSelector() );

Review the example project for additional setup and configuration options.

ASP.NET Web API with OData NuGet Package

Everything you need to add versioned documentation to your OData controllers using the OData API Explorer extensions with Swashbuckle.

configuration.AddApiVersioning();

var modelBuilder = new VersionedODataModelBuilder( configuration )
{
    ModelConfigurations = { new MyModelConfiguration() }
};

configuration.MapVersionedODataRoutes( "odata", "api", modelBuilder );

// (optional) format the version as "'v'major[.minor][-status]"
var apiExplorer = configuration.AddODataApiExplorer( o => o.GroupNameFormat = "'v'VVV" );

configuration.EnableSwagger(
    "{apiVersion}/swagger",
    swagger =>
    {
        swagger.MultipleApiVersions(
            ( apiDescription, version ) => apiDescription.GetGroupName() == version,
            info =>
            {
                foreach ( var group in apiExplorer.ApiDescriptions )
                {
                    info.Version( group.Name, $"Example API {group.ApiVersion}" );
                }
            } );
    } )
 .EnableSwaggerUi( swagger => swagger.EnableDiscoveryUrlSelector() );

Review the following example projects for additional setup and configuration options:

Note: This API explorer does not directly tie into Swashbuckle with OData because that project also prescribes how API versioning is performed, which is incompatible with this project.

ASP.NET Core NuGet Package NuGet Package

Applies to ASP.NET Core 10.0+. For earlier versions, see the previous examples with Swashbuckle.

Everything you need to add versioned documentation to your Minimal and controller-based APIs using the API Explorer extensions, OpenAPI extensions, and Scalar.

var builder = WebApplication.CreateBuilder( args );

// only required if you're using controllers
builder.Services.AddControllers();

builder.Services.AddProblemDetails();
builder.Services.AddApiVersioning()
                .AddMvc() // ← bring in MVC (Core); not required for Minimal APIs
                .AddApiExplorer(
                     // (optional) format the version as "'v'major[.minor][-status]"
                     options => options.GroupNameFormat = "'v'VVV" )
                .AddOpenApi(
                     // (optional) apply Scalar-specific transformers
                     options => options.Document.AddScalarTransformers()
                );

var app = builder.Build();

// configure OpenAPI and Scalar to use a document per version
app.MapOpenApi().WithDocumentPerVersion();
app.MapScalarApiReference(
    options =>
    {
        var descriptions = app.DescribeApiVersions();

        for ( var i = 0; i < descriptions.Count; i++ )
        {
            var description = descriptions[i];
            var isDefault = i == descriptions.Count - 1;

            options.AddDocument( description.GroupName, description.GroupName, isDefault: isDefault );
        }
    } );

// only required if you're using controllers
app.MapControllers();

app.Run();

Review the following example projects for additional setup and configuration options:

ASP.NET Core with OData NuGet Package NuGet Package

Everything you need to add versioned documentation to your OData controllers using the API Explorer extensions, OpenAPI extensions, and Scalar.

var builder = WebApplication.CreateBuilder( args );

builder.Services.AddControllers().AddOData();
builder.Services.AddProblemDetails();
builder.Services.AddApiVersioning()
                .AddOData( options => options.AddRouteComponents() )
                .AddODataApiExplorer(
                     // (optional) format the version as "'v'major[.minor][-status]"
                     options => options.GroupNameFormat = "'v'VVV" )
                .AddOpenApi(
                     // (optional) apply Scalar-specific transformers
                     options => options.Document.AddScalarTransformers()
                );

var app = builder.Build();

// configure OpenAPI and Scalar to use a document per version
app.MapOpenApi().WithDocumentPerVersion();
app.MapScalarApiReference(
    options =>
    {
        var descriptions = app.DescribeApiVersions();

        for ( var i = 0; i < descriptions.Count; i++ )
        {
            var description = descriptions[i];
            var isDefault = i == descriptions.Count - 1;

            options.AddDocument( description.GroupName, description.GroupName, isDefault: isDefault );
        }
    } );

app.MapControllers();
app.Run();

Review the following example projects for additional setup and configuration options:

Clone this wiki locally