El cambio estructural: de paths a requests
En OpenAPI 3.1, la estructura top-level gira alrededor de paths:
# OpenAPI 3.1, centrado en paths
openapi: "3.1.0"
paths:
/users/{userId}:
get:
operationId: getUser
parameters:
- name: userId
in: path
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/User"
OpenAPI 4.0 reorganiza alrededor de requests y pathItems:
# OpenAPI 4.0, centrado en requests
openapi: "4.0.0"
info:
title: User Service
version: "2.0"
pathItems:
user:
parameters:
userId:
in: path
schema:
type: string
requests:
getUser:
method: get
outcomes:
success:
status: 200
contentType: application/json
body:
schema:
$ref: "#/components/schemas/User"
notFound:
status: 404
contentType: application/problem+json
body:
schema:
$ref: "#/components/schemas/Problem"
urls:
/users/{userId}: { $ref: "#/pathItems/user" }
/v2/users/{userId}: { $ref: "#/pathItems/user" }
Observar varias cosas. Primero, los pathItems están desacoplados de las URLs. El mismo pathItem user sirve tanto /users/{userId} como /v2/users/{userId}. Segundo, las responses ahora son outcomes, resultados semánticos nombrados en vez de entradas indexadas por status code. success y notFound son más significativos que "200" y "404".
Overlays: capas sin forkear
Esta es una feature largamente esperada. Los overlays te permiten tomar un documento base de OpenAPI y aplicar modificaciones sin editar el original:
# base.yaml, tu spec canónica
openapi: "4.0.0"
info:
title: Payment API
version: "1.0"
pathItems:
charge:
requests:
createCharge:
method: post
body:
schema:
$ref: "#/components/schemas/ChargeRequest"
outcomes:
created:
status: 201
body:
schema:
$ref: "#/components/schemas/Charge"
urls:
/charges: { $ref: "#/pathItems/charge" }
# overlay-production.yaml
overlay: "1.0.0"
extends: base.yaml
actions:
- target: "$.servers"
update:
- url: https://api.example.com
description: Production US-East
- target: "$.pathItems.charge.requests.createCharge"
update:
security:
- oauth2:
scopes: ["charges:write"]
La spec final se construye para cada ambiente:
redocly bundle base.yaml --overlay overlay-production.yaml -o production-spec.yaml
redocly bundle base.yaml --overlay overlay-staging.yaml -o staging-spec.yaml
Esto elimina el patrón de "copiar la spec y cambiar la URL del server" que plaga toda API multi-ambiente.
Webhooks de primera clase
En 4.0 están integrados en el modelo de request/outcome:
webhooks:
paymentCompleted:
requests:
notify:
method: post
contentType: application/json
body:
schema:
type: object
required: [event, data]
properties:
event:
type: string
const: payment.completed
data:
$ref: "#/components/schemas/Payment"
outcomes:
acknowledged:
status: 200
retry:
status: [500, 502, 503]
delivery:
retryPolicy:
maxRetries: 5
backoff: exponential
initialDelay: 30s
signing:
algorithm: hmac-sha256
headerName: X-Webhook-Signature
La sección delivery es nueva, documenta políticas de reintento y mecanismos de firmado como parte de la spec.
Migración desde 3.1
La migración de una spec de OpenAPI 3.1 de 2.400 líneas a 4.0 sigue este proceso:
npx @redocly/cli transform openapi-3.1.yaml --to 4.0 -o openapi-4.0.yaml
npx @redocly/cli lint openapi-4.0.yaml --ruleset recommended
El conversor automático maneja ~85% de la transformación. El 15% restante es nombrar outcomes semánticamente, extraer pathItems compartidos, y agregar metadata de delivery de webhooks.
Patrones de diseño de spec
Patrón: Outcomes de error compartidos
components:
outcomes:
validationError:
status: 422
contentType: application/problem+json
body:
schema:
$ref: "#/components/schemas/ValidationProblem"
unauthorized:
status: 401
contentType: application/problem+json
body:
schema:
$ref: "#/components/schemas/AuthProblem"
pathItems:
charge:
requests:
createCharge:
method: post
outcomes:
created:
status: 201
body:
schema:
$ref: "#/components/schemas/Charge"
validation:
$ref: "#/components/outcomes/validationError"
auth:
$ref: "#/components/outcomes/unauthorized"
Outcomes compartidos eliminan el problema de "copiar error responses a cada endpoint".
¿Deberías migrar ahora?
Evaluación honesta: para proyectos de API nuevos y tu toolchain soporta 4.0, usalo. Las mejoras estructurales hacen que las specs sean más fáciles de mantener a medida que crecen. Si teners una spec 3.1 grande que funciona bien, esperá 6-12 meses para que el tooling madure.
La mayor ganancia son los overlays. Pasar de mantener cuatro copias de una spec (dev, staging, prod, partner) a una base más cuatro archivos de overlay de 20 líneas representa una mejora significativa. Eso solo justifica el esfuerzo de migración.