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
    How Zuplo WorksRequest LifecycleProject StructureAuthenticationAPI KeysRate LimitingAPI ErrorsRoutingPolicy FundamentalsOpenAPIEnvironmentsSource Control and DeploymentDevelopment Options
Development
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
Concepts

Project Structure

A Zuplo project is a standard Node.js-style project managed via Git. Here is the typical layout:

Code
my-api/ ├── config/ │ ├── routes.oas.json # Route definitions (OpenAPI format) │ └── policies.json # Policy configuration ├── modules/ │ └── my-handler.ts # Custom handlers and policies ├── docs/ # Developer portal (optional) │ └── zudoku.config.ts ├── zuplo.jsonc # Project configuration ├── package.json ├── .env # Local environment variables (do not commit) └── .env.zuplo # Generated by `zuplo link` (do not commit)

Core files

config/routes.oas.json

This is an OpenAPI 3.1 specification that defines your API routes. Each route specifies the HTTP method, path, handler, and which policies to apply. Zuplo extends the OpenAPI spec with x-zuplo-route to attach handlers and policies to each operation.

Code
{ "paths": { "/users/{userId}": { "get": { "operationId": "get-user", "x-zuplo-route": { "corsPolicy": "anything-goes", "handler": { "export": "urlForwardHandler", "module": "$import(@zuplo/runtime)", "options": { "baseUrl": "https://api.example.com" } }, "policies": { "inbound": ["api-key-inbound", "rate-limit-inbound"] } } } } } }

You can have multiple OpenAPI files. They are processed in alphabetical order during route matching.

See OpenAPI and Routing for details.

config/policies.json

This file defines policy instances by name, type, and configuration. Routes reference policies by name in their policies.inbound and policies.outbound arrays.

Code
{ "policies": [ { "name": "api-key-inbound", "policyType": "api-key-inbound", "handler": { "export": "ApiKeyInboundPolicy", "module": "$import(@zuplo/runtime)" } }, { "name": "rate-limit-inbound", "policyType": "rate-limit-inbound", "handler": { "export": "RateLimitInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "rateLimitBy": "ip", "requestsAllowed": 100, "timeWindowMinutes": 1 } } } ] }

zuplo.jsonc

Project-level configuration including the runtime compatibility date and deployment type.

Code
{ "version": 1, "compatibilityDate": "2025-02-06", "projectType": "managed-edge" }

The projectType can be managed-edge, managed-dedicated, or self-hosted. The compatibilityDate locks runtime behavior so updates don't break your project unexpectedly.

See Project Configuration for all options.

modules/

Contains your custom TypeScript code for handlers and policies. These modules are referenced from routes.oas.json and policies.json using $import(./modules/...).

Code
{ "handler": { "export": "default", "module": "$import(./modules/my-handler)" } }

docs/ (optional)

If you use the Zuplo Developer Portal, this directory contains the portal configuration and custom pages. See Developer Portal for details.

How the files relate

  1. zuplo.jsonc sets project-wide configuration (runtime version, deployment type)
  2. config/routes.oas.json defines API routes and wires each route to a handler and policies by name
  3. config/policies.json defines the named policy instances with their configuration and points to either built-in modules (@zuplo/runtime) or custom modules in ./modules
  4. modules/ contains the TypeScript implementations for custom handlers and policies

All of this lives in Git and deploys automatically when you push.

The $import() syntax

JSON configuration files (routes.oas.json and policies.json) use the $import() syntax to reference code modules. This is a Zuplo-specific syntax that resolves module references at build time.

Code
{ "module": "$import(@zuplo/runtime)" }

References starting with @zuplo/runtime point to built-in Zuplo modules (policies, handlers, and utilities).

Code
{ "module": "$import(./modules/my-handler)" }

References starting with ./modules/ point to your custom TypeScript files in the modules/ directory. The export field specifies which named export to use from that module.

Edit this page
Last modified on March 27, 2026
Request LifecycleAuthentication
On this page
  • Core files
    • config/routes.oas.json
    • config/policies.json
    • zuplo.jsonc
    • modules/
    • docs/ (optional)
  • How the files relate
  • The $import() syntax
JSON
JSON
JSON
JSON
JSON
JSON