﻿---
title: API Explorer
description: The API Explorer turns an OpenAPI spec into HTML pages. If you add an api: entry in docset.yml, docs-builder generates: a product landing page, one tag...
url: https://docs-v3-preview.elastic.dev/elastic/docs-builder/pull/3958/data/openapi/api-explorer
products:
  - Elastic Docs Builder
---

# API Explorer
The API Explorer turns an OpenAPI spec into HTML pages. If you add an `api:` entry in `docset.yml`, docs-builder generates:
- a product landing page
- one tag landing page per tag
- one operation page per operation
- schema type pages for shared types

<warning>
  This feature is still under development and the functionality described on this page might change.
</warning>


## Get started

This repository includes a working example. Follow these steps against that example.
<stepper>
  <step title="Read the `api:` entry in `_docset.yml`">
    The `api` key is valid in `docset.yml` only. Do not put it in `toc.yml`.This repository uses `_docset.yml`. The live entry is:
    ```yaml
    api:
      docs-builder-elasticsearch:
        - spec: elasticsearch.json
          product: elasticsearch
          repository: elastic/elasticsearch-specification
    ```
    The map key is the URL suffix. This key produces `/api/doc/docs-builder-elasticsearch/`.Each key takes a sequence with exactly one entry. That entry requires `spec:` and `product:`. `local_spec:`, `repository:`, and `children:` are optional. See [Reference](#reference).
  </step>

  <step title="Preview the generated pages">
    If you pass `--watch`, docs-builder does not generate API pages. Run serve without `--watch`:
    ```bash
    docs-builder serve
    ```
    Open [http://localhost:3000/api/doc/docs-builder-elasticsearch/](http://localhost:3000/api/doc/docs-builder-elasticsearch/). docs-builder generates API pages on the first `/api/` request. After that, it rebuilds them when the spec file or files under `api/<key>/` change.If you only edit Markdown outside the API tree, pass `--skip-api` to `docs-builder build`.
  </step>

  <step title="Open the supplemental fixture">
    Put operation files in `api/<key>/`. The file name is `op-` plus the spec `operationId`. Do not add a toc entry.This repository includes `docs/api/docs-builder-elasticsearch/op-async-search-get.md`. After serve, open:[http://localhost:3000/api/doc/docs-builder-elasticsearch/operation/operation-async-search-get/](http://localhost:3000/api/doc/docs-builder-elasticsearch/operation/operation-async-search-get/)That file:
    - replaces the spec description
    - overrides the `keep_alive` and `id` parameter text
    - appends a **When to poll** section after the generated reference
    Heading rules, tag files, and `children:` pages are in [Writing supplemental content](https://docs-v3-preview.elastic.dev/elastic/docs-builder/pull/3958/data/openapi/supplemental).
  </step>

  <step title="Override one major version">
    If one major needs different text, add a `.vN.md` file next to the base file. This repository does not ship a `.vN.md` file. The pattern is:
    ```text
    api/elasticsearch/
      op-search.md
      op-search.v8.md
    ```
    The unversioned `/api/doc/<key>/` tree uses the overlay of the highest numeric major that this product renders. Merge rules are in [Writing supplemental content](/elastic/docs-builder/pull/3958/data/openapi/supplemental#version-specific-files).
  </step>

  <step title="Read the build error, then fix the file">
    If the file name does not match an `operationId`, the build fails. If a parameter key is not in the spec, the build also fails.
    ```text
    API supplemental file 'op-nope.md' does not match any operationId in the latest spec
    API supplemental: Parameter 'typo' not found in operation 'async-search-get' in the latest spec
    ```
    Fix the file. Then rebuild. More messages are in [Writing supplemental content](/elastic/docs-builder/pull/3958/data/openapi/supplemental#validation-errors).
  </step>
</stepper>


## Reference


| `docset.yml` key | Required | Description                                                                                                                                                                                                                                                        |
|------------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `spec:`          | yes      | The hosted spec basename used to look up the remote version index, for example `elasticsearch-openapi.json`. If no `local_spec:` is set and a file with this name exists next to `docset.yml`, docs-builder also uses it as an implicit local override for `main`. |
| `local_spec:`    | no       | Path to a local OpenAPI file, relative to `docset.yml`, that may sit anywhere in the same git checkout. When present, docs-builder renders it for `main`.                                                                                                          |
| `product:`       | yes      | A product id from `products.yml`. This binds the API to that product's versioning system.                                                                                                                                                                          |
| `repository:`    | no       | `org/repo` used to look up the version index. Set this when the spec is published from a different GitHub repository than the docset.                                                                                                                              |
| `children:`      | no       | Extra Markdown pages under `api/<key>/`, in declared order. See [children:](/elastic/docs-builder/pull/3958/data/openapi/supplemental#children-pages).                                                                                                             |

Each product key must have exactly one sequence entry. That entry must have exactly one `spec:`. An empty sequence fails the build. A sequence with more than one entry also fails the build.

### `spec:`

The basename always looks up the version index, whether or not a local file exists. See [Remote spec resolution](#remote-spec-resolution).
If you omit `local_spec:` and a file with this name exists next to `docset.yml` (or in a subfolder of it), docs-builder uses that file as an implicit local override for `main`. A missing implicit file stays silent and the hosted spec is used.

### `local_spec:`

A path to a local OpenAPI file, relative to the folder that contains `docset.yml`. The file may sit anywhere in the same git checkout. An absolute path is allowed only when it stays under the checkout root.
When the file exists, docs-builder uses it for the current (`main`) version. When the file is missing, docs-builder emits a warning and renders the hosted spec named in `spec:`.
```yaml
api:
  elasticsearch:
    - spec: elasticsearch.json
      local_spec: ../output/openapi/elasticsearch.json
      product: elasticsearch
      repository: elastic/elasticsearch-specification
```

Do not set `local_spec:` in a docset that never carries a local file — a missing implicit `spec:` file stays silent and uses the hosted spec.

### `product:`

If `product:` is not a known product id, the build fails. The error includes a suggestion.

### `repository:`

This repository sets `repository: elastic/elasticsearch-specification` because the spec is published from that repository, not from `elastic/docs-builder`.
If you omit `repository:`, docs-builder uses the GitHub remote of the current checkout.

### `children:`

`children:` adds full Markdown pages under the product root. Supplemental `op-*.md` and `tag-*.md` files are not `children:` pages. They merge into generated operation and tag pages.
docs-builder does not emit child files as normal docset HTML. Do not add them to `exclude:`.

## Page URLs

`{key}` is the `api:` map key. It is not the `product:` id.

| Page                  | Path                                                |
|-----------------------|-----------------------------------------------------|
| Product root (`main`) | `/api/doc/{key}/`                                   |
| Released major        | `/api/doc/{key}/v9/`, `/api/doc/{key}/v8/`          |
| Operation             | `/api/doc/{key}/operation/operation-{operationId}/` |
| Tag landing           | `/api/doc/{key}/group/endpoint-{tagSlug}/`          |
| Schema type           | `/api/doc/{key}/types/{schemaMoniker}/`             |
| Child Markdown        | `/api/doc/{key}/{slug}/`                            |

docs-builder lowercases the `operationId` in the URL. For tag slugs, it replaces spaces with hyphens and lowercases the name. Underscores stay.
The `api:` key creates this URL tree. Do not list generated operation pages in `toc.yml`. From Markdown inside an API page, you can link with paths such as `../group/endpoint-search` and `../operation/operation-search`. docs-builder rewrites those links against the current product base.

## Multi-version behavior

For a versioned product, docs-builder renders every resolved version:

| Index moniker | URL path                     | Role                   |
|---------------|------------------------------|------------------------|
| `main`        | `/api/doc/{key}/`            | Current-major tree     |
| `9`, `8`      | `/api/doc/{key}/v9/`, `/v8/` | Frozen major snapshots |

The numeric `9` entry is a frozen snapshot. It is not the same as `main`. The unversioned tree uses the overlay of the highest numeric major that this product renders.
If a local spec file exists, it overrides `main` only.
A versionless product (`versioning: serverless` and similar) renders only `/api/doc/{key}/`. If more than one version is rendered, the left navigation shows a version dropdown.

## Remote spec resolution

A local file is in use when `local_spec:` points at an existing file, or when `local_spec:` is omitted and a file exists at the docset-relative `spec:` path. When no local file is in use, docs-builder fetches `main` from a CloudFront version index. Repositories that publish OpenAPI specs share this index.
Object keys in the bucket look like this:
```
<org>/<repo>/<branch>/<spec-name>.<ext>
```

Example: `elastic/elasticsearch-specification/main/elasticsearch.json`.
The root manifest is `https://d29hkgsdo66d1n.cloudfront.net/index.json`. It is keyed by `org/repo`, then spec basename, then moniker (`main`, `9`, `8`). docs-builder fetches that manifest once per build. It looks up `repository:` first. If `repository:` is missing, it uses the GitHub remote of the current checkout. Spec objects are fetched at `{base}/{org}/{repo}/{version}/{spec-basename}`.
If there is no local spec and the index has no matching entry, the build fails. If a local spec exists, that miss is a warning. Then docs-builder renders the local file.

## When the API Explorer runs

- **`docs-builder build`.** docs-builder generates API pages unless you pass `--skip-api`.
- **`docs-builder serve`.** docs-builder generates API pages on the first `/api/` request. It rebuilds them when the spec or `api/<key>/` Markdown files change. `--watch` skips API generation.
- **Assembler builds.** docs-builder generates API pages when the `assembler-api-explorer` feature flag is on. `staging` and `preview` set `ASSEMBLER_API_EXPLORER`. Production does not.


## OpenAPI extensions

These spec extensions change how pages render. They live in the OpenAPI file, not in supplemental Markdown.

### `x-codeSamples`

If an operation has `x-codeSamples`, the operation page shows a **Code Examples** section. Each array item needs `lang` and `source`. Console is sorted first when present. The tab list is the `lang` values in the spec. Tabs use the `api-language` sync group, so the selected language stays across pages.
```json
"x-codeSamples": [
  { "lang": "Console", "source": "GET /_search" },
  { "lang": "curl", "source": "curl -X GET ..." }
]
```


### `x-req-auth`

If an operation has `x-req-auth` as a JSON array of strings, the operation page shows a **Prerequisites** section after **Paths**. Empty strings are dropped. If the value is not an array, the section is omitted and the build may log a warning.
```json
"x-req-auth": [
  "Cluster privilege: `cluster:admin/snapshot`"
]
```


### `x-displayName`

If a tag object has `x-displayName`, navigation and tag headings use that string. URLs still use the canonical tag `name`. If two tag names slug to the same URL segment, the build fails.

### `x-tagGroups`

If the document has `x-tagGroups`, the sidebar groups tags by those lists. Group order follows the array. A group title links to the product landing page. It is not its own URL. Tags that are missing from every group appear under `unknown`. The build logs a warning.