ZuploZuplo
LoginStart for Free
  • Documentation
  • API Reference
Introduction
Getting Started
    Develop on the web portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
    Develop locally with the CLI
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
Concepts
Development
    CORSEnvironment VariablesBranch-Based DeploymentsTestingTroubleshootingGitOps vs TerraformCustom Code
    Local Development
    Guides
      Advanced Path MatchingAPI VersioningOpenAPI Server URLsConvert URLs to OpenAPIOpenAPI Extension DataFormat Validation WarningsPath Modification ScriptsOpenAPI OverlaysCanary Routing for EmployeesGeolocation Backend RoutingUser-Based Backend RoutingTransform Route ParametersBypass a PolicyTesting GraphQL QueriesHealth ChecksPerformance TestingTroubleshooting Slow ResponsesNon-Standard PortsHandling FormDataS3 Signed URL UploadsCheck IP AddressLazy Load ConfigurationSharing Code Across ProjectsBackstage IntegrationGitHub Action Automation
Policies
Handlers
API Keys
Rate Limiting
MCP Server
MCP Gateway
AI Gateway
Developer Portal
Monetization
GraphQL
Deploying & Source Control
Analytics
Observability
Networking & Infrastructure
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsSecuritySupportTrust & ComplianceChangelog
powered by Zudoku
Guides

Modifying OpenAPI Paths with Scripts

There are many scenarios where you need to modify all paths in your OpenAPI specification - adding version prefixes, environment-specific paths, API gateway base paths, or regional endpoints. Rather than manually editing every route, you can write a simple script to transform all paths programmatically.

Common Use Cases

Path modification scripts are useful for:

  • API Versioning: Add /v1, /v2, or /2024-01 prefixes
  • Environment Routing: Add /staging, /dev, or /preview prefixes
  • Gateway Integration: Prepend /api or /gateway base paths
  • Regional Endpoints: Add /us-east, /eu-west regional prefixes
  • Multi-Tenant: Add /{tenantId} path segments
  • Legacy Migration: Transform old path structures to new patterns

Basic Path Prefix Script

Here's a simple script that adds a prefix to all paths in your OpenAPI document:

