Files
vigilcare-clinical/docs/guides/20-openapi-swagger-documentation.md
T

8.2 KiB

Guide 20: OpenAPI / Swagger Documentation

What is OpenAPI and Swagger?

OpenAPI (formerly called Swagger Specification) is a standard format for describing REST APIs. An OpenAPI specification is a JSON or YAML file that lists every endpoint, its parameters, request/response shapes, authentication requirements, and error codes. Think of it as a machine-readable instruction manual for your API.

Swagger is a set of tools that work with OpenAPI specifications:

  • Swagger UI: A web-based interactive API explorer. Developers can browse endpoints, see parameter descriptions, and make live test requests — all from the browser, without writing any code.
  • Swashbuckle: A .NET library that automatically generates the OpenAPI specification from your controller code and XML documentation comments, and hosts Swagger UI.

Why does this matter? Without API documentation, frontend developers need to read the backend C# code (or ask the backend developer) to understand how to call each endpoint. With Swagger UI, they open a browser, see every endpoint, and can test them immediately. The documentation stays in sync with the code automatically because it's generated from the code.


Setup in Program.cs

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    // Basic API information
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Title = "VigilCare Clinical API",
        Version = "v1",
        Description = "Clinical monitoring and alerting platform API"
    });

    // Tell Swagger UI that the API requires a JWT Bearer token
    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Name = "Authorization",
        Type = SecuritySchemeType.Http,
        Scheme = "bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "Enter your JWT token"
    });

    // Apply the Bearer requirement to all endpoints by default
    options.AddSecurityRequirement(document => new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecuritySchemeReference("Bearer", document),
            new List<string>()
        }
    });

    // Include XML documentation comments from the compiled assembly
    var xmlPath = Path.Combine(AppContext.BaseDirectory,
        $"{Assembly.GetExecutingAssembly().GetName().Name}.xml");
    options.IncludeXmlComments(xmlPath);
});

What does each part do?

Setting Purpose
AddEndpointsApiExplorer() Enables the metadata extraction that Swashbuckle needs to discover your endpoints
SwaggerDoc("v1", ...) Names the API spec "v1" with a title and description shown at the top of Swagger UI
AddSecurityDefinition("Bearer", ...) Adds an "Authorize" button to Swagger UI where developers can paste their JWT token
AddSecurityRequirement(...) Shows a lock icon on every endpoint, indicating authentication is required
IncludeXmlComments(xmlPath) Reads the /// XML doc comments from your C# code and displays them as endpoint descriptions

Enabling Swagger UI

app.UseSwagger();        // Serves the OpenAPI spec at /swagger/v1/swagger.json
app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("/swagger/v1/swagger.json", "VigilCare Clinical API v1");
});

Available at: http://localhost:5270/swagger/ui


Writing Good Swagger Documentation

Swagger UI shows two things about each endpoint: information from your C# code attributes, and information from XML documentation comments.

Controller and Action Attributes

[ApiController]
[Route("api/v1/alert-thresholds")]
[Produces("application/json")]
[Authorize]
public class AlertThresholdsController : ControllerBase
{
    [HttpPost]
    [AuthorizePermission(ClinicalPermissions.ThresholdsWrite)]
    [ProducesResponseType(typeof(ApiResponse<AlertThreshold>), StatusCodes.Status201Created)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    public async Task<IActionResult> Create([FromBody] AlertThresholdRequest req)
  • [Produces("application/json")] tells Swagger the response format
  • [ProducesResponseType(...)] documents which status codes the endpoint can return and what the response body looks like. Swagger UI shows these as expandable response examples.
  • [FromBody] tells Swagger the request body schema comes from AlertThresholdRequest

XML Documentation Comments

/// <summary>
/// Creates a new alert threshold for an observation code.
/// </summary>
/// <param name="req">Threshold bounds and display metadata.</param>
/// <returns>The created threshold.</returns>
[HttpPost]
public async Task<IActionResult> Create([FromBody] AlertThresholdRequest req)

The <summary> appears as the endpoint description in Swagger UI. The <param> tags describe individual parameters. The <returns> tag describes the response.

How does this work? When you build a C# project with <GenerateDocumentationFile>true</GenerateDocumentationFile> in the .csproj file, the compiler creates an XML file containing all /// comments. Swashbuckle reads this XML file at runtime and merges the comments into the OpenAPI specification.


What Swagger UI Shows

When you open http://localhost:5270/swagger/ui, you see:

  1. API title and description from SwaggerDoc()
  2. Grouped endpoints organized by controller (Encounters, Observations, Alert Thresholds, FHIR, etc.)
  3. For each endpoint:
    • HTTP method and URL (e.g., POST /api/v1/encounters/{encounterId}/observations)
    • Summary from <summary> XML comment
    • Parameter descriptions from <param> XML comments
    • Request body schema (auto-generated from the C# request class)
    • Response schemas for each status code (from [ProducesResponseType])
  4. "Authorize" button — paste a JWT token to authenticate all subsequent requests
  5. "Try it out" button — fill in parameters and execute real requests against the running API

Security Scheme in Swagger UI

The security definition adds an "Authorize" button at the top of Swagger UI:

options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
    Name = "Authorization",
    Type = SecuritySchemeType.Http,
    Scheme = "bearer",
    BearerFormat = "JWT",
    In = ParameterLocation.Header,
    Description = "Enter your JWT token"
});

How to use it:

  1. Call POST /api/v1/auth/login with username/password to get a token
  2. Click "Authorize" in Swagger UI
  3. Paste the token (without the "Bearer " prefix — Swagger adds it automatically)
  4. Click "Authorize" — all subsequent requests include the Authorization: Bearer <token> header

The Generated OpenAPI Specification

The raw specification is available at /swagger/v1/swagger.json. It's a standard OpenAPI 3.0 document that can be consumed by:

  • Code generators: Generate API client libraries for TypeScript, Python, Java, etc. using tools like openapi-generator or nswag
  • Testing tools: Import into Postman, Insomnia, or Bruno for manual testing
  • Documentation platforms: Host on ReadMe, Stoplight, or Redocly for public documentation
  • Contract testing: Validate that the API implementation matches the specification

Key Takeaways

  • Swagger UI makes your API self-documenting — developers can explore and test endpoints from a browser without reading C# code
  • Write <summary> comments on every controller action — they become the endpoint descriptions in Swagger UI. Without them, endpoints are listed without any explanation.
  • Use [ProducesResponseType] for every status code — this documents the possible responses and their shapes, making it clear what success and error responses look like
  • The security definition enables authenticated testing — developers can paste a JWT token in the UI and test protected endpoints without using curl or Postman
  • The OpenAPI spec is a machine-readable contract — frontend teams can generate TypeScript API clients from it, ensuring type-safe API calls without manual typing
  • Documentation stays in sync with code — because it's generated from the actual controller code and attributes, it can never go stale (unlike a manually-written Wiki page)