Transforms Reference
Complete technical reference for OpenAPI spec transforms
For practical examples and common use cases, see the transforms guide.
Transforms modify your OpenAPI spec during SDK generation. Define them in stainless.yaml under openapi.transformations. Stainless applies transforms in order using JSONPath Plus queries.
openapi: transformations: - 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
Section titled “update”Replace values at existing paths. Fails if path doesn’t exist.
Arguments:
target(string | Array): JSONPath query to value(s) to replacevalue(any): New value to settemplate(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: trueWhen 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
Section titled “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.
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: falseNested objects merge recursively. Use merge for permanent overrides, append for temporary fixes.
remove
Section titled “remove”Delete nodes or specific keys from objects.
Arguments:
target(string | Array): JSONPath query to node(s) to removekeys(Array<string>, 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 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 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
Section titled “JSONPath Queries”All transforms use JSONPath Plus for targeting.
Common patterns:
# Exact pathtarget: "$.components.schemas.User.properties.id"
# Bracket notation for special characterstarget: '$.paths["/users/{id}"].get'
# Wildcard (immediate children)target: "$.components.schemas.*"
# Recursive descenttarget: "$..parameters"target: "$.paths..responses"
# Array indextarget: "$.servers[0]"target: "$.paths./users.get.parameters[2]"
# Filter by valuetarget: '$.paths..parameters[?(@.in == "query")]'target: '$.components.schemas[?(@.type == "object")]'
# Filter by propertytarget: '$.paths..parameters[?(@.name == "account_id")]'
# Multiple conditionstarget: '$.paths..parameters[?(@.in == "query" && @.required == true)]'
# Combining wildcards and filterstarget: '$.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
Section titled “Schema Matching”Find all schemas that exactly match a template:
target: - matches_schema: <path-to-template> ignore: <optional-path-to-exclude>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.ErrorPatternError Messages
Section titled “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.