Skip to content

OpenAPI

Callspec emits OpenAPI 3.1 — useful for API gateways, contract tests, mocks, and multi-language SDK/docs tools (e.g. Fern, Kiota).

It is a projection for the ecosystem, not the source of truth for Callspec’s TypeScript client. For npx callspec / ApiClient, use callspec.json, not OpenAPI.

NeedUse
TypeScript SDK + Result errors + schemascallspec.jsonSDK generation
Gateway, Postman, Pact, OpenAPI lint/openapi.json or emitOpenApi
Public multi-lang SDKs / hosted docsOpenAPI → multi-language SDKs (Fern, Kiota, …)
Try methods in the browserDocs UI
  • Each public RPC method as a POST path
  • Request/response schemas from route preds (multipart/form-data when the route uses file())
  • Errors grouped by HTTP status (builtins + route domain errors)
  • Bearer security when auth: 'bearer'
  • scope: 'private' routes omitted unless visibility: 'all'

Auth/scope details: Auth and scope.

Served at {mount}/openapi.json whenever docs is enabled (default). Disabled with mountSpec(router, api, {docs: false}) — same switch as the docs UI and callspec.json.

Replace the host (127.0.0.1), port (3000), and mount (/v1) with yours:

bash
curl -fsS http://127.0.0.1:3000/v1/openapi.json -o openapi.json

Same document mountSpec would serve — for CI or offline packaging:

typescript
import {writeFileSync} from 'fs';
import {emitOpenApi} from 'callspec/document';
import {api} from '../src/spec';
const basePath = '/v1'; // must match Express mount + mountSpec basePath if set
writeFileSync(
'openapi.json',
JSON.stringify(
emitOpenApi(api.routes, {
title: api.meta.title ?? 'My API',
version: api.meta.version ?? '1.0.0',
basePath,
description: api.meta.intro,
}),
null,
2,
),
);

emitOpenApi is exported from callspec/document.