Open API y cómo agregarlo en Spring Boot

Intermedio
SpringBoot
SpringBoot
Actualizado: 13/06/2025

¡Desbloquea el curso completo!

IA
Ejercicios
Certificado
Entrar

Fundamento teórico de OpenAPI y Swagger

La documentación de APIs es un aspecto fundamental en el desarrollo de servicios REST modernos. Sin una documentación clara y actualizada, los desarrolladores que consumen nuestras APIs enfrentan dificultades para entender cómo utilizarlas correctamente, qué parámetros requieren y qué respuestas pueden esperar.

OpenAPI (anteriormente conocido como Swagger Specification) es una especificación estándar de la industria para describir APIs REST. Define un formato estructurado que permite documentar endpoints, parámetros, respuestas, esquemas de datos y métodos de autenticación de manera consistente y legible tanto para humanos como para máquinas.

Diferencia entre OpenAPI y Swagger

Es importante distinguir entre OpenAPI como especificación y Swagger como conjunto de herramientas. OpenAPI es el estándar que define cómo documentar una API, mientras que Swagger se refiere al ecosistema de herramientas que trabajan con esta especificación.

Las herramientas principales del ecosistema Swagger incluyen:

  • Swagger UI: Interfaz web interactiva que permite visualizar y probar la API directamente desde el navegador
  • Swagger Editor: Editor online para crear y editar especificaciones OpenAPI
  • Swagger Codegen: Generador de código cliente y servidor a partir de especificaciones OpenAPI

Estructura de una especificación OpenAPI

Una especificación OpenAPI se estructura en formato YAML o JSON y contiene varias secciones principales que describen completamente una API:

openapi: 3.0.3
info:
  title: API de Gestión de Usuarios
  description: API para gestionar usuarios en el sistema
  version: 1.0.0
servers:
  - url: http://localhost:8080/api
    description: Servidor de desarrollo
paths:
  /usuarios:
    get:
      summary: Obtener lista de usuarios
      responses:
        '200':
          description: Lista de usuarios obtenida exitosamente
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Usuario'
components:
  schemas:
    Usuario:
      type: object
      properties:
        id:
          type: integer
          format: int64
        nombre:
          type: string
        email:
          type: string
          format: email

La sección info contiene metadatos básicos como título, descripción y versión de la API. La sección servers especifica las URLs donde está disponible la API. La sección paths define todos los endpoints disponibles con sus operaciones HTTP correspondientes.

Beneficios de usar OpenAPI

La adopción de OpenAPI en proyectos Spring Boot aporta múltiples ventajas tanto para el desarrollo como para el mantenimiento de APIs:

Documentación automática: La especificación se genera automáticamente a partir del código, eliminando la necesidad de mantener documentación separada que puede quedar desactualizada.

Interfaz interactiva: Swagger UI proporciona una interfaz web donde los desarrolladores pueden probar los endpoints directamente, enviando peticiones reales y viendo las respuestas.

Validación de contratos: La especificación actúa como un contrato entre el frontend y backend, facilitando el desarrollo en paralelo de ambas partes.

Generación de código cliente: A partir de la especificación, se pueden generar automáticamente clientes para diferentes lenguajes de programación.

Anotaciones básicas para documentación

Spring Boot integra OpenAPI mediante anotaciones que se colocan directamente en los controladores REST. Estas anotaciones permiten enriquecer la documentación generada automáticamente:

@RestController
@RequestMapping("/api/usuarios")
@Tag(name = "Usuarios", description = "Operaciones relacionadas con usuarios")
public class UsuarioController {
    
    @GetMapping
    @Operation(summary = "Obtener todos los usuarios", 
               description = "Retorna una lista paginada de todos los usuarios del sistema")
    @ApiResponse(responseCode = "200", description = "Lista obtenida exitosamente")
    public List<Usuario> obtenerUsuarios() {
        // Implementación del método
    }
    
    @PostMapping
    @Operation(summary = "Crear nuevo usuario")
    @ApiResponse(responseCode = "201", description = "Usuario creado exitosamente")
    @ApiResponse(responseCode = "400", description = "Datos de entrada inválidos")
    public Usuario crearUsuario(@RequestBody @Valid Usuario usuario) {
        // Implementación del método
    }
}

La anotación @Tag agrupa endpoints relacionados bajo una categoría común. @Operation proporciona información específica sobre cada endpoint, incluyendo resumen y descripción detallada. @ApiResponse documenta las posibles respuestas HTTP que puede devolver el endpoint.

