--- title: Transforms reference | Stainless description: Complete technical reference for Stainless OpenAPI transforms --- For practical examples and common use cases, see the [transforms guide](/docs/openapi/transforms/index.md). Transforms modify your OpenAPI spec during SDK generation. Define them in `stainless.yaml` under `openapi.transforms`. Stainless applies transforms in order using [JSONPath Plus](https://www.npmjs.com/package/jsonpath-plus) queries. ``` openapi: transforms: - command: update # Command name reason: "Why this transform exists" args: target: "$.path.to.field" value: "new value" ``` Transforms fail loudly when paths don’t exist or operations conflict. All values are deep-cloned to prevent shared references. ## update Replace values at existing paths. Fails if path doesn’t exist. **Arguments:** - `target` (string | Array): JSONPath query to value(s) to replace - `value` (any): New value to set - `template` (boolean, optional): Enable `{{value}}` substitution for strings **Examples:** ``` # Replace simple value - command: update args: target: "$.info.version" value: "2.0.0" # Fix types across endpoints - command: update args: target: '$.paths..parameters[?(@.name == "account_id")].schema.type' value: "string" # String templating: append - command: update args: target: "$.paths./v1/users.get.summary" value: "{{value}}\n\nDEPRECATED: Use /v2/users" template: true # Schema matching: replace duplicates - command: update args: target: - matches_schema: $.components.schemas.ErrorTemplate ignore: $.components.schemas.ErrorTemplate value: $ref: "#/components/schemas/Error" ``` **String templating:** When `template: true`, `value` must contain `{{value}}`. Each target must be a string. The placeholder gets replaced with the current value. **Examples:** ``` # Append text - command: update args: target: "$.paths./v1/users.get.description" value: "{{value}}\n\n⚠️ Deprecated. Use /v2/users." template: true # Prepend text - command: update args: target: '$.paths./beta/*.get.summary' value: "[BETA] {{value}}" template: true # Wrap text - command: update args: target: "$.components.schemas.User.properties.id.description" value: "**{{value}}**" template: true ``` When targeting multiple paths, `{{value}}` is replaced with each target’s individual current value. **Schema matching:** Use `matches_schema` to find schemas that exactly match a template (deep equality). The `ignore` field excludes paths from replacement. ## append Add items to arrays or properties to objects. Fails if object property already exists (safety feature). **Arguments:** - `target` (string | Array): JSONPath query to array(s) or object(s) - `value` (any): Item(s) to push (arrays) or properties to add (objects) **Examples:** ``` # Add to array - command: append args: target: "$.components.schemas.User.required" value: "id" # Add properties (fails if exists) - command: append args: target: "$.components.schemas.User.properties" value: id: type: "string" format: "uuid" # Add to multiple arrays - command: append args: target: "$.components.schemas.*.required" value: "id" ``` For objects, append fails if any property already exists. This alerts you when the spec is fixed and your transform becomes redundant. Use `merge` if you want to overwrite. ## merge Deep-merge object into targets. Overwrites existing properties. **Arguments:** - `target` (string | Array): JSONPath query to object(s) - `value` (object): Object to merge **Examples:** ``` # Add x-stainless extension - command: merge args: target: '$.paths..parameters[?(@.name == "limit")]' value: schema: x-stainless-skip: ["terraform"] # Language-specific naming - command: merge args: target: "$.components.schemas.Request.properties.timeout" value: x-stainless-naming: python: method_argument: "api_timeout" # Merge into multiple schemas - command: merge args: target: "$.components.schemas.*" value: additionalProperties: false ``` Nested objects merge recursively. Use `merge` for permanent overrides, `append` for temporary fixes. ## remove Delete nodes or specific keys from objects. **Arguments:** - `target` (string | Array): JSONPath query to node(s) to remove - `keys` (`Array`, optional): If target is object, remove only these keys. Otherwise removes entire node. **Examples:** ``` # Remove entire nodes - command: remove args: target: - "$.paths.*.*.examples" - "$.components.schemas.*.example" # Remove specific keys - command: remove args: target: "$.components.schemas.User.properties.middleName" keys: ["default"] # Remove with filter - command: remove args: target: '$.paths..parameters[?(@.deprecated == true)]' ``` When removing from arrays, handles index shifting correctly by removing in descending order. ## copy Copy value from source to one or more destinations. Creates destination if parent exists. **Arguments:** - `from` (string): JSONPath query to source (must match exactly one node) - `to` (string | Array): JSONPath query to destination(s). Creates if doesn’t exist (parent must exist). **Examples:** ``` # Copy schema - command: copy args: from: "$.components.schemas.User" to: "$.components.schemas.Admin" # Copy to multiple destinations - command: copy args: from: "$.components.schemas.NotFoundError" to: - "$.paths./users/{id}.get.responses.404.content.application/json.schema" - "$.paths./posts/{id}.get.responses.404.content.application/json.schema" # Extract inline schema - command: copy args: from: "$.paths./users.post.responses.400.content.application/json.schema" to: "$.components.schemas.BadRequestError" ``` Values are deep-cloned to each destination. Cannot create array indices (use `append` instead). ## move Move or rename a value. Efficiently renames within same parent, otherwise copies and removes. **Arguments:** - `from` (string): JSONPath query to source (must match exactly one node) - `to` (string): JSONPath query to destination **Examples:** ``` # Rename schema - command: move args: from: "$.components.schemas.user_response" to: "$.components.schemas.UserResponse" # Rename property - command: move args: from: "$.components.schemas.User.properties.firstName" to: "$.components.schemas.User.properties.first_name" # Move across parents - command: move args: from: "$.components.schemas.User" to: "$.components.parameters.UserParam" ``` If source and destination share the same parent, `move` renames the key without copying. Otherwise, it copies to the destination and removes from the source. ## JSONPath Queries All transforms use [JSONPath Plus](https://www.npmjs.com/package/jsonpath-plus) for targeting. **Common patterns:** ``` # Exact path target: "$.components.schemas.User.properties.id" # Bracket notation for special characters target: '$.paths["/users/{id}"].get' # Wildcard (immediate children) target: "$.components.schemas.*" # Recursive descent target: "$..parameters" target: "$.paths..responses" # Array index target: "$.servers[0]" target: "$.paths./users.get.parameters[2]" # Filter by value target: '$.paths..parameters[?(@.in == "query")]' target: '$.components.schemas[?(@.type == "object")]' # Filter by property target: '$.paths..parameters[?(@.name == "account_id")]' # Multiple conditions target: '$.paths..parameters[?(@.in == "query" && @.required == true)]' # Combining wildcards and filters target: '$.paths.*.get.parameters[?(@.name == "limit")]' ``` **Multiple targets:** ``` target: - "$.components.schemas.User.example" - "$.components.schemas.Post.example" ``` Always quote paths with special characters or filter expressions. Use single quotes for paths containing double quotes. ## Schema Matching Find all schemas that exactly match a template: ``` target: - matches_schema: ignore: ``` **Example:** ``` - command: update args: target: - matches_schema: $.components.schemas.ErrorTemplate ignore: $.components.schemas.ErrorTemplate value: $ref: "#/components/schemas/Error" ``` Traverses entire spec, compares each schema with template for exact match (deep equality), returns matches. Use `ignore` to exclude the template itself. Can mix with explicit paths: ``` target: - "$.components.schemas.SpecificError" - matches_schema: $.components.schemas.ErrorPattern ``` ## Error Messages **Path not found:** “JSONPath did not match any nodes” Query didn’t find anything. Check for typos or verify the path exists. **Constraint violation:** “Properties already exist… use ‘merge’ instead” Using `append` on existing property (safety feature). Remove transform if the spec was fixed, or switch to `merge` to overwrite. **Type mismatch:** “Target must point to objects. Got string” Command expects specific type but found something else. Verify target path points to expected structure. **Invalid operation:** “Cannot create array index” Operation doesn’t support this structure. Use appropriate command (e.g., `append` for arrays). **Root targeting:** “Cannot update document root” Targeting `$` not allowed. Target specific fields within the document.