add-path-prefix.mjs
import { readFile, writeFile } from "fs/promises"; async function addPathPrefix(inputPath, outputPath, prefix) { // Read the OpenAPI document const content = await readFile(inputPath, "utf-8"); const openapi = JSON.parse(content); // Create new paths object with prefixed paths const newPaths = {}; for (const [path, pathItem] of Object.entries(openapi.paths)) { // Add the prefix to the path const prefixedPath = `${prefix}${path}`; newPaths[prefixedPath] = pathItem; } // Replace the paths in the document openapi.paths = newPaths; // Write the modified document await writeFile(outputPath, JSON.stringify(openapi, null, 2)); console.log(`✅ Added prefix "${prefix}" to all paths`); console.log(`✅ Output written to: ${outputPath}`); } // Usage const prefix = process.argv[2] || "/v1"; const inputFile = process.argv[3] || "openapi.json"; const outputFile = process.argv[4] || `openapi-${prefix.replace(/\//g, "")}.json`; addPathPrefix(inputFile, outputFile, prefix).catch(console.error);

Run the script:

TerminalCode
# Add /v1 prefix node add-path-prefix.mjs /v1 openapi.json openapi-v1.json # Add /v2 prefix node add-path-prefix.mjs /v2 openapi.json openapi-v2.json # Add /api prefix node add-path-prefix.mjs /api openapi.json openapi-api.json

Example transformation:

Before (openapi.json)
{ "paths": { "/users": { "get": {...} }, "/products": { "get": {...} } } }
After (openapi-v1.json)
{ "paths": { "/v1/users": { "get": {...} }, "/v1/products": { "get": {...} } } }

Multiple Versions in Build Pipeline

You can generate multiple versions as part of your build process:

package.json
{ "scripts": { "build:api:v1": "node add-path-prefix.mjs /v1 openapi.json dist/openapi-v1.json", "build:api:v2": "node add-path-prefix.mjs /v2 openapi.json dist/openapi-v2.json", "build:api:all": "npm run build:api:v1 && npm run build:api:v2" } }

Or create a build script for multiple variants:

Terminalbuild-versions.sh
#!/bin/bash # Define prefixes to build PREFIXES=("v1" "v2" "api" "staging") BASE_FILE="openapi.json" OUTPUT_DIR="dist" mkdir -p $OUTPUT_DIR for prefix in "${PREFIXES[@]}"; do echo "Building with prefix: /$prefix" node add-path-prefix.mjs \ "/$prefix" \ "$BASE_FILE" \ "$OUTPUT_DIR/openapi-$prefix.json" echo "✅ Generated $OUTPUT_DIR/openapi-$prefix.json" done echo "🎉 All variants built successfully!"

Make it executable and run:

TerminalCode
chmod +x build-versions.sh ./build-versions.sh

Advanced Use Cases

Inserting Path Segments

Insert a prefix after an existing base path:

insert-path-segment.ts
import { readFile, writeFile } from "fs/promises"; interface OpenAPIDocument { paths: Record<string, any>; [key: string]: any; } async function insertPathSegment( inputPath: string, outputPath: string, basePrefix: string, insertSegment: string, ) { const content = await readFile(inputPath, "utf-8"); const openapi: OpenAPIDocument = JSON.parse(content); const newPaths: Record<string, any> = {}; for (const [path, pathItem] of Object.entries(openapi.paths)) { let newPath: string; // If path starts with basePrefix, insert the segment after it if (path.startsWith(basePrefix)) { const remainingPath = path.slice(basePrefix.length); newPath = `${basePrefix}${insertSegment}${remainingPath}`; } else { // Otherwise just prepend the segment newPath = `${insertSegment}${path}`; } newPaths[newPath] = pathItem; } openapi.paths = newPaths; await writeFile(outputPath, JSON.stringify(openapi, null, 2)); console.log(`✅ Inserted "${insertSegment}" into paths`); } const basePrefix = process.argv[2] || "/api"; const insertSegment = process.argv[3] || "/v1"; const inputFile = process.argv[4] || "openapi.json"; const outputFile = process.argv[5] || "openapi-modified.json"; insertPathSegment(inputFile, outputFile, basePrefix, insertSegment).catch( console.error, );
TerminalCode
# Transform /api/users to /api/v1/users npx tsx insert-path-segment.ts /api /v1 openapi.json openapi-v1.json

Path Transformation with Patterns

Transform paths based on patterns:

transform-paths.ts
import { readFile, writeFile } from "fs/promises"; interface OpenAPIDocument { paths: Record<string, any>; [key: string]: any; } type PathTransformer = (path: string) => string; async function transformPaths( inputPath: string, outputPath: string, transformer: PathTransformer, ) { const content = await readFile(inputPath, "utf-8"); const openapi: OpenAPIDocument = JSON.parse(content); const newPaths: Record<string, any> = {}; for (const [path, pathItem] of Object.entries(openapi.paths)) { const transformedPath = transformer(path); newPaths[transformedPath] = pathItem; } openapi.paths = newPaths; await writeFile(outputPath, JSON.stringify(openapi, null, 2)); console.log(`✅ Transformed paths written to: ${outputPath}`); } // Example transformers const transformers = { // Add version prefix addVersion: (path: string) => `/v1${path}`, // Add regional prefix addRegion: (path: string) => `/us-east${path}`, // Add tenant ID parameter addTenant: (path: string) => `/{tenantId}${path}`, // Convert to kebab-case (example) kebabCase: (path: string) => path.replace(/([A-Z])/g, "-$1").toLowerCase(), }; // Usage example const transformerName = (process.argv[2] as keyof typeof transformers) || "addVersion"; const transformer = transformers[transformerName]; if (!transformer) { console.error(`Unknown transformer: ${transformerName}`); console.error(`Available: ${Object.keys(transformers).join(", ")}`); process.exit(1); } transformPaths("openapi.json", "openapi-transformed.json", transformer).catch( console.error, );
TerminalCode
# Add version npx tsx transform-paths.ts addVersion # Add region npx tsx transform-paths.ts addRegion # Add tenant ID npx tsx transform-paths.ts addTenant

Environment-Specific Paths

Generate different paths for different environments:

environment-paths.ts
import { readFile, writeFile } from "fs/promises"; interface OpenAPIDocument { paths: Record<string, any>; [key: string]: any; } const environments = { development: "/dev", staging: "/staging", preview: "/preview", production: "", // No prefix for production }; async function addEnvironmentPrefix( inputPath: string, environment: keyof typeof environments, ) { const content = await readFile(inputPath, "utf-8"); const openapi: OpenAPIDocument = JSON.parse(content); const prefix = environments[environment]; const newPaths: Record<string, any> = {}; for (const [path, pathItem] of Object.entries(openapi.paths)) { const newPath = prefix ? `${prefix}${path}` : path; newPaths[newPath] = pathItem; } openapi.paths = newPaths; const outputPath = `openapi-${environment}.json`; await writeFile(outputPath, JSON.stringify(openapi, null, 2)); console.log(`✅ Generated ${environment} variant: ${outputPath}`); } const env = (process.argv[2] as keyof typeof environments) || "development"; if (!environments[env]) { console.error(`Unknown environment: ${env}`); console.error(`Available: ${Object.keys(environments).join(", ")}`); process.exit(1); } addEnvironmentPrefix("openapi.json", env).catch(console.error);
TerminalCode
# Generate all environment variants npx tsx environment-paths.ts development npx tsx environment-paths.ts staging npx tsx environment-paths.ts production

Best Practices

  1. Keep Base OpenAPI Clean: Maintain a version-agnostic base OpenAPI file and use overlays to generate versioned variants

  2. Automate Version Generation: Use scripts and CI/CD to generate all version variants automatically

  3. Test Generated Files: Validate generated OpenAPI files with tools like Spectral or Vacuum

  4. Version Your Overlays: Store overlay generation scripts in version control alongside your OpenAPI files

  5. Document Version Differences: Use overlay descriptions to document what changes between versions

  6. Use Consistent Patterns: Stick to one versioning scheme (/v1, /v2 or /2024-01, etc.) across your organization

Next Steps

  • Learn about API versioning strategies in Zuplo
  • Explore more OpenAPI Overlay techniques
  • Check out the OpenAPI Overlay CLI reference
  • Read about OpenAPI best practices
Edit this page
Last modified on June 10, 2026
Format Validation WarningsOpenAPI Overlays
On this page
  • Common Use Cases
  • Basic Path Prefix Script
  • Multiple Versions in Build Pipeline
  • Advanced Use Cases
    • Inserting Path Segments
    • Path Transformation with Patterns
    • Environment-Specific Paths
  • Best Practices
  • Next Steps
Javascript
JSON
JSON
JSON
TypeScript
TypeScript
TypeScript