6.7 KiB
API Reference Customization
The API reference is auto-generated from public/openapi.json using fumadocs-openapi. We customize the rendering with hooks and CSS overrides that depend on fumadocs-openapi internals.
When upgrading fumadocs-openapi, verify all customizations below still work.
Architecture
public/openapi.json ← v3.1 spec (auto-fetched, don't edit manually)
public/openapi-v3.json ← v3.0 spec (auto-fetched, don't edit manually)
components/api-page.tsx ← createAPIPage config, schema render hook
components/api-page.client.tsx ← Client-side playground config
components/schema-generator.tsx ← Server-side: walks OpenAPI schema → SchemaUIGeneratedData
components/custom-schema-ui.tsx ← Client-side: renders schemas with inline expansion
app/global.css ← CSS overrides targeting fumadocs-openapi classes
Custom Schema Rendering
We replace fumadocs-openapi's default popover-based schema rendering with Stripe-style inline expandable sections.
api-page.tsx
schemaUI.renderhook: intercepts all schema rendering- Returns
nullfor#/components/schemas/Errorto hide redundant error schemas - Passes
isResponseflag (derived fromreadOnly/writeOnly) to hide "Required" labels on response fields generateTypeScriptSchema: falsedisables the TypeScript Definitions copy boxplayground: { enabled: true }enables the interactive API playground (requests are proxied through/api/proxy)
schema-generator.tsx
- Server component that walks OpenAPI schemas into a normalized
SchemaUIGeneratedDatastructure - Handles: objects, arrays, oneOf/anyOf, allOf (merged), enums, nullable types
- Generates info tags for
default(skips{}and[]) andformat - Uses
ctx.schema.getRawReffor schema identity, falls back to auto-generated IDs
custom-schema-ui.tsx
- Client component (
'use client') with Radix Collapsible for expand/collapse ResponseContextthreadsisResponsedown to suppress "Required" on response fieldsisExpandable()checks if schemas have actual nested structure (avoids useless expand buttons for primitive unions likestring | string[])- Enums render as compact inline badges with "Possible values:" label
CSS Overrides (fragile on upgrade)
All in app/global.css under the "OpenAPI Reference" section. These target fumadocs-openapi's internal class structure because no hooks exist for these customizations. Parameter fields (Path/Query/Header) and content type labels are rendered by built-in components with no render hooks.
| Rule | Purpose | Why CSS-only |
|---|---|---|
Hide span.text-red-400 / span.text-fd-muted-foreground |
Remove default * and ? field indicators |
Parameter fields rendered by built-in components, no hook available |
::after with content: "Required" |
Add explicit "Required" label for required fields | Same as above |
div.border.rounded-lg:not(:has(*)) |
Hide empty schema wrapper divs (when Error schema returns null) | Wrapper div rendered outside schemaUI.render hook |
p.text-fd-muted-foreground.not-prose:has(> code.text-xs) |
Hide application/json content type labels |
No hook to control content type display |
API Versioning (v3.0 / v3.1)
Two API versions are served side-by-side with a Stripe-style version selector in the top nav bar.
URL structure
- v3.1 (default):
/reference/...— e.g./reference/api-reference/tools/getTools - v3.0:
/reference/v3/...— e.g./reference/v3/api-reference/tools/getTools - All existing v3.1 URLs are unchanged — no breaking changes.
How it works
lib/openapi.ts ← Creates two OpenAPI instances (v3.1 + v3.0)
lib/source.ts ← Combined source: v3.1 at api-reference/, v3.0 at v3/api-reference/
lib/api-version.ts ← Shared detectApiVersion() utility (single source of truth)
lib/use-api-version.ts ← Client hook wrapping detectApiVersion for React components
lib/filter-api-version.ts ← Tree filter: hides V3 folder for v3.1, lifts V3 children for v3.0
app/(home)/reference/(v31)/layout.tsx ← v3.1 layout: hardcodes version, renders DocsLayout with filtered tree
app/(home)/reference/v3/layout.tsx ← v3.0 layout: hardcodes version, renders DocsLayout with filtered tree
components/version-selector.tsx ← Dropdown in top nav, navigates between /reference/ ↔ /reference/v3/
components/api-base-url.tsx ← Dynamic base URL: v3.1 or v3 based on current path
components/api-endpoints-table.tsx ← Endpoint tables in index pages, shows versioned paths
components/version-badge.tsx ← Badge on endpoint pages showing API version
Content structure
v3.0 has its own complete page tree under content/reference/v3/:
v3/index.mdx— Overview (with v3 links and base URL)v3/authentication.mdx— Auth docs (with v3 curl examples)v3/rate-limits.mdx,v3/errors.mdx— Duplicated non-API pagesv3/api-reference/— Auto-generated index pages + OpenAPI endpoint pagesv3/meta.json— Sidebar ordering
SDK Reference is version-independent and shared across both trees. Meta Tools moved out of the reference tree entirely — they now live under the Toolkits tab at /toolkits/meta-tools.
Version selector behavior
- On an API page: swaps
/reference/↔/reference/v3/(stays on same endpoint/category) - On overview (
/reference): navigates to/reference/v3(v3 has its own overview) - Full page reload on every version switch (server re-renders layout with filtered tree)
Auto-generation pipeline (docs-update-data.yml)
fetch-openapi.mjs— fetches both v3.1 and v3.0 specs from backendgenerate-api-index.ts— generates index pages for bothapi-reference/andv3/api-reference/- CI tracks:
openapi.json,openapi-v3.json,api-reference/,v3/api-reference/
Adding/modifying v3 content
- API endpoint pages are auto-generated from the OpenAPI spec — no manual work needed
- Index pages are auto-generated by
bun run generate:api-index - Non-API pages (
v3/index.mdx,v3/authentication.mdx, etc.) are manual copies — update both versions when content changes v3/meta.jsonandv3/api-reference/meta.jsoncontrol sidebar ordering
OpenAPI Spec Notes
- v3.1 spec is OAS 3.0.0 format
- v3.0 spec is also OAS 3.0.0 format with the same tag structure
- All error responses use identical
#/components/schemas/Errorschema - Error descriptions vary per endpoint and are useful
info.descriptionis empty (backend issue)- No response examples (backend issue)
nullable: true(OAS 3.0) is converted by fumadocs-openapi's dereferencer- Some properties named
deprecatedare required fields (spec issue, not the OpenAPI deprecated flag)