An API reference in Leed is a documentation set whose pages are generated from an OpenAPI spec rather than written. It gets the same navigation, the same URLs, the same theming and the same search as any other set — what differs is where its content comes from, and that nobody edits it by hand.
What an API set is
An API set is a page type whose Type of Page is API Documentation. Everything the rest of this category describes applies to it unchanged: it has exactly one bound left menu, its folder names set its URLs, and links to its pages are page references that survive a move. What a Documentation Set Is is the shared model, and Page Types covers the record itself.
Two things are specific to it:
- The pages are generated. They are produced from your spec on your machine, reviewed locally, and then uploaded into the CMS.
- The set is Content Locked, permanently. Editing a generated page in the CMS is refused with API pages are generated from a spec and can’t be edited in the CMS. This is not the Content Locked checkbox you can toggle on any other page type — for an API set it is enforced by the backend regardless of the stored flag, and there is no role that lifts it. The Content Locked toggle on the page type panel shows as on and cannot be turned off.
Versioning by page type
An API set’s path may nest and carry a version — docs/api/3.7.0 — and every page of the set lives under it. A new version is a new set: create a second page type at docs/api/3.8.0, import into it, and both versions stay live at their own URLs with their own navigation. Page ids are scoped by page type, so the same spec can be imported into both sets without the two colliding.
Two versions can share a display name, because only the path carries the version. That is why retiring one makes you type the path rather than the name (see Retiring a set).
Building the set: four steps
The flow is four steps, in order. Create the page type in the CMS — the Create Page Type dialog offers API Documentation — or from the CLI with leed settings pagetype create --type api; either way the new set gets its own left menu and a search index. There is no CMS control that imports pages, so the remaining steps are CLI-only.
| Step | Command | What it produces | What it checks first |
|---|---|---|---|
| 1. Create the set | leed settings pagetype create --type api, or the CMS | A page type in the CMS with its bound left menu | That you are signed in |
| 2. Stage | leed import openapi <spec> | Pages and a menu staged into your checkout under src/<path>/, plus a manifest recording what was staged | That the spec is a readable .json, .yaml or .yml, and within the size cap |
| 3. Build and review | leed site build | A local render of the pages you are about to upload | Nothing — this step exists so you look |
| 4. Apply | leed import apply | Pages in the CMS, merged into the set’s menu, and the spec staged for commit | The two guards below |
leed settings pagetype create --type api --name "Public API" --slug docs/api/3.7.0
leed import openapi ./openapi.yaml --page-type-id <pageTypeId> --page-type-path docs/api/3.7.0
leed site build --serve
leed import status --page-type-id <pageTypeId>
leed import apply --page-type-id <pageTypeId>The first staging run needs --page-type-path, because nothing in your checkout records the new set’s path yet; an explicit --page-type-path always wins. leed import status shows what is staged, how many of those pages the CMS already holds, and anything that would block apply. To abandon a staged set instead, run leed import clean.
flowchart TD
Spec[OpenAPI spec on disk] --> Create["leed settings pagetype create<br/>(page type in the CMS)"]
Create --> Stage["leed import openapi<br/>staged pages + manifest"]
Stage --> Build["leed site build<br/>you review the real output"]
Build --> G1{"Spec unchanged<br/>since staging?"}
G1 -- No --> R1["Re-run leed import openapi, then build"]
G1 -- Yes --> G2{"A recorded build<br/>newer than the staging?"}
G2 -- No --> R2["Run leed site build<br/>(builds run with -d are not recorded)"]
G2 -- Yes --> Apply["leed import apply"]
Apply --> CMS["Pages in the CMS<br/>+ menu + staged spec files"]
CMS --> Publish["Publish the set"]
R1 --> Stage
R2 --> Build
The two guards before import
Apply refuses unless both hold, and each says which one failed.
- The spec must be the one you staged from. Its checksum is recorded at staging time and re-checked at apply. If the file moved or changed, you get The OpenAPI spec changed or is missing since you staged it. — because the upload is re-derived from the file on disk, and a changed file would upload pages nobody reviewed.
- A build must have happened since you staged. Otherwise: Build and review the generated set before importing., naming when the last recorded build actually was. This guard is the whole reason the flow has a review step rather than being one command.
What apply does
Apply first checks the whole set against the CMS without writing anything — an id held by another page, a page the menu references zero times or twice, a page whose path disagrees with its menu position — and if anything fails, refuses the set with every violation listed and nothing created. Then it uploads the pages in batches of at most twenty, and reports every page individually.
| Outcome | Meaning | Safe to re-run? |
|---|---|---|
| Imported | The page was created, or the body of an unpublished draft was replaced from the spec | Yes — the manifest records it |
| Skipped | The page exists and may not be written — it has been published, holds pending suggestions, or has moved — so nothing was changed | Yes |
| Failed | That page could not be written; the reason is reported per page | Yes — a re-run retries only what is outstanding |
It ends on a summary in the form Import summary: X imported, Y skipped, Z failed (of N)., plus whether the menu was applied. Apply never overwrites a published page. Page ids are derived from the page type, the operation and its version, so re-importing a spec addresses the same pages: an unpublished page has its body replaced, and a published one is skipped and left exactly as it is. Only the body is ever replaced — title, slug and folder stay as the CMS holds them. Run leed import status first to see how many of the staged pages the CMS already holds.
On a partial failure the manifest and the staged files stay in place so the re-run can resume, and the command names the manifest path. On full success it removes the staged files and the manifest, because the CMS is now authoritative.
Where the spec itself goes
The source spec is uploaded and staged, not committed on its own. It rides along into the site repository with the pages when they publish, so the spec and the pages it produced always land together. Files above 25 MB are refused.
What a reader gets on an endpoint page
An endpoint page renders in two columns. The main column carries the operation itself:
- Security — the schemes the operation accepts, with their scopes
- Parameters, grouped by where they go: path, query, header and cookie
- Request body, with a selector when the operation accepts more than one content type
- Responses, with a selector for the status code and content type, each showing the schema and an example
The side column carries the code samples for the same operation, as a tab strip.
Everything else on the page — breadcrumbs, previous and next, the sidebar, search — is the ordinary documentation reading experience, described at Documentation Reading Experience. An API page has no on-page table of contents; its mini bar shows breadcrumbs instead.
To add your own content above an API page’s Previous and Next links — a feedback prompt, a support link — create _includes/api-page-cta.hbs in your site. It is picked up automatically on every plan, and it is separate from _includes/docs-page-cta.hbs, which does the same for written documentation pages. On an API page it renders twice, once for the wide layout and once for the narrow one, and both copies are visible unless your partial hides one.
Code sample languages
Samples are generated in four languages — cURL, TypeScript, Python and Go — and rendered through the reserved API Languages tab group, which supplies each tab’s display title and icon.
Two constraints are worth knowing before you touch that group:
- It is created and repaired for you. Leed creates it if it is missing and fills in any icon that has gone absent. It is also the one tab group hidden from the editor’s tab-group menu, because it is not a general-purpose language group — for a hand-written page, make a group of your own. Tab Groups for Consistent Examples is the page for that.
- Do not rename or trim it. Its entries are matched to the generated tabs by name. Remove or rename one and that tab still renders — as a bare label with no icon, because the lookup no longer finds it.
Navigation for an API set
The menu is generated with the pages: a folder per resource group, holding a Methods folder with that group’s endpoints, and — when the group has named subgroups — a Resource folder with one folder per subgroup, each holding its own Methods folder. Endpoints are sorted by name. Apply merges the generated menu into the set’s bound menu rather than replacing it, reusing folders that already match. Each endpoint leaf carries an icon that encodes its HTTP method — that is what renders the method badge in the sidebar, and it is also how a reader’s AI client reads the method back out of your navigation.
The rest of the menu behaves exactly as it does for a written set, including the folder-name-to-URL rule — see Folders Set Your URLs before you reorganize one.
Retiring a set
Settings → Page Types is the only entry point, deliberately: this destroys a whole set rather than acting on one page, so it lives with the set’s settings and nowhere else.
| Artifact | Removed? | Recoverable? |
|---|---|---|
| Every page in the set | Yes | No |
| The committed OpenAPI spec files | Yes | No |
| The set’s navigation menu | No — it is kept as an ordinary menu, its entries for the deleted pages are removed, and it is renamed with an “(unbound)” suffix if it carries the set’s name | Delete it yourself if you no longer need it |
| The set’s live URLs | They stop resolving at the next deployment | Only by rebuilding the set |
Where the command detail lives
This page owns the product model. Every flag on every command in the flow, with its defaults and its failure messages, is at OpenAPI Commands, and the workflow written from the CLI’s side — including what to do when a guard refuses — is at Importing an OpenAPI Spec. None of it works until the CLI is installed and signed in: Installing the Leed CLI.
Once the set is live, your readers’ AI clients can query it directly, method and all — Docs MCP Tool Reference covers the tools that read an API set.