La API es el contrato entre una aplicación y quienes la consumen. Define operaciones, datos de entrada y salida y respuestas posibles.
| Enfoque | Punto de partida | Uso del contrato |
|---|---|---|
| API First | Se diseña el contrato antes de implementar | Guía y permite acordar el trabajo de clientes y servidor |
| Code First | Se implementa primero | El contrato se deriva después del código, por ejemplo, con anotaciones |
API First hace explícitas las decisiones de interfaz y permite revisarlas antes de implementarlas. El contrato describe lo que necesita el cliente; no expone automáticamente los modelos internos.
OpenAPI es una especificación para describir APIs HTTP en YAML o JSON. Define rutas y operaciones, parámetros, esquemas de datos, respuestas y restricciones.
Swagger es un conjunto de herramientas para trabajar con OpenAPI. Por ejemplo, Swagger UI presenta el contrato como documentación interactiva.
Este fragmento define una solicitud y dos respuestas de una operación:
paths:
/orders:
post:
operationId: createOrder
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
responses:
'201':
description: Order created
'400':
description: Invalid request
El contrato HTTP y el código que implementa sus operaciones son responsabilidades relacionadas, pero pueden mantenerse separados. En Spring, springdoc-openapi genera un documento OpenAPI y Swagger UI a partir de las anotaciones del código.
Una opción es declarar rutas, parámetros y documentación en una interfaz Java como OrderHttpApi, y dejar que OrderController implemente sus operaciones. El nombre indica que es el contrato HTTP, distinto de una API interna que un módulo pueda ofrecer a otros módulos:
@Tag(name = "Orders")
public interface OrderHttpApi {
@Operation(summary = "Create an order")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "Order created"),
@ApiResponse(responseCode = "400", description = "Invalid request")
})
@PostMapping("/orders")
ResponseEntity<OrderResponse> create(
@Valid @RequestBody CreateOrderRequest request);
}
@RestController
public class OrderController implements OrderHttpApi {
@Override
public ResponseEntity<OrderResponse> create(CreateOrderRequest request) {
// Delegar la operación y producir la respuesta.
}
}
Así se separan las declaraciones del contrato HTTP de la lógica del controlador y springdoc-openapi puede generar la documentación. La interfaz puede diseñarse antes de implementar el controlador y formar parte de un flujo API First, pero queda ligada al código Java; el documento generado no es una especificación independiente del código.
Otra opción es mantener una especificación OpenAPI en un archivo, por ejemplo orders-api.yaml, como fuente de diseño antes de implementar. Es útil para revisar el contrato con consumidores, trabajar en paralelo o generar artefactos. La implementación debe comprobarse contra esa especificación.
| Fuente del contrato | Ventaja | Precaución |
|---|---|---|
Interfaz Java OrderHttpApi y anotaciones | Contrato y documentación junto a la interfaz HTTP; documentación generada desde Spring | Se define desde el código; los cambios requieren revisar el contrato resultante |
Archivo orders-api.yaml | Contrato independiente, revisable antes de implementar | Hay que comprobar que la implementación sigue la especificación |
Elegir una fuente de verdad evita mantener dos contratos manuales que puedan divergir. En ambos enfoques, los DTO HTTP describen los datos públicos y se mapean a modelos internos; no se exponen directamente los modelos del dominio.
Un cambio es incompatible si obliga a los consumidores a cambiar sus solicitudes o cómo interpretan las respuestas. Eliminar un campo, cambiar su tipo o alterar el significado de una respuesta puede romper clientes.
Al revisar cambios, comprobar:
Se puede validar la sintaxis OpenAPI, comparar versiones y comprobar solicitudes y respuestas de la implementación. Las pruebas HTTP de controller verifican el comportamiento integrado; abrir Swagger UI no demuestra por sí solo la conformidad. Si se usa un archivo OpenAPI como fuente, hay que comprobar que la implementación se ajusta a él.