ZuploZuplo
LoginSign Up
  • Documentation
  • API Reference
Introduction
Getting Started
    Develop using the Portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingMCP - Quick start
    Develop Locally
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth
Concepts
Development
    CORSEnvironment VariablesBranch-Based DeploymentsTestingTroubleshootingGitOps vs TerraformCustom Code
    Local Development
    Guides
      Advanced Path MatchingAPI VersioningOpenAPI Server URLsConvert URLs to OpenAPIOpenAPI Extension DataPath Modification ScriptsOpenAPI OverlaysCanary Routing for EmployeesGeolocation Backend RoutingUser-Based Backend RoutingBypass 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
MCP Server
MCP Gateway
AI Gateway
Developer Portal
Monetization
Deploying & Source Control
Observability
Networking & Infrastructure
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsSecuritySupportTrust & ComplianceChangelog
powered by Zudoku
Guides

Modifying OpenAPI Files with OpenAPI Overlays

OpenAPI Overlays provide a powerful way to modify OpenAPI specifications without directly editing the source files. This is especially useful when you need to:

  • Apply consistent changes across multiple API versions
  • Add Zuplo-specific extensions to third-party OpenAPI specs
  • Maintain separation between base API definitions and environment-specific configurations
  • Automate modifications as part of your build or deployment process

What are OpenAPI Overlays

OpenAPI Overlays are JSON or YAML documents that describe modifications to be applied to an OpenAPI specification. They use a simple, declarative syntax to target specific parts of your API definition and apply changes.

The Zuplo CLI provides the openapi overlay command to apply these overlays to your OpenAPI files.

Basic Usage

The basic syntax for applying an overlay is:

TerminalCode
npx zuplo openapi overlay \ --input openapi.json \ --overlay changes.json \ --output result.json

You can also use the --watch flag to automatically reapply overlays when files change during development:

TerminalCode
npx zuplo openapi overlay \ --input openapi.json \ --overlay changes.json \ --output result.json \ --watch

Example 1: Modifying Route Summaries and Descriptions

One common use case is updating the summary and description fields of your API routes to improve documentation or add context-specific information. Overlays can both modify existing properties and add missing properties.

openapi.json
{ "openapi": "3.1.0", "info": { "title": "My API", "version": "1.0.0" }, "paths": { "/users/{userId}": { "get": { "summary": "Get user", "description": "Retrieves a user", "operationId": "getUser" } }, "/products": { "get": { "operationId": "listProducts" } } } }

Notice that /users/{userId} already has a summary and description (which we'll enhance), while /products has neither (which we'll add).

overlay.json
{ "overlay": "1.0.0", "info": { "title": "Enhanced Documentation Overlay", "version": "1.0.0" }, "actions": [ { "target": "$.paths['/users/{userId}'].get", "description": "Enhance existing summary and description", "update": { "summary": "Get User by ID", "description": "Retrieves detailed information about a specific user by their unique identifier. This endpoint requires authentication and returns comprehensive user profile data including preferences and account settings." } }, { "target": "$.paths['/products'].get", "description": "Add missing summary and description", "update": { "summary": "List All Products", "description": "Returns a paginated list of all products in the catalog. Supports filtering by category, price range, and availability status." } } ] }
TerminalCode
npx zuplo openapi overlay \ --input openapi.json \ --overlay overlay.json \ --output openapi-enhanced.json

Example 2: Adding Parameter Schemas

Overlays are excellent for adding parameter definitions to your OpenAPI spec, especially when working with APIs that have incomplete documentation.

Adding Path Parameters

add-path-params.json
{ "overlay": "1.0.0", "info": { "title": "Add Path Parameters", "version": "1.0.0" }, "actions": [ { "target": "$.paths['/users/{userId}'].get", "update": { "parameters": [ { "name": "userId", "in": "path", "required": true, "description": "The unique identifier of the user", "schema": { "type": "string", "format": "uuid", "example": "123e4567-e89b-12d3-a456-426614174000" } } ] } }, { "target": "$.paths['/orders/{orderId}/items/{itemId}'].get", "update": { "parameters": [ { "name": "orderId", "in": "path", "required": true, "description": "The order identifier", "schema": { "type": "integer", "minimum": 1, "example": 12345 } }, { "name": "itemId", "in": "path", "required": true, "description": "The item identifier within the order", "schema": { "type": "integer", "minimum": 1, "example": 67890 } } ] } } ] }

Adding Query Parameters

add-query-params.json
{ "overlay": "1.0.0", "info": { "title": "Add Query Parameters", "version": "1.0.0" }, "actions": [ { "target": "$.paths['/products'].get", "update": { "parameters": [ { "name": "category", "in": "query", "required": false, "description": "Filter products by category", "schema": { "type": "string", "enum": ["electronics", "clothing", "home", "sports"], "example": "electronics" } }, { "name": "minPrice", "in": "query", "required": false, "description": "Minimum price filter (inclusive)", "schema": { "type": "number", "format": "float", "minimum": 0, "example": 9.99 } }, { "name": "maxPrice", "in": "query", "required": false, "description": "Maximum price filter (inclusive)", "schema": { "type": "number", "format": "float", "minimum": 0, "example": 99.99 } }, { "name": "page", "in": "query", "required": false, "description": "Page number for pagination", "schema": { "type": "integer", "minimum": 1, "default": 1, "example": 1 } }, { "name": "limit", "in": "query", "required": false, "description": "Number of items per page", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20, "example": 20 } } ] } } ] }
TerminalCode
npx zuplo openapi overlay \ --input openapi.json \ --overlay add-query-params.json \ --output openapi-with-params.json

