C# Academy · Lesson

Documenting Versioned APIs

Expose docs for multiple API versions.

Lesson 4 of 413 steps

Documenting Versioned APIs is a free C# Academy lesson on CoddyKit. This is lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, and your progress syncs across the web and the CoddyKit app. The C# Academy course includes 4 lessons in total.

One Document per Version

When an API has several versions, you typically want a separate OpenAPI document for each version so consumers see only the endpoints relevant to them.

// /openapi/v1.json -> only v1 endpoints
// /openapi/v2.json -> only v2 endpoints

The API Version Description Provider

Asp.Versioning exposes IApiVersionDescriptionProvider, which lists every discovered API version. You loop over it to register a document per version.

var provider = app.Services
    .GetRequiredService<IApiVersionDescriptionProvider>();

foreach (var desc in provider.ApiVersionDescriptions)
{
    // desc.GroupName is e.g. "v1", "v2"
}

Registering a Document per Version

Call AddOpenApi once per version group, naming each document after the group.

builder.Services
    .AddApiVersioning()
    .AddApiExplorer(o =>
    {
        o.GroupNameFormat = "'v'VVV";
        o.SubstituteApiVersionInUrl = true;
    });

builder.Services.AddOpenApi("v1");
builder.Services.AddOpenApi("v2");

Filtering Endpoints into the Right Document

Use a document transformer or the ShouldInclude predicate so each document contains only its version's endpoints, matched by group name.

builder.Services.AddOpenApi("v1", options =>
{
    options.ShouldInclude = description =>
        description.GroupName == "v1";
});

Mapping the Documents

MapOpenApi with the default pattern serves every named document at /openapi/{documentName}.json.

app.MapOpenApi();
// /openapi/v1.json and /openapi/v2.json both available

Setting Per-Document Info

Give each version document its own title and version in a transformer so the docs are self-describing.

builder.Services.AddOpenApi("v2", options =>
{
    options.AddDocumentTransformer((doc, ctx, ct) =>
    {
        doc.Info.Title = "Catalog API v2";
        doc.Info.Version = "2.0";
        return Task.CompletedTask;
    });
});

Marking Deprecated Versions in Docs

If a version is deprecated, surface that in its document description so consumers see the warning in the UI.

options.AddDocumentTransformer((doc, ctx, ct) =>
{
    if (ctx.DocumentName == "v1")
        doc.Info.Description = "DEPRECATED - migrate to v2.";
    return Task.CompletedTask;
});

Substituting the Version in URLs

SubstituteApiVersionInUrl = true rewrites the {version:apiVersion} route token into the concrete version (e.g. v1) in the document, so paths read cleanly.

// Without: /api/v{version}/products
// With:    /api/v1/products

A UI Tab per Version

Most viewers can show a dropdown of all documents. Configure the UI to point at each version's JSON.

app.MapScalarApiReference(options =>
{
    options.AddDocument("v1", "API v1", "/openapi/v1.json");
    options.AddDocument("v2", "API v2", "/openapi/v2.json");
});

Documenting Request and Response Shapes

Because v2 may change DTOs, give each version its own DTO types. OpenAPI then renders distinct schemas per document automatically.

// V1 DTO
public record ProductV1(int Id, string Name);
// V2 DTO (breaking change)
public record ProductV2(int Id, string Title, decimal Price);

Putting It Together

The full flow: configure versioning + API explorer, register one OpenApi document per version with a filter, map them, and point your UI at each.

builder.Services.AddApiVersioning().AddApiExplorer(o =>
{
    o.GroupNameFormat = "'v'VVV";
    o.SubstituteApiVersionInUrl = true;
});
builder.Services.AddOpenApi("v1");
builder.Services.AddOpenApi("v2");
// ...
app.MapOpenApi();
app.MapScalarApiReference();

Quick Check

Confirm how versioned docs are produced.

Recap

You documented versioned APIs:

  • Register one named OpenAPI document per version with AddOpenApi("vN").
  • IApiVersionDescriptionProvider enumerates versions; ShouldInclude filters endpoints.
  • SubstituteApiVersionInUrl renders concrete versioned paths.
  • Point the UI at each document for a per-version view.

That completes the versioning and OpenAPI course.

Free to start

Learn C# with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
93
Lessons
346

Frequently Asked Questions

Is the “Documenting Versioned APIs” lesson free?

Yes — the full text of “Documenting Versioned APIs” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO. The C# Academy course includes 4 lessons in total.

What will I learn in “Documenting Versioned APIs”?

Expose docs for multiple API versions. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “Documenting Versioned APIs” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. API Versioning Strategies
  2. Configuring Asp.Versioning
  3. Generating OpenAPI Documents
  4. Documenting Versioned APIs
← Back to C# Academy