23. Documentation Best Practices
- Documentation Best Practices
About this chapter
Write clear, comprehensive API documentation that helps developers understand authentication flows, endpoint purposes, and usage patterns through annotations and organized grouping.
- Authentication documentation: Explaining JWT, API Key, and mixed authentication schemes
- Endpoint descriptions: Summary and remarks for clarity
- Tags and grouping: Organizing endpoints logically in Swagger UI
- Security scheme indicators: Showing which auth methods each endpoint requires
- Examples and remarks: Providing context beyond simple descriptions
- Developer guidance: Helping developers understand the authentication flow
Learning outcomes:
- Document different authentication schemes clearly
- Use Summary and Remarks for comprehensive descriptions
- Apply Tags to group related endpoints
- Explain security requirements per endpoint
- Provide examples and guidance for authentication flows
- Create developer-friendly documentation
23.1 Documenting Authentication
Your API likely has multiple authentication schemes (JWT + API Key). Swagger needs to know how to test each endpoint.
// Controllers using JWT only
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/[controller]")]
[ApiController]
public class RegistrationsController : ControllerBase
{
/// <summary>
/// Register a new API key for your account
/// </summary>
/// <remarks>
/// Requires JWT authentication from Auth0.
/// The returned key is displayed once and cannot be retrieved again—save it securely.
/// </remarks>
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ApiKeyResponse))]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<ActionResult<ApiKeyResponse>> RegisterKey(
KeyRegistrationMutateDto registrationDto)
{
// Implementation
return Ok();
}
}
// Controllers using API Key only
[Authorize(AuthenticationSchemes = ApiKeyConstants.SchemeName)]
[Route("api/[controller]")]
[ApiController]
public class CommandsController : ControllerBase
{
/// <summary>
/// Get all commands
/// </summary>
/// <remarks>
/// Requires x-api-key header. Get your key from the Registrations endpoint using JWT.
/// </remarks>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<ActionResult> GetCommands(int pageIndex = 1, int pageSize = 10)
{
// Implementation
return Ok();
}
}
In Swagger UI, the lock icon next to each endpoint shows which auth methods it accepts. Multiple security definitions let developers understand the auth flow.
23.2 Grouping Related Endpoints
[Route("api/[controller]")]
[ApiController]
[Tags("Platforms")] // Group name in Swagger
[Authorize(AuthenticationSchemes = ApiKeyConstants.SchemeName)]
public class PlatformsController : ControllerBase
{
[HttpGet]
[Tags("Platforms", "Read")]
public async Task<ActionResult> GetPlatforms() { }
[HttpPost]
[Tags("Platforms", "Write")]
public async Task<ActionResult> CreatePlatform(PlatformMutateDto dto) { }
[HttpDelete("{id}")]
[Tags("Platforms", "Write")]
public async Task<ActionResult> DeletePlatform(int id) { }
}
[Route("api/[controller]")]
[ApiController]
[Tags("Commands")]
[Authorize(AuthenticationSchemes = ApiKeyConstants.SchemeName)]
public class CommandsController : ControllerBase
{
[HttpGet]
[Tags("Commands", "Read")]
public async Task<ActionResult> GetCommands() { }
[HttpPost]
[Tags("Commands", "Write")]
public async Task<ActionResult> CreateCommand(CommandMutateDto dto) { }
}
[Route("api/[controller]")]
[ApiController]
[Tags("Authentication")]
public class RegistrationsController : ControllerBase
{
[HttpPost]
[Tags("Authentication", "API Keys")]
public async Task<ActionResult> RegisterKey(KeyRegistrationMutateDto dto) { }
}
Swagger UI now shows collapsible sections for Platforms, Commands, and Authentication with their endpoints nested underneath.