After setting up Swagger for basic API documentation, I realized there's so much more you can do with it — especially in real-world projects. Grouping endpoints, supporting versioning, securing Swagger with JWT, and even hiding endpoints when needed — these advanced use cases have made my development workflow smoother and more professional.
In this article, I’m sharing the Swagger features I actually use in .NET 6, 7, and 8 projects — along with code snippets, tips, and things to avoid.
📚 1. Grouping Endpoints (Using Tags)
Sometimes your Swagger UI becomes overwhelming with too many endpoints. Grouping them into logical sections makes it easier to navigate.
🔧 Option 1. Group by controller name (default)
This happens automatically, but you can customize it further.
🔧 Option 2. Use [ApiExplorerSettings(GroupName = "v1")]
Or use SwaggerDoc and define multiple groups.
// Program.cs 
builder.Services.AddSwaggerGen(c => 
{ 
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API V1", Version = "v1" }); 
    c.SwaggerDoc("v2", new OpenApiInfo { Title = "My API V2", Version = "v2" }); 
}); 
// Controller 
[ApiExplorerSettings(GroupName = "v2")] 
[Route("api/v2/[controller]")] 
public class OrdersController : ControllerBase 
{ 
    //... 
}
Now, Swagger UI will show v1 and v2 as tabs.
🔄 2. API Versioning in Swagger
If your app supports multiple API versions, Swagger should reflect that. Here’s how to set it up.
✅ Step 1. Add required NuGet packages
dotnet add package Microsoft.AspNetCore.Mvc.Versioning 
dotnet add package Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer
✅ Step 2. Configure versioning
builder.Services.AddApiVersioning(options => 
{ 
    options.ReportApiVersions = true; 
    options.AssumeDefaultVersionWhenUnspecified = true; 
    options.DefaultApiVersion = new ApiVersion(1, 0); 
}); 
builder.Services.AddVersionedApiExplorer(options => 
{ 
    options.GroupNameFormat = "'v'VVV"; 
    options.SubstituteApiVersionInUrl = true; 
});
✅ Step 3. Update SwaggerGen
builder.Services.AddSwaggerGen(); 
builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();
(You’ll need to create a ConfigureSwaggerOptions class — I can generate this for you if needed.)
🔐 3. Add JWT Authentication to Swagger UI
If you're using JWT Bearer tokens, you can allow Swagger to send them in request headers.
✅ Configure Swagger with Security Definitions
builder.Services.AddSwaggerGen(c => 
{ 
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme 
    { 
        Description = "Enter 'Bearer' followed by your JWT token.", 
        Name = "Authorization", 
        In = ParameterLocation.Header, 
        Type = SecuritySchemeType.ApiKey, 
        Scheme = "Bearer" 
    }); 
    c.AddSecurityRequirement(new OpenApiSecurityRequirement 
    { 
        { 
            new OpenApiSecurityScheme 
            { 
                Reference = new OpenApiReference 
                { 
                    Type = ReferenceType.SecurityScheme, 
                    Id = "Bearer" 
                } 
            }, 
            Array.Empty<string>() 
        } 
    }); 
});
Now Swagger UI will show an Authorize button at the top where you can paste your token.
🙈 4. Hiding Specific Endpoints from Swagger
Sometimes you don’t want every endpoint exposed in Swagger, especially internal or admin-only APIs.
🔧 Option. Use [ApiExplorerSettings(IgnoreApi = true)]
[ApiExplorerSettings(IgnoreApi = true)] 
[HttpGet("internal-only")] 
public IActionResult HiddenEndpoint() 
{ 
    return Ok("This won't appear in Swagger"); 
}
Works at both the action and controller level.
📤 5. Export Swagger JSON/YAML
You can share your API contract with clients or import it into tools like Postman or Azure API Management.
	- 
	JSON endpoint:
 https://localhost:5001/swagger/v1/swagger.json
 
- 
	YAML: You’ll need a separate generator, or use tools like Swagger Editor or SwaggerHub to convert JSON to YAML. 
📝 6. Improve Models with DataAnnotations
Swagger auto-generates schemas from your models. Enhance them with [Required], [StringLength], and summaries.
public class ProductDto 
{ 
    [Required] 
    [StringLength(50)] 
    public string Name { get; set; } 
    /// <summary>Product price in USD</summary> 
    public decimal Price { get; set; } 
}
Make sure XML comments are enabled to see them in the UI.
🎨 7. UI Customizations (Logo, Layout, etc.)
You can style Swagger UI by injecting CSS or JS.
app.UseSwaggerUI(c => 
{ 
    c.InjectStylesheet("/swagger-ui/custom.css"); 
    c.DocumentTitle = "My API Docs"; 
});
Use this to:
	- Add your company logo
- Change the default collapsed/expanded state
- Customize font/colors
🚀 Best Practices I Follow
	
		
			| Practice | Why It Matters | 
	
	
		
			| Group endpoints and support versioning | Helps clients consume APIs reliably | 
		
			| Secure Swagger UI with tokens or roles | Avoids exposing sensitive endpoints | 
		
			| Use meaningful model annotations | Improves documentation quality | 
		
			| Keep Swagger in sync with real behavior | Prevents confusion for API consumers | 
		
			| Don’t expose internal/test-only APIs | Keeps docs clean and production-safe | 
	
 
👋 Conclusion
When you go beyond the basics, Swagger becomes a powerful tool, not just for docs, but for API governance and developer experience. These advanced use cases have helped me a lot when working with large APIs and teams.
If you’re already using Swagger in your .NET app, I highly recommend trying out a few of these. They’re not hard to implement, and the payoff is worth it.