Documentación de modelos de datos

Los esquemas de datos se documentan automáticamente a partir de las clases Java utilizadas como parámetros y respuestas. Sin embargo, podemos enriquecer esta documentación con anotaciones específicas:

@Schema(description = "Entidad que representa un usuario del sistema")
public class Usuario {
    
    @Schema(description = "Identificador único del usuario", example = "1")
    private Long id;
    
    @Schema(description = "Nombre completo del usuario", example = "Juan Pérez")
    private String nombre;
    
    @Schema(description = "Correo electrónico del usuario", example = "juan@ejemplo.com")
    private String email;
    
    @Schema(description = "Fecha de registro del usuario")
    private LocalDateTime fechaRegistro;
    
    // Constructores, getters y setters
}

La anotación @Schema permite añadir descripciones detalladas y ejemplos para cada campo, mejorando significativamente la comprensión de la estructura de datos por parte de los consumidores de la API.

Versionado y evolución de APIs

OpenAPI facilita el manejo de versiones de APIs mediante la especificación clara de cambios y la documentación de múltiples versiones simultáneamente. Esto es especialmente importante en entornos de producción donde diferentes clientes pueden estar utilizando versiones distintas de la API.

La especificación OpenAPI se convierte así en una herramienta fundamental para el desarrollo de APIs REST profesionales, proporcionando claridad, consistencia y facilidad de uso tanto para desarrolladores como para consumidores de la API.

¿Te está gustando esta lección?

Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

Más de 25.000 desarrolladores ya confían en CertiDevs

Integración de SpringDoc OpenAPI

La integración de OpenAPI en Spring Boot se realiza mediante SpringDoc, una biblioteca que genera automáticamente la documentación OpenAPI a partir del código de nuestros controladores REST. Esta herramienta elimina la necesidad de escribir manualmente archivos de especificación, manteniendo la documentación siempre sincronizada con el código.

Configuración inicial del proyecto

Para integrar SpringDoc en un proyecto Spring Boot, necesitamos añadir la dependencia correspondiente en nuestro archivo pom.xml:

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.3.0</version>
</dependency>

Esta dependencia incluye tanto la generación automática de la especificación OpenAPI como la interfaz Swagger UI para visualizar y probar la documentación. Una vez añadida la dependencia, no se requiere configuración adicional para empezar a generar documentación básica.

Al iniciar la aplicación, SpringDoc escanea automáticamente todos los controladores REST y genera la especificación OpenAPI. La documentación estará disponible en las siguientes URLs:

  • Especificación JSON: http://localhost:8080/v3/api-docs
  • Interfaz Swagger UI: http://localhost:8080/swagger-ui.html

Configuración personalizada de SpringDoc

Aunque SpringDoc funciona sin configuración adicional, podemos personalizar su comportamiento mediante propiedades en el archivo application.properties:

# Personalizar la ruta de la documentación JSON
springdoc.api-docs.path=/api-docs

# Personalizar la ruta de Swagger UI
springdoc.swagger-ui.path=/documentacion

# Habilitar el modo de prueba (try it out) por defecto
springdoc.swagger-ui.tryItOutEnabled=true

# Configurar el servidor por defecto para las pruebas
springdoc.swagger-ui.server=http://localhost:8080

Para una configuración más avanzada, podemos crear una clase de configuración que defina los metadatos de nuestra API:

@Configuration
public class OpenApiConfig {
    
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
            .info(new Info()
                .title("API de Gestión Empresarial")
                .description("Sistema completo para la gestión de empleados y departamentos")
                .version("v1.0")
                .contact(new Contact()
                    .name("Equipo de Desarrollo")
                    .email("desarrollo@empresa.com")
                    .url("https://empresa.com/contacto"))
                .license(new License()
                    .name("MIT License")
                    .url("https://opensource.org/licenses/MIT")))
            .servers(List.of(
                new Server().url("http://localhost:8080").description("Entorno de desarrollo"),
                new Server().url("https://api.empresa.com").description("Entorno de producción")
            ));
    }
}

Configuración de grupos de APIs

En aplicaciones grandes, es útil organizar los endpoints en grupos lógicos. SpringDoc permite crear múltiples grupos de documentación para diferentes módulos de la aplicación:

@Configuration
public class OpenApiConfig {
    
    @Bean
    public GroupedOpenApi publicApi() {
        return GroupedOpenApi.builder()
            .group("publico")
            .pathsToMatch("/api/public/**")
            .build();
    }
    
