Skip to main content

How We Document APIs

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.

Overview

Our API documentation workflow follows these principles:
  1. Code-first: The manifest in packages/api-spec/src/manifest.ts is the source of truth
  2. Auto-generated: Reference tables are generated from the manifest
  3. Scope-safe: Guardrails ensure no SuperAdmin endpoints leak into tenant docs
  4. Lightweight: Regex-based scanning, no runtime code changes

Workflow

Step 1: Scan Routes

Discover all API routes in the codebase:
This scans apps/scm/app/api/**/route.ts files and generates:
  • packages/.generated/api-routes.json - Complete route inventory
  • packages/.generated/manifest-stubs.ts - Suggested manifest entries
What it does:
  • Finds all route handlers
  • Detects HTTP methods (GET, POST, etc.)
  • Identifies authentication patterns
  • Extracts Zod schema names
  • Classifies routes as tenant-facing vs internal-only

Step 2: Generate Stubs

Create manifest stub suggestions:
This reads the scan results and generates:
  • packages/.generated/api-manifest.stubs.ts - Ready-to-copy manifest entries
What it does:
  • Converts paths to stable IDs
  • Infers tags from path prefixes
  • Detects auth types
  • Sets default stability (beta for safety)
  • Marks internal-only routes

Step 3: Refine Manifest

Copy relevant stubs to packages/api-spec/src/manifest.ts and:
  1. Fill in summaries: Replace “TODO: Add summary” with clear descriptions
  2. Add descriptions: Provide detailed endpoint documentation
  3. Add examples: Include request/response examples
  4. Set permissions: Document required permissions
  5. Adjust stability: Mark stable endpoints as stable (default is beta)
  6. Add query params: Document query parameters
  7. Add path params: Document dynamic route segments
Example:

Step 4: Validate

Check the manifest against guardrails:
Validations:
  • ✅ No SuperAdmin paths or references
  • ✅ All tenant routes have proper auth
  • ✅ All IDs are unique
  • ✅ All paths start with /api/
  • ✅ All routes have summaries and tags

Step 5: Generate Docs

Update Mintlify reference tables:
This updates the delimited blocks in:
  • docs-site/api-reference/forecasting.mdx
  • docs-site/api-reference/inventory.mdx
  • docs-site/api-reference/alerts.mdx
  • docs-site/api-reference/transfers.mdx
  • docs-site/api-reference/catalog.mdx
What it does:
  • Groups routes by tag
  • Sorts by path, then method
  • Generates markdown tables
  • Includes permissions when available
  • Marks beta endpoints with ⚠️
  • Only updates delimited blocks (preserves other content)

CI Guard

Before committing, run the CI guard:
Checks:
  • ✅ Manifest doesn’t contain excluded paths (SuperAdmin)
  • ✅ Generated docs blocks are present in all target files
  • ✅ Docs blocks are properly formatted
This should be run in CI to prevent regressions.

Scope Rules

✅ Include

  • Tenant-facing APIs in apps/scm/app/api/**
  • APIs consumed by external integrators
  • Tenant-admin configuration APIs (/api/admin/*)

❌ Exclude

  • SuperAdmin endpoints (apps/admin/**)
  • Tenant provisioning APIs
  • Entitlement assignment APIs
  • Billing admin operations
  • Internal cron endpoints (unless tenant-configurable)

⚠️ When in Doubt

Mark ambiguous endpoints as internalOnly: true until confirmed tenant-facing.

File Structure

Delimited Blocks

Generated tables are wrapped in delimited blocks:
Important:
  • Do NOT edit content between these markers
  • The generator will overwrite it
  • All other content in the file is preserved

Best Practices

  1. Keep it lightweight: Use regex-based scanning, don’t refactor runtime code
  2. Prefer correctness: Mark ambiguous endpoints as internalOnly: true
  3. Scope safety first: Better to exclude than include SuperAdmin endpoints
  4. Update regularly: Run api:scan when adding new routes
  5. Validate before commit: Run api:validate and api:guard

Troubleshooting

”Route not in docs”

  1. Check if route is in manifest: packages/api-spec/src/manifest.ts
  2. Verify route has correct tags matching target file
  3. Run pnpm api:docs to regenerate tables
  4. Check if route is marked internalOnly: true

”CI guard failing”

  1. Check for SuperAdmin paths: pnpm api:validate
  2. Verify docs blocks exist: Check target files for delimited blocks
  3. Regenerate docs: pnpm api:docs

”Missing permissions column”

Permissions column is only shown when routes have permissions defined in manifest. Add permissions to routes that need them.