OpenAPI Spec
Auto-generated OpenAPI 3.1 specification from your Quickback definitions.
The compiler generates an OpenAPI 3.1 specification from your feature definitions. By default it's both written to openapi.json at your project root and served as a runtime route.
Endpoint
GET /openapi.jsonReturns the full OpenAPI spec as JSON.
curl https://your-api.example.com/openapi.jsonWhat's included
The generated spec documents every route the compiler produces:
- CRUD endpoints (list, get, create, update, delete)
- Batch operations
- Views
- Actions (including standalone actions)
- Auth routes (
/api/auth/**) - Storage, embeddings, and webhook routes (when configured)
Each endpoint includes request/response schemas derived from your Drizzle column types, access control metadata, and error responses.
Schema fidelity
The generated component schemas carry enough type information that strict validators (zod, openapi-typescript, openapi-fetch) produce non-optional, narrowed types out of the box:
required[]on response components — every non-nullable column is listed, so generated SDKs treat them as guaranteed-present rather than optional.- Closed enums on
text(_, { enum: [...] })columns — emitted as{ type: "string", enum: [...] }, narrowing to a literal union in TS. Error.codeis a closed enum — everycodevalue the API can emit (AUTH_MISSING,DB_UNIQUE_VIOLATION,BATCH_SIZE_EXCEEDED, …) is enumerated so consumers canswitchexhaustively.- ID
format— only emitted asformat: "uuid"when your project'sgenerateIdactually produces UUIDs. cuid2 / prefixed / nanoid / serial generators get plain{ type: "string" }, keeping strict OpenAPI validators happy.
Action input schemas
Actions defined with defineAction({ input: z.object(...) }) get their full input schema lifted into the operation's requestBody. Simple z.object({...}) shapes are extracted at compile time; for discriminated unions, refinements, recursive schemas, and bare-identifier references (input: createPersonInput), the compiler runs your action file through Zod 4's native z.toJSONSchema() during compilation so the OpenAPI request body and the MCP tool's inputSchema round-trip exactly what your Zod expression declares — no static translator to maintain.
Configuration
Both generation and publishing default to true. You can control them independently in quickback.config.ts:
export default defineConfig({
name: "my-app",
// ...
openapi: {
generate: true, // write openapi.json to project root
publish: true, // serve GET /openapi.json at runtime
},
});| Option | Default | Description |
|---|---|---|
generate | true | Write openapi.json to the project root during compilation |
publish | true | Serve the spec at GET /openapi.json (requires generate: true) |
docs | false | Mount an interactive API browser at GET /docs — "scalar", "swagger", or false |
Omitting the openapi key entirely is equivalent to generate: true, publish: true, docs: false.
Generate only (no runtime route)
openapi: {
generate: true,
publish: false,
}The file is still written so you can use it in CI or commit it to your repo, but no route is added to the app.
Disable entirely
openapi: {
generate: false,
}No file is written and no route is served.
Interactive API browser at /docs
Mount an in-browser API reference by setting openapi.docs:
openapi: {
docs: 'scalar', // or 'swagger'
}| Value | UI | Notes |
|---|---|---|
"scalar" | Scalar API Reference — modern, lightweight | Recommended default |
"swagger" | Swagger UI — the familiar standard | Good if your team expects it |
false / unset | No /docs route | Default |
Both UIs are loaded from CDN in a generated static HTML route — no npm package is added to your project, no Hono middleware is installed, and the runtime bundle stays the same size. The flag is purely compile-time: it toggles whether a /docs route is emitted.
Requires publish: true (the default). When publish is off, /docs is silently skipped — there's no spec for it to read.
Usage with tools
Import into Postman
- Open Postman and click Import
- Paste the URL
https://your-api.example.com/openapi.jsonor upload the file - Postman creates a collection with every endpoint pre-configured
Generated TypeScript types (api-types.gen.ts)
The compiler emits api-types.gen.ts next to openapi.json by default — a fully typed view of every route, request body, and response, ready to import in client code:
import type { paths, components } from '../api-types.gen';
type Job = components['schemas']['Job'];
type ListJobsResponse = paths['/api/v1/jobs']['get']['responses']['200']['content']['application/json'];Pair it with openapi-fetch for a fully typed client:
import createClient from 'openapi-fetch';
import type { paths } from '../api-types.gen';
const client = createClient<paths>({ baseUrl: 'https://your-api.example.com' });
const { data, error } = await client.GET('/api/v1/jobs', { params: { query: { limit: 25 } } });Configuration
openapi.types | Behavior |
|---|---|
true (default) | Write api-types.gen.ts to the project root |
false | Don't emit the types file |
"src/lib/api-types.ts" | Custom output path (relative to project root) |
// quickback.config.ts
export default defineConfig({
// ...
openapi: {
types: 'src/lib/api-types.gen.ts', // emit straight into your client app
},
});The file is generated by piping the in-memory spec through openapi-typescript — you can keep running it manually if you want a different output path or version, but for the typical case there's nothing to wire up. Skipped automatically when openapi.generate is false.
External viewer
Point any OpenAPI-compatible viewer at the endpoint:
https://petstore.swagger.io/?url=https://your-api.example.com/openapi.jsonOr enable the in-project browser via the docs config option above and visit /docs directly.
Example output (excerpt)
{
"openapi": "3.1.0",
"info": {
"title": "my-app API",
"version": "1.0.0"
},
"paths": {
"/api/v1/jobs": {
"get": {
"summary": "List jobs",
"operationId": "listJobs",
"parameters": [
{ "name": "limit", "in": "query", "schema": { "type": "integer" } },
{ "name": "offset", "in": "query", "schema": { "type": "integer" } }
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": { "type": "array", "items": { "$ref": "#/components/schemas/Job" } }
}
}
}
}
}
}
}
}
}
}