    @Bean
    public GroupedOpenApi adminApi() {
        return GroupedOpenApi.builder()
            .group("administracion")
            .pathsToMatch("/api/admin/**")
            .build();
    }
    
    @Bean
    public GroupedOpenApi empleadosApi() {
        return GroupedOpenApi.builder()
            .group("empleados")
            .pathsToMatch("/api/empleados/**", "/api/departamentos/**")
            .build();
    }
}

Con esta configuración, cada grupo tendrá su propia documentación accesible desde Swagger UI, permitiendo a los desarrolladores enfocarse únicamente en las APIs relevantes para su trabajo.

Exclusión de endpoints de la documentación

En ocasiones necesitamos excluir ciertos endpoints de la documentación generada, especialmente aquellos destinados únicamente para uso interno o de depuración:

@RestController
@RequestMapping("/api/sistema")
public class SistemaController {
    
    @GetMapping("/salud")
    public String verificarSalud() {
        return "Sistema funcionando correctamente";
    }
    
    @GetMapping("/debug")
    @Hidden  // Este endpoint no aparecerá en la documentación
    public Map<String, Object> informacionDebug() {
        // Información sensible solo para desarrollo
        return Map.of("memoria", "512MB", "version", "1.0.0");
    }
}

También podemos excluir endpoints mediante configuración, especificando patrones de rutas que deben ignorarse:

@Bean
public GroupedOpenApi publicApi() {
    return GroupedOpenApi.builder()
        .group("api-publica")
        .pathsToMatch("/api/**")
        .pathsToExclude("/api/interno/**", "/api/debug/**")
        .build();
}

Configuración de seguridad en la documentación

Cuando nuestra API utiliza autenticación y autorización, debemos configurar SpringDoc para que Swagger UI pueda realizar peticiones autenticadas correctamente:

@Configuration
public class OpenApiConfig {
    
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
            .info(new Info().title("API Segura").version("v1.0"))
            .addSecurityItem(new SecurityRequirement().addList("bearerAuth"))
            .components(new Components()
                .addSecuritySchemes("bearerAuth", new SecurityScheme()
                    .type(SecurityScheme.Type.HTTP)
                    .scheme("bearer")
                    .bearerFormat("JWT")
                    .description("Introduce el token JWT en el formato: Bearer {token}")
                )
            );
    }
}

Esta configuración añade un botón "Authorize" en Swagger UI donde los usuarios pueden introducir su token JWT para probar endpoints protegidos.

Personalización de la interfaz Swagger UI

SpringDoc permite personalizar la apariencia y comportamiento de Swagger UI mediante propiedades adicionales:

# Personalizar el título de la página
springdoc.swagger-ui.operationsSorter=method

# Ordenar las operaciones por método HTTP
springdoc.swagger-ui.tagsSorter=alpha

# Ordenar los tags alfabéticamente
springdoc.swagger-ui.docExpansion=none

# Contraer todas las secciones por defecto
springdoc.swagger-ui.filter=true

# Habilitar el filtro de búsqueda
springdoc.swagger-ui.showExtensions=true

# Mostrar extensiones personalizadas
springdoc.swagger-ui.showCommonExtensions=true

Validación automática de la especificación

SpringDoc incluye validación automática de la especificación OpenAPI generada, detectando inconsistencias o errores en la documentación durante el arranque de la aplicación. Esto garantiza que la documentación sea válida y completa.

Si se detectan problemas, la aplicación mostrará advertencias en los logs, permitiendo corregir los errores antes de que lleguen a producción:

WARN: Missing response description for operation GET /api/usuarios
WARN: Parameter 'id' in path '/api/usuarios/{id}' is not documented

La integración de SpringDoc OpenAPI transforma el desarrollo de APIs REST en Spring Boot, proporcionando documentación automática, interactiva y siempre actualizada que mejora significativamente la experiencia tanto de desarrollo como de consumo de nuestras APIs.

Documentación de endpoints

La documentación detallada de endpoints es fundamental para que los consumidores de nuestra API comprendan exactamente cómo interactuar con cada servicio. SpringDoc OpenAPI permite enriquecer automáticamente la documentación mediante anotaciones específicas que describen el comportamiento, parámetros y respuestas de cada endpoint.

Documentación básica con @Operation

La anotación @Operation proporciona información esencial sobre cada endpoint, incluyendo un resumen conciso y una descripción detallada de su funcionalidad:

