How can I use OpenAPI overlays to copy or move elements in an OpenAPI document?

How can I use OpenAPI overlays to copy or move elements in an OpenAPI document? #

Before version 1.1.0, the OpenAPI Overlay Specification only offered update and remove actions. Both are useful, but neither can reference a value that already exists elsewhere in the target document — every value has to be spelled out literally in the overlay. Version 1.1.0 (released 14 January 2026) closes that gap with a new copy action, which sources its value from another location in the document being transformed rather than from a literal value in the overlay. This makes it possible to duplicate, rename, or move existing nodes with overlays alone.

How copy Differs From update #

The copy action behaves like update — it merges an object, concatenates an array, or replaces a primitive — but the value being merged is selected by a second JSONPath expression instead of being written out inline:

  • target — the JSONPath expression selecting the destination node(s).
  • copy — a JSONPath expression selecting a single source node to copy from.
- target: '$.paths["/some-items"]'
  copy: '$.paths["/items"]'

If the target selects an object, the value merged in comes from the object selected by copy. If target selects an array, the copied value is concatenated or appended, following the same merge rules as update. A given action cannot set both update and copyupdate is ignored if copy is present.

Simple Copy #

Given the following OpenAPI document:

openapi: 3.1.0
info:
  title: Example API
  version: 1.0.0
paths:
  /items:
    get:
      responses:
        200:
          description: OK
  /some-items:
    delete:
      responses:
        200:
          description: OK

This overlay copies every operation from /items into /some-items, merging with what is already there:

overlay: 1.1.0
info:
  title: Copy contents of an existing path to a new location
  version: 1.0.0
actions:
  - target: '$.paths["/some-items"]'
    copy: '$.paths["/items"]'
    description: 'copies recursively all elements from the "items" path item to the new "some-items" path item'

The result keeps the existing delete operation on /some-items and adds the get operation copied from /items:

paths:
  /items:
    get:
      responses:
        200:
          description: OK
  /some-items:
    get:
      responses:
        200:
          description: OK
    delete:
      responses:
        200:
          description: OK

Ensuring the Target Exists Before Copying #

The copy action merges into whatever target currently resolves to. If the destination path doesn’t exist yet, add an update action first to create it, then copy into it:

overlay: 1.1.0
info:
  title: Create a path and copy the contents of an existing path to the new path
  version: 1.0.0
actions:
  - target: '$.paths'
    update: { "/other-items": {} }
  - target: '$.paths["/other-items"]'
    copy: '$.paths["/items"]'
    description: 'copies recursively all elements from the "items" path item to the new "other-items" path item while ensuring the node exists before the copy'

Because Overlay actions are applied in sequential order, the update action runs first and creates an empty /other-items path item, and the subsequent copy action then has somewhere to merge into.

Moving or Renaming a Path #

Combining update, copy, and remove in sequence lets you move or rename an existing node — something the update/remove actions alone could not express, since they cannot reference existing values:

overlay: 1.1.0
info:
  title: Update the path for an API endpoint
  version: 1.0.0
actions:
  - target: '$.paths'
    update: { "/new-items": {} }
  - target: '$.paths["/new-items"]'
    copy: '$.paths["/items"]'
  - target: '$.paths["/items"]'
    remove: true
    description: 'moves (renames) the "items" path item to "new-items"'

Applied to a document containing /items, this produces a document where /items no longer exists and /new-items contains everything that used to live under /items:

paths:
  /new-items:
    get:
      responses:
        200:
          description: OK
  /some-items:
    delete:
      responses:
        200:
          description: OK

This three-step pattern — ensure the target exists, copy the source into it, remove the source — is the general recipe for any move or rename operation expressed as an overlay.

When to Use copy Instead of update #

copy is most useful when:

  • Renaming paths or operations during API evolution, without having to retype the entire operation body in the overlay.
  • Duplicating a well-defined operation or schema as the starting point for a new, slightly different one, followed by a targeted update to adjust the copy.
  • Reorganizing a document programmatically (for example, grouping endpoints under a new base path) where the content to move is large or frequently changing, making it impractical to hardcode in the overlay.

For simple literal changes — replacing a description, adding an x- extension, or removing a field — update and remove remain the right tools, since they don’t require a second JSONPath lookup.

Tooling Support #

The copy action is part of Overlay Specification version 1.1.0. Since this feature is newer than the original update/remove actions, confirm that your overlay tooling has been updated to a version that implements 1.1.0 before relying on copy in production pipelines — consult the Overlay Specification repository for the current list of tools with 1.1.0 support.


Last updated on July 22, 2026.

This website is not affiliated with the OpenAPI Initiative.