OpenAPI es un estándar para describir una API HTTP de forma estructurada y legible por herramientas.
No hay nada más frustrante para un desarrollador frontend o móvil que intentar consumir una API “a ciegas”. “¿A qué URL tengo que llamar? ¿Qué JSON tengo que enviar? ¿Qué me devuelve si falla?”
Antiguamente, la solución era escribir un documento de Word o un PDF infumable que, seamos sinceros, quedaba desactualizado en cuanto cambiabas una línea de código.
En el desarrollo moderno, la documentación debe estar viva. Debe generarse automáticamente a partir de tu código.
Para eso tenemos el estándar OpenAPI y herramientas como Swagger UI o Scalar.
Hoy vamos a ver cómo hacer que tu API explique por sí misma cómo funciona.
OpenAPI vs Swagger: ¿Es lo mismo?
Es común usar los términos indistintamente, pero hay una diferencia sutil:
- OpenAPI: es el estándar. Es un archivo JSON o YAML que describe tu API de forma técnica: “tengo un endpoint GET en /productos que devuelve un array de objetos…”. Es el contrato.
- Swagger: es una familia de herramientas que trabajan con ese estándar.
- Swagger UI: la página web interactiva que muestra la documentación.
- Swashbuckle: una librería muy usada en ASP.NET Core para generar documentos OpenAPI y servir Swagger UI.
En proyectos actuales de ASP.NET Core conviene separar las ideas: OpenAPI es el documento; Swagger UI es solo una forma de verlo y probarlo.
Configuración en ASP.NET Core
La buena noticia es que ASP.NET Core moderno incluye soporte integrado para generar documentos OpenAPI.
En un proyecto moderno podemos registrar el generador nativo en Program.cs:
var builder = WebApplication.CreateBuilder(args);
// 1. Añade los servicios que generan el documento OpenAPI
builder.Services.AddOpenApi();
var app = builder.Build();
// 2. Publica el documento OpenAPI
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.Run();Con solo esto, si arrancas la app y vas a /openapi/v1.json, tendrás el contrato de tu API. Eso ya sirve para generar clientes, compartir documentación o alimentar otras herramientas.
Lo que no trae de serie es una interfaz visual. Para eso puedes añadir Swagger UI, Scalar, ReDoc u otra herramienta compatible con OpenAPI.
Por ejemplo, con Swagger UI:
dotnet add package Swashbuckle.AspNetCore.SwaggerUIY en Program.cs:
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/openapi/v1.json", "v1");
});
}Ahora sí, al ir a /swagger, verás una lista interactiva de tus endpoints. Pero… es una documentación “pobre”. Vamos a enriquecerla.
Enriqueciendo la documentación
Por defecto, el generador solo sabe lo que puede inferir por tus rutas, parámetros, modelos y metadatos. Pero no siempre sabe qué hace tu método o qué significa cada parámetro.
Para decírselo, usamos los Comentarios XML de C# (///).
Activar documentación XML
Primero, debemos decirle al compilador que no tire esos comentarios a la basura, sino que los guarde en un archivo XML.
Abre tu archivo .csproj y añade esto dentro de <PropertyGroup>:
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>Conectar XML con OpenAPI
En ASP.NET Core 10, el generador nativo incorpora los comentarios XML al documento OpenAPI cuando el proyecto está configurado para generarlos.
Si usas Swashbuckle como generador en lugar de AddOpenApi(), instala el paquete completo Swashbuckle.AspNetCore y configura AddSwaggerGen():
using System.Reflection;
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Mi API de Tienda",
Version = "v1",
Description = "API para gestionar productos y pedidos."
});
// Buscamos el archivo XML generado
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
// Le decimos a Swashbuckle que lo use
options.IncludeXmlComments(xmlPath);
});Escribir comentarios
Ahora, ve a tu Controlador y añade comentarios summary, param y returns.
/// <summary>
/// Obtiene un producto específico por su ID.
/// </summary>
/// <param name="id">El identificador único del producto.</param>
/// <returns>El objeto producto si existe.</returns>
[HttpGet("{id}")]
public IActionResult GetProducto(int id) { ... }Cuando recargues la UI, verás esas descripciones junto a cada endpoint. Ahora tu API habla humano.
Describir las respuestas con ProducesResponseType
Si tu método devuelve IActionResult, el generador puede no saber qué tipo de dato vas a devolver, ni qué códigos de error posibles existen. Por defecto puede acabar mostrando una documentación demasiado vaga.
Podemos usar el atributo ProducesResponseType para describir con precisión esas respuestas.
/// <summary>
/// Crea un nuevo usuario en el sistema.
/// </summary>
/// <response code="201">Usuario creado correctamente.</response>
/// <response code="400">Datos inválidos o incompletos.</response>
[HttpPost]
[ProducesResponseType(typeof(UsuarioDto), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public IActionResult CrearUsuario(CrearUsuarioDto dto)
{
// ...
return CreatedAtAction(..., usuario);
}Ahora la UI mostrará claramente: “este endpoint puede devolver un 201 con este JSON o un 400”.
Probando la API desde el navegador
La mejor parte de una UI interactiva como Swagger UI o Scalar es poder probar la API desde el navegador.
Convierte la documentación en un cliente HTTP (como Postman) integrado en el navegador.
- Pulsas “Try it out”.
- Rellenas los campos del formulario.
- Pulsas “Execute”.
- Ves la respuesta real de tu servidor.
Esto permite que el equipo de Frontend pruebe los endpoints incluso antes de escribir una sola línea de código en su aplicación.
Autenticación en Swagger UI
Si tu API está protegida con JWT (lo veremos en el próximo bloque), el botón “Try it out” fallará porque le falta el Token.
Si usas Swashbuckle, puedes configurar Swagger UI para que tenga un botón de “Authorize”:
// Configuración avanzada para soportar JWT con Swashbuckle
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Inserte el token JWT así: Bearer {tu_token}",
Name = "Authorization",
Type = SecuritySchemeType.ApiKey
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] { }
}
});