@RestController
@RequestMapping("/api/productos")
@Tag(name = "Productos", description = "Gestión del catálogo de productos")
public class ProductoController {
    
    @GetMapping("/{id}")
    @Operation(
        summary = "Obtener producto por ID",
        description = "Recupera la información completa de un producto específico utilizando su identificador único. " +
                     "Incluye detalles como nombre, precio, stock disponible y categoría."
    )
    public ResponseEntity<Producto> obtenerProducto(@PathVariable Long id) {
        // Implementación del método
    }
}

La descripción detallada ayuda a los desarrolladores a entender no solo qué hace el endpoint, sino también qué información específica pueden esperar en la respuesta.

Documentación de parámetros de entrada

Los parámetros de entrada requieren documentación específica para explicar su propósito, formato esperado y restricciones. SpringDoc documenta automáticamente los parámetros, pero podemos enriquecerlos con información adicional:

@GetMapping
@Operation(summary = "Buscar productos con filtros")
public ResponseEntity<List<Producto>> buscarProductos(
    @Parameter(description = "Nombre o parte del nombre del producto", example = "laptop")
    @RequestParam(required = false) String nombre,
    
    @Parameter(description = "Precio mínimo en euros", example = "100.00")
    @RequestParam(required = false) BigDecimal precioMinimo,
    
    @Parameter(description = "Precio máximo en euros", example = "500.00")
    @RequestParam(required = false) BigDecimal precioMaximo,
    
    @Parameter(description = "Número de página (empezando en 0)", example = "0")
    @RequestParam(defaultValue = "0") int pagina,
    
    @Parameter(description = "Cantidad de elementos por página", example = "10")
    @RequestParam(defaultValue = "10") int tamaño
) {
    // Implementación del método
}

Documentación de cuerpos de petición

Para endpoints que reciben datos en el cuerpo de la petición, es importante documentar la estructura esperada y proporcionar ejemplos claros:

@PostMapping
@Operation(summary = "Crear nuevo producto")
public ResponseEntity<Producto> crearProducto(
    @Parameter(description = "Datos del producto a crear")
    @RequestBody @Valid CrearProductoRequest request
) {
    // Implementación del método
}

La clase del cuerpo de petición debe estar documentada con @Schema para proporcionar información detallada sobre cada campo:

@Schema(description = "Datos necesarios para crear un nuevo producto")
public class CrearProductoRequest {
    
    @Schema(description = "Nombre del producto", example = "Laptop Gaming Pro", required = true)
    @NotBlank(message = "El nombre es obligatorio")
    private String nombre;
    
    @Schema(description = "Precio del producto en euros", example = "899.99", required = true)
    @NotNull(message = "El precio es obligatorio")
    @DecimalMin(value = "0.01", message = "El precio debe ser mayor que cero")
    private BigDecimal precio;
    
    @Schema(description = "Cantidad disponible en stock", example = "50")
    @Min(value = 0, message = "El stock no puede ser negativo")
    private Integer stock;
    
    @Schema(description = "Identificador de la categoría", example = "1")
    @NotNull(message = "La categoría es obligatoria")
    private Long categoriaId;
    
    // Constructores, getters y setters
}

Documentación completa de respuestas

La documentación de respuestas HTTP debe cubrir todos los posibles códigos de estado que puede devolver el endpoint, incluyendo casos de éxito y error:

@PutMapping("/{id}")
@Operation(summary = "Actualizar producto existente")
@ApiResponses(value = {
    @ApiResponse(
        responseCode = "200",
        description = "Producto actualizado exitosamente",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = Producto.class)
        )
    ),
    @ApiResponse(
        responseCode = "400",
        description = "Datos de entrada inválidos",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = ErrorResponse.class),
            examples = @ExampleObject(
                value = "{\"mensaje\": \"El precio debe ser mayor que cero\", \"codigo\": \"PRECIO_INVALIDO\"}"
            )
        )
    ),
    @ApiResponse(
        responseCode = "404",
        description = "Producto no encontrado",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = ErrorResponse.class)
        )
    )
})
public ResponseEntity<Producto> actualizarProducto(
    @PathVariable Long id,
    @RequestBody @Valid ActualizarProductoRequest request
) {
    // Implementación del método
}

Ejemplos de respuesta personalizados

Los ejemplos específicos en las respuestas ayudan a los desarrolladores a entender exactamente qué estructura de datos pueden esperar:

