Skip to main content

OpenAPI & Swagger

BurgerAPI automatically generates an OpenAPI 3.1 specification from your routes and Zod schemas, and serves an interactive docs UI. OpenAPI 3.1 matches the JSON Schema dialect Zod emits, so generated schemas stay accurate. The spec is derived from the code, so it stays in sync as your API changes.

Document metadata​

Set document metadata in src/openapi.config.ts, the convention file that burger-api create scaffolds. It is auto-discovered in dev, and burger-api build embeds it into the production entry:

src/openapi.config.ts
import type { OpenAPIConfig } from "burger-api";

export default {
title: "Widget Management API",
description: "API for creating, reading, updating, and deleting widgets.",
version: "1.0.2",
servers: [{ url: "https://api.example.com", description: "Production" }],
contact: { name: "Widget Team", email: "api@example.com" },
} satisfies OpenAPIConfig;

All fields:

FieldTypePurpose
titlestringAPI title. Defaults to "Burger API"
descriptionstringAPI description. Defaults to "Burger API documentation"
versionstringAPI version. Defaults to "1.0.0"
serversOpenAPIServer[]Server URLs ({ url, description? })
contactOpenAPIContact{ name?, url?, email? }
licenseOpenAPILicense{ name, url? }
termsOfServicestringURL to the terms of service
externalDocsOpenAPIExternalDocs{ url, description? }
securityArray<Record<string, string[]>>Root security requirements. Defaults to []
pathstringPath of the JSON spec. Defaults to /openapi.json
docsPathstringPath of the docs UI. Defaults to /docs
enabledbooleanEnable the OpenAPI endpoints. Defaults to true
docsAuthDocsAuthBasic auth for /docs and /openapi.json ({ username, password }). Omit for no protection
providerDocsProviderDocs UI function. Defaults to Swagger UI; alternatives: scalarDocs(), redocDocs()
mapJsonSchemaRecord<string, JsonSchemaConverter>JSON Schema converters keyed by vendor, for validators that can't describe themselves (for example Valibot)

new Burger({ title, version, description }) is a fallback for programmatic apps that do not use the convention file. When both exist, openapi.config.ts wins.

For programmatic apps (no filesystem), pass the same object in the openapi option instead:

src/index.ts
const burger = new Burger({
apiRoutes: routes,
openapi: { title: "Widget Management API", version: "1.0.2" },
});

Route-level metadata: the openapi type​

Add rich details per endpoint in openapi.ts, with per-method named exports:

api/products/[id]/openapi.ts
export const GET = {
summary: "Get a specific product by ID",
tags: ["Products"],
operationId: "getProductById",
responses: {
200: { description: "Product details returned successfully" },
404: { description: "Product not found" },
},
};

The openapi type allows summary, description, tags, operationId, deprecated, responses, and externalDocs per HTTP method. BurgerAPI infers request and response schemas from your schema.ts where possible.

Generated details​

  • A requestBody is marked required only when the body schema rejects undefined. z.object({ ... }).optional() produces required: false.
  • Wildcard routes document the wildcard as a {wildcard} path parameter that may contain slashes.
  • Param names may contain - and _; [user-id] documents as {user-id}.
  • Validators that support Standard JSON Schema (Zod, ArkType, ...) are documented automatically, with no converter.
  • Other Standard Schema libraries (for example Valibot) emit parameters by name. With a mapJsonSchema converter the parameter gets the real schema; without one it gets schema: {} instead of being dropped. A mapJsonSchema converter always wins over the built-in conversion.
  • docsAuth accepts any UTF-8 username/password, including accented characters.

Docs UI providers​

BurgerAPI serves an interactive UI at /docs and the raw spec at /openapi.json. The default provider is Swagger UI. The alternatives are exported from burger-api:

  • swaggerDocs()
  • scalarDocs()
  • redocDocs()

The provider is set in the OpenAPI config, along with the spec path, docs path, and optional basic auth. Both the spec path (/openapi.json by default) and the docs path (/docs by default) are configurable there. docsAuth protects /docs and /openapi.json; the docs UI loads the spec from the configured path.

Types for this feature​

The types you use (from burger-api):

  • openapi: the per-route metadata object, keyed by lowercase method
  • OpenAPIMeta: one method's metadata (summary, tags, responses, ...)
  • OpenAPIConfig: the docs configuration (dev openapi.config.ts, production openapi option)

✅ Correct: lowercase keys in programmatic metadata:

import type { RouteDefinition } from "burger-api";

const def: RouteDefinition = {
path: "/products",
handlers: { GET: (ctx) => Response.json([]) },
openapi: { get: { summary: "List products" } }, // lowercase 'get'
};

❌ Wrong: an uppercase key is a silent no-op at runtime, so it fails at compile time:

const def: RouteDefinition = {
path: "/products",
handlers: { GET: (ctx) => Response.json([]) },
openapi: { GET: { summary: "List" } }, // ❌ 'GET' is not allowed (use 'get')
};

❌ Wrong: a response value must be an object:

openapi: { get: { responses: { "200": 42 } } }; // ❌ 42 is not an object

See the TypeScript overview.

Check your code: bun run typecheck.