Api Reference
This document explains our code-first approach to API documentation. We maintain a single source of truth (the API manifest) and auto-generate Mintlify reference tables from it.
Our API documentation workflow follows these principles:
packages/api-spec/src/manifest.ts is the source of truthDiscover all API routes in the codebase:
1pnpm api:scanThis scans apps/scm/app/api/**/route.ts files and generates:
packages/.generated/api-routes.json - Complete route inventorypackages/.generated/manifest-stubs.ts - Suggested manifest entriesWhat it does:
Create manifest stub suggestions:
1pnpm api:stubsThis reads the scan results and generates:
packages/.generated/api-manifest.stubs.ts - Ready-to-copy manifest entriesWhat it does:
Copy relevant stubs to packages/api-spec/src/manifest.ts and:
stable (default is beta)Example:
1{2 id: 'forecast.events.create',3 method: 'POST',4 path: '/api/forecast/events',5 summary: 'Create an external event',6 description: 'Create a new external event (promotion, holiday, etc.) to drive forecast adjustments',7 tags: ['forecasting'],8 audience: 'tenant',9 auth: 'session',10 stability: 'stable',11 permissions: ['forecast.write'],12 requestSchema: 'CreateEventSchema',13 queryParams: [14 { name: 'from', type: 'string', required: false, description: 'Start date (ISO string)' },15 { name: 'to', type: 'string', required: false, description: 'End date (ISO string)' },16 ],17 examples: [18 {19 title: 'Create promotion event',20 request: {21 body: {22 name: 'Summer Sale 2024',23 type: 'PROMOTION',24 startsAt: '2024-06-01T00:00:00Z',25 endsAt: '2024-06-30T23:59:59Z',26 },27 },28 response: {29 status: 201,30 body: {31 id: 'event_789',32 name: 'Summer Sale 2024',33 },34 },35 },36 ],37}Check the manifest against guardrails:
1pnpm api:validateValidations:
/api/Update Mintlify reference tables:
1pnpm api:docsThis updates the delimited blocks in:
docs-site/api-reference/forecasting.mdxdocs-site/api-reference/inventory.mdxdocs-site/api-reference/alerts.mdxdocs-site/api-reference/transfers.mdxdocs-site/api-reference/catalog.mdxWhat it does:
Before committing, run the CI guard:
1pnpm api:guardChecks:
This should be run in CI to prevent regressions.
apps/scm/app/api/**/api/admin/*)Mark ambiguous endpoints as internalOnly: true until confirmed tenant-facing.
1packages/api-spec/2├── src/3│ ├── types.ts # Type definitions4│ ├── manifest.ts # API route specifications (source of truth)5│ └── index.ts # Package exports6├── scripts/7│ ├── scan-routes.ts # Route scanner8│ ├── build-manifest.ts # Manifest stub generator9│ ├── validate-manifest.ts # Manifest validator10│ ├── generate-mintlify.ts # Docs generator11│ └── ci-guard.ts # CI guard12└── package.json13 14packages/.generated/15├── api-routes.json # Scan results16├── manifest-stubs.ts # Generated stubs17└── api-manifest.stubs.ts # Refined stubs18 19docs-site/api-reference/20├── forecasting.mdx # Contains generated table block21├── inventory.mdx # Contains generated table block22├── alerts.mdx # Contains generated table block23├── transfers.mdx # Contains generated table block24└── catalog.mdx # Contains generated table blockGenerated tables are wrapped in delimited blocks:
1{/* BEGIN:API_TABLE tag=forecasting */}2{/* this block is generated; do not edit by hand */}3| Method | Path | Summary | Auth | Stability | Permissions |4| ... | ... | ... | ... | ... | ... |5{/* END:API_TABLE tag=forecasting */}Important:
internalOnly: trueapi:scan when adding new routesapi:validate and api:guardpackages/api-spec/src/manifest.tspnpm api:docs to regenerate tablesinternalOnly: truepnpm api:validate and review manifest exclusionspnpm api:docsPermissions column is only shown when routes have permissions defined in manifest. Add permissions to routes that need them.
The docs repository ships public/api-reference/openapi.json and runs node scripts/validate-public-openapi.mjs as part of pnpm run docs:guardrails (prebuild). Policy and allowlist live in:
internal/docs/openapi-publication-governance.mdscripts/openapi-publication-config.jsonWhen replacing the public bundle, update the tag allowlist intentionally; do not rely on blacklist-only reviews.