@GetMapping("/{id}")
@Operation(summary = "Obtener producto por ID")
@ApiResponse(
    responseCode = "200",
    description = "Producto encontrado",
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = Producto.class),
        examples = @ExampleObject(
            name = "Producto ejemplo",
            value = """
                {
                    "id": 1,
                    "nombre": "Laptop Gaming Pro",
                    "precio": 899.99,
                    "stock": 15,
                    "categoria": {
                        "id": 1,
                        "nombre": "Electrónicos"
                    },
                    "fechaCreacion": "2024-01-15T10:30:00"
                }
                """
        )
    )
)
public ResponseEntity<Producto> obtenerProducto(@PathVariable Long id) {
    // Implementación del método
}

Documentación de endpoints con paginación

Los endpoints que devuelven listas paginadas requieren documentación específica para explicar la estructura de la respuesta paginada:

@GetMapping
@Operation(
    summary = "Listar productos con paginación",
    description = "Obtiene una lista paginada de productos con información de navegación incluida"
)
@ApiResponse(
    responseCode = "200",
    description = "Lista de productos obtenida exitosamente",
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = PageProducto.class)
    )
)
public ResponseEntity<Page<Producto>> listarProductos(
    @Parameter(description = "Número de página (empezando en 0)")
    @RequestParam(defaultValue = "0") int pagina,
    
    @Parameter(description = "Tamaño de página")
    @RequestParam(defaultValue = "20") int tamaño,
    
    @Parameter(description = "Campo por el cual ordenar", example = "nombre")
    @RequestParam(defaultValue = "id") String ordenarPor
) {
    // Implementación del método
}

Agrupación lógica de endpoints

Para mantener la documentación organizada y fácil de navegar, es importante agrupar endpoints relacionados bajo tags descriptivos:

@RestController
@RequestMapping("/api/inventario")
@Tag(name = "Inventario", description = "Operaciones de gestión de inventario y stock")
public class InventarioController {
    
    @PostMapping("/productos/{id}/stock")
    @Operation(summary = "Actualizar stock de producto")
    public ResponseEntity<Void> actualizarStock(
        @PathVariable Long id,
        @RequestBody ActualizarStockRequest request
    ) {
        // Implementación del método
    }
    
    @GetMapping("/productos/bajo-stock")
    @Operation(summary = "Productos con stock bajo")
    public ResponseEntity<List<Producto>> productosConStockBajo(
        @Parameter(description = "Umbral mínimo de stock", example = "5")
        @RequestParam(defaultValue = "10") int umbral
    ) {
        // Implementación del método
    }
}

Documentación de validaciones

Es importante documentar las reglas de validación que se aplican a los datos de entrada, para que los consumidores de la API entiendan qué restricciones deben cumplir:

@Schema(description = "Datos para actualizar un producto")
public class ActualizarProductoRequest {
    
    @Schema(
        description = "Nombre del producto (entre 3 y 100 caracteres)",
        example = "Smartphone Pro Max",
        minLength = 3,
        maxLength = 100
    )
    @Size(min = 3, max = 100, message = "El nombre debe tener entre 3 y 100 caracteres")
    private String nombre;
    
    @Schema(
        description = "Precio en euros (debe ser positivo)",
        example = "299.99",
        minimum = "0.01"
    )
    @DecimalMin(value = "0.01", message = "El precio debe ser mayor que cero")
    private BigDecimal precio;
    
    // Getters y setters
}

La documentación completa de endpoints transforma la especificación OpenAPI en una guía comprensiva que facilita la integración y reduce significativamente el tiempo necesario para que los desarrolladores comprendan y utilicen correctamente nuestra API.

Aprendizajes de esta lección

  • Comprender qué es OpenAPI y la diferencia con Swagger.
  • Aprender la estructura básica de una especificación OpenAPI.
  • Integrar SpringDoc OpenAPI en un proyecto Spring Boot para generar documentación automática.
  • Documentar endpoints, parámetros, cuerpos de petición y respuestas con anotaciones específicas.
  • Configurar y personalizar la documentación, incluyendo seguridad, agrupación y exclusión de endpoints.

Completa SpringBoot y certifícate

Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.

Asistente IA

Resuelve dudas al instante

Ejercicios

Practica con proyectos reales

Certificados

Valida tus conocimientos

Más de 25.000 desarrolladores ya se han certificado con CertiDevs

⭐⭐⭐⭐⭐
4.9/5 valoración