Example 3: Adding Zuplo Route Extensions

One of the more common uses of overlays is to add the Zuplo-specific extensions like x-zuplo-route to your OpenAPI files. This allows you to configure policies, handlers, and CORS settings without modifying your base OpenAPI specification.

zuplo-routes.json
{ "overlay": "1.0.0", "info": { "title": "Zuplo Route Extensions", "version": "1.0.0" }, "actions": [ { "target": "$.paths['/users/{userId}'].get", "update": { "x-zuplo-route": { "corsPolicy": "anything-goes", "handler": { "export": "default", "module": "$import(./modules/my-handler)", "options": { "someOption": true } }, "policies": { "inbound": ["api-key-inbound"] } } } }, { "target": "$.paths['/products'].get", "update": { "x-zuplo-route": { "corsPolicy": "anything-goes", "handler": { "export": "default", "module": "$import(@zuplo/runtime)", "options": { "backend": "backend-1" } }, "policies": { "inbound": [ "api-key-inbound", { "name": "rate-limit-inbound", "policyType": "rate-limit-inbound", "handler": { "export": "default", "module": "$import(@zuplo/runtime)", "options": { "rateLimitBy": "ip", "requestsAllowed": 100, "timeWindowMinutes": 1 } } } ], "outbound": ["log-response-outbound"] } } } }, { "target": "$.paths['/admin/settings'].put", "update": { "x-zuplo-route": { "corsPolicy": "none", "handler": { "export": "default", "module": "$import(./modules/admin-handler)", "options": {} }, "policies": { "inbound": [ "api-key-inbound", { "name": "jwt-auth", "policyType": "jwt-auth-inbound", "handler": { "export": "JwtInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "issuer": "https://auth.example.com", "audience": "api.example.com", "jwkUrl": "https://auth.example.com/.well-known/jwks.json" } } } ] } } } } ] }
TerminalCode
npx zuplo openapi overlay \ --input openapi.json \ --overlay zuplo-routes.json \ --output openapi-zuplo.json

This overlay adds:

  • CORS policies to control cross-origin requests
  • Request handlers that specify how Zuplo should process the request
  • Inbound policies like API key authentication, JWT validation, and rate limiting
  • Outbound policies for logging and response transformation

Combining Multiple Overlays

You can apply multiple overlays sequentially to build up complex configurations:

TerminalCode
# First add parameters npx zuplo openapi overlay \ --input openapi.json \ --overlay add-params.json \ --output temp.json # Then add Zuplo extensions npx zuplo openapi overlay \ --input temp.json \ --overlay zuplo-routes.json \ --output final.json # Clean up temporary file rm temp.json

Or create a script that chains the commands:

Terminalapply-overlays.sh
#!/bin/bash npx zuplo openapi overlay -i openapi.json -l docs.json -o step1.json && \ npx zuplo openapi overlay -i step1.json -l params.json -o step2.json && \ npx zuplo openapi overlay -i step2.json -l zuplo.json -o final.json && \ rm step1.json step2.json

Using Overlays in Your Build Process

Integrate overlay application into your CI/CD pipeline by adding it to your build scripts:

package.json
{ "scripts": { "build:openapi": "npx zuplo openapi overlay -i src/openapi.json -l overlays/production.json -o dist/openapi.json", "build:openapi:dev": "npx zuplo openapi overlay -i src/openapi.json -l overlays/development.json -o dist/openapi.json", "watch:openapi": "npx zuplo openapi overlay -i src/openapi.json -l overlays/development.json -o dist/openapi.json --watch" } }

JSONPath Target Syntax

Overlays use JSONPath syntax to target specific parts of your OpenAPI document. Here are common patterns:

JSONPath examples
{ "actions": [ { "target": "$.paths['/users/{userId}'].get", "description": "Target a specific operation" }, { "target": "$.paths['/users/{userId}'].get.parameters[0]", "description": "Target the first parameter" }, { "target": "$.paths['/users/*'].get", "description": "Target all GET operations under /users" }, { "target": "$.components.schemas['User']", "description": "Target a schema definition" } ] }

Best Practices

  1. Version Control Overlays: Store overlay files in version control alongside your OpenAPI specs

  2. Use Descriptive Names: Name overlay files clearly to indicate their purpose (for example, add-auth-policies.json, staging-config.json)

  3. Keep Overlays Focused: Create separate overlay files for different concerns rather than one large overlay

  4. Test Overlay Output: Always validate the resulting OpenAPI file after applying overlays

  5. Document Your Overlays: Add comments in the info.title and info.description fields to explain what each overlay does

  6. Use Watch Mode for Development: The --watch flag makes iterative development faster

Next Steps

  • Learn more about OpenAPI extensions in Zuplo
  • Check out the full CLI reference for OpenAPI overlay
Edit this page
Last modified on November 18, 2025
Path Modification ScriptsCanary Routing for Employees
On this page
  • What are OpenAPI Overlays
  • Basic Usage
  • Example 1: Modifying Route Summaries and Descriptions
  • Example 2: Adding Parameter Schemas
    • Adding Path Parameters
    • Adding Query Parameters
  • Example 3: Adding Zuplo Route Extensions
  • Combining Multiple Overlays
  • Using Overlays in Your Build Process
  • JSONPath Target Syntax
  • Best Practices
  • Next Steps
JSON
JSON
JSON
JSON
JSON
JSON
JSON