API reference
Point a navigation group at an OpenAPI spec, and Writedocs writes the API reference: a page for every endpoint, grouped by tag, with its parameters, request body, responses, code examples and a Try it playground. There are no page files to write or keep up to date - change the spec, and the pages follow.
Set it up
Put the spec in your project, and give a group openapi in place of pages:
{
"navigation": [
"index",
{
"group": "API reference",
"openapi": {
"src": "openapi.yaml",
"path": "/api"
}
}
]
}The spec’s path from the project folder: an OpenAPI 3.0 or 3.1 file, in YAML or JSON.
The address the pages go under - see Page addresses. Each OpenAPI group needs its own.
How readers see the group: "writedocs", a page per endpoint as described on this page, or "scalar", the whole API on one page with Scalar’s API reference - see Scalar’s API reference.
This site’s Example API group, in this tab’s sidebar, is set up exactly like this - its pages are generated from a sample spec.
The spec must be a file in the project - a URL isn’t fetched. writedocs validate checks every spec in the navigation: a spec that’s missing or doesn’t parse is an error, and one that parses but isn’t valid OpenAPI is a warning.
Previewing your changes
With writedocs dev running, save the spec and the open tab reloads with the change, usually within a few seconds - no restart needed:
- A changed
summary,description, parameter, schema or example shows on the endpoint’s page; a changedsummaryalso renames it in the sidebar. - An endpoint you add appears in the sidebar, under its tag, and its page is ready. One you remove or rename leaves the sidebar, and its old address shows “Page not found”.
- An edit to a file the spec points to with
$ref- a shared schema in its own file, say - counts as an edit to the spec. - Pointing a group’s
openapiat another spec, or giving it anotherpath, inwritedocs.jsonregenerates the pages the same way.
While you’re typing, the spec may not parse for a moment. The terminal says where, and every page of the preview shows the same error until the spec parses again; the preview keeps running, and the pages come back on their own once it’s fixed:
✗ openapi.yaml:12:5 bad indentation of a mapping entryA page of your own for an endpoint, added while the preview runs, takes the endpoint’s place at the next edit to the spec, or when you restart writedocs dev.
What each page shows
- The endpoint - its method and path, title (the operation’s
summary) and description. Descriptions are Markdown, as OpenAPI specifies. - Authorization - the security schemes the endpoint accepts.
- Parameters - path, query and header parameters, with their type, whether they’re required, their default and description.
- Request body - every field, with nested objects that open and close.
- Responses - each status code, with its fields and an example.
- Code examples - the request in several languages, ready to copy, beside the page.
- Try it - a playground that sends a real request to your API - see Try it playground.
The page also has the Copy page menu, and its Markdown copy, llms-full.txt and the MCP server include the endpoint written out in full.
Page addresses
An endpoint’s page is served at the group’s path, then the endpoint’s first tag, then its method and path:
| Endpoint | Tags | Address, with path: "/api" |
|---|---|---|
POST /customers | Customers | /api/customers/post-customers/ |
GET /customers/{id} | Customers, Admin | /api/customers/get-customers-id/ |
GET /health | none | /api/get-health/ |
To choose an endpoint’s address yourself, give it a page of its own with a slug.
In search results and link previews, the page’s description is the endpoint’s description as plain text, cut to about 160 characters - or, when it has none, its summary and request: List all customers - GET /customers.
Limits
allOfschemas are merged into one. ForoneOfandanyOf, the page shows the first option only - describe the others in itsdescription.
The sidebar
The group lists the endpoints under one group per tag, in the order the tags first appear in the spec. An endpoint takes its first tag; endpoints with no tag go in a group called Other. Each endpoint shows its method next to its name.
Writing a good spec
The pages are only as good as the spec. What helps most:
- A
summaryfor every operation - it’s the page’s title and its name in the sidebar. - A
descriptionfor operations, parameters and fields. exampleorexamplesvalues, for the response examples and the playground’s starting values.tags, to group the endpoints.servers, for the address the playground sends requests to.
Scalar’s API reference
With "renderer": "scalar", the group is one page instead of a page per endpoint: Scalar’s API reference, at the group’s path, inside your site - the top bar, tabs, footer, colors, font and light/dark theme are your site’s. The reference takes your site’s look too: its list of endpoints looks like your sidebar, and its titles, text and spacing like your other pages.
{
"group": "API reference",
"openapi": {
"src": "openapi.yaml",
"path": "/api",
"renderer": "scalar"
}
}Each group chooses for itself: one API can use Scalar’s reference and another the page-per-endpoint reference, in the same site.
What the reader sees
- One page with every endpoint, grouped by tag, with Scalar’s own list of endpoints at its side. Each endpoint has its own address on that page, like
/api/#tag/customers/POST/customers, made from its first tag, method and path - it stays the same from one build to the next while those don’t change. - The sidebar. When the group is all there is in its part of the navigation - an API tab, say - Scalar’s list of endpoints takes the place of your sidebar. When the sidebar has other pages, the two stand side by side. On phones, your sidebar is in the site’s menu, as on every page, and Scalar’s list in a menu of its own at the top of the reference.
- Scalar’s Try it. Every endpoint has a Test Request button that opens Scalar’s API client on it. Requests follow
api.proxy: straight to your API, then through Writedocs’ proxy if the browser blocks them - never Scalar’s hosted proxy. What a reader types as credentials stays in that browser tab, and is forgotten when the tab closes. - A spec download button, except in a protected section.
- Search is the site’s. Searching for an endpoint finds it, and the result opens it on the reference page. Scalar’s own search box, its AI assistant, its developer tools and its theme switch are turned off.
- While it loads, the page shows the reference’s outline in your site’s colors: the list of endpoints, your API’s title and description as gray bars, and the Server, Authentication and Client Libraries boxes, with a soft shine passing over them (still, for readers whose system asks for less motion). The reference then takes its place, without the page moving. Screen readers hear that the reference is loading.
- If the reference can’t load - the reader’s connection dropped, say - the page lists the endpoints instead, each linking to its page, with a Try again button.
What stays the same
Writedocs still builds the page of each endpoint described above, at its usual address, and everything that reads those pages works as for any OpenAPI group:
- Search finds each endpoint by its title and description, and opens it on the reference page.
llms.txt,llms-full.txt, the MCP server and the Markdown copies have every endpoint, written out in full. The reference page’s own Markdown copy lists the endpoints, each linking to its page.- Links to an endpoint’s address - from your own pages, or from other sites - open the endpoint on the reference page.
Those pages aren’t listed in the sidebar or in Previous/Next links, and they tell search engines not to index them: the reference page is the one indexed, and the one in sitemap.xml. A reader whose browser has JavaScript turned off stays on the endpoint’s page, which shows everything.
Weight
The reference is drawn in the reader’s browser. Opening it downloads about 1.2 MB of compressed code the first time - the browser keeps it for later visits - and the page carries your spec. Measured on a laptop with an empty cache: with 7 endpoints, the endpoints show in about 0.4 seconds, and in about 8 seconds on a slow mobile connection; with 800 endpoints, in about 0.8 and 10 seconds - meanwhile the page shows the reference’s outline (above). A page-per-endpoint reference shows its endpoint in well under half a second either way. Choose Scalar’s reference knowing your readers’ connections.
With api.playground
api.playground picks the Try it of the page-per-endpoint references. A group with "renderer": "scalar" always uses Scalar’s client, built into its reference, whatever api.playground says; your other OpenAPI groups follow api.playground.
Limits
-
pathcan’t be/, and no page of your own can be at it - the reference is a page at that address.writedocs validatereports both, with the line inwritedocs.json:✗ 1 error in writedocs.json writedocs.json:7 (navigation.tabs.1.pages.0.openapi.path) writedocs.json's "Orbit API" group has openapi.renderer "scalar" and openapi.path "/" - the reference is a page at that path, so give it one of its own, like "/api". -
A page of your own for an endpoint in this group isn’t shown: links to it open the endpoint on the reference page, and its text is still found by search and included in
llms-full.txt. -
No JavaScript, no reference. The reference page then lists the endpoints, each linking to its page.
-
In a protected section, the reference page - with your spec in it - is protected like the section’s other pages.
More
- More specs, and your own pages - several specs in one site, and replacing a generated page with one you write.
- Try it playground - how requests are sent, and the CORS proxy.
- Parameter and RequestExample - to document an API by hand.