{"schemaVersion":1,"id":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification","title":"OpenAPI 4.0 (Moonwalk): The Spec Rewrite That Actually Matters","description":"New overlay mechanism, first-class webhooks, reusable workflows, comparison with 3.1, and a real migration path from Swagger, OpenAPI 4.0 is the biggest API spec change in a decade.","language":"en","datePublished":"2025-10-26","dateModified":null,"contentFormat":"text/markdown","content":"API Design\n\n# OpenAPI 4.0 (Moonwalk): The Spec Rewrite That Actually Matters\n\n2025-10-265 min read\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nAlso available in: [Español](<https://lucioduran.com/es/blog/openapi-4-moonwalk-api-specification>)\n\n## The structural shift: from paths to requests\n\nIn [OpenAPI](<https://www.openapis.org/>) 3.1, the top-level structure revolves around ` paths `:\n\n```yaml\n# OpenAPI 3.1, path-centric\nopenapi: \"3.1.0\"\npaths:\n /users/{userId}:\n get:\n operationId: getUser\n parameters:\n - name: userId\n in: path\n required: true\n schema:\n type: string\n responses:\n \"200\":\n content:\n application/json:\n schema:\n $ref: \"#/components/schemas/User\"\n```\n\nOpenAPI 4.0 reorganizes around ` requests ` and ` pathItems `:\n\n```yaml\n# OpenAPI 4.0, request-centric\nopenapi: \"4.0.0\"\ninfo:\n title: User Service\n version: \"2.0\"\n\npathItems:\n user:\n parameters:\n userId:\n in: path\n schema:\n type: string\n requests:\n getUser:\n method: get\n outcomes:\n success:\n status: 200\n contentType: application/json\n body:\n schema:\n $ref: \"#/components/schemas/User\"\n notFound:\n status: 404\n contentType: application/problem+json\n body:\n schema:\n $ref: \"#/components/schemas/Problem\"\n\nurls:\n /users/{userId}: { $ref: \"#/pathItems/user\" }\n /v2/users/{userId}: { $ref: \"#/pathItems/user\" }\n```\n\nNotice several things. First, ` pathItems ` are decoupled from URLs. The same ` user ` pathItem serves both ` /users/{userId} ` and ` /v2/users/{userId} `. In 3.1, you'd duplicate the entire path definition or use ` $ref ` gymnastics. Second, responses are now ` outcomes `, named semantic results rather than status-code-indexed entries. ` success ` and ` notFound ` are more meaningful than ` \"200\" ` and ` \"404\" `. Third, parameters belong to the pathItem, not repeated per operation.\n\n## Overlays: layering without forking\n\nThis is a long-awaited feature. Overlays let you take a base OpenAPI document and apply modifications without editing the original. Think of it like CSS overrides for your API spec.\n\n```yaml\n# base.yaml, your canonical API spec\nopenapi: \"4.0.0\"\ninfo:\n title: Payment API\n version: \"1.0\"\npathItems:\n charge:\n requests:\n createCharge:\n method: post\n body:\n schema:\n $ref: \"#/components/schemas/ChargeRequest\"\n outcomes:\n created:\n status: 201\n body:\n schema:\n $ref: \"#/components/schemas/Charge\"\nurls:\n /charges: { $ref: \"#/pathItems/charge\" }\n```\n\n```yaml\n# overlay-staging.yaml, staging environment specifics\noverlay: \"1.0.0\"\ninfo:\n title: Staging Overlay\nextends: base.yaml\nactions:\n - target: \"$.info\"\n update:\n description: \"STAGING ENVIRONMENT, test data only\"\n - target: \"$.servers\"\n update:\n - url: https://staging-api.example.com\n description: Staging\n - target: \"$.pathItems.charge.requests.createCharge\"\n update:\n security:\n - apiKey: [] # Simpler auth in staging\n```\n\n```yaml\n# overlay-production.yaml\noverlay: \"1.0.0\"\nextends: base.yaml\nactions:\n - target: \"$.servers\"\n update:\n - url: https://api.example.com\n description: Production US-East\n - url: https://eu-api.example.com\n description: Production EU-West\n - target: \"$.pathItems.charge.requests.createCharge\"\n update:\n security:\n - oauth2:\n scopes: [\"charges:write\"]\n rateLimit:\n limit: 100\n window: 60s\n```\n\nBuild the final spec for each environment:\n\n```bash\n# Merge base + overlay\nredocly bundle base.yaml --overlay overlay-production.yaml -o production-spec.yaml\nredocly bundle base.yaml --overlay overlay-staging.yaml -o staging-spec.yaml\n```\n\nThis eliminates the \"copy the spec and change the server URL\" pattern that plagues every multi-environment API. The base spec is your single source of truth. Overlays adapt it per environment, per partner, per version.\n\n## First-class webhooks\n\nIn 3.1, webhooks were bolted on as a top-level ` webhooks ` field, structurally identical to paths but semantically different. In 4.0, they're integrated into the request/outcome model:\n\n```yaml\nwebhooks:\n paymentCompleted:\n description: Fired when a payment is successfully processed\n requests:\n notify:\n method: post\n contentType: application/json\n body:\n schema:\n type: object\n required: [event, data]\n properties:\n event:\n type: string\n const: payment.completed\n data:\n $ref: \"#/components/schemas/Payment\"\n timestamp:\n type: string\n format: date-time\n outcomes:\n acknowledged:\n status: 200\n description: Webhook received and acknowledged\n retry:\n status: [500, 502, 503]\n description: Server error, webhook will be retried\n delivery:\n retryPolicy:\n maxRetries: 5\n backoff: exponential\n initialDelay: 30s\n signing:\n algorithm: hmac-sha256\n headerName: X-Webhook-Signature\n```\n\nThe ` delivery ` section is new, it documents retry policies and signing mechanisms as part of the spec. In 3.1, this information lived in your docs' prose. Now it's machine-readable, and code generators can produce webhook verification code automatically.\n\n## Migration from 3.1: the practical path\n\nA 2,400-line OpenAPI 3.1 spec migration to 4.0 follows this process:\n\n```bash\n# Step 1: Automated conversion\nnpx @redocly/cli transform openapi-3.1.yaml --to 4.0 -o openapi-4.0.yaml\n\n# Step 2: Validate the output\nnpx @redocly/cli lint openapi-4.0.yaml --ruleset recommended\n\n# Step 3: Manual cleanup, name your outcomes semantically\n# The converter uses status codes as outcome names; rename them\n```\n\nThe automated converter handles ~85% of the transformation. The remaining 15% is:\n\n1. **Naming outcomes**: The converter maps ` \"200\" ` to ` outcome200 `. Rename to ` success `, ` created `, ` notFound `, etc.\n2. **Extracting shared pathItems**: If you had duplicated path definitions, consolidate them.\n3. **Webhook delivery metadata**: Add retry policies and signing info that didn't exist in 3.1.\n4. **Parameter deduplication**: Move shared parameters from operations to pathItems.\n\nThe total migration takes about 6 hours for a 2,400-line spec. Most of the time was spent on semantic naming.\n\n## Code generation reality check\n\nHere's the honest state of tooling as of January 2026:\n\n| Tool | 4.0 Support | Notes |\n| --- | --- | --- |\n| Redocly CLI | Full | Linting, bundling, overlays |\n| Swagger UI | Partial | Renders but misses outcomes |\n| OpenAPI Generator | Beta | Java/Python/TypeScript clients |\n| Stoplight | Full | Design-first editor |\n| Prism (mock server) | Partial | Basic mocking works |\n| Postman | Partial | Import works, some features missing |\n\nIf your workflow depends on a specific tool, check its 4.0 support before migrating. The spec is ahead of the tooling ecosystem by roughly 6 months, which is normal for a major version.\n\n## Real-world spec design patterns\n\nAfter extended work with 4.0, these patterns emerge:\n\n**Pattern: Shared error outcomes**\n\n```yaml\ncomponents:\n outcomes:\n validationError:\n status: 422\n contentType: application/problem+json\n body:\n schema:\n $ref: \"#/components/schemas/ValidationProblem\"\n unauthorized:\n status: 401\n contentType: application/problem+json\n body:\n schema:\n $ref: \"#/components/schemas/AuthProblem\"\n rateLimited:\n status: 429\n headers:\n Retry-After:\n schema:\n type: integer\n\npathItems:\n charge:\n requests:\n createCharge:\n method: post\n outcomes:\n created:\n status: 201\n body:\n schema:\n $ref: \"#/components/schemas/Charge\"\n validation:\n $ref: \"#/components/outcomes/validationError\"\n auth:\n $ref: \"#/components/outcomes/unauthorized\"\n throttled:\n $ref: \"#/components/outcomes/rateLimited\"\n```\n\nShared outcomes eliminate the \"copy error responses to every endpoint\" problem. Define your error shapes once, reference everywhere.\n\n## Should you migrate now?\n\nHonest assessment: for new API projects and your toolchain supports 4.0, use it. The structural improvements (overlays, decoupled pathItems, semantic outcomes) make specs easier to maintain as they grow. If you have a large existing 3.1 spec that works fine, wait 6-12 months for tooling to mature. The migration itself is straightforward but the ecosystem needs to catch up.\n\nThe biggest win is overlays. Going from maintaining four copies of a spec (dev, staging, prod, partner) to one base plus four 20-line overlay files represents significant improvement. That alone justifies the migration effort.\n\n## Frequently asked questions\n\n### What changed from OpenAPI 3.1 to 4.0?\n\nThe structure is reorganized around 'requests' and 'outcomes' instead of paths and operations. Webhooks are first-class citizens. Overlays allow layering modifications. URL templates replace path patterns. The component reuse model is simplified.\n\n### Is OpenAPI 4.0 backward compatible with 3.1?\n\nNo, it's a structural rewrite. However, automated migration tools (like Redocly and Stoplight converters) handle most of the transformation. The conceptual model is similar enough that migration is mechanical, not creative.\n\n### Should I migrate existing APIs to 4.0?\n\nNot immediately. Wait for tooling maturity, code generators, validators, and documentation renderers need to catch up. For new APIs, 4.0 is worth adopting if your toolchain supports it.\n\n## Tips\n\n1. **Tip:** Start with Overlays before migrating your full spec to 4.0. You can keep your 3.1 source of truth and layer environment-specific details (server URLs, auth schemes) with ` overlay.yaml ` files.\n2. **Tip:** Use ` pathItems ` instead of the old ` paths ` object when building shared patterns. A single pathItem definition can be referenced from multiple URL templates, eliminating copy-paste in large APIs.\n3. **Tip:** Validate your 4.0 spec with ` @redocly/cli lint ` before trusting code generators. Most generators lag behind the spec by 3-6 months, and invalid input produces subtly broken client code.\n\n- openapi\n- moonwalk\n- api-design\n- api-specification\n- webhooks\n- swagger\n- rest-api\n- api-gateway\n\n[Back to Blog](<https://lucioduran.com/blog>)","headings":[{"level":1,"text":"OpenAPI 4.0 (Moonwalk): The Spec Rewrite That Actually Matters","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#title"},{"level":2,"text":"The structural shift: from paths to requests","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#the-structural-shift-from-paths-to-requests"},{"level":2,"text":"Overlays: layering without forking","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#overlays-layering-without-forking"},{"level":2,"text":"First-class webhooks","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#first-class-webhooks"},{"level":2,"text":"Migration from 3.1: the practical path","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#migration-from-31-the-practical-path"},{"level":2,"text":"Code generation reality check","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#code-generation-reality-check"},{"level":2,"text":"Real-world spec design patterns","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#real-world-spec-design-patterns"},{"level":2,"text":"Should you migrate now?","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#should-you-migrate-now"},{"level":2,"text":"Frequently asked questions","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#questions"},{"level":3,"text":"What changed from OpenAPI 3.1 to 4.0?","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#question-1"},{"level":3,"text":"Is OpenAPI 4.0 backward compatible with 3.1?","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#question-2"},{"level":3,"text":"Should I migrate existing APIs to 4.0?","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#question-3"},{"level":2,"text":"Tips","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#article-tips"}],"sections":[{"heading":"OpenAPI 4.0 (Moonwalk): The Spec Rewrite That Actually Matters","level":1,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification","content":"API Design"},{"heading":"OpenAPI 4.0 (Moonwalk): The Spec Rewrite That Actually Matters","level":1,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#title","content":"2025-10-265 min read\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nAlso available in: [Español](<https://lucioduran.com/es/blog/openapi-4-moonwalk-api-specification>)"},{"heading":"The structural shift: from paths to requests","level":2,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#the-structural-shift-from-paths-to-requests","content":"In [OpenAPI](<https://www.openapis.org/>) 3.1, the top-level structure revolves around ` paths `:\n\n```yaml\n# OpenAPI 3.1, path-centric\nopenapi: \"3.1.0\"\npaths:\n /users/{userId}:\n get:\n operationId: getUser\n parameters:\n - name: userId\n in: path\n required: true\n schema:\n type: string\n responses:\n \"200\":\n content:\n application/json:\n schema:\n $ref: \"#/components/schemas/User\"\n```\n\nOpenAPI 4.0 reorganizes around ` requests ` and ` pathItems `:\n\n```yaml\n# OpenAPI 4.0, request-centric\nopenapi: \"4.0.0\"\ninfo:\n title: User Service\n version: \"2.0\"\n\npathItems:\n user:\n parameters:\n userId:\n in: path\n schema:\n type: string\n requests:\n getUser:\n method: get\n outcomes:\n success:\n status: 200\n contentType: application/json\n body:\n schema:\n $ref: \"#/components/schemas/User\"\n notFound:\n status: 404\n contentType: application/problem+json\n body:\n schema:\n $ref: \"#/components/schemas/Problem\"\n\nurls:\n /users/{userId}: { $ref: \"#/pathItems/user\" }\n /v2/users/{userId}: { $ref: \"#/pathItems/user\" }\n```\n\nNotice several things. First, ` pathItems ` are decoupled from URLs. The same ` user ` pathItem serves both ` /users/{userId} ` and ` /v2/users/{userId} `. In 3.1, you'd duplicate the entire path definition or use ` $ref ` gymnastics. Second, responses are now ` outcomes `, named semantic results rather than status-code-indexed entries. ` success ` and ` notFound ` are more meaningful than ` \"200\" ` and ` \"404\" `. Third, parameters belong to the pathItem, not repeated per operation."},{"heading":"Overlays: layering without forking","level":2,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#overlays-layering-without-forking","content":"This is a long-awaited feature. Overlays let you take a base OpenAPI document and apply modifications without editing the original. Think of it like CSS overrides for your API spec.\n\n```yaml\n# base.yaml, your canonical API spec\nopenapi: \"4.0.0\"\ninfo:\n title: Payment API\n version: \"1.0\"\npathItems:\n charge:\n requests:\n createCharge:\n method: post\n body:\n schema:\n $ref: \"#/components/schemas/ChargeRequest\"\n outcomes:\n created:\n status: 201\n body:\n schema:\n $ref: \"#/components/schemas/Charge\"\nurls:\n /charges: { $ref: \"#/pathItems/charge\" }\n```\n\n```yaml\n# overlay-staging.yaml, staging environment specifics\noverlay: \"1.0.0\"\ninfo:\n title: Staging Overlay\nextends: base.yaml\nactions:\n - target: \"$.info\"\n update:\n description: \"STAGING ENVIRONMENT, test data only\"\n - target: \"$.servers\"\n update:\n - url: https://staging-api.example.com\n description: Staging\n - target: \"$.pathItems.charge.requests.createCharge\"\n update:\n security:\n - apiKey: [] # Simpler auth in staging\n```\n\n```yaml\n# overlay-production.yaml\noverlay: \"1.0.0\"\nextends: base.yaml\nactions:\n - target: \"$.servers\"\n update:\n - url: https://api.example.com\n description: Production US-East\n - url: https://eu-api.example.com\n description: Production EU-West\n - target: \"$.pathItems.charge.requests.createCharge\"\n update:\n security:\n - oauth2:\n scopes: [\"charges:write\"]\n rateLimit:\n limit: 100\n window: 60s\n```\n\nBuild the final spec for each environment:\n\n```bash\n# Merge base + overlay\nredocly bundle base.yaml --overlay overlay-production.yaml -o production-spec.yaml\nredocly bundle base.yaml --overlay overlay-staging.yaml -o staging-spec.yaml\n```\n\nThis eliminates the \"copy the spec and change the server URL\" pattern that plagues every multi-environment API. The base spec is your single source of truth. Overlays adapt it per environment, per partner, per version."},{"heading":"First-class webhooks","level":2,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#first-class-webhooks","content":"In 3.1, webhooks were bolted on as a top-level ` webhooks ` field, structurally identical to paths but semantically different. In 4.0, they're integrated into the request/outcome model:\n\n```yaml\nwebhooks:\n paymentCompleted:\n description: Fired when a payment is successfully processed\n requests:\n notify:\n method: post\n contentType: application/json\n body:\n schema:\n type: object\n required: [event, data]\n properties:\n event:\n type: string\n const: payment.completed\n data:\n $ref: \"#/components/schemas/Payment\"\n timestamp:\n type: string\n format: date-time\n outcomes:\n acknowledged:\n status: 200\n description: Webhook received and acknowledged\n retry:\n status: [500, 502, 503]\n description: Server error, webhook will be retried\n delivery:\n retryPolicy:\n maxRetries: 5\n backoff: exponential\n initialDelay: 30s\n signing:\n algorithm: hmac-sha256\n headerName: X-Webhook-Signature\n```\n\nThe ` delivery ` section is new, it documents retry policies and signing mechanisms as part of the spec. In 3.1, this information lived in your docs' prose. Now it's machine-readable, and code generators can produce webhook verification code automatically."},{"heading":"Migration from 3.1: the practical path","level":2,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#migration-from-31-the-practical-path","content":"A 2,400-line OpenAPI 3.1 spec migration to 4.0 follows this process:\n\n```bash\n# Step 1: Automated conversion\nnpx @redocly/cli transform openapi-3.1.yaml --to 4.0 -o openapi-4.0.yaml\n\n# Step 2: Validate the output\nnpx @redocly/cli lint openapi-4.0.yaml --ruleset recommended\n\n# Step 3: Manual cleanup, name your outcomes semantically\n# The converter uses status codes as outcome names; rename them\n```\n\nThe automated converter handles ~85% of the transformation. The remaining 15% is:\n\n1. **Naming outcomes**: The converter maps ` \"200\" ` to ` outcome200 `. Rename to ` success `, ` created `, ` notFound `, etc.\n2. **Extracting shared pathItems**: If you had duplicated path definitions, consolidate them.\n3. **Webhook delivery metadata**: Add retry policies and signing info that didn't exist in 3.1.\n4. **Parameter deduplication**: Move shared parameters from operations to pathItems.\n\nThe total migration takes about 6 hours for a 2,400-line spec. Most of the time was spent on semantic naming."},{"heading":"Code generation reality check","level":2,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#code-generation-reality-check","content":"Here's the honest state of tooling as of January 2026:\n\n| Tool | 4.0 Support | Notes |\n| --- | --- | --- |\n| Redocly CLI | Full | Linting, bundling, overlays |\n| Swagger UI | Partial | Renders but misses outcomes |\n| OpenAPI Generator | Beta | Java/Python/TypeScript clients |\n| Stoplight | Full | Design-first editor |\n| Prism (mock server) | Partial | Basic mocking works |\n| Postman | Partial | Import works, some features missing |\n\nIf your workflow depends on a specific tool, check its 4.0 support before migrating. The spec is ahead of the tooling ecosystem by roughly 6 months, which is normal for a major version."},{"heading":"Real-world spec design patterns","level":2,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#real-world-spec-design-patterns","content":"After extended work with 4.0, these patterns emerge:\n\n**Pattern: Shared error outcomes**\n\n```yaml\ncomponents:\n outcomes:\n validationError:\n status: 422\n contentType: application/problem+json\n body:\n schema:\n $ref: \"#/components/schemas/ValidationProblem\"\n unauthorized:\n status: 401\n contentType: application/problem+json\n body:\n schema:\n $ref: \"#/components/schemas/AuthProblem\"\n rateLimited:\n status: 429\n headers:\n Retry-After:\n schema:\n type: integer\n\npathItems:\n charge:\n requests:\n createCharge:\n method: post\n outcomes:\n created:\n status: 201\n body:\n schema:\n $ref: \"#/components/schemas/Charge\"\n validation:\n $ref: \"#/components/outcomes/validationError\"\n auth:\n $ref: \"#/components/outcomes/unauthorized\"\n throttled:\n $ref: \"#/components/outcomes/rateLimited\"\n```\n\nShared outcomes eliminate the \"copy error responses to every endpoint\" problem. Define your error shapes once, reference everywhere."},{"heading":"Should you migrate now?","level":2,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#should-you-migrate-now","content":"Honest assessment: for new API projects and your toolchain supports 4.0, use it. The structural improvements (overlays, decoupled pathItems, semantic outcomes) make specs easier to maintain as they grow. If you have a large existing 3.1 spec that works fine, wait 6-12 months for tooling to mature. The migration itself is straightforward but the ecosystem needs to catch up.\n\nThe biggest win is overlays. Going from maintaining four copies of a spec (dev, staging, prod, partner) to one base plus four 20-line overlay files represents significant improvement. That alone justifies the migration effort."},{"heading":"Frequently asked questions","level":2,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#questions","content":""},{"heading":"What changed from OpenAPI 3.1 to 4.0?","level":3,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#question-1","content":"The structure is reorganized around 'requests' and 'outcomes' instead of paths and operations. Webhooks are first-class citizens. Overlays allow layering modifications. URL templates replace path patterns. The component reuse model is simplified."},{"heading":"Is OpenAPI 4.0 backward compatible with 3.1?","level":3,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#question-2","content":"No, it's a structural rewrite. However, automated migration tools (like Redocly and Stoplight converters) handle most of the transformation. The conceptual model is similar enough that migration is mechanical, not creative."},{"heading":"Should I migrate existing APIs to 4.0?","level":3,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#question-3","content":"Not immediately. Wait for tooling maturity, code generators, validators, and documentation renderers need to catch up. For new APIs, 4.0 is worth adopting if your toolchain supports it."},{"heading":"Tips","level":2,"url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#article-tips","content":"1. **Tip:** Start with Overlays before migrating your full spec to 4.0. You can keep your 3.1 source of truth and layer environment-specific details (server URLs, auth schemes) with ` overlay.yaml ` files.\n2. **Tip:** Use ` pathItems ` instead of the old ` paths ` object when building shared patterns. A single pathItem definition can be referenced from multiple URL templates, eliminating copy-paste in large APIs.\n3. **Tip:** Validate your 4.0 spec with ` @redocly/cli lint ` before trusting code generators. Most generators lag behind the spec by 3-6 months, and invalid input produces subtly broken client code.\n\n- openapi\n- moonwalk\n- api-design\n- api-specification\n- webhooks\n- swagger\n- rest-api\n- api-gateway\n\n[Back to Blog](<https://lucioduran.com/blog>)"}],"links":[{"text":"Español","url":"https://lucioduran.com/es/blog/openapi-4-moonwalk-api-specification"},{"text":"OpenAPI","url":"https://www.openapis.org/"},{"text":"Back to Blog","url":"https://lucioduran.com/blog"}],"structuredData":[{"@context":"https://schema.org","@graph":[{"@type":"BlogPosting","@id":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification#article","mainEntityOfPage":{"@type":"WebPage","@id":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification"},"headline":"OpenAPI 4.0 (Moonwalk): The Spec Rewrite That Actually Matters","description":"New overlay mechanism, first-class webhooks, reusable workflows, comparison with 3.1, and a real migration path from Swagger, OpenAPI 4.0 is the biggest API spec change in a decade.","datePublished":"2025-10-26","author":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"publisher":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"image":"https://lucioduran.com/favicons/og-default.png","url":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification","inLanguage":"en","isPartOf":{"@id":"https://lucioduran.com/blog#blog"},"articleSection":"API Design","keywords":"openapi, moonwalk, api-design, api-specification, webhooks, swagger, rest-api, api-gateway","wordCount":934,"timeRequired":"PT5M","workTranslation":[{"@type":"BlogPosting","inLanguage":"es","url":"https://lucioduran.com/es/blog/openapi-4-moonwalk-api-specification"}]},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://lucioduran.com/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https://lucioduran.com/blog"},{"@type":"ListItem","position":3,"name":"OpenAPI 4.0 (Moonwalk): The Spec Rewrite That Actually Matters","item":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification"}]},{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"What changed from OpenAPI 3.1 to 4.0?","acceptedAnswer":{"@type":"Answer","text":"The structure is reorganized around 'requests' and 'outcomes' instead of paths and operations. Webhooks are first-class citizens. Overlays allow layering modifications. URL templates replace path patterns. The component reuse model is simplified."}},{"@type":"Question","name":"Is OpenAPI 4.0 backward compatible with 3.1?","acceptedAnswer":{"@type":"Answer","text":"No, it's a structural rewrite. However, automated migration tools (like Redocly and Stoplight converters) handle most of the transformation. The conceptual model is similar enough that migration is mechanical, not creative."}},{"@type":"Question","name":"Should I migrate existing APIs to 4.0?","acceptedAnswer":{"@type":"Answer","text":"Not immediately. Wait for tooling maturity, code generators, validators, and documentation renderers need to catch up. For new APIs, 4.0 is worth adopting if your toolchain supports it."}}]}]}],"contentHash":"2f72d045357720d3158d88c7a6afad1fad1e59507aac948fd7dca367dae0a9ba","provenance":{"method":"Deterministic serialization of the server-rendered main element","source":"https://lucioduran.com/blog/openapi-4-moonwalk-api-specification","hashAlgorithm":"sha256","hashScope":"JSON document fields before contentHash and provenance","sourceHTMLBytes":56512,"contentBytes":9710}}
