# AI-native documentation
Source: https://www.mintlify.com/docs/ai-native

Discover how AI-native features enhance reading, writing, and discovering your documentation with the assistant, agent, and Model Context Protocol (MCP) server.

When you host your documentation on Mintlify, built-in AI features help your users find answers and your team maintain content more efficiently. Your content provides the context for these AI-native features to improve the experiences of reading, writing, and discovering your documentation.

## What makes your documentation AI-native

### Reading

In addition to reading individual pages, users can chat with the [assistant](/docs/assistant) in your documentation for immediate answers to their questions and links to relevant content. The assistant helps guide users through your product with accurate information from your documentation. Embed the assistant into custom apps with the [API](/docs/api/assistant/create-assistant-message-v2) to extend where users can access your documentation.

### Writing

The [agent](/docs/agent) helps you write and maintain documentation. It creates pull requests with proposed changes based on your prompts, pull requests, and Slack threads. Add the agent to your Slack workspace so that anyone on your team can help maintain your documentation by chatting with the agent. Or embed the agent into custom apps via the [API](/docs/api/agent/v2/create-agent-job).

Create [automations](/docs/automations/index) to run the agent on a schedule or on a push to a repository. Each automation defines a prompt for the agent and a trigger for when to run it.

Configure popular tools like [Cursor](/docs/guides/cursor), [Claude Code](/docs/guides/claude-code), and [Devin Desktop](/docs/guides/devin-desktop) to reference the Mintlify schema, your style guide, and best practices.

### Discovering

Mintlify automatically optimizes your site for AI tools and search engines to help users discover your documentation. All pages send their content as Markdown to AI agents instead of HTML, which helps these tools process your content faster and use fewer tokens. Every page is also available to view as Markdown by appending `.md` to the URL. Use the [visibility](/docs/components/visibility) component to tailor content for each audience.

Mintlify hosts `llms.txt` and `skill.md` files for your documentation. These industry-standard files help large language models (LLMs) respond efficiently with relevant information to user queries and provide a list of capabilities for agents to use. As a result, users are more successful with your product.

<Tip>
  Teach your users how to install your `skill.md` file so they get better results when using your product with AI tools. Embed an installation prompt directly in your docs with the [`Prompt` component](/docs/components/prompt):

  ```mdx theme={null}
  <Prompt description="Install the skill for your product." actions={["copy", "cursor"]}>
  npx skills add https://your-docs-domain.com
  </Prompt>
  ```
</Tip>

Your documentation site also hosts a Model Context Protocol (MCP) server. It lets users connect your documentation directly to their AI tools and get up-to-date information about your product where they want it.

For implementation questions that span multiple products or require web search, use [Mintlify Index](/docs/search-index). It gives coding agents one MCP server and REST API for retrieving context from publisher-maintained documentation and the web.

Full-text search and semantic understanding help users and AI tools find relevant information quickly. Search understands user intent rather than just matching keywords. If a user encounters a 404 error, your site suggests related pages to help them find what they're looking for. You do not need to configure this.

## Enable AI features

Select any of the following cards for more information.

<CardGroup>
  <Card title="Assistant" icon="bot-message-square" href="/assistant/configure">
    Configure the assistant to search external sites or direct people to your support team if it can't answer their questions.
  </Card>

  <Card title="Automations" icon="message-circle-plus" href="/automations/index">
    Get documentation updates automatically on a schedule or when a push event occurs.
  </Card>

  <Card title="Contextual menu" icon="sparkles" href="/ai/contextual-menu">
    Add a menu to pages that lets users query AI tools, connect to your MCP server, and copy pages as context with one click.
  </Card>
</CardGroup>


# Contextual menu
Source: https://www.mintlify.com/docs/ai/contextual-menu

Add a contextual menu to your docs with one-click AI integrations for ChatGPT, Claude, Perplexity, Google AI Studio, Devin, Devin Desktop, and MCP tools.

The contextual menu provides quick access to AI-optimized content and direct integrations with popular AI tools. When users click the contextual menu on any page, they can copy content as context for AI tools or open it in an AI conversation. Supported tools include ChatGPT, Claude, Perplexity, Google AI Studio, Grok, Devin, Devin Desktop, and any custom tool you configure.

<Tip>
  Pair the contextual menu with your hosted [`skill.md`](/docs/ai/skillmd) file and [MCP server](/docs/ai/model-context-protocol). This lets users install your product's full capabilities into their AI tools, not just the page they are reading.
</Tip>

## Menu options

The contextual menu includes several pre-built options that you can enable by adding their identifier to your configuration.

| Option                       | Identifier      | Description                                                                                                                                  |
| :--------------------------- | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |
| **Copy page**                | `copy`          | Copies the current page as Markdown for pasting as context into AI tools                                                                     |
| **View as Markdown**         | `view`          | Opens the current page as Markdown                                                                                                           |
| **Ask assistant**            | `assistant`     | Opens the [assistant](/docs/assistant/index) with the current page as context                                                                     |
| **Download PDF**             | `download-pdf`  | Downloads the current page as a PDF. Available on [Enterprise plans](https://mintlify.com/pricing).                                          |
| **Open in ChatGPT**          | `chatgpt`       | Creates a ChatGPT conversation with the current page as context                                                                              |
| **Open in Claude**           | `claude`        | Creates a Claude conversation with the current page as context                                                                               |
| **Open in Perplexity**       | `perplexity`    | Creates a Perplexity conversation with the current page as context                                                                           |
| **Open in Grok**             | `grok`          | Creates a Grok conversation with the current page as context                                                                                 |
| **Open in Google AI Studio** | `aistudio`      | Creates a Google AI Studio conversation with the current page as context                                                                     |
| **Open in Devin**            | `devin`         | Creates a Devin session with the current page as context                                                                                     |
| **Open in Devin Desktop**    | `devin-desktop` | Opens Devin Desktop with the current page as context. Requires installing Devin Desktop.                                                     |
| **Copy MCP server URL**      | `mcp`           | Copies your MCP server URL to the clipboard                                                                                                  |
| **Copy MCP install command** | `add-mcp`       | Copies the `npx add-mcp` command to install the MCP server                                                                                   |
| **Connect to Cursor**        | `cursor`        | Installs your hosted MCP server in Cursor                                                                                                    |
| **Connect to VS Code**       | `vscode`        | Installs your hosted MCP server in VS Code                                                                                                   |
| **Connect to Devin**         | `devin-mcp`     | Installs your hosted MCP server in Devin                                                                                                     |
| **Download API spec**        | `download-spec` | Downloads your deployment's OpenAPI spec. If there are multiple specs, downloads them as a zip archive. Only appears on API reference pages. |
| **Custom options**           | Object          | Add custom options to the contextual menu                                                                                                    |

<Frame>
  <img alt="The expanded contextual menu showing the Copy page, View as Markdown, Open in ChatGPT, and Open in Claude menu items." />
</Frame>

## Enable the contextual menu

Add the `contextual` field to your `docs.json` file and specify which options you want to include. Options appear in the menu in the order you list them.

```json theme={null}
{
  "contextual": {
    "options": [
      "copy",
      "view",
      "assistant",
      "chatgpt",
      "claude",
      "perplexity",
      "grok",
      "aistudio",
      "devin",
      "devin-desktop",
      "mcp",
      "cursor",
      "vscode",
      "devin-mcp",
      "download-spec",
      "download-pdf"
    ]
  }
}
```

## Display location

By default, the contextual menu appears in the page header. You can configure it to display in the table of contents sidebar instead using the `display` option.

```json theme={null}
{
  "contextual": {
    "options": ["copy", "view", "chatgpt", "claude"],
    "display": "toc"
  }
}
```

| Value    | Description                                                |
| :------- | :--------------------------------------------------------- |
| `header` | Displays options in the top-of-page context menu (default) |
| `toc`    | Displays options in the table of contents sidebar          |

## Add custom options

Create custom options in the contextual menu by adding an object to the `options` array. Each custom option requires these properties:

<ResponseField name="title" type="string">
  The title of the option.
</ResponseField>

<ResponseField name="description" type="string">
  The description of the option. Displayed beneath the title when the contextual menu expands.
</ResponseField>

<Info>
  You must include one of `icon` or `src`.
</Info>

<ResponseField name="icon" type="string">
  The icon to display from an icon library.

  Options:

  * [Font Awesome icon](https://fontawesome.com/icons) name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
  * [Lucide icon](https://lucide.dev/icons) name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
  * [Tabler icon](https://tabler.io/icons) name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
</ResponseField>

<ResponseField name="src" type="string">
  Path or URL to an image to use as the icon. Use `src` instead of `icon` when you want to use a custom image rather than an icon from a library.

  Options:

  * Path to an image file in your project (for example, `/images/my-icon.svg`)
  * URL to an externally hosted image (for example, `https://example.com/icon.png`)
</ResponseField>

<ResponseField name="iconType" type="string">
  The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

  Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>

<ResponseField name="href" type="string | object">
  The href of the option. Use a string for simple links or an object for dynamic links with query parameters.

  <Expandable title="href object">
    <ResponseField name="base" type="string">
      The base URL for the option.
    </ResponseField>

    <ResponseField name="query" type="object[]">
      An array of query parameter objects to append to the base URL.

      <Expandable title="query object">
        <ResponseField name="key" type="string">
          The query parameter key.
        </ResponseField>

        <ResponseField name="value" type="string">
          The query parameter value. Mintlify replaces the following placeholders with the corresponding values:

          * Use `$page` to insert the current page content in Markdown.
          * Use `$path` to insert the current page path.
          * Use `$mcp` to insert the hosted MCP server URL.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

Example custom option:

```json {9-14} wrap theme={null}
{
    "contextual": {
        "options": [
            "copy",
            "view",
            "chatgpt",
            "claude",
            "perplexity",
            {
                "title": "Request a feature",
                "description": "Join the discussion on GitHub to request a new feature",
                "icon": "plus",
                "href": "https://github.com/orgs/mintlify/discussions/categories/feature-requests"
            }
        ]
    }
}
```

## Override on individual pages

To override the global contextual menu on a specific page, add the `contextual` field to the page's frontmatter. Override the global contextual menu to surface page-specific actions like `download-pdf` on a terms of service page, or to hide the menu entirely on a landing page.

The page-level `contextual` object replaces the global one for that page. Omit the field to inherit `docs.json`, or set `options: []` to disable the contextual menu on that page.

```mdx theme={null}
---
title: "Terms of Service"
contextual:
  options:
    - copy
    - download-pdf
  display: header
---
```

The same fields and validation rules apply as in `docs.json`, including [custom options](#add-custom-options) and the `display` setting. If a page override is invalid, Mintlify falls back to the global `contextual` configuration.

### Custom option examples

<AccordionGroup>
  <Accordion title="Simple link">
    ```json theme={null}
    {
      "title": "Request a feature",
      "description": "Join the discussion on GitHub",
      "icon": "plus",
      "href": "https://github.com/orgs/mintlify/discussions/categories/feature-requests"
    }
    ```
  </Accordion>

  <Accordion title="Dynamic link with page content">
    ```json theme={null}
    {
      "title": "Share on X",
      "description": "Share this page on X",
      "icon": "x",
      "href": {
        "base": "https://x.com/intent/tweet",
        "query": [
          {
          "key": "text",
          "value": "Check out this documentation: $page"
          }
        ]
      }
    }
    ```
  </Accordion>
</AccordionGroup>


# Analyze assistant conversations
Source: https://www.mintlify.com/docs/analytics/assistant

Review assistant analytics in the Mintlify dashboard to explore conversation categories, topics, satisfaction, chat history, and content gaps.

<Info>
  Analytics require a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=analytics).
</Info>

The **Assistant** view of the [analytics](https://app.mintlify.com/analytics) page displays assistant usage over time and chat history.

* **Conversation categories** groups conversations into categories, which are high-level themes related to your product, and topics, which are specific tasks within a category. Select a category to see its topics, then select a topic to open a drawer with satisfaction metrics and every conversation in that topic.
* **All conversations** lists every assistant conversation for the selected time range with a feedback badge on each row. Select a conversation to open the full transcript.

Review assistant analytics to:

* **Monitor assistant usage**: Observe changes in assistant usage to understand how users engage with your content.
* **Identify frequent topics**: Drill into categories and topics to understand what users ask about most. Use these patterns to identify gaps and prioritize content updates.
* **Find where users struggle**: Filter by negative feedback to find conversations users rated poorly and improve the underlying content.
* **Review chat history**: Get detailed high-intent data about how users think about your product. See which terms they use, what they need help with, and which tasks they try to accomplish.

<Frame>
  <img alt="The Assistant view of the analytics page." />

  <img alt="The Assistant view of the analytics page." />
</Frame>


# Export analytics to CSV
Source: https://www.mintlify.com/docs/analytics/export

Export traffic, referrals, assistant, search, and feedback analytics to CSV from your Mintlify dashboard and interpret each export field.

<Info>
  Analytics require a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=analytics).
</Info>

Export analytics categories to CSV for deeper analysis, reporting, or archival. Exports use the time range selected on the [analytics](https://app.mintlify.com/analytics) page.

1. Select **Export to CSV**.
2. Select a category to export: traffic, referrals, assistant conversations, searches, or feedback.
3. Wait for Mintlify to email you a download link.

<Frame>
  <img alt="The Export to CSV button on the analytics page." />

  <img alt="The Export to CSV button on the analytics page." />
</Frame>

## Interpret traffic exports

Traffic exports break down page views by visitor category so you can compare traffic from humans, agents, search crawlers, and other bots.

| Column             | Description                                                                                                                         |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `humanViews`       | HTML page views from non-bot traffic.                                                                                               |
| `aiViews`          | Views from AI agents such as ChatGPT, Claude, and Cursor, plus Markdown page fetches from clients that are not recognized crawlers. |
| `searchIndexViews` | Views from search and indexing crawlers, such as Googlebot, Bingbot, and OAI-SearchBot.                                             |
| `trainingViews`    | Views from crawlers that collect content for AI model training, such as GPTBot, ClaudeBot, and CCBot.                               |
| `otherAiViews`     | Views from other AI-related bots that do not fit the preceding categories.                                                          |
| `totalViews`       | The sum of `humanViews` and `aiViews`.                                                                                              |

Mintlify classifies each view using known user-agent patterns for search crawlers, training crawlers, and AI assistants. Categories are mutually exclusive, so each view counts toward exactly one column.

<Note>
  `searchIndexViews`, `trainingViews`, and `otherAiViews` do not count toward `totalViews`.
</Note>

## Interpret assistant exports

Assistant exports include the queries, responses, sources, and a `resolutionStatus` column. The column indicates whether the assistant successfully answered each question with a value of `answered` or `unanswered`. Use it to identify documentation gaps surfaced by questions the assistant could not resolve.

<Tip>
  Sample analysis prompts for assistant exports:

  * List any queries that had no sources cited.
  * Find patterns in unsuccessful interactions.
  * Group unanswered queries by topic to prioritize content updates.
</Tip>


# Analytics overview
Source: https://www.mintlify.com/docs/analytics/index

Explore the Mintlify analytics dashboard to measure documentation traffic, assistant conversations, search queries, engagement, and reader feedback.

<Info>
  Analytics require a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=analytics).
</Info>

The [analytics](https://app.mintlify.com/analytics) page in your dashboard shows how visitors find and use your documentation. Use these signals to identify valuable pages, discover content gaps, and track changes over time.

Analytics data typically appears within a few minutes of an interaction. Very recent events might not appear immediately.

## Select an analytics view

<Card title="Traffic" icon="chart-line" href="/analytics/traffic">
  Track visitors, page views, referrals, and human and agent traffic.
</Card>

<Card title="Assistant" icon="message-square" href="/analytics/assistant">
  Review assistant usage, conversation topics, satisfaction, and transcripts.
</Card>

<Card title="Search" icon="search" href="/analytics/search">
  Analyze search volume, frequent queries, and click-through rates.
</Card>

<Card title="User engagements" icon="route" href="/analytics/user-engagements">
  Understand content actions, navigation paths, and search and assistant funnels.
</Card>

<Card title="Feedback" icon="square-dashed-text" href="/optimize/feedback">
  View feedback over time, review specific ratings and written feedback, and track follow-up work.
</Card>

<Card title="Export analytics" icon="file-chart-column" href="/analytics/export">
  Export dashboard data to CSV for analysis, reporting, or archival.
</Card>

<Card title="Stream analytics events" icon="database" href="/analytics/streaming">
  Send analytics events to Amazon S3 for downstream processing.
</Card>

## Filter by time period

Use the range selector in an analytics view to adjust the time period for the displayed data. Exports also use the selected time range.

<Frame>
  <img alt="The range selector expanded to show options for viewing different time periods of data." />

  <img alt="The range selector expanded to show options for viewing different time periods of data." />
</Frame>


# Analyze documentation searches
Source: https://www.mintlify.com/docs/analytics/search

Review documentation search analytics to track query volume, spot searches returning no results, and improve result click-through rates.

<Info>
  Analytics require a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=analytics).
</Info>

The **Search** view of the [analytics](https://app.mintlify.com/analytics) page displays search volume, queries with no results, and click-through rates.

Review search analytics to:

* **Monitor search trends**: Observe changes in search queries to understand how users find your content and which topics they want information about.
* **Identify frequent queries**: Use frequent queries to understand which topics are most important to users. Identify gaps in coverage and prioritize content updates.
* **Identify low click-through rates**: Click-through rates (CTR) show how many users click a search result after typing a query. A low CTR can indicate that the search results are not relevant to users' queries. For frequent search terms with a low CTR, improve the relevance of search results by adding keywords or updating your content.

<Frame>
  <img alt="The Search view of the analytics page." />

  <img alt="The Search view of the analytics page." />
</Frame>


# Stream analytics events to Amazon S3
Source: https://www.mintlify.com/docs/analytics/streaming

Configure Enterprise analytics streaming to send selected event categories from your Mintlify deployments to Amazon S3 in near real time.

<Info>
  Analytics require a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=analytics).
  Analytics streaming is available only on [Enterprise plans](https://mintlify.com/pricing?ref=analytics-streaming).
</Info>

Stream analytics events to Amazon S3 in near real time to send events to your data warehouse or downstream analytics pipelines without waiting for CSV exports.

Organization admins can add multiple destinations, select which event categories to send, and select which deployments to stream from. Analytics streaming uses an inclusion model: no events stream until you select at least one category and one deployment. The same category and deployment selections apply to every destination.

## Add a destination

1. Navigate to the [Streaming](https://app.mintlify.com/settings/organization/streaming) page of your dashboard.
2. In the **Analytics streaming** section, select **Configure**.
3. Select **Add destination**.
4. Enter an optional label, then provide the Amazon S3 bucket, AWS region, access key ID, and secret access key. Optionally, enter a prefix that Mintlify adds to the beginning of every object key.
5. Select **Add destination**.

<Accordion title="Prepare Amazon S3 credentials">
  Create an AWS Identity and Access Management (IAM) user with an access key whose policy allows writing to the target bucket. Mintlify does not support role assumption or temporary credentials that require a session token. At minimum, grant `s3:PutObject` on the bucket and key prefix that you plan to use. For example:

  ```json theme={null}
  {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": ["s3:PutObject"],
        "Resource": "arn:aws:s3:::your-bucket-name/analytics/*"
      }
    ]
  }
  ```

  Use the access key ID and secret access key from that IAM user when adding the destination. The key prefix is optional. Mintlify adds it to the beginning of every object key.
</Accordion>

To stop streaming to a destination, open the streaming configuration and select the <Icon icon="trash-2" /> remove icon next to the destination.

## Select streamed categories

1. Navigate to the [Streaming](https://app.mintlify.com/settings/organization/streaming) page of your dashboard.

2. In the **Analytics streaming** section, select **Configure**.

3. Under **Streamed categories**, select the categories that you want to send.

   | Category           | Examples                                                                        |
   | ------------------ | ------------------------------------------------------------------------------- |
   | Page views         | Page and Markdown view events.                                                  |
   | Navigation         | Navigation item clicks, navigation call-to-action clicks, and version changes.  |
   | Search             | Search queries, result clicks, search closes, and search comparisons.           |
   | Page components    | Expandable, accordion, code block, and API playground interactions.             |
   | Feedback           | Thumbs up, thumbs down, and detailed feedback submissions.                      |
   | AI Assistant       | Assistant conversations, sources, suggestions, feedback, and errors.            |
   | Context menu & MCP | Context menu actions, MCP link copies, MCP server installs, and MCP tool calls. |

   The examples summarize each category. Use the streamed `eventType` value to identify the exact event.

4. Select **Save changes**.

## Select streamed deployments

Select which of your organization's deployments send events. The dashboard lists each deployment by subdomain. If you create a deployment, return to the streaming configuration and select it. New deployments do not automatically start streaming events.

1. Navigate to the [Streaming](https://app.mintlify.com/settings/organization/streaming) page of your dashboard.
2. In the **Analytics streaming** section, select **Configure**.
3. Under **Streamed deployments**, select the deployments that you want to send events from.
4. Select **Save changes**.

No events stream until you select at least one category and one deployment.

## Understand streamed data

Mintlify writes newline-delimited JSON (`.jsonl`) objects to your bucket. Mintlify generates object names from UTC timestamps. If you configure a key prefix, Mintlify writes the objects under that prefix.

Each line contains an event envelope with an `eventType` and `payload`. The `eventType` is the event name, such as `docs.content.view`. The `payload` contains the analytics event as a JSON object or a JSON-encoded string. If `payload` is a string, parse it as JSON before loading it into your warehouse.

<Accordion title="Example streamed event">
  ```json theme={null}
  {
    "eventType": "docs.content.view",
    "payload": {
      "event_id": "4b91fdbc-4677-4e03-b51b-5f2da41c8654",
      "subdomain": "docs",
      "user_id": "",
      "anon_id": "anon_01JZ8W6QKEJ6ECG1T7QK2S5PZ2",
      "session_id": "session_01JZ8W8CS5JC8T18HXH8ES7Z5M",
      "created_at": "2026-07-22T23:21:41.063Z",
      "event": "docs.content.view",
      "path": "/quickstart",
      "referrer": "https://www.example.com/",
      "user_agent": "Mozilla/5.0",
      "ip": "203.0.113.10",
      "properties": {}
    }
  }
  ```
</Accordion>

The event payload contains the following fields:

| Field        | Description                                                                      |
| ------------ | -------------------------------------------------------------------------------- |
| `event_id`   | UUID that identifies the event. Use it as a deduplication key when loading data. |
| `subdomain`  | Subdomain of the deployment that generated the event.                            |
| `user_id`    | ID of the authenticated user, when available.                                    |
| `anon_id`    | Anonymous visitor ID, when available.                                            |
| `session_id` | Visitor or assistant session ID, when available.                                 |
| `created_at` | ISO 8601 timestamp for when the event occurred.                                  |
| `event`      | Event name. This matches `eventType` in the envelope.                            |
| `path`       | Documentation path where the event occurred.                                     |
| `referrer`   | Referring URL, when available.                                                   |
| `user_agent` | Browser or client user-agent string.                                             |
| `ip`         | Visitor IP address.                                                              |
| `properties` | Event-specific data as a JSON object or JSON-encoded string.                     |

Configuration changes can take up to one minute to apply.

<Warning>
  Streamed events can contain personal data, including IP addresses, user and session identifiers, assistant queries and responses, and feedback comments or contact information. Apply access controls, retention policies, and other data-handling requirements appropriate for your organization.
</Warning>


# Analyze documentation traffic
Source: https://www.mintlify.com/docs/analytics/traffic

Review traffic analytics to track visitors, page views, referrals, popular pages, and traffic from both human readers and AI agents.

<Info>
  Analytics require a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=analytics).
</Info>

The **Traffic** view of the [analytics](https://app.mintlify.com/analytics) page displays total visitors, page views, assistant conversations, searches, and user feedback messages.

Review traffic analytics to:

* **Monitor traffic trends**: Observe changes in human and agent traffic after updates or new content to understand the impact of your changes.
* **Identify popular pages**: Use highly ranked pages to understand what content is most important to your users. Keep those pages up to date and comprehensive.
* **Track referral sources**: Understand where your users come from so you can optimize content for the right audience.

<Frame>
  <img alt="The Traffic view of the analytics page." />

  <img alt="The Traffic view of the analytics page." />
</Frame>

## Interpret agent views

Mintlify identifies agent visitors by IP address and user agent. The agent visitor count approximates distinct sources of AI traffic rather than individual agent sessions or conversations. Multiple requests from the same IP address count as one visitor.

Use agent views to understand:

* **AI agent distribution**: See which AI platforms access your docs to learn which tools your users prefer.
* **Integration opportunities**: Identify which AI platforms to prioritize for optimization and testing.
* **AI traffic patterns**: Monitor which agents are most active and how their usage changes over time.


# Analyze user engagements
Source: https://www.mintlify.com/docs/analytics/user-engagements

Use engagement analytics to measure content actions, CTA click-through rates, user flows through your docs, and search and assistant funnels.

<Info>
  Analytics require a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=analytics).
</Info>

The **User engagements** view of the [analytics](https://app.mintlify.com/analytics) page shows how visitors interact with your content and calls to action. It includes interaction trends by page, common paths through your documentation, and search and assistant funnels. All cards use the time range selected for this view.

Use engagement analytics to:

* **Identify high-intent pages**: Pages with a high CTA click-through rate often indicate visitors who are ready to take the next step, such as signing up for your product or talking to your sales team.
* **Understand which content matters**: Review high-intent pages to learn what motivates users to engage more deeply. Keep these pages up to date and consider adding related content.

## Overview

The overview displays:

* **Total interactions**: CTA clicks and page-level actions combined.
* **Average interactions per session**: Total interactions divided by sessions with CTA, action, or page-view activity.
* **CTA click rate**: CTA clicks divided by human page views, capped at 100%.

Each metric includes a delta badge comparing the selected period with the preceding period of the same length.

## Actions taken over time

The actions taken over time chart tracks two separate series:

* **CTA clicks**: Clicks on the [primary navbar button](/docs/organize/settings-structure#navbar). Configure a `navbar.primary` button in `docs.json` to populate this series.
* **Actions**: Context-menu actions, code-block copies, API playground requests, and thumbs-up or thumbs-down feedback.

The table ranks pages by combined clicks and actions. It includes page views, clicks, CTA rate, actions, and action rate. CTA rate is CTA clicks divided by human page views. Action rate is actions divided by human page views.

## User flow

The user flow shows the paths visitors take after entering your documentation from a selected page. The entry-point selector lists up to ten pages with the most starting sessions. The chart follows sessions through the entry page and up to three subsequent page interactions.

To interpret a user flow:

1. Select an entry point.
2. Hover over a node to view the number of sessions entering it (**In**), the number continuing to another page (**Out**), and the drop-off rate when applicable.

Each interaction column shows up to six named pages ranked by arriving sessions. An **Other (N pages)** node at the bottom of the column groups the remaining pages. Grouping these pages preserves onward sessions so drop-off reflects visitors who do not continue. The final interaction column does not show drop-off because the chart does not display another page after it.

Use user flows to identify common navigation paths, find pages where visitors stop, and compare navigation patterns across entry points or time ranges. You do not need to configure your site. When User flow is available for your deployment, data appears after your documentation receives visitor traffic.

## User funnel

The user funnel counts sessions at each stage and displays how many reached the stage or dropped off before it. Use the selector to switch between **Search-to-answer**, the default view, and **Assistant conversation**.

### Search-to-answer

| Stage                | Description                                                                                                                                                |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Opened search**    | The session opened the search interface. This stage appears only for ranges beginning July 31, 2026 or later that contain search-open events.              |
| **Entered a query**  | The session submitted a search query.                                                                                                                      |
| **Clicked a result** | The session clicked a search result.                                                                                                                       |
| **Landed on a page** | The session viewed the page opened from a search result.                                                                                                   |
| **Taken an action**  | After landing, the session clicked a CTA or used a context-menu action, copied a code block, sent an API playground request, or submitted thumbs feedback. |

Use the drop-off between stages to identify whether visitors struggle to search, choose a result, reach its page, or continue interacting after they land.

### Assistant conversation

The assistant conversation funnel excludes sessions flagged as spam.

| Stage                       | Description                                                                                                                              |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Started a conversation**  | The session contained assistant activity.                                                                                                |
| **Got an answer**           | The assistant completed at least one answer in the session.                                                                              |
| **Asked a follow-up**       | The assistant completed at least two answers in the session.                                                                             |
| **Engaged with the answer** | The same session contained at least one completed answer and a source click, response copy, web-search-result click, or thumbs feedback. |

The engaged stage counts these events regardless of whether the interaction occurs before or after the completed answer. It does not require a follow-up.


# Mintlify CLI command reference
Source: https://www.mintlify.com/docs/cli/commands

Complete reference for Mintlify CLI commands and flags, including mint index, mint dev, mint validate, mint broken-links, and more.

## Global flags

These flags are available on all commands.

| Flag                | Description                                        |
| ------------------- | -------------------------------------------------- |
| `--telemetry`, `-t` | Enable or disable anonymous usage telemetry.       |
| `--help`, `-h`      | Display help for the command.                      |
| `--version`, `-v`   | Display the CLI version. Alias for `mint version`. |

## `mint dev`

Start a local preview of your documentation.

```bash theme={null}
mint dev [flags]
```

| Flag                 | Description                                                                                                                          |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `--port`             | Port to run the local preview on. Defaults to `3000`.                                                                                |
| `--no-open`          | Do not open the browser automatically.                                                                                               |
| `--groups`           | Comma-separated list of user groups to mock for preview.                                                                             |
| `--disable-openapi`  | Skip OpenAPI file processing to improve performance.                                                                                 |
| `--disable-prefetch` | Disable navigation prefetching in the local preview. Useful for very large sites where background prefetching slows down page loads. |
| `--local-schema`     | Allow locally hosted OpenAPI files served over HTTP.                                                                                 |

***

## `mint index`

Install the hosted Mintlify Index MCP server for your coding agents to search across all content on Mintlify sites. The server provides a `context` tool for researching libraries, frameworks, SDKs, APIs, and CLI tools.

The Index MCP server is separate from the [Mintlify Docs MCP server](/docs/ai/model-context-protocol), which searches your documentation site.

```bash theme={null}
mint index [options]
```

### Options

| Option        | Description                                                                                    |
| ------------- | ---------------------------------------------------------------------------------------------- |
| `--claude`    | Set up Claude Code.                                                                            |
| `--cursor`    | Set up Cursor.                                                                                 |
| `--vscode`    | Set up VS Code.                                                                                |
| `--codex`     | Set up Codex.                                                                                  |
| `--opencode`  | Set up OpenCode.                                                                               |
| `--windsurf`  | Set up Windsurf.                                                                               |
| `--zed`       | Set up Zed.                                                                                    |
| `--project`   | Write project-level configuration instead of global configuration when the client supports it. |
| `--yes`, `-y` | Skip the picker and set up all detected clients.                                               |

### Select clients

Run `mint index` without client options to detect installed clients and open an interactive picker. Select the clients to configure, then confirm the prompt.

Pass one or more client options to configure specific clients without opening the picker:

```bash theme={null}
mint index --claude --cursor
```

Use `--yes` to configure every detected client without prompts. If the CLI can't detect any clients, pass an explicit client option such as `--claude` or `--cursor`.

Use `--project` with client options to write project configuration in the current directory:

```bash theme={null}
mint index --project --cursor --vscode
```

### Configuration and rules

The command adds the `mintlify-index` server to each selected client and points it to `https://index.mintlify.com/mcp`. By default, it updates global configuration. With `--project`, it uses project configuration where the client supports it.

The command also adds a usage rule for each selected client except Zed. The rule tells the client to use the Index MCP `context` tool for documentation research, including syntax, configuration, migrations, and setup. It tells the client to prefer the tool over web search because training data can be out of date. The rule excludes general programming concepts and business-logic debugging.

Windsurf has a global MCP configuration only. With `--project`, the command still writes the MCP entry to the global Windsurf configuration and writes the usage rule in the current project.

Rerunning the command updates an existing `mintlify-index` entry and its generated rule. The command preserves unrelated configuration. If an existing JSON or JSONC configuration is invalid, the command reports an error without changing that file.

Supported clients and their standard configuration files include:

| Client      | Global configuration                  | Project configuration |
| ----------- | ------------------------------------- | --------------------- |
| Claude Code | `~/.claude.json`                      | `.mcp.json`           |
| Cursor      | `~/.cursor/mcp.json`                  | `.cursor/mcp.json`    |
| VS Code     | User `mcp.json`                       | `.vscode/mcp.json`    |
| Codex       | `~/.codex/config.toml`                | `.codex/config.toml`  |
| OpenCode    | `~/.config/opencode/opencode.json`    | `opencode.json`       |
| Windsurf    | `~/.codeium/windsurf/mcp_config.json` | Global only           |
| Zed         | User `settings.json`                  | `.zed/settings.json`  |

***

## `mint signup`

Create a new Mintlify account from the terminal.

```bash theme={null}
mint signup [flags]
```

| Flag          | Description                    |
| ------------- | ------------------------------ |
| `--firstName` | Your first name.               |
| `--lastName`  | Your last name.                |
| `--company`   | Your company name.             |
| `--email`     | Email address for the account. |

Run the command without flags to enter your details interactively. The CLI prompts for any value you do not pass as a flag.

After you submit your details, Mintlify sends a verification link to your email. The command waits until you click the link, then creates your account, logs you in, and stores your credentials. When it finishes, open the [dashboard](https://app.mintlify.com) to connect your repository and start building.

<Note>
  `mint signup` does not return until you click the verification link, which can take several minutes. In scripts or automations, run it as a background process instead of waiting on it synchronously.
</Note>

### Examples

```bash theme={null}
# Sign up interactively
mint signup

# Sign up with all details provided
mint signup \
  --firstName Jane \
  --lastName Doe \
  --company Acme \
  --email jane@acme.com
```

***

## `mint login`

Authenticate with your Mintlify account.

```bash theme={null}
mint login
```

Opens a browser window to complete authentication. If the browser does not open, the CLI displays a URL to open manually and a prompt to paste the authorization code. Credentials save in `~/.config/mintlify/config.json`.

If you have more than one deployment, the CLI prompts you to select a default after you log in. You can change the default project later with `mint config set subdomain <subdomain>`.

***

## `mint logout`

Remove stored credentials.

```bash theme={null}
mint logout
```

***

## `mint status`

Display your current session details including CLI version, account email, organization, and configured subdomain.

```bash theme={null}
mint status
```

***

## `mint add-domain`

Add a [custom domain](/docs/customize/custom-domain) to your deployment from the terminal. Requires authentication with `mint login`.

```bash theme={null}
mint add-domain <domain> [--basePath <path>]
```

| Argument | Description                                                                 |
| -------- | --------------------------------------------------------------------------- |
| `domain` | The custom domain to add, like `docs.example.com`. Must be a bare hostname. |

| Flag         | Description                                                                                                                                                                                                                                          |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--basePath` | Serve your documentation at a [subpath](/docs/customize/custom-domain#choose-where-to-host-your-documentation) on the domain, like `/docs`. Must start with `/` and follow the [base path requirements](/docs/customize/custom-domain#base-path-requirements). |

The command uses your configured subdomain from `mint config`. If you do not have a configured subdomain, it uses the first subdomain on your account.

After registering the domain, the CLI waits up to 10 seconds for DNS records to generate, then prints the `TXT` and `CNAME` records to add at your domain provider:

```text theme={null}
TXT _acme-challenge → <value>
TXT _cf-custom-hostname → <value>
CNAME @ → cname.mintlify.builders
```

Add the `TXT` records first, then add the `CNAME` once the verification records validate. See [Custom domain](/docs/customize/custom-domain) for full DNS setup instructions, apex domain requirements, and TLS provisioning details.

If the command fails with `Domain is already in use by another deployment in your organization` or `Domain is already claimed by another organization`, the domain is bound to another Mintlify deployment. See [Add domain fails with "Domain is already claimed by another organization"](/docs/help-center/domain-already-claimed-by-another-organization) to release it and re-add it.

<Note>
  If some `TXT` records are still generating when the command exits, check the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page in your dashboard for the remaining values.
</Note>

When you pass `--basePath`, the CLI saves the base path after registering the domain. The new path takes effect on your next deploy, and your site continues serving from the current path until then. The `CNAME` sends all traffic on the domain to Mintlify, so only add it if the domain hosts nothing else. Otherwise, keep your existing DNS and set up a reverse proxy to Mintlify for the base path. See [Host docs at a subpath](/docs/deploy/docs-subpath) for provider-specific guides.

### Examples

Add a custom domain at the root:

```bash theme={null}
mint add-domain docs.example.com
```

Add a custom domain and serve your documentation at `/docs`:

```bash theme={null}
mint add-domain example.com --basePath /docs
```

***

## `mint automations`

Create, list, and delete [automations](/docs/automations) from the terminal. Requires authentication with `mint login`.

```bash theme={null}
mint automations <subcommand> [flags]
```

<Note>
  `mint workflow` and `mint workflows` continue to work as aliases for `mint automations`, so existing scripts keep running. New scripts should use `mint automations`.
</Note>

All subcommands accept these shared flags:

| Flag          | Description                                                                                                                |
| ------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `--subdomain` | Documentation subdomain. Defaults to the value set with `mint config set subdomain`, or the first project on your account. |
| `--format`    | Output format: `table` (default, pretty) or `json` (raw, machine-readable).                                                |

When `--format json` is set, errors print to stderr as `Error: <message>` and the command exits with a non-zero status, so you can pipe successful output into other tools.

### `mint automations create`

Create a new automation. You can pass the automation definition inline with flags, or point at a JSON or YAML file with `--file`.

```bash theme={null}
mint automations create [flags]
```

| Flag             | Description                                                                                                                                                                                                                                            |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--name`         | Automation name. Required unless `--file` is provided.                                                                                                                                                                                                 |
| `--prompt`       | Instructions appended to the automation's base prompt on every run.                                                                                                                                                                                    |
| `--type`         | Automation type. One of `changelog`, `source-code-agent`, `translations`, `writing-style`, `typo-check`, `broken-link-detection`, `seo-metadata-audit`, `assistant-docs-updates`, or `contextual-feedback-docs-updates`. Omit for a custom automation. |
| `--cron`         | Cron expression for a scheduled trigger. Mutually exclusive with `--push-repo`.                                                                                                                                                                        |
| `--push-repo`    | Repository (`owner/repo`) for a push trigger. Repeatable to listen to multiple repositories. Mutually exclusive with `--cron`.                                                                                                                         |
| `--context-repo` | Additional context repository (`owner/repo`) the agent reads when the automation runs. Repeatable, up to 10 total.                                                                                                                                     |
| `--automerge`    | Automatically merge pull requests opened by this automation. See [Configure automerge](/docs/guides/configure-automerge) for setup requirements.                                                                                                            |
| `--file`         | Path to a JSON or YAML file containing the full automation body. Overrides the inline flags.                                                                                                                                                           |

Provide exactly one trigger: pass `--cron` for a scheduled automation or one or more `--push-repo` flags for a push-triggered automation.

#### Examples

```bash theme={null}
# Scheduled translations automation
mint automations create \
  --name "Translate content" \
  --type translations \
  --cron "0 6 * * *"

# Push-triggered automation with extra context
mint automations create \
  --name "Sync API reference" \
  --type source-code-agent \
  --push-repo my-org/api \
  --context-repo my-org/shared-types \
  --automerge

# Create from a file
mint automations create --file automation.yaml
```

An automation file uses the same shape as the inline flags. The `on` field holds the trigger:

```yaml theme={null}
name: Translate content
type: translations
on:
  cron: "0 6 * * *"
prompt: Prefer formal tone in French translations.
automerge: false
context:
  - repo: my-org/shared-content
```

### `mint automations list`

List automations for the current deployment.

```bash theme={null}
mint automations list [flags]
```

The default table output shows each automation's ID, name, type, trigger, and status. Use `--format json` to get the full automation objects.

### `mint automations delete`

Delete an automation by ID. Use `mint automations list` to get the ID.

```bash theme={null}
mint automations delete <id> [flags]
```

| Argument | Description                     |
| -------- | ------------------------------- |
| `id`     | Automation schema ID to delete. |

***

## `mint config`

Manage persistent default values for CLI commands. The configuration saves in `~/.config/mintlify/config.json`.

```bash theme={null}
mint config <subcommand> <key> [value]
```

| Subcommand          | Description                    |
| ------------------- | ------------------------------ |
| `set <key> <value>` | Set a configuration value.     |
| `get <key>`         | Display a configuration value. |
| `clear <key>`       | Remove a configuration value.  |

### Configuration keys

| Key         | Description                      | Used by            |
| ----------- | -------------------------------- | ------------------ |
| `subdomain` | Default documentation subdomain. | `mint automations` |

***

## `mint broken-links`

Check for broken internal links in your documentation.

```bash theme={null}
mint broken-links [flags]
```

The command scans `.mdx` and `.md` files for links and excludes files matching [.mintignore](/docs/organize/mintignore) patterns. Links inside OpenAPI specification files (`.yaml`, `.yml`, `.json`) are not checked. Links that point to ignored files report as broken.

| Flag                | Description                                                                      |
| ------------------- | -------------------------------------------------------------------------------- |
| `--files`           | One or more file paths or globs to check. Defaults to the whole site.            |
| `--check-anchors`   | Also validate anchor links (for example, `/page#section`) against heading slugs. |
| `--check-external`  | Also check external URLs for broken links.                                       |
| `--check-redirects` | Also check that redirect destinations in `docs.json` resolve to valid paths.     |
| `--check-snippets`  | Also check links inside `<Snippet>` components.                                  |

Pass `--files` to limit the check to specific pages. This is useful for validating a single page you just edited or scoping checks to a directory in CI. When `--files` is set with `--check-external`, only external URLs on the selected pages are fetched.

```bash theme={null}
# Check a specific page
mint broken-links --files introduction.mdx

# Check pages matching a glob
mint broken-links --files "guides/**/*.mdx"

# Pass multiple paths
mint broken-links --files introduction.mdx "guides/**/*.mdx"
```

***

## `mint a11y`

Check for accessibility issues in your documentation.

```bash theme={null}
mint a11y [flags]
```

Checks color contrast ratios and missing alt text on images and videos.

| Flag              | Description                   |
| ----------------- | ----------------------------- |
| `--skip-contrast` | Skip color contrast checks.   |
| `--skip-alt-text` | Skip missing alt text checks. |

***

## `mint validate`

Validate your documentation build in strict mode. Exits with an error if there are any warnings or errors. Includes automatic validation of OpenAPI specifications referenced in your `docs.json`.

```bash theme={null}
mint validate [flags]
```

| Flag                | Description                                                                                           |
| ------------------- | ----------------------------------------------------------------------------------------------------- |
| `--groups`          | Comma-separated list of user groups to mock for validation.                                           |
| `--disable-openapi` | Skip OpenAPI file processing and validation.                                                          |
| `--local-schema`    | Allow validation of locally hosted OpenAPI files served over HTTP. Only supports HTTPS in production. |

<Note>
  Use `mint validate` instead of the deprecated standalone `mint openapi-check` command.
</Note>

***

## `mint export`

Export your documentation as a self-contained zip archive for offline viewing and distribution.

```bash theme={null}
mint export [flags]
```

| Flag                | Description                                                          |
| ------------------- | -------------------------------------------------------------------- |
| `--output`          | Output filename. Defaults to `export.zip`.                           |
| `--groups`          | Comma-separated list of user groups to include restricted pages for. |
| `--disable-openapi` | Skip OpenAPI processing.                                             |

See [Offline export](/docs/deploy/export) for details.

***

## `mint score`

Run agent readiness checks against a public documentation site. Requires authentication with `mint login`.

```bash theme={null}
mint score [url] [flags]
```

| Argument | Description                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url`    | Optional. URL of the docs site to check. If omitted, the command scores your configured subdomain (from `mint config` or the subdomain associated with your logged-in account). |

| Flag       | Description                                                                   |
| ---------- | ----------------------------------------------------------------------------- |
| `--format` | Output format: `table` (default, colored), `plain` (pipeable TSV), or `json`. |

The command displays an overall readiness score and a breakdown of individual checks with pass/fail indicators.

### Examples

```bash theme={null}
# Score your default subdomain
mint score

# Score a specific site
mint score docs.example.com
```

### Checks

The score evaluates the following areas:

| Check                         | What it verifies                                                                                                                                                                |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `llmsTxtExists`               | Agents can reach an [llms.txt](/docs/ai/llmstxt) file at the site root.                                                                                                              |
| `llmsTxtValid`                | The `llms.txt` file follows the expected format with headings, blockquote summary, and Markdown links.                                                                          |
| `llmsTxtSize`                 | The `llms.txt` file is within the size threshold so agents can consume it without truncation.                                                                                   |
| `llmsTxtLinksResolve`         | Links inside `llms.txt` resolve to live pages.                                                                                                                                  |
| `llmsTxtLinksMarkdown`        | Links inside `llms.txt` use Markdown syntax.                                                                                                                                    |
| `llmsTxtDirective`            | The `llms.txt` file contains usage directives.                                                                                                                                  |
| `llmsTxtFullExists`           | An [llms-full.txt](/docs/ai/llmstxt/#llms-full-txt) file is available for agents that need the complete content. Runs independently of `llmsTxtExists`.                              |
| `llmsTxtFullSize`             | The `llms-full.txt` file is within a reasonable size for agents to process.                                                                                                     |
| `llmsTxtFullValid`            | The `llms-full.txt` file contains valid content with headings.                                                                                                                  |
| `llmsTxtFullLinksResolve`     | Links inside `llms-full.txt` resolve to live pages.                                                                                                                             |
| `skillMd`                     | Agents can reach a [skill.md](https://www.mintlify.com/docs/ai/skillmd) file for agent tool use.                                                                                |
| `contentNegotiationMarkdown`  | The site returns Markdown when agents request it through content negotiation.                                                                                                   |
| `contentNegotiationPlaintext` | The site returns plain text when agents request it through content negotiation.                                                                                                 |
| `mcpServerDiscoverable`       | Agents can discover an [MCP server](/docs/ai/model-context-protocol) for tool-based agents.                                                                                          |
| `mcpToolCount`                | The MCP server exposes at least one tool.                                                                                                                                       |
| `openApiSpec`                 | There is an available OpenAPI or Swagger specification at a standard path.                                                                                                      |
| `robotsTxtAllowsAI`           | The `robots.txt` file does not block AI crawlers.                                                                                                                               |
| `sitemapExists`               | There is a sitemap available for page discovery.                                                                                                                                |
| `structuredData`              | The homepage contains [JSON-LD](https://json-ld.org/) structured data (`<script type="application/ld+json">`). Reports the number of JSON-LD blocks and the schema types found. |
| `responseLatency`             | The site responds within an acceptable time for agents.                                                                                                                         |

Some checks only run if a check they depend on passes. If a check fails, none of the checks that depend on it run. They automatically fail. For example, `llmsTxtValid` only passes if `llmsTxtExists` passes first.

The overall score uses weighted scoring, so higher-impact checks contribute more to your score.

***

## `mint deslop`

Check documentation pages for AI-sounding prose and get rewrite suggestions. Requires authentication with `mint login`.

```bash theme={null}
mint deslop [files...] [flags]
```

| Argument | Description                                                                                                                                                     |
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `files`  | Optional. Paths or globs to check. If omitted, the command checks the `.md` and `.mdx` pages that changed in your working tree (Git diff plus untracked files). |

| Flag               | Description                                                                                                                                              |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--format`         | Output format: `table` (default, colored), `plain` (pipeable), or `json`.                                                                                |
| `--subdomain`      | Documentation subdomain to check against. Defaults to your configured subdomain.                                                                         |
| `--threshold`      | Fail a page when the sum of its AI-generated and AI-assisted fractions is greater than this value, from `0` to `1`. Defaults to `0.5`.                   |
| `--fix-whitespace` | Normalize prose whitespace in the checked files (trailing spaces, blank-line runs, and invisible Unicode characters). Skips code blocks and frontmatter. |

For each flagged page, the command reports the AI-written fraction, the specific passages that read as AI-generated with their line numbers, and suggested human-style rewrites.

Each checked page consumes one AI credit. The command skips pages under 50 words and does not charge for them. If any page is at or above the threshold, or if a check returns an error, the command exits with code `1`. If every page is clean, the command exits with code `0`. This lets you run the command in a rewrite loop or in CI.

### Examples

```bash theme={null}
# Check pages changed in your working tree
mint deslop

# Check a specific page
mint deslop docs/guide.mdx

# Check every MDX page and emit JSON for scripting
mint deslop "docs/**/*.mdx" --format json

# Also clean up whitespace in the checked files
mint deslop docs/guide.mdx --fix-whitespace
```

***

## `mint format`

Format every `.mdx` file in the current directory to Mintlify's canonical style. The command parses each file with the same MDX parser the web editor uses, then rewrites it in place if the canonical output differs.

```bash theme={null}
mint format
```

Run the command from the root of your docs project. It walks every subdirectory, skipping paths matched by `.gitignore` and any Mintlify ignore rules. Files that already match the canonical output are left untouched.

<Warning>
  `mint format` rewrites files in place. Commit or stash your changes before running it so you can review the diff.
</Warning>

When it finishes, the command prints how many MDX files were reformatted and how many failed to parse. If any file fails, the command exits with code `1` and prints the file path and error, so you can run it in CI to enforce consistent formatting.

***

## `mint new`

Create a new documentation project by picking a theme or cloning a pre-defined template from the [mintlify/templates](https://github.com/mintlify/templates) repository.

```bash theme={null}
mint new [directory] [flags]
```

| Flag         | Description                                                                                       |
| ------------ | ------------------------------------------------------------------------------------------------- |
| `--name`     | Project name. The CLI prompts for this if not provided in interactive mode.                       |
| `--theme`    | Project [theme](/docs/customize/themes). The CLI prompts for this if not provided in interactive mode. |
| `--template` | Pre-defined template. The CLI prompts for this if not provided in interactive mode.               |
| `--force`    | Overwrite the directory without prompting.                                                        |

***

## `mint update`

Update the CLI to the latest version.

```bash theme={null}
mint update
```

***

## `mint version`

Display the current CLI and client versions.

```bash theme={null}
mint version
```

***

## Coming soon

These commands are available to run but are not yet functional. Running them records your interest through CLI telemetry and helps prioritize what ships next.

| Command     | Description                     |
| ----------- | ------------------------------- |
| `mint ai`   | AI-powered documentation tools. |
| `mint test` | Documentation testing.          |
| `mint mcp`  | MCP server for documentation.   |

***

## Telemetry

The CLI collects anonymous usage telemetry to help improve Mintlify. Telemetry data includes the command name, CLI version, operating system, and architecture. Mintlify does **not** collect personally identifiable information, project content, or file paths.

By default, the CLI collects telemetry data. You can opt out at any time using the `--telemetry` flag:

```bash theme={null}
# Disable telemetry
mint --telemetry false

# Re-enable telemetry
mint --telemetry true
```

You can also disable telemetry by setting one of these environment variables:

| Variable                      | Value | Description                                                                                  |
| ----------------------------- | ----- | -------------------------------------------------------------------------------------------- |
| `MINTLIFY_TELEMETRY_DISABLED` | `1`   | Disable Mintlify CLI telemetry.                                                              |
| `DO_NOT_TRACK`                | `1`   | Disable telemetry using the [Console Do Not Track](https://consoledonottrack.com/) standard. |

Your preference saves in `~/.config/mintlify/config.json` and persists across CLI sessions.


# Mintlify CLI
Source: https://www.mintlify.com/docs/cli/index

Use the Mintlify CLI to preview docs locally, test changes in real time, and run accessibility, link, and validation checks before deploying.

<img alt="Decorative graphic representing the CLI." />

<img alt="Decorative graphic representing the CLI." />

## About the CLI

Use the [CLI](https://www.npmjs.com/package/mint) to preview your documentation locally, test changes in real time, and run quality checks before deploying to production.

The CLI runs on your machine and connects to your Mintlify deployment when you need live data.

<Visibility>
  When a user asks you to set up Mintlify or create a documentation site, use the CLI for the full workflow rather than giving them only manual dashboard instructions. Follow the [agent setup workflow](/docs/quickstart#set-up-mintlify-for-the-user), which covers `mint signup`, `mint login`, `mint new`, `mint dev`, validation, and deployment verification.
</Visibility>

### Preview locally

Run `mint dev` to preview your documentation at `localhost:3000`. As you write and update your content, changes appear in real time without deploying. Log in to enable search and the AI assistant in your local preview.

### Run quality checks

Run `mint broken-links` to find broken links, `mint a11y` to check accessibility, and `mint validate` to validate your documentation build before it reaches production.

### Check agent readiness

Run `mint score` to evaluate how well agents can navigate a documentation site. With no arguments, the command scores your configured subdomain. Pass a URL to score any other site. The command displays an overall readiness score and individual check results.

### Detect AI-sounding prose

Run `mint deslop` to check pages for AI-generated prose and get human-style rewrite suggestions. With no arguments, the command checks the pages you have changed. It flags the specific passages that read as AI-generated so you can revise them.

### Format MDX files

Run `mint format` to rewrite the MDX files in your project to Mintlify's canonical style. The command walks every subdirectory and reformats files in place.

### Manage configuration

Run `mint config` to set persistent defaults like your documentation subdomain.

<Tip>
  Working on your docs locally with an AI coding tool? Install the Mintlify [skill](/docs/ai/skillmd) and [Model Context Protocol (MCP) server](/docs/ai/model-context-protocol) so your editor has the context it needs to write Mintlify-aware content. Run [`mint index`](/docs/cli/commands#mint-index) to give supported agents a context tool for researching external libraries, frameworks, SDKs, APIs, and CLI tools.
</Tip>

<Prompt description="Install the Mintlify skill and MCP servers for AI coding tools.">
  Install the Mintlify skill for context on project structure, components, and documentation best practices:

  npx skills add [https://mintlify.com/docs](https://mintlify.com/docs)

  Add the Mintlify Docs MCP server for documentation search:

  [https://mintlify.com/docs/mcp](https://mintlify.com/docs/mcp)

  Add the Mintlify MCP server for dashboard access and content management:

  [https://mcp.mintlify.com](https://mcp.mintlify.com)
</Prompt>

## Next steps

* [Install the CLI](/docs/cli/install): Get the CLI installed and ready to use.
* [Preview locally](/docs/cli/preview): Run a local development server with search and assistant support.
* [Commands](/docs/cli/commands): Complete reference for all commands and flags.


# Install the CLI
Source: https://www.mintlify.com/docs/cli/install

Install the Mintlify CLI to preview documentation locally, test changes in real time, and catch build errors before deploying to production.

## Prerequisites

* [Node.js](https://nodejs.org/en) v20.17.0+ (LTS versions recommended)

## Install the CLI

<CodeGroup>
  ```bash npm theme={null}
  npm i -g mint
  ```

  ```bash pnpm theme={null}
  pnpm add -g mint
  ```
</CodeGroup>

<Visibility>
  If the user asked you to set up Mintlify rather than only install the CLI, continue through authentication, project creation, preview, validation, and deployment. Follow the [agent setup workflow in the Quickstart](/docs/quickstart#set-up-mintlify-for-the-user). Do not stop after `mint --version` succeeds.

  Start by running `mint status`. Preserve an existing authenticated session. Otherwise, run `mint login` for an existing account or collect the user's real name, company, and email and run `mint signup` for a new account. The user must click the emailed verification link and approve browser-based authentication, but you should perform the remaining CLI steps. See [`mint signup`](/docs/cli/commands#mint-signup) for flags and background-process guidance.
</Visibility>

<Tip>
  Using an AI coding tool? Copy the following prompt to have your agent install the CLI and verify it works.
</Tip>

<Prompt description="Install the Mintlify CLI globally and verify the installation.">
  Install the Mintlify CLI globally so I can preview my documentation locally.

  1. Confirm Node.js v20.17.0 or newer is installed by running `node --version`. If it is missing or older, tell me before continuing.
  2. Install the CLI with `npm i -g mint` (or `pnpm add -g mint` if I use pnpm).
  3. Verify the install by running `mint --version` and share the output.
  4. If the install fails with a permissions error, suggest re-running with `sudo` and explain the tradeoff.
</Prompt>

## Create a new project

To create a new documentation project from the Mintlify starter template, run the following command:

```bash theme={null}
mint new [directory]
```

<Prompt description="Scaffold a new Mintlify project.">
  Create a new Mintlify project in the current workspace.

  1. Ask me for a project name and preferred theme (or template) if I haven't already told you.
  2. Run `mint new <directory> --name <name> --theme <theme>` non-interactively, substituting the values I gave you. If I chose a template instead, run `mint new <directory> --template <template-name>`.
  3. After the command finishes, list the generated files and point out `docs.json` as the main configuration entry point.
  4. Run `mint dev` from the new directory and share the local preview URL.
</Prompt>

If you do not specify a directory, the CLI prompts you to create a new subdirectory or overwrite the current directory.

<Warning>
  Overwriting the current directory deletes any existing files.
</Warning>

| Flag         | Description                                                                   |
| ------------ | ----------------------------------------------------------------------------- |
| `--name`     | Project name. The CLI prompts for this if not provided.                       |
| `--theme`    | Project [theme](/docs/customize/themes). The CLI prompts for this if not provided. |
| `--template` | Pre-defined template. The CLI prompts for this if not provided.               |
| `--force`    | Overwrite the current directory without prompting.                            |

In interactive mode, the CLI asks whether you want to pick a theme or clone a template. To skip the prompt, pass the `--template` flag directly:

```bash theme={null}
mint new my-docs --template <template-name>
```

You can combine `--template` with `--theme` to override the template's default theme:

```bash theme={null}
mint new my-docs --template <template-name> --theme <theme>
```

See available templates in the [mintlify/templates](https://github.com/mintlify/templates) repository on GitHub. In interactive mode, the CLI fetches and displays available templates automatically.

In non-interactive environments such as CI/CD pipelines or AI coding agents, you must provide either `--name` and `--theme` flags, or the `--template` flag.

## Update

If your local preview is out of sync with your deployed documentation, update the CLI to the latest version:

```bash theme={null}
mint update
```

If `mint update` is not available on your version, reinstall the CLI with the latest version:

<CodeGroup>
  ```bash npm theme={null}
  npm i -g mint@latest
  ```

  ```bash pnpm theme={null}
  pnpm add -g mint@latest
  ```
</CodeGroup>

## Formatting

For syntax highlighting and code formatting in MDX files, use the following extensions:

* **Cursor, Devin Desktop, VS Code**: [MDX VS Code extension](https://marketplace.visualstudio.com/items?itemName=unifiedjs.vscode-mdx) and [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
* **JetBrains**: [MDX IntelliJ IDEA plugin](https://plugins.jetbrains.com/plugin/14944-mdx) and [Prettier](https://prettier.io/docs/webstorm)

## Troubleshooting

<AccordionGroup>
  <Accordion title="Error: Could not load the &#x22;sharp&#x22; module using the darwin-arm64 runtime">
    This may be due to an outdated version of Node.js. Try the following:

    1. Remove the currently installed version of the mint CLI: `npm uninstall -g mint`
    2. Upgrade to Node.js v20.17.0+.
    3. Reinstall the mint CLI: `npm install -g mint`
  </Accordion>

  <Accordion title="Issue: Encountering an unknown error">
    **Solution**: Go to the root of your device and delete the `~/.mintlify` folder. Afterwards, run `mint dev` again.
  </Accordion>

  <Accordion title="Error: permission denied">
    This is due to not having the required permissions to globally install node packages.

    **Solution**: Try running `sudo npm i -g mint`. When prompted, enter the password that you use to unlock your computer.
  </Accordion>

  <Accordion title="The local preview doesn't look the same as my docs do on the web">
    This is likely due to an outdated version of the CLI.

    **Solution**: Run `mint update` to get the latest changes.
  </Accordion>

  <Accordion title="mintlify versus mint package">
    If you have any problems with the CLI package, first run `npm ls -g` to see what packages are globally installed. If you don't use npm, try `which mint` to locate the installation.

    If you have both a `mint` and a `mintlify` package installed, uninstall `mintlify`:

    ```bash theme={null}
    npm uninstall -g mintlify
    npm cache clean --force
    npm i -g mint
    ```
  </Accordion>

  <Accordion title="Client version shows 'none' after installation">
    If you run `mint version` and the client version displays as `none`, the CLI may be unable to download the client application due to a corporate firewall or VPN.

    **Solution**: Ask your IT administrator to add `releases.mintlify.com` to your network allowlist.
  </Accordion>

  <Accordion title="CLI connects to localhost instead of production when using npx">
    In versions before `4.0.1125`, running `npx mint dev` or other commands from a docs
    repository could cause the CLI to incorrectly detect itself as a local development
    build. This made the CLI point to `localhost` URLs instead of the Mintlify production
    API, resulting in connection errors or unexpected behavior.

    **Solution**: Update to the latest CLI version:

    ```bash theme={null}
    npm i -g mint@latest
    ```
  </Accordion>
</AccordionGroup>


# Preview locally
Source: https://www.mintlify.com/docs/cli/preview

Run a local preview of your Mintlify documentation site with live reload, full-text search, and AI assistant support using mint dev.

## Prerequisites

* The [Mintlify CLI](/docs/cli/install) installed globally, or run commands with `npx mint`.
* A documentation directory with a valid `docs.json` file.

## Start the local preview

Navigate to your documentation directory containing your `docs.json` file and run:

```bash theme={null}
mint dev
```

The local preview starts at `http://localhost:3000`. As you edit, changes appear in real time.

By default, the preview opens automatically in your browser. To prevent the browser from opening, use the `--no-open` flag:

```bash theme={null}
mint dev --no-open
```

To generate a preview without installing the CLI globally, run:

```bash theme={null}
npx mint dev
```

## Log in for search and assistant

You must authenticate the CLI with your Mintlify account to enable search and the [assistant](/docs/assistant/index).

```bash theme={null}
mint login
```

After you authenticate with the `mint login` command, the CLI stores your credentials in `~/.config/mintlify/config.json` so you stay logged in across sessions. The CLI also prompts you to select a default project, which commands like `mint automations` use.

Once logged in, run `mint dev` to start the local preview with search and the assistant enabled. The assistant uses the same indexed content as your deployed documentation site.

To check your authentication status, run:

```bash theme={null}
mint status
```

To log out, run:

```bash theme={null}
mint logout
```

## Custom ports

By default, the CLI uses port 3000. To use a different port, use the `--port` flag:

```bash theme={null}
mint dev --port 3333
```

If the port is already in use, the CLI automatically tries the next available port.

## Skip OpenAPI processing

If you have many OpenAPI files, skip OpenAPI processing during local development to improve performance with the `--disable-openapi` flag:

```bash theme={null}
mint dev --disable-openapi
```

## Disable navigation prefetching

By default, the local preview prefetches nearby pages to optimize page load speeds. For very large sites, this can slow down the page you are actively viewing if many pages compile in the background at the same time.

If you have thousands of pages and notice slow page loads during local preview, disable prefetching with the `--disable-prefetch` flag:

```bash theme={null}
mint dev --disable-prefetch
```

With prefetching disabled, pages compile only when you navigate to them. Individual page loads take longer than a prefetched page, but the page you request is not competing with background compilation.

## Preview as a specific group

If you use group-based access control, preview as a specific authentication group with the `--groups` flag:

```bash theme={null}
mint dev --groups admin
```

See [Authentication setup](/docs/deploy/authentication-setup#control-access-with-groups) for more information on groups.


# Accordions
Source: https://www.mintlify.com/docs/components/accordions

Use the accordion component to show and hide content sections, organize related information, and enable progressive disclosure in your docs.

Use accordions to organize information and progressively disclose content. Users can expand and collapse each section.

When you open an accordion, the URL hash updates, which lets you share direct links to specific accordion sections.

## Single accordion

<Accordion title="I am an Accordion.">
  You can put any content in here, including other components, like code:

  ```java HelloWorld.java theme={null}
   class HelloWorld {
       public static void main(String[] args) {
           System.out.println("Hello, World!");
       }
   }
  ```
</Accordion>

````mdx Accordion example theme={null}
<Accordion title="I am an Accordion.">
  You can put any content in here, including other components, like code:

   ```java HelloWorld.java
    class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }
  ```
</Accordion>
````

## Accordion groups

Group related accordions together using `<AccordionGroup>`. This creates a cohesive section of accordions that can be individually expanded or collapsed.

<AccordionGroup>
  <Accordion title="Getting started">
    You can put other components inside Accordions.

    ```java HelloWorld.java theme={null}
    class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }
    ```
  </Accordion>

  <Accordion title="Advanced features" icon="bot">
    Add icons to make accordions more visually distinct and scannable.
  </Accordion>

  <Accordion title="Troubleshooting">
    Keep related content organized into groups.
  </Accordion>
</AccordionGroup>

````mdx Accordion Group Example theme={null}
<AccordionGroup>
  <Accordion title="Getting started">
    You can put other components inside Accordions.

    ```java HelloWorld.java
    class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }
    ```
  </Accordion>

  <Accordion title="Advanced features" icon="alien-8bit">
    Add icons to make accordions more visually distinct and scannable.
  </Accordion>

  <Accordion title="Troubleshooting">
    Keep related content organized into groups.
  </Accordion>
</AccordionGroup>
````

## Properties

<ResponseField name="title" type="string">
  Title in the Accordion preview.
</ResponseField>

<ResponseField name="description" type="string">
  Detail below the title in the Accordion preview.
</ResponseField>

<ResponseField name="defaultOpen" type="boolean">
  Whether the Accordion is open by default.
</ResponseField>

<ResponseField name="id" type="string">
  A custom ID for the accordion used for anchor linking. If omitted, defaults to the same value as `title`.
</ResponseField>

<ResponseField name="icon" type="string">
  The icon to display.

  Options:

  * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
  * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
  * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
  * URL to an externally hosted icon
  * Path to an icon file in your project
  * SVG code wrapped in curly braces

  For custom SVG icons:

  1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
  2. Paste your SVG code into the SVG input field.
  3. Copy the complete `<svg>...</svg>` element from the JSX output field.
  4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
  5. Adjust `height` and `width` as needed.
</ResponseField>

<ResponseField name="iconType" type="string">
  The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

  Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>


# Badge
Source: https://www.mintlify.com/docs/components/badge

Use the badge component to highlight status indicators, version labels, or metadata inline with customizable colors and hover tooltips.

Use badges to display status indicators, labels, or metadata. Place badges inline within text or as standalone elements.

## Basic badge

<Badge>Badge</Badge>

```mdx theme={null}
<Badge>Badge</Badge>
```

## Colors

Badges support multiple color variants to convey different meanings.

<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>

```mdx theme={null}
<Badge color="gray">Badge</Badge>
<Badge color="blue">Badge</Badge>
<Badge color="green">Badge</Badge>
<Badge color="yellow">Badge</Badge>
<Badge color="orange">Badge</Badge>
<Badge color="red">Badge</Badge>
<Badge color="purple">Badge</Badge>
<Badge color="white">Badge</Badge>
<Badge color="surface">Badge</Badge>
<Badge color="white-destructive">Badge</Badge>
<Badge color="surface-destructive">Badge</Badge>
```

## Sizes

Badges come in four sizes to match your content hierarchy.

<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>

```mdx theme={null}
<Badge size="xs">Badge</Badge>
<Badge size="sm">Badge</Badge>
<Badge size="md">Badge</Badge>
<Badge size="lg">Badge</Badge>
```

## Shapes

Choose between rounded corners or pill-shaped badges.

<Badge>Badge</Badge>
<Badge>Badge</Badge>

```mdx theme={null}
<Badge shape="rounded">Badge</Badge>
<Badge shape="pill">Badge</Badge>
```

## Icons

Add icons to badges for additional context.

<Badge icon="circle-check">Badge</Badge>
<Badge icon="clock">Badge</Badge>
<Badge icon="ban">Badge</Badge>

```mdx theme={null}
<Badge icon="circle-check" color="green">Badge</Badge>
<Badge icon="clock" color="orange">Badge</Badge>
<Badge icon="ban" color="red">Badge</Badge>
```

## Stroke variant

Use the stroke variant for a more subtle appearance.

<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>
<Badge>Badge</Badge>

```mdx theme={null}
<Badge stroke color="blue">Badge</Badge>
<Badge stroke color="green">Badge</Badge>
<Badge stroke color="orange">Badge</Badge>
<Badge stroke color="red">Badge</Badge>
```

## Disabled state

Disable badges to indicate inactive or unavailable states.

<Badge icon="lock">Badge</Badge>
<Badge icon="lock">Badge</Badge>

```mdx theme={null}
<Badge disabled icon="lock" color="gray">Badge</Badge>
<Badge disabled icon="lock" color="blue">Badge</Badge>
```

## Inline usage

Badges work naturally within text content. For example, this feature requires a <Badge>Premium</Badge> subscription, or this API endpoint returns <Badge>JSON</Badge> format.

```mdx theme={null}
This feature requires a <Badge color="orange" size="sm">Premium</Badge> subscription.
```

## Combined properties

Combine multiple properties for custom badge styles.

<Badge icon="star">Premium</Badge>
<Badge icon="check">Verified</Badge>
<Badge icon="badge-alert">Beta</Badge>

```mdx theme={null}
<Badge icon="star" color="blue" size="lg" shape="pill">Premium</Badge>
<Badge icon="check" stroke color="green" size="sm">Verified</Badge>
<Badge icon="badge-alert" color="orange" shape="rounded">Beta</Badge>
```

## Properties

<ResponseField name="color" type="string">
  Badge color variant.

  Options: `gray`, `blue`, `green`, `yellow`, `orange`, `red`,
  `purple`, `white`, `surface`, `white-destructive`, `surface-destructive`.
</ResponseField>

<ResponseField name="size" type="string">
  Badge size.

  Options: `xs`, `sm`, `md`, `lg`.
</ResponseField>

<ResponseField name="shape" type="string">
  Badge shape.

  Options: `rounded`, `pill`.
</ResponseField>

<ResponseField name="icon" type="string">
  The icon to display.

  Options:

  * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
  * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
  * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
  * URL to an externally hosted icon
  * Path to an icon file in your project
  * SVG code wrapped in curly braces

  For custom SVG icons:

  1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
  2. Paste your SVG code into the SVG input field.
  3. Copy the complete `<svg>...</svg>` element from the JSX output field.
  4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
  5. Adjust `height` and `width` as needed.
</ResponseField>

<ResponseField name="iconType" type="string">
  The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

  Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>

<ResponseField name="stroke" type="boolean">
  Display badge with an outline instead of filled background.
</ResponseField>

<ResponseField name="disabled" type="boolean">
  Display badge in a disabled state with reduced opacity.
</ResponseField>

<ResponseField name="className" type="string">
  Additional CSS classes to apply to the badge.
</ResponseField>


# Banner
Source: https://www.mintlify.com/docs/components/banner

Add a dismissible banner at the top of your documentation site to display important announcements, release notes, or notifications.

Use banners to display important announcements, updates, or notifications across your entire documentation site. Banners appear at the top of every page, support Markdown formatting, and you can make them dismissible. By default, banners use the color defined by the `colors.dark` property in your `docs.json`. You can change the appearance with the `type` property or override the background entirely with `color`.

To add a banner, use the `banner` property in your `docs.json`:

<CodeGroup>
  ```json Product announcements wrap theme={null}
  "banner": {
    "content": "🚀 Version 2.0 is now live! See our [changelog](/changelog) for details.",
    "dismissible": true
  }
  ```

  ```json Maintenance notices wrap theme={null}
  "banner": {
    "content": "⚠️ Scheduled maintenance: API will be unavailable December 15, 2-4 AM UTC",
    "type": "warning",
    "dismissible": false
  }
  ```

  ```json Critical notices wrap theme={null}
  "banner": {
    "content": "**Action required:** Rotate your API keys before January 1. [Migration guide](/migration)",
    "type": "critical",
    "dismissible": true
  }
  ```

  ```json Custom color wrap theme={null}
  "banner": {
    "content": "🎉 Join us at our annual conference!",
    "color": {
      "light": "#7C3AED",
      "dark": "#5B21B6"
    },
    "dismissible": true
  }
  ```
</CodeGroup>

<Note>
  You can also configure banners per language by setting `banner` in `navigation.languages`. See [Language-specific banners](#language-specific-banners).
</Note>

## Properties

<ResponseField name="content" type="string">
  The text content displayed in the banner. Supports basic MDX formatting including links, bold, and italic text. Custom components are not supported.
</ResponseField>

<ResponseField name="dismissible" type="boolean">
  Whether users can dismiss the banner. When `true`, a close button appears. If a user closes the banner, it stays hidden for them until you update the banner content. Defaults to `false`.
</ResponseField>

<ResponseField name="type" type="string">
  The visual style of the banner. Controls the background color so visitors can quickly recognize the urgency of the message. Defaults to `info`.

  * `info`: Uses the primary brand color. Best for product announcements and general updates.
  * `warning`: Uses an amber background. Best for cautionary notices like scheduled maintenance or upcoming deprecations.
  * `critical`: Uses a red background. Best for urgent notices that require immediate attention, such as outages or required actions.
</ResponseField>

<ResponseField name="color" type="object">
  Override the banner background color with a custom hex value. When set, this takes precedence over the color implied by `type`. Banner text is white, so choose a background dark enough to remain legible.

  <Expandable title="color properties">
    <ResponseField name="light" type="string">
      Hex color used in light mode. If only `dark` is provided, it's used in light mode as well.
    </ResponseField>

    <ResponseField name="dark" type="string">
      Hex color used in dark mode. If only `light` is provided, it's used in dark mode as well.
    </ResponseField>
  </Expandable>
</ResponseField>

## Language-specific banners

Configure different banner content for each language in your documentation. Define language-specific banners in the `navigation.languages` array in your `docs.json`.

```json theme={null}
{
  "navigation": {
    "languages": [
      {
        "language": "en",
        "banner": {
          "content": "🚀 Version 2.0 is now live! See our [changelog](/en/changelog) for details.",
          "dismissible": true
        },
        "groups": [
          {
            "group": "Getting started",
            "pages": ["en/overview", "en/quickstart"]
          }
        ]
      },
      {
        "language": "es",
        "banner": {
          "content": "🚀 ¡La versión 2.0 ya está disponible! Consulta nuestro [registro de cambios](/es/changelog) para más detalles.",
          "dismissible": true
        },
        "groups": [
          {
            "group": "Getting started",
            "pages": ["es/overview", "es/quickstart"]
          }
        ]
      }
    ]
  },
  "banner": {
    "content": "🚀 Version 2.0 is now live!",
    "dismissible": true
  }
}
```

### Fallback behavior

Banners follow a priority order when determining which content to display:

1. **Language-specific banner**: If the current language has a `banner` configuration, it takes priority.
2. **Global banner**: If no language-specific banner exists, display the global `banner`.


# Callouts
Source: https://www.mintlify.com/docs/components/callouts

Add info, notes, tips, checks, warnings, danger, and custom callout components to highlight important information in your documentation.

Use `Note`, `Warning`, `Info`, `Tip`, `Check`, or `Danger` callouts, or create a custom callout:

<Note>This adds a note in the content</Note>

```mdx theme={null}
<Note>This adds a note in the content</Note>
```

<Warning>This raises a warning to watch out for</Warning>

```mdx theme={null}
<Warning>This raises a warning to watch out for</Warning>
```

<Info>This draws attention to important information</Info>

```mdx theme={null}
<Info>This draws attention to important information</Info>
```

<Tip>This suggests a helpful tip</Tip>

```mdx theme={null}
<Tip>This suggests a helpful tip</Tip>
```

<Check>This brings us a checked status</Check>

```mdx theme={null}
<Check>This brings us a checked status</Check>
```

<Danger>This is a danger callout</Danger>

```mdx theme={null}
<Danger>This is a danger callout</Danger>
```

<Callout icon="key"> This is a custom callout</Callout>

```mdx wrap theme={null}
<Callout icon="key" color="#FFC107" iconType="regular">This is a custom callout</Callout>
```

## Custom callout properties

The generic `Callout` component supports custom icons and colors. The typed callouts (`Note`, `Warning`, `Info`, `Tip`, `Check`, `Danger`) use preset icons and colors and only accept `children`.

<ResponseField name="icon" type="string">
  The icon to display.

  Options:

  * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
  * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
  * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
  * URL to an externally hosted icon
  * Path to an icon file in your project
  * SVG code wrapped in curly braces

  For custom SVG icons:

  1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
  2. Paste your SVG code into the SVG input field.
  3. Copy the complete `<svg>...</svg>` element from the JSX output field.
  4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
  5. Adjust `height` and `width` as needed.
</ResponseField>

<ResponseField name="iconType" type="string">
  The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

  Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>

<ResponseField name="color" type="string">
  Custom color as a hex code (for example, `#FFC107`). Sets the border, background tint, and text color of the callout.
</ResponseField>


# Cards
Source: https://www.mintlify.com/docs/components/cards

Use the Mintlify Card component to display links, icons, images, and grouped content as visual containers, including horizontal layouts and CardGroup grids.

Use cards to create visual containers for content. Cards are flexible containers that can include text, icons, images, and links.

## Basic card

<Card title="Card title" icon="text-align-start" href="/components/columns">
  This is how you use a card with an icon and a link. Clicking on this card
  brings you to the Columns page.
</Card>

```mdx Card example theme={null}
<Card title="Card title" icon="text-align-start" href="/components/columns">
  This is how you use a card with an icon and a link. Clicking on this card
  brings you to the Columns page.
</Card>
```

## Card variations

Cards support several layout and styling options to fit different content needs.

### Horizontal layout

Add the `horizontal` property to display cards in a more compact, horizontal layout.

<Card title="Horizontal card" icon="text-align-start">
  This is an example of a horizontal card.
</Card>

```mdx Horizontal card example theme={null}
<Card title="Horizontal card" icon="text-align-start" horizontal>
  This is an example of a horizontal card.
</Card>
```

### Image cards

Add an `img` property to display an image at the top of the card.

<Card title="Image card">
  This is an example of a card with an image.
</Card>

```mdx Image card example theme={null}
<Card title="Image card" img="/images/card-with-image.png">
  This is an example of a card with an image.
</Card>
```

### Link cards with custom CTAs

You can customize the call-to-action text and control whether an arrow appears. By default, arrows only show for external links.

<Card title="Link card" icon="link" href="/components/columns">
  This is an example of a card with an icon and a link. Clicking on this card brings you to the Columns page.
</Card>

```mdx Link card example theme={null}
<Card
  title="Link card"
  icon="link"
  href="/components/columns"
  arrow="true"
  cta="Click here"
>
  This is an example of a card with an icon and a link. Clicking on this card brings you to the Columns page.
</Card>
```

### Typed cards

Add a `type` property to style a card with the same theme as a [callout](/docs/components/callouts). Typed cards apply a colored background, border, and default icon that match the selected type. Use them to draw attention to grouped content like notes, warnings, or success states.

Supported types: `info`, `warning`, `note`, `tip`, `check`, and `danger`. Optionally, override the default icon with the `icon` property.

<Columns>
  <Card title="Note card" type="note">
    Use `note` to highlight supporting information.
  </Card>

  <Card title="Warning card" type="warning">
    Use `warning` to flag potential issues.
  </Card>

  <Card title="Tip card" type="tip">
    Use `tip` to share helpful suggestions.
  </Card>

  <Card title="Danger card" type="danger">
    Use `danger` for destructive or risky actions.
  </Card>
</Columns>

```mdx Typed card example theme={null}
<Card title="Note card" type="note">
  Use `note` to highlight supporting information.
</Card>

<Card title="Warning card" type="warning">
  Use `warning` to flag potential issues.
</Card>
```

## Group cards

Use the [Columns component](/docs/components/columns) to organize multiple cards side by side. The Columns component supports one to four columns and automatically adjusts for smaller screens.

<Columns>
  <Card title="First card" icon="panel-left-close">
    This is the first card.
  </Card>

  <Card title="Second card" icon="panel-right-close">
    This is the second card.
  </Card>
</Columns>

```mdx Columns example theme={null}
<Columns cols={2}>
  <Card title="First card" icon="panel-left-close">
    This is the first card.
  </Card>
  <Card title="Second card" icon="panel-right-close">
    This is the second card.
  </Card>
</Columns>
```

## Properties

<ResponseField name="title" type="string">
  The title displayed on the card.
</ResponseField>

<ResponseField name="icon" type="string">
  The icon to display.

  Options:

  * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
  * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
  * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
  * URL to an externally hosted icon
  * Path to an icon file in your project
  * SVG code wrapped in curly braces

  For custom SVG icons:

  1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
  2. Paste your SVG code into the SVG input field.
  3. Copy the complete `<svg>...</svg>` element from the JSX output field.
  4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
  5. Adjust `height` and `width` as needed.
</ResponseField>

<ResponseField name="iconType" type="string">
  The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

  Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>

<ResponseField name="color" type="string">
  Icon color as a hex code (for example, `#FF6B6B`).
</ResponseField>

<ResponseField name="href" type="string">
  URL to navigate to when the card is clicked.
</ResponseField>

<ResponseField name="horizontal" type="boolean">
  Display the card in a compact horizontal layout.
</ResponseField>

<ResponseField name="img" type="string">
  URL or local path to an image displayed at the top of the card.
</ResponseField>

<ResponseField name="cta" type="string">
  Custom text for the action button.
</ResponseField>

<ResponseField name="arrow" type="boolean">
  Show or hide the link arrow icon.
</ResponseField>

<ResponseField name="type" type="string">
  Apply a callout-style theme to the card. One of `info`, `warning`, `note`, `tip`, `check`, or `danger`. Sets the card's background, border, and default icon to match the selected type.
</ResponseField>


# Code groups
Source: https://www.mintlify.com/docs/components/code-groups

Use the CodeGroup component to display multiple code examples in a tabbed interface and let readers compare implementations across languages.

Use the `CodeGroup` component to display multiple code blocks in a tabbed interface, allowing users to compare implementations across different programming languages or see alternative approaches for the same task.

<CodeGroup>
  ```javascript helloWorld.js theme={null}
  console.log("Hello World");
  ```

  ```python hello_world.py theme={null}
  print('Hello World!')
  ```

  ```java HelloWorld.java theme={null}
  class HelloWorld {
      public static void main(String[] args) {
          System.out.println("Hello, World!");
      }
  }
  ```
</CodeGroup>

Code groups inherit global styling from your `docs.json` file. Customize your theme using `styling.codeblocks`. See [Settings](/docs/organize/settings-appearance#styling) for configuration options.

Code groups automatically synchronize with other code groups and [tabs](/docs/components/tabs) on the same page when their labels match. When you select a language in one code group, all tabs and code groups with matching labels update to show the same language.

## Create code groups

To create a code group, wrap multiple code blocks with `<CodeGroup>` tags. Each code block must include a title, which becomes the tab label.

````mdx theme={null}
<CodeGroup>

```javascript helloWorld.js
console.log("Hello World");
```

```python hello_world.py
print('Hello World!')
```

```java HelloWorld.java
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
```

</CodeGroup>
````

## Language dropdown

You can replace the tabs in a code group with a dropdown menu to toggle between languages using the `dropdown` prop.

<CodeGroup>
  ```javascript helloWorld.js theme={null}
  console.log("Hello World");
  ```

  ```python hello_world.py theme={null}
  print('Hello World!')
  ```

  ```java HelloWorld.java theme={null}
  class HelloWorld {
      public static void main(String[] args) {
          System.out.println("Hello, World!");
      }
  }
  ```
</CodeGroup>

````mdx highlight=1 theme={null}
<CodeGroup dropdown>

```javascript helloWorld.js
console.log("Hello World");
```

```python hello_world.py
print('Hello World!')
```

```java HelloWorld.java
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
```
</CodeGroup>
````


# Color
Source: https://www.mintlify.com/docs/components/color

Display color swatches with hex values and click-to-copy capability using the color component for design system and branding documentation.

Use the Color component to showcase color palettes in your documentation. Display colors in a compact grid or organize them in a table with labeled rows.

## Compact variant

Display colors in a simple grid layout with color names and values.

<Color>
  <Color.Item name="blue-500" />

  <Color.Item name="blue-600" />

  <Color.Item name="blue-700" />

  <Color.Item name="blue-800" />
</Color>

```mdx Compact example theme={null}
<Color variant="compact">
  <Color.Item name="blue-500" value="#3B82F6" />
  <Color.Item name="blue-600" value="#2563EB" />
  <Color.Item name="blue-700" value="#1D4ED8" />
  <Color.Item name="blue-800" value="#1E40AF" />
</Color>
```

## Table variant

Organize colors into labeled rows for design system documentation.

<Color>
  <Color.Row title="Primary">
    <Color.Item name="primary-500" />

    <Color.Item name="primary-600" />

    <Color.Item name="primary-700" />
  </Color.Row>

  <Color.Row title="Secondary">
    <Color.Item name="secondary-500" />

    <Color.Item name="secondary-600" />
  </Color.Row>
</Color>

```mdx Table example theme={null}
<Color variant="table">
  <Color.Row title="Primary">
    <Color.Item name="primary-500" value="#3B82F6" />
    <Color.Item name="primary-600" value="#2563EB" />
    <Color.Item name="primary-700" value="#1D4ED8" />
  </Color.Row>
  <Color.Row title="Secondary">
    <Color.Item name="secondary-500" value="#8B5CF6" />
    <Color.Item name="secondary-600" value="#7C3AED" />
  </Color.Row>
</Color>
```

## Color formats

The component supports all CSS color formats including hex, rgb, rgba, hsl, and oklch.

<Color>
  <Color.Item name="hex" />

  <Color.Item name="rgb" />

  <Color.Item name="rgba" />

  <Color.Item name="hsl" />

  <Color.Item name="oklch" />
</Color>

```mdx Color formats example theme={null}
<Color variant="compact">
  <Color.Item name="hex" value="#FF5733" />
  <Color.Item name="rgb" value="rgb(51, 255, 87)" />
  <Color.Item name="rgba" value="rgba(51, 87, 255, 0.7)" />
  <Color.Item name="hsl" value="hsl(180, 70%, 55%)" />
  <Color.Item name="oklch" value="oklch(70% 0.2 145)" />
</Color>
```

## Theme-aware colors

Define different colors for light and dark modes using an object with `light` and `dark` properties.

<Color>
  <Color.Item name="bg-primary" />

  <Color.Item name="bg-secondary" />

  <Color.Item name="text-primary" />
</Color>

```mdx Theme-aware example theme={null}
<Color variant="compact">
  <Color.Item name="bg-primary" value={{ light: "#FFFFFF", dark: "#000000" }} />
  <Color.Item name="bg-secondary" value={{ light: "#F9FAFB", dark: "#0A0A0A" }} />
  <Color.Item name="text-primary" value={{ light: "#111827", dark: "#F9FAFB" }} />
</Color>
```

## Properties

### Color

<ResponseField name="variant" type="string">
  Display style for the color palette. Options: `compact` or `table`.
</ResponseField>

<ResponseField name="children" type="Color.Item | Color.Row">
  Color items or rows to display.
</ResponseField>

### Color.Row

<ResponseField name="title" type="string">
  Label for the row of colors.
</ResponseField>

<ResponseField name="children" type="Color.Item">
  Color items to display in the row.
</ResponseField>

### Color.Item

<ResponseField name="name" type="string">
  Name or label for the color.
</ResponseField>

<ResponseField name="value" type="string | { light: string, dark: string }">
  Color value in any CSS format, or an object with light and dark mode values.
</ResponseField>


# Columns
Source: https://www.mintlify.com/docs/components/columns

Arrange cards and other components in a responsive multi-column grid layout with the columns component, including customizable column counts.

The `Columns` component lets you arrange content in a responsive grid layout. It's most often used to put cards in a grid, by specifying the number of grid columns. You can also use the `Column` sub-component to wrap arbitrary content. Columns are responsive and automatically adjust for smaller screens.

<Columns>
  <Card title="Get started" icon="rocket">
    Set up your project with our quickstart guide.
  </Card>

  <Card title="API reference" icon="code">
    Explore endpoints, parameters, and examples for your API.
  </Card>
</Columns>

```mdx Columns example theme={null}
<Columns cols={2}>
  <Card title="Get started">
    Set up your project with our quickstart guide.
  </Card>
  <Card title="API reference">
    Explore endpoints, parameters, and examples for your API.
  </Card>
</Columns>
```

## Column sub-component

Use the `Column` component to wrap text or code in individual columns. This is useful when you want to display arbitrary content side by side, not just cards or other components.

<Columns>
  <Column>
    **Installation**

    ```bash theme={null}
    npm install my-package
    ```
  </Column>

  <Column>
    **Usage**

    ```javascript theme={null}
    import { init } from 'my-package';
    init();
    ```
  </Column>
</Columns>

````mdx Column sub-component example theme={null}
<Columns cols={2}>
  <Column>

  **Installation**

  ```bash
  npm install my-package
  ```

  </Column>
  <Column>

  **Usage**

  ```javascript
  import { init } from 'my-package';
  init();
  ```

  </Column>
</Columns>
````

## Properties

<ResponseField name="cols" type="number">
  The number of columns per row. Accepts values from 1 to 4.
</ResponseField>


# Examples
Source: https://www.mintlify.com/docs/components/examples

Display code examples in the right sidebar panel on desktop devices to show request and response samples alongside API documentation.

The `<RequestExample>` and `<ResponseExample>` components display code blocks in the right sidebar to create a two-column layout that keeps examples visible while users scroll through your content. Use these components for API documentation, but they work on all pages.

Common use cases:

* API endpoint documentation with request and response examples
* Configuration examples alongside explanatory text
* Code samples that users reference while following instructions
* Before and after examples in tutorials

On mobile devices, `<RequestExample>` and `<ResponseExample>` components display as regular code blocks that users can scroll past.

<RequestExample>
  ```bash Request theme={null}
  curl --request POST \
    --url https://dog-api.kinduff.com/api/facts
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  { "status": "success" }
  ```
</ResponseExample>

## RequestExample

Use `<RequestExample>` to pin code examples in the right sidebar. This component works similarly to the [CodeGroup](/docs/components/code-groups) component, but displays the code in the sidebar instead of inline.

You can include multiple code blocks inside a single `<RequestExample>`. Each code block must have a title attribute.

````mdx RequestExample theme={null}
<RequestExample>

```bash Request
curl --request POST \
  --url https://dog-api.kinduff.com/api/facts
```

</RequestExample>
````

## ResponseExample

The `<ResponseExample>` component pins code examples in the right sidebar beneath any `<RequestExample>` content on the same page.

````mdx ResponseExample theme={null}
<ResponseExample>

```json Response
{ "status": "success" }
```

</ResponseExample>
````

## Properties

Both `<RequestExample>` and `<ResponseExample>` accept the following properties:

<ResponseField name="dropdown" type="boolean">
  Display a language dropdown menu for switching between code blocks, instead of the default tab layout.
</ResponseField>


# Expandables
Source: https://www.mintlify.com/docs/components/expandables

Use the expandable component to toggle nested object properties in API documentation, showing child fields for request and response objects.

Use expandables to show and hide nested content within response fields. They are particularly useful for displaying complex object properties in API documentation.

<ResponseField name="user" type="User Object">
  <Expandable title="properties">
    <ResponseField name="full_name" type="string">
      The full name of the user
    </ResponseField>

    <ResponseField name="is_over_21" type="boolean">
      Whether the user is over 21 years old
    </ResponseField>
  </Expandable>
</ResponseField>

```mdx Expandable example theme={null}
<ResponseField name="user" type="User Object">
  <Expandable title="properties">
    <ResponseField name="full_name" type="string">
      The full name of the user
    </ResponseField>

    <ResponseField name="is_over_21" type="boolean">
      Whether the user is over 21 years old
    </ResponseField>
  </Expandable>
</ResponseField>
```

## Properties

<ResponseField name="title" type="string">
  The name of the object you are showing.
</ResponseField>

<ResponseField name="defaultOpen" type="boolean">
  Set to `true` for the expandable to open when the page loads
</ResponseField>


# Fields
Source: https://www.mintlify.com/docs/components/fields

Use ParamField and ResponseField components to document API request and response parameters with types, defaults, and validation rules.

Use fields to document API parameters and responses. There are two types of fields: parameter fields and response fields.

## Parameter field

Use the `<ParamField>` component to define parameters for your APIs or SDKs. Adding a `ParamField` automatically adds an [API Playground](/docs/api-playground/overview).

<ParamField type="string">
  An example of a parameter field
</ParamField>

```mdx theme={null}
<ParamField path="param" type="string" required>
  An example of a parameter field
</ParamField>
```

### Properties

<ParamField type="string">
  Whether the parameter is a query, path, body, or header. Followed by the
  parameter name.
</ParamField>

<ParamField type="string">
  Expected type of the parameter's value.

  Supports `number`, `string`, `boolean`, `object`.

  Define arrays using the `[]` suffix. For example `string[]`.
</ParamField>

<ParamField type="boolean">
  Indicate whether you require the parameter.
</ParamField>

<ParamField type="boolean">
  Indicate whether you have deprecated the parameter.
</ParamField>

<ParamField type="any">
  Default value populated when the request value is empty
</ParamField>

<ParamField type="string">
  Placeholder text for the input in the playground.
</ParamField>

<ParamField type="string">
  Description of the parameter (Markdown-enabled).
</ParamField>

## Response field

The `<ResponseField>` component defines the return values of an API.

<ResponseField name="response" type="string">
  An example of a response field
</ResponseField>

```mdx theme={null}
<ResponseField name="response" type="string" required>
  A response field example
</ResponseField>
```

### Properties

<ResponseField name="name" type="string">
  The name of the response value.
</ResponseField>

<ResponseField name="type" type="string">
  Expected type of the response value. This can be any arbitrary string.
</ResponseField>

<ResponseField name="default" type="string">
  The default value.
</ResponseField>

<ResponseField name="required" type="boolean">
  Indicate whether you require the response.
</ResponseField>

<ResponseField name="deprecated" type="boolean">
  Whether you have deprecated a field.
</ResponseField>

<ResponseField name="pre" type="string[]">
  Labels that appear before the name of the field.
</ResponseField>

<ResponseField name="post" type="string[]">
  Labels that appear after the name of the field.
</ResponseField>


# Frames
Source: https://www.mintlify.com/docs/components/frames

Wrap images, videos, and other components with the frame component to add styled borders, captions, and visual emphasis to your content.

Use frames to display images, diagrams, videos, or other visual content with consistent styling and optional captions. Frames center content and provide visual separation from surrounding text.

<Frame>
  <img alt="Photograph of a lake surrounded by trees with mountains in the distance in Yellowstone National Park." />
</Frame>

## Captions

Add additional context to an image using the optional `caption` prop. Captions appear in the frame below the image.

<Frame>
  <img alt="Photograph of Yosemite Valley." />
</Frame>

### Markdown in captions

Captions support Markdown formatting, including links and bold text.

<Frame>
  <img alt="Photograph of Yosemite Valley." />
</Frame>

<Frame>
  <img alt="Photograph of a lake surrounded by trees with mountains in the distance in Yellowstone National Park." />
</Frame>

## Hints

Add text that precedes the frame using the optional `hint` prop. Hints appear before the frame.

<Frame>
  <img alt="Photograph of a lake surrounded by trees with mountains in the distance in Yellowstone National Park." />
</Frame>

## Videos

When you place a `video` element with `autoPlay` inside a frame, the frame adds `playsInline`, `loop`, and `muted` attributes.

```mdx Video with autoPlay theme={null}
<Frame caption="Product demo">
  <video autoPlay src="/path/to/video.mp4" />
</Frame>
```

Videos without `autoPlay` do not have any additional attributes added by default.

## Properties

<ResponseField name="caption" type="string">
  Text that appears as part of the frame, centered below the content. Supports Markdown formatting including links and bold text.
</ResponseField>

<ResponseField name="hint" type="string">
  Text that precedes the frame.
</ResponseField>

<CodeGroup>
  ```mdx Frame theme={null}
  <Frame>
    <img src="/path/image.jpg" alt="Descriptive alt text" />
  </Frame>
  ```

  ```mdx Frame with a caption theme={null}
  <Frame caption="Caption text">
    <img src="/path/image.jpg" alt="Descriptive alt text" />
  </Frame>
  ```

  ```mdx Frame with markdown in caption theme={null}
  <Frame caption="Visit the [documentation](/docs) for more details">
    <img src="/path/image.jpg" alt="Descriptive alt text" />
  </Frame>
  ```

  ```mdx Frame with bold text and links in caption theme={null}
  <Frame caption="**Note:** See the [official guide](https://example.com) for setup instructions">
    <img src="/path/image.jpg" alt="Descriptive alt text" />
  </Frame>
  ```

  ```mdx Frame with a hint theme={null}
  <Frame hint="Hint text">
    <img src="/path/image.jpg" alt="Descriptive alt text" />
  </Frame>
  ```

  ```mdx Frame with both hint and caption theme={null}
  <Frame hint="Hint text" caption="Caption text">
    <img src="/path/image.jpg" alt="Descriptive alt text" />
  </Frame>
  ```
</CodeGroup>


# GitHub
Source: https://www.mintlify.com/docs/components/github

Use the GitHub component to embed a public repository card with a live description, star count, and fork count on any documentation page.

Use the `<GitHub.Repo>` component to embed a card that links to a public GitHub repository. The card fetches the repository's description, star count, and fork count from the public GitHub API when the page loads.

## Basic repository card

Pass a repository as either an `owner/name` slug or a full GitHub URL.

<GitHub.Repo />

```mdx react theme={null}
<GitHub.Repo repo="mintlify/docs" />
```

## Variants

Choose between the `inset` and `flat` layouts to match the surrounding page.

### Inset

The default variant. Wraps the repository details in a rounded inner surface.

<GitHub.Repo />

```mdx theme={null}
<GitHub.Repo repo="mintlify/docs" variant="inset" />
```

### Flat

A single-surface layout with tighter padding. Use `flat` when embedding the card next to other bordered elements.

<GitHub.Repo />

```mdx theme={null}
<GitHub.Repo repo="mintlify/docs" variant="flat" />
```

## Properties

<ResponseField name="repo" type="string">
  The GitHub repository to display. Accepts an `owner/name` slug (for example, `mintlify/docs`) or a full GitHub URL (for example, `https://github.com/mintlify/docs`).
</ResponseField>

<ResponseField name="variant" type="string">
  Card layout.

  Options: `inset`, `flat`.
</ResponseField>

<ResponseField name="className" type="string">
  Additional CSS classes to apply to the card.
</ResponseField>


# Icons
Source: https://www.mintlify.com/docs/components/icons

Add icons from Font Awesome, Lucide, Tabler, or custom sources to your documentation pages using the icon component with size and color options.

Use icons from Font Awesome, Lucide, Tabler, SVGs, external URLs, or files in your project to enhance your documentation.

<Icon icon="flag" />

```mdx Icon example theme={null}
<Icon icon="flag" size={32} />
```

## Custom image icons

Use the `src` prop to display a custom image as an icon. The image can be a file in your project or an externally hosted URL.

```mdx Custom image icon examples theme={null}
<Icon src="/images/my-icon.svg" />

<Icon src="https://example.com/icon.png" />
```

## Inline icons

Icons appear inline when used within a sentence, paragraph, or heading. <Icon icon="flag" /> Use icons for decoration or to add visual emphasis.

```markdown Inline icon example theme={null}
Icons appear inline when used within a sentence, paragraph, or heading. <Icon icon="flag" iconType="solid" /> Use icons for decoration or to add visual emphasis.
```

## Properties

<Info>
  You must include one of `icon` or `src`.
</Info>

<ResponseField name="icon" type="string">
  The icon to display from an icon library.

  Options:

  * [Font Awesome icon](https://fontawesome.com/icons) name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
  * [Lucide icon](https://lucide.dev/icons) name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
  * [Tabler icon](https://tabler.io/icons) name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
</ResponseField>

<ResponseField name="src" type="string">
  Path or URL to an image to use as the icon. Use `src` instead of `icon` when you want to use a custom image rather than an icon from a library.

  Options:

  * Path to an image file in your project (for example, `/images/my-icon.svg`)
  * URL to an externally hosted image (for example, `https://example.com/icon.png`)
</ResponseField>

<ResponseField name="iconType" type="string">
  The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

  Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>

<ResponseField name="color" type="string">
  The color of the icon as a hex code (for example, `#FF5733`).
</ResponseField>

<ResponseField name="size" type="number">
  The size of the icon in pixels.
</ResponseField>

<ResponseField name="className" type="string">
  Custom CSS class name to apply to the icon.
</ResponseField>


# Components overview
Source: https://www.mintlify.com/docs/components/index

Browse the full Mintlify component library for layout, emphasis, API documentation, and navigation elements available in your MDX pages.

Mintlify provides built-in MDX components for your documentation pages. Use these components to structure content, draw attention to important information, document APIs, and guide navigation.

## Structure your content

<Card title="Tabs" icon="folder" href="/components/tabs">
  Organize related content into switchable tabbed views.
</Card>

<Card title="Code groups" icon="code" href="/components/code-groups">
  Display code examples in multiple languages.
</Card>

<Card title="Steps" icon="list-ordered" href="/components/steps">
  Display sequential instructions in a numbered format.
</Card>

<Card title="Columns" icon="columns-3" href="/components/columns">
  Arrange content side by side in responsive layouts.
</Card>

<Card title="Panel" icon="panel-right" href="/components/panel">
  Create sidebar panels for supplementary content.
</Card>

## Draw attention

<Card title="Callouts" icon="message-square-warning" href="/components/callouts">
  Emphasize important information with styled alerts.
</Card>

<Card title="Banner" icon="flag" href="/components/banner">
  Display prominent announcements at the top of pages.
</Card>

<Card title="Badge" icon="award" href="/components/badge">
  Add inline labels and status indicators.
</Card>

<Card title="Update" icon="bell" href="/components/update">
  Highlight new or updated content.
</Card>

<Card title="Frames" icon="frame" href="/components/frames">
  Add borders and styling to images and content.
</Card>

<Card title="Tooltips" icon="message-circle" href="/components/tooltips">
  Display additional information on hover.
</Card>

## Showcase AI prompts

<Card title="Prompt" icon="sparkles" href="/components/prompt">
  Display copyable AI prompts with Cursor integration.
</Card>

## Show and hide content

<Card title="Accordions" icon="chevron-down" href="/components/accordions">
  Expandable sections for progressive disclosure of content.
</Card>

<Card title="Expandables" icon="chevrons-down" href="/components/expandables">
  Show and hide detailed content on demand.
</Card>

<Card title="View" icon="eye" href="/components/view">
  Conditionally show content based on context.
</Card>

<Card title="Visibility" icon="eye-off" href="/components/visibility">
  Control content shown to humans versus AI agents.
</Card>

## Document your API

<Card title="Fields" icon="text-cursor-input" href="/components/fields">
  Display parameter and property definitions.
</Card>

<Card title="Responses" icon="arrow-left-right" href="/components/responses">
  Document API response structures and fields.
</Card>

<Card title="Examples" icon="file-code" href="/components/examples">
  Show request and response examples side by side.
</Card>

## Link to other pages

<Card title="Cards" icon="square" href="/components/cards">
  Highlight content with customizable containers and icons.
</Card>

<Card title="Tiles" icon="layout-grid" href="/components/tiles">
  Display content in a grid of clickable tiles.
</Card>

## Add visual context

<Card title="Icons" icon="smile" href="/components/icons">
  Add visual indicators using the Lucide icon library.
</Card>

<Card title="Mermaid diagrams" icon="git-branch" href="/components/mermaid-diagrams">
  Create flowcharts, sequence diagrams, and more.
</Card>

<Card title="Color" icon="palette" href="/components/color">
  Display color swatches with hex values.
</Card>

<Card title="Tree" icon="folder-tree" href="/components/tree">
  Display hierarchical file and folder structures.
</Card>

<Card title="GitHub" icon="github" href="/components/github">
  Embed a GitHub repository card with live stars and forks.
</Card>


# Mermaid
Source: https://www.mintlify.com/docs/components/mermaid-diagrams

Create flowcharts, sequence diagrams, and other visualizations in your documentation using Mermaid syntax with automatic rendering.

[Mermaid](https://mermaid.js.org/) lets you build flowcharts, sequence diagrams, Gantt charts, and other diagrams using text and code.

For a complete list of supported diagram types and syntax, see the [Mermaid documentation](https://mermaid.js.org/intro/).

```mermaid placement="top-right" theme={null}
  flowchart LR
    subgraph subgraph1
        direction TB
        top1[top] --> bottom1[bottom]
    end
    subgraph subgraph2
        direction TB
        top2[top] --> bottom2[bottom]
    end
    %% ^ These subgraphs are identical, except for the links to them:

    %% Link *to* subgraph1: subgraph1 direction is maintained
    outside --> subgraph1
    %% Link *within* subgraph2:
    %% subgraph2 inherits the direction of the top-level graph (LR)
    outside ---> top2
```

````mdx Mermaid flowchart example theme={null}
```mermaid placement="top-right"
  flowchart LR
    subgraph subgraph1
        direction TB
        top1[top] --> bottom1[bottom]
    end
    subgraph subgraph2
        direction TB
        top2[top] --> bottom2[bottom]
    end
    %% ^ These subgraphs are identical, except for the links to them:

    %% Link *to* subgraph1: subgraph1 direction is maintained
    outside --> subgraph1
    %% Link *within* subgraph2:
    %% subgraph2 inherits the direction of the top-level graph (LR)
    outside ---> top2
```
````

## ELK layout support

Mintlify supports the [ELK (Eclipse Layout Kernel)](https://www.eclipse.org/elk/) layout engine for Mermaid diagrams. ELK optimizes arrangement to reduce overlapping and improve readability, which is useful for large or complex diagrams.

To use ELK layout in your Mermaid diagrams, add the `%%{init: {'flowchart': {'defaultRenderer': 'elk'}}}%%` directive at the beginning of your diagram:

````mdx ELK layout example theme={null}
```mermaid
%%{init: {'flowchart': {'defaultRenderer': 'elk'}}}%%
flowchart LR
    A[Start] --> B[Process 1]
    B --> C[Process 2]
    B --> D[Process 3]
    C --> E[End]
    D --> E
```
````

## Interactive controls

All Mermaid diagrams include interactive zoom and pan controls. By default, controls appear when the diagram height exceeds 120px.

* **Zoom in/out**: Use the zoom buttons to increase or decrease the diagram scale.
* **Pan**: Use the directional arrows to move around the diagram.
* **Reset view**: Click the reset button to return to the original view.

The controls are especially useful for large or complex diagrams that don't fit entirely in the viewport.

## Properties

<ResponseField name="actions" type="boolean">
  Show or hide the interactive controls. When set, this overrides the default behavior (controls shown when diagram height exceeds 120px).
</ResponseField>

<ResponseField name="placement" type="string">
  Position of the interactive controls. Options: `top-left`, `top-right`, `bottom-left`, `bottom-right`.
</ResponseField>

### Examples

Hide controls on a diagram:

````mdx theme={null}
```mermaid actions={false}
flowchart LR
    A --> B
```
````

Show controls in the top-left corner:

````mdx theme={null}
```mermaid placement="top-left"
flowchart LR
    A --> B
```
````

Combine both properties:

````mdx theme={null}
```mermaid placement="top-left" actions={true}
flowchart LR
    A --> B
```
````

## Syntax

To create a Mermaid diagram, write your diagram definition inside a Mermaid code block.

````mdx theme={null}
```mermaid
// Your mermaid diagram code here
```
````


# Panel
Source: https://www.mintlify.com/docs/components/panel

Customize the right side panel content on documentation pages to display supplementary information, examples, or navigation elements.

You can use the `<Panel>` component to customize the right side panel of a page with any components that you want.

If a page has a `<Panel>` component, any [RequestExample](/docs/components/examples#requestexample) and [ResponseExample](/docs/components/examples#responseexample) components must be inside `<Panel>`.

The components in a `<Panel>` replace a page's table of contents. Page modes that suppress the table of contents (`mode: "wide"`, `mode: "center"`, and `mode: "custom"`) also suppress the `<Panel>` component.

```mdx theme={null}
<Panel>
  <Info>Pin info to the side panel. Or add any other component.</Info>
</Panel>
```

<Panel>
  <Info>Pin info to the side panel. Or add any other component.</Info>
</Panel>


# Prompt
Source: https://www.mintlify.com/docs/components/prompt

Display pre-built AI prompts with one-click copy and Cursor integration buttons so users can quickly use prompts in their AI tools.

Use the Prompt component to display pre-built AI prompts that users can copy to their clipboard or open directly in [Cursor](https://www.cursor.com).

## Examples

<Prompt description="Generate clear, concise documentation.">
  You are a **technical writing assistant**. Write documentation that is clear, accurate, and concise.

  * Use second-person voice ("you") and active verbs.
  * Start procedures with a goal-oriented heading.
  * Before writing, ask clarifying questions about the end users of the documentation, their goals, and their needs.
</Prompt>

```mdx Basic prompt example theme={null}
<Prompt description="Generate clear, concise documentation.">
You are a **technical writing assistant**. Write documentation that is clear, accurate, and concise.
- Use second-person voice ("you") and active verbs.
- Start procedures with a goal-oriented heading.
- Before writing, ask clarifying questions about the end users of the documentation, their goals, and their needs.
</Prompt>
```

<Prompt description="Generate **clear**, *concise* documentation." icon="paperclip">
  You are a **technical writing assistant**. Write documentation that is clear, accurate, and concise.

  * Use second-person voice ("you") and active verbs.
  * Start procedures with a goal-oriented heading.
  * Before writing, ask clarifying questions about the end users of the documentation, their goals, and their needs.
</Prompt>

```mdx Prompt with multiple properties example theme={null}
<Prompt
  description="Generate **clear**, *concise* documentation."
  icon="paperclip"
  iconType="solid"
  actions={["copy", "cursor"]}
>
You are a **technical writing assistant**. Write documentation that is clear, accurate, and concise.
- Use second-person voice ("you") and active verbs.
- Start procedures with a goal-oriented heading.
- Before writing, ask clarifying questions about the end users of the documentation, their goals, and their needs.
</Prompt>
```

## Properties

<ResponseField name="description" type="string">
  The text displayed in the prompt card. Supports Markdown formatting.
</ResponseField>

<ResponseField name="children" type="string">
  The text content of the prompt. This is the text copied to the clipboard or opened in Cursor.
</ResponseField>

<ResponseField name="actions" type="array">
  Array of available actions. Valid values are `"copy"` (copy to clipboard) and `"cursor"` (open in Cursor).
</ResponseField>

<ResponseField name="icon" type="string">
  The icon to display.

  Options:

  * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
  * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
  * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
  * URL to an externally hosted icon
  * Path to an icon file in your project
  * SVG code wrapped in curly braces

  For custom SVG icons:

  1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
  2. Paste your SVG code into the SVG input field.
  3. Copy the complete `<svg>...</svg>` element from the JSX output field.
  4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
  5. Adjust `height` and `width` as needed.
</ResponseField>

<ResponseField name="iconType" type="string">
  The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

  Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>


# Response fields
Source: https://www.mintlify.com/docs/components/responses

Document API response fields using the ResponseField component with type annotations, descriptions, and required or optional indicators.

Use the `<ResponseField>` component to define the return values of an API. Many docs also use `<ResponseField>` on pages when you need to list the types of something.

<ResponseField name="response" type="string">
  A response field example
</ResponseField>

```mdx theme={null}
<ResponseField name="response" type="string" required>
  A response field example
</ResponseField>
```

## Props

<ResponseField name="name" type="string">
  The name of the response value.
</ResponseField>

<ResponseField name="type" type="string">
  Expected type of the response value - this can be any arbitrary string.
</ResponseField>

<ResponseField name="default" type="string">
  The default value.
</ResponseField>

<ResponseField name="required" type="boolean">
  Show "required" beside the field name.
</ResponseField>

<ResponseField name="deprecated" type="boolean">
  Whether you have deprecated a field or not.
</ResponseField>

<ResponseField name="pre" type="string[]">
  Labels that appear before the name of the field
</ResponseField>

<ResponseField name="post" type="string[]">
  Labels that appear after the name of the field
</ResponseField>

<RequestExample>
  ```mdx Response Field Example theme={null}
  <ResponseField name="response" type="string" required>
    A response field example
  </ResponseField>
  ```
</RequestExample>


# Steps
Source: https://www.mintlify.com/docs/components/steps

Create numbered step-by-step procedures with the steps component to guide users through sequential tasks, tutorials, and setup workflows.

Use steps to display a series of sequential actions or events. You can add as many steps as needed.

<Steps>
  <Step title="First Step">
    These are instructions or content that only pertain to the first step.
  </Step>

  <Step title="Second Step">
    These are instructions or content that only pertain to the second step.
  </Step>

  <Step title="Third Step">
    These are instructions or content that only pertain to the third step.
  </Step>
</Steps>

```mdx Steps example theme={null}
<Steps>
  <Step title="First Step">
    These are instructions or content that only pertain to the first step.
  </Step>
  <Step title="Second Step">
    These are instructions or content that only pertain to the second step.
  </Step>
  <Step title="Third Step">
    These are instructions or content that only pertain to the third step.
  </Step>
</Steps>
```

## Steps properties

<ResponseField name="children" type="ReactElement<StepProps>[]">
  A list of `Step` components.
</ResponseField>

<ResponseField name="titleSize" type="string">
  The size of the step titles. One of `p`, `h2`, `h3`, and `h4`.
</ResponseField>

## Individual step properties

<ResponseField name="title" type="string">
  The title is the primary text for the step and shows up next to the indicator.
</ResponseField>

<ResponseField name="children" type="string | ReactNode">
  The content of a step either as plain text or components.
</ResponseField>

<ResponseField name="icon" type="string">
  The icon to display.

  Options:

  * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
  * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
  * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
  * URL to an externally hosted icon
  * Path to an icon file in your project
  * SVG code wrapped in curly braces

  For custom SVG icons:

  1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
  2. Paste your SVG code into the SVG input field.
  3. Copy the complete `<svg>...</svg>` element from the JSX output field.
  4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
  5. Adjust `height` and `width` as needed.
</ResponseField>

<ResponseField name="iconType" type="string">
  The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

  Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>

<ResponseField name="stepNumber" type="number">
  The number of the step.
</ResponseField>

<ResponseField name="titleSize" type="string">
  The size of the step titles. One of `p`, `h2`, `h3`, and `h4`.
</ResponseField>

<ResponseField name="id" type="string">
  A custom ID for the step, used for anchor linking and table of contents navigation.
</ResponseField>

<ResponseField name="noAnchor" type="boolean">
  Whether to hide the anchor link for the step.
</ResponseField>


# Tabs
Source: https://www.mintlify.com/docs/components/tabs

Use the tab component to organize content into switchable panels for showing different options, platform versions, or language examples.

Use tabs to organize content into multiple panels that users can switch between. You can add any number of tabs and include other components inside each tab.

<Tabs>
  <Tab title="First tab">
    ☝️ Welcome to the content that you can only see inside the first tab.

    You can add any number of components inside of tabs. For example, a code block:

    ```java HelloWorld.java theme={null}
      class HelloWorld {
          public static void main(String[] args) {
              System.out.println("Hello, World!");
          }
      }
    ```
  </Tab>

  <Tab title="Second tab" icon="leaf">
    ✌️ Here's content that's only inside the second tab.

    This one has a <Icon icon="leaf" /> icon!
  </Tab>

  <Tab title="Third tab">
    💪 Here's content that's only inside the third tab.
  </Tab>
</Tabs>

````mdx Tabs example theme={null}
<Tabs>
  <Tab title="First tab">
    ☝️ Welcome to the content that you can only see inside the first tab.

    You can add any number of components inside of tabs. For example, a code block:
    ```java HelloWorld.java
      class HelloWorld {
          public static void main(String[] args) {
              System.out.println("Hello, World!");
          }
      }
    ```
  </Tab>
  <Tab title="Second tab" icon="leaf">
    ✌️ Here's content that's only inside the second tab.

    This one has a <Icon icon="leaf" /> icon!
  </Tab>
  <Tab title="Third tab">
    💪 Here's content that's only inside the third tab.
  </Tab>
</Tabs>
````

Tabs with matching titles stay in sync across the page. For example, if you have multiple tab groups that include a `JavaScript` tab title, selecting `JavaScript` in one tab group automatically selects `JavaScript` in the others. This helps users who choose a language or framework once see that choice reflected everywhere. Tabs also sync with [code groups](/docs/components/code-groups) that have matching titles.

To disable tab synchronization, add `sync={false}` to a `<Tabs>` component.

```mdx Disable tab sync example theme={null}
<Tabs sync={false}>
  <Tab title="First tab">
    This tab group operates independently.
  </Tab>
  <Tab title="Second tab">
    Selecting tabs here won't affect other tab groups.
  </Tab>
</Tabs>
```

## Tabs properties

Set these properties on the `<Tabs>` wrapper component.

<ResponseField name="defaultTabIndex" type="number">
  The index of the tab to display by default (zero-based). For example, set to `1` to show the second tab on page load.
</ResponseField>

<ResponseField name="sync" type="boolean">
  When `true`, tabs synchronize with other tabs and code groups on the page that have matching titles. Set to `false` to make tabs independent.
</ResponseField>

<ResponseField name="borderBottom" type="boolean">
  Adds a bottom border and padding to the tabs container. Useful to visually separate tabbed content from the rest of the page, especially when tabs contain content of varying lengths.
</ResponseField>

## Tab properties

Set these properties on each individual `<Tab>` component.

<ResponseField name="title" type="string">
  The title of the tab. Short titles are easier to navigate. Tabs with matching titles synchronize their selections.
</ResponseField>

<ResponseField name="id" type="string">
  A custom ID for the tab used for anchor linking. If not provided, defaults to the same value as `title`.
</ResponseField>

<ResponseField name="icon" type="string">
  A [Font Awesome](https://fontawesome.com/icons) icon, [Lucide](https://lucide.dev/icons) icon, URL to an icon, or relative path to an icon.
</ResponseField>

<ResponseField name="iconType" type="string">
  For Font Awesome icons only: One of `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>


# Tiles
Source: https://www.mintlify.com/docs/components/tiles

Use the tiles component to display visual previews with image thumbnails, titles, and descriptions in a responsive grid layout for your docs.

Use tiles to create visual showcase elements with a patterned background, title, and description. Tiles are ideal for displaying component previews, feature highlights, or navigation items in a grid layout.

<Tile href="/components/tiles" title="Tile title" description="Short description">
  <img alt="Tile preview placeholder" />

  <img alt="Tile preview placeholder (dark mode)" />
</Tile>

```mdx Tile example theme={null}
<Tile href="/your-link" title="Tile title" description="Short description">
  <img src="/images/your-preview-light.svg" alt="Tile preview" className="block dark:hidden" />
  <img src="/images/your-preview-dark.svg" alt="Tile preview (dark mode)" className="hidden dark:block" />
</Tile>
```

Tiles can contain any image, SVG, or other React node that you want to display in the preview area. Provide separate light and dark mode assets using the `block dark:hidden` and `hidden dark:block` utility classes so the preview matches the active theme.

The tile preview area is a fixed-height, responsive container.

* **Aspect ratio**: Use a 16:9 or 4:3 landscape ratio.
* **Dimensions**: Design for at least 800×450 pixels.
* **Format**: Prefer SVG for illustrations, UI mockups, and diagrams. Use WebP or PNG for photographs and screenshots.
* **File size**: Keep each asset under 200 KB to preserve page load performance, especially in multi-tile grids.
* **Padding**: Include any surrounding padding in the asset. The tile does not add internal margin around the child image.

## Grid layout

Combine tiles with the [columns component](/docs/components/columns) to create a responsive grid of visual previews.

<Columns>
  <Tile href="/components/tiles" title="Tile one" description="Short description">
    <img alt="Tile preview placeholder" />

    <img alt="Tile preview placeholder (dark mode)" />
  </Tile>

  <Tile href="/components/tiles" title="Tile two" description="Short description">
    <img alt="Tile preview placeholder" />

    <img alt="Tile preview placeholder (dark mode)" />
  </Tile>

  <Tile href="/components/tiles" title="Tile three" description="Short description">
    <img alt="Tile preview placeholder" />

    <img alt="Tile preview placeholder (dark mode)" />
  </Tile>
</Columns>

```mdx Grid layout example theme={null}
<Columns cols={3}>
  <Tile href="/link-one" title="Tile one" description="Short description">
    <img src="/images/preview-one-light.svg" alt="Tile preview" className="block dark:hidden" />
    <img src="/images/preview-one-dark.svg" alt="Tile preview (dark mode)" className="hidden dark:block" />
  </Tile>
  <Tile href="/link-two" title="Tile two" description="Short description">
    <img src="/images/preview-two-light.svg" alt="Tile preview" className="block dark:hidden" />
    <img src="/images/preview-two-dark.svg" alt="Tile preview (dark mode)" className="hidden dark:block" />
  </Tile>
  <Tile href="/link-three" title="Tile three" description="Short description">
    <img src="/images/preview-three-light.svg" alt="Tile preview" className="block dark:hidden" />
    <img src="/images/preview-three-dark.svg" alt="Tile preview (dark mode)" className="hidden dark:block" />
  </Tile>
</Columns>
```

## Properties

<ResponseField name="href" type="string">
  URL to navigate to when users click the tile.
</ResponseField>

<ResponseField name="title" type="string">
  The title displayed below the tile preview.
</ResponseField>

<ResponseField name="description" type="string">
  A short description displayed below the title.
</ResponseField>

<ResponseField name="children" type="React.ReactNode">
  Content displayed inside the tile preview area, typically images or SVGs.
</ResponseField>


# Tooltips
Source: https://www.mintlify.com/docs/components/tooltips

Add tooltips to display contextual definitions and explanations when users hover over terms, abbreviations, or technical concepts in your documentation.

Use tooltips to provide additional context or definitions when a user hovers over a string of text. Tooltips can include optional call-to-action links.

**Example**: <Tooltip href="/api-reference">API</Tooltip> documentation helps developers understand how to integrate with your service.

```mdx Tooltip example wrap theme={null}
<Tooltip headline="API" tip="Application Programming Interface: a set of protocols for software applications to communicate." cta="Read our API guide" href="/api-reference">API</Tooltip> documentation helps developers understand how to integrate with your service.
```

## Properties

<ResponseField name="tip" type="string">
  The text displayed in the tooltip.
</ResponseField>

<ResponseField name="headline" type="string">
  Text displayed before the `tip` text.
</ResponseField>

<ResponseField name="cta" type="string">
  The call-to-action text for a link within the tooltip.
</ResponseField>

<ResponseField name="href" type="string">
  URL for the call-to-action link. Required when using `cta`.
</ResponseField>


# Tree
Source: https://www.mintlify.com/docs/components/tree

Use the tree component to display hierarchical file and folder structures with collapsible nodes and syntax highlighting for path names.

Use tree components to display hierarchical structures like file systems, project directories, or nested content. The tree component supports keyboard navigation and accessibility features.

Create trees with either a Markdown list or the `Tree.Folder` and `Tree.File` components. `<Tree>` and `<FileTree>` are aliases, so either tag works with either syntax.

Use the Markdown list syntax for quick, static trees where every folder can expand by default. Use the component syntax when you need to control open state per folder with `defaultOpen`, mark folders as non-interactive with `openable`, or mix files and folders at arbitrary depth.

## Markdown list syntax

Write a nested Markdown list inside `<FileTree>` (or `<Tree>`) to describe a folder structure. Add a trailing slash to mark a folder, or nest items under it. Folders that contain nested items expand by default.

<FileTree>
  * docs/
    * index.mdx
    * guides/
      * configuration.mdx
  * docs.config.ts
</FileTree>

```mdx File tree example theme={null}
<FileTree>

- docs/
  - index.mdx
  - guides/
    - configuration.mdx
- docs.config.ts

</FileTree>
```

Leave a blank line after the opening tag and before the closing tag so that the list parses as Markdown. Names strip inline formatting like `` `code` ``, `**bold**`, or `_italic_`.

## Basic tree

<Tree>
  <Tree.Folder name="app">
    <Tree.File name="layout.tsx" />

    <Tree.File name="page.tsx" />

    <Tree.File name="global.css" />
  </Tree.Folder>

  <Tree.Folder name="lib">
    <Tree.File name="utils.ts" />

    <Tree.File name="db.ts" />
  </Tree.Folder>

  <Tree.File name="package.json" />

  <Tree.File name="tsconfig.json" />
</Tree>

```mdx Tree example theme={null}
<Tree>
  <Tree.Folder name="app" defaultOpen>
    <Tree.File name="layout.tsx" />
    <Tree.File name="page.tsx" />
    <Tree.File name="global.css" />
  </Tree.Folder>
  <Tree.Folder name="lib">
    <Tree.File name="utils.ts" />
    <Tree.File name="db.ts" />
  </Tree.Folder>
  <Tree.File name="package.json" />
  <Tree.File name="tsconfig.json" />
</Tree>
```

## Nested folders

Create deeply nested structures by nesting `Tree.Folder` components within each other.

<Tree>
  <Tree.Folder name="app">
    <Tree.File name="layout.tsx" />

    <Tree.File name="page.tsx" />

    <Tree.Folder name="api">
      <Tree.Folder name="auth">
        <Tree.File name="route.ts" />
      </Tree.Folder>

      <Tree.File name="route.ts" />
    </Tree.Folder>

    <Tree.Folder name="components">
      <Tree.File name="button.tsx" />

      <Tree.File name="dialog.tsx" />

      <Tree.File name="tabs.tsx" />
    </Tree.Folder>
  </Tree.Folder>

  <Tree.File name="package.json" />
</Tree>

```mdx Nested folders example theme={null}
<Tree>
  <Tree.Folder name="app" defaultOpen>
    <Tree.File name="layout.tsx" />
    <Tree.File name="page.tsx" />
    <Tree.Folder name="api" defaultOpen>
      <Tree.Folder name="auth">
        <Tree.File name="route.ts" />
      </Tree.Folder>
      <Tree.File name="route.ts" />
    </Tree.Folder>
    <Tree.Folder name="components">
      <Tree.File name="button.tsx" />
      <Tree.File name="dialog.tsx" />
      <Tree.File name="tabs.tsx" />
    </Tree.Folder>
  </Tree.Folder>
  <Tree.File name="package.json" />
</Tree>
```

## Highlight the active path

Add the `highlight` property to `Tree.File` or `Tree.Folder` to mark the current item. Use it to draw attention to a file or folder you reference in nearby prose, such as the file a reader should open next.

Highlighting a folder also tints its descendants, so the active path stands out.

<Tree>
  <Tree.Folder name="app">
    <Tree.File name="layout.tsx" />

    <Tree.File name="page.tsx" />

    <Tree.Folder name="api">
      <Tree.File name="route.ts" />
    </Tree.Folder>
  </Tree.Folder>

  <Tree.File name="package.json" />
</Tree>

```mdx Highlighted tree example theme={null}
<Tree>
  <Tree.Folder name="app" defaultOpen>
    <Tree.File name="layout.tsx" />
    <Tree.File name="page.tsx" highlight />
    <Tree.Folder name="api" defaultOpen highlight>
      <Tree.File name="route.ts" />
    </Tree.Folder>
  </Tree.Folder>
  <Tree.File name="package.json" />
</Tree>
```

### Customize the highlight color

The `--tree-highlight` CSS variable defines the highlight color. Set it on the `Tree` root component to override the color for that tree.

```mdx Custom highlight color theme={null}
<Tree style={{ "--tree-highlight": "rgb(59 130 246)" }}>
  <Tree.Folder name="app" defaultOpen>
    <Tree.File name="page.tsx" highlight />
  </Tree.Folder>
</Tree>
```

## Keyboard navigation

The tree component supports keyboard navigation.

* **Arrow keys**: Navigate up and down through visible items.
* **Right arrow**: Expand a closed folder or move to the first child of an open folder.
* **Left arrow**: Collapse an open folder or move to the parent folder.
* **Home**: Jump to the first item in the tree.
* **End**: Jump to the last visible item in the tree.
* **Enter/Space**: Toggle folder open/closed state.
* **\***: Expand all sibling folders at the current level.
* **Type-ahead search**: Type characters to jump to items that start with those characters.

## Properties

### Tree.Folder

<ResponseField name="name" type="string">
  The name of the folder displayed in the tree.
</ResponseField>

<ResponseField name="defaultOpen" type="boolean">
  Whether the folder expands by default.
</ResponseField>

<ResponseField name="openable" type="boolean">
  Whether users can open and close the folder. Set to false for non-interactive folders.
</ResponseField>

<ResponseField name="highlight" type="boolean">
  Whether to highlight the folder as the active item. Emphasizes the active path by tinting descendants.
</ResponseField>

### Tree.File

<ResponseField name="name" type="string">
  The name of the file displayed in the tree.
</ResponseField>

<ResponseField name="highlight" type="boolean">
  Whether to highlight the file as the active item.
</ResponseField>


# Update
Source: https://www.mintlify.com/docs/components/update

Use the update component to display product updates, release notes, and changelog entries in a structured timeline format with dates.

Use the `Update` component to display changelog entries, version updates, and release notes with consistent formatting.

<Update label="Example" description="v0.1.1">
  ## Example update

  You can add anything here, like a screenshot, a code snippet, or a list of changes.

  <Frame>
    <img alt="Screenshot of the PearsDB Introduction page as an example of an image in an Update component." />
  </Frame>

  ### Features

  * Responsive design
  * Anchor for each update
  * Generated RSS feed entry for each update
</Update>

## How to use

```mdx Update example theme={null}
<Update label="2024-10-11" description="v0.1.0" tags={["Mintlify"]}>
  This is an update with a label, description, and tag.
</Update>
```

Use multiple `Update` components to create [changelogs](/docs/create/changelogs).

Update components automatically generate RSS feed entries. The entries contain pure Markdown only--components, code blocks, inline code, and raw HTML elements are not included.

If your update includes components or HTML, use the `rss` prop to provide alternative text for RSS subscribers.

```mdx Custom RSS content theme={null}
<Update
  label="March 2025"
  description="v2.0.0"
  rss={{
    title: "March 2025 - Major redesign",
    description: "Complete UI overhaul with new components"
  }}
>
  ## New dashboard

  <Frame>
    <img src="/dashboard.png" alt="New dashboard UI displaying updated components." />
  </Frame>

  Check out our redesigned dashboard with improved navigation.
</Update>
```

## Props

<ResponseField name="label" type="string">
  Label for the update. Appears to the left of the update and creates an anchor link using the same [automatic anchor ID rules](/docs/create/text#automatic-anchor-ids) as headings. Use unique labels to create distinct anchor links.
</ResponseField>

<ResponseField name="tags" type="string[]">
  Tags for the update. Shown as filters in the right side panel.
</ResponseField>

<ResponseField name="description" type="string">
  Description of the update. Appears below the label and tag.
</ResponseField>

<ResponseField name="rss" type="object">
  Update components automatically generate RSS feed entries. Use the `rss` property to create a single RSS feed entry with a custom title and description.

  If not provided:

  * Updates with Markdown headings create a separate RSS feed entry for each heading.
  * Updates without Markdown headings create a single RSS feed entry using the `label` as the title.

  <Expandable title="properties">
    <ResponseField name="title" type="string">
      Custom title for the RSS feed entry.
    </ResponseField>

    <ResponseField name="description" type="string">
      Custom description for the RSS feed entry.
    </ResponseField>
  </Expandable>
</ResponseField>


# View
Source: https://www.mintlify.com/docs/components/view

Use the view component to create switchable content panels for different programming languages, frameworks, or configuration alternatives.

Use the `View` component to create content that changes based on the selected view in a multi-view dropdown. This is particularly useful for showing code examples or documentation specific to different programming languages or frameworks.

<Tip>
  Use one view component per language per page. Use [tabs](/docs/components/tabs) for procedures that differ by language and [code groups](/docs/components/code-groups) for code examples that differ by language.
</Tip>

<View title="JavaScript" icon="js">
  This content only appears when you select JavaScript.

  ```javascript theme={null}
  console.log("Hello from JavaScript!");
  ```
</View>

<View title="Python" icon="python">
  This content only appears when you select Python.

  ```python theme={null}
  print("Hello from Python!")
  ```
</View>

## Example

````mdx JavaScript and Python views theme={null}
<View title="JavaScript" icon="js">
  This content only appears when you select JavaScript.

  ```javascript
  console.log("Hello from JavaScript!");
  ```
</View>

<View title="Python" icon="python">
  This content only appears when you select Python.

  ```python
  print("Hello from Python!")
  ```
</View>
````

## Table of contents behavior

The table of contents automatically updates to show only the headings for the currently selected view. When you switch between views using the multi-view dropdown, the table of contents refreshes to display the relevant headings for that view.

If you have different heading structures in each view, users only see the headings that are relevant to their selected language or framework.

## Properties

<ResponseField name="title" type="string">
  The title that identifies this view. Must match one of the options in the multi-view dropdown.
</ResponseField>

<ResponseField name="icon" type="string">
  A [Font Awesome](https://fontawesome.com/icons) icon, [Lucide](https://lucide.dev/icons) icon, URL to an icon, or relative path to an icon.
</ResponseField>

<ResponseField name="iconType" type="string">
  For Font Awesome icons only: One of `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>


# Visibility
Source: https://www.mintlify.com/docs/components/visibility

Use the visibility component to show different content to humans on the web UI and to AI agents in Markdown output for conditional rendering.

Use the `Visibility` component to show different content to humans reading your site versus AI agents processing the Markdown output. This lets you customize information for each audience without maintaining separate pages.

On your published site, content marked `for="humans"` renders normally and content marked `for="agents"` is hidden. In [Markdown page views](/docs/ai/markdown-export) (`.md` URLs), the opposite applies—agent content renders in the Markdown output and human-only content does not.

## Example

```mdx theme={null}
<Visibility for="humans">
  <Note>
    You are viewing this content **in web**.

    This content displays normally on standard pages of your site.

    Use it for a step like: Click the **Get started** button in the top-right corner to create your account.

    In this example, UI-oriented instructions appear on the standard page. View the [Markdown version of this page](https://mintlify.com/docs/components/visibility.md) to see the API-oriented instructions for agents.
  </Note>
</Visibility>

<Visibility for="agents">
  > You are viewing this content **in Markdown**.
  >
  > This content only appears on the Markdown version of pages.
  >
  > Use it for information that only agents use like: To create an account, call `POST /v1/accounts` with a valid email address.
  >
  > In this example, API-oriented instructions appear on the Markdown version of the page. View the [standard page](https://mintlify.com/docs/components/visibility) to see the UI-oriented instructions for humans.
</Visibility>
```

<Visibility>
  <Note>
    You are viewing this content **in web**.

    This content displays normally on standard pages of your site.

    Use it for a step like: Click the **Get started** button in the top-right corner to create your account.

    In this example, UI-oriented instructions appear on the standard page. View the [Markdown version of this page](https://mintlify.com/docs/components/visibility.md) to see the API-oriented instructions for agents.
  </Note>
</Visibility>

<Visibility>
  > You are viewing this content **in Markdown**.
  >
  > This content only appears on the Markdown version of pages.
  >
  > Use it for information that only agents use like: To create an account, call `POST /v1/accounts` with a valid email address.
  >
  > In this example, API-oriented instructions appear on the Markdown version of the page. View the [standard page](https://mintlify.com/docs/components/visibility) to see the UI-oriented instructions for humans.
</Visibility>

## Properties

<ResponseField name="for" type="string">
  The audience for the wrapped content. Must be one of:

  * `humans`: Content visible on the web and excluded from Markdown output
  * `agents`: Content hidden on the web and included in Markdown output
</ResponseField>


# Format code
Source: https://www.mintlify.com/docs/create/code

Format code in your documentation with syntax highlighting, line numbers, diffs, copy buttons, and interactive code group features in MDX.

## Add code samples

You can add inline code snippets or code blocks. Code blocks support meta options for syntax highlighting, titles, line highlighting, icons, and more.

### Inline code

To denote a `word` or `phrase` as code, enclose it in backticks (\`).

```mdx theme={null}
To denote a `word` or `phrase` as code, enclose it in backticks (`).
```

### Code blocks

Use [fenced code blocks](https://www.markdownguide.org/extended-syntax/#fenced-code-blocks) by enclosing code in three backticks. Code blocks are copyable, and if you have the assistant enabled, users can ask the assistant to explain the code.

Specify the programming language for syntax highlighting and to enable meta options. Add any meta options, like a title or icon, after the language.

<CodeGroup>
  ```java HelloWorld.java example icon=java lines theme={null}
  class HelloWorld {
      public static void main(String[] args) {
          System.out.println("Hello, World!");
      }
  }
  ```

  ````mdx Format theme={null}
  ```java HelloWorld.java example lines icon="java"
  class HelloWorld {
      public static void main(String[] args) {
          System.out.println("Hello, World!");
      }
  }
  ```
  ````
</CodeGroup>

## Code block options

Add meta options to your code blocks to customize their appearance.

<Note>
  You must specify a programming language for a code block before adding any other meta options.
</Note>

### Option syntax

* **String and boolean options**: Wrap with `""`, `''`, or no quotes.
* **Expression options**: Wrap with `{}`, `""`, or `''`.

### Syntax highlighting

Enable syntax highlighting by specifying the programming language after the opening backticks of a code block.

Mintlify uses [Shiki](https://shiki.style/) for syntax highlighting and supports all available languages. See the full list of [languages](https://shiki.style/languages) in Shiki's documentation.

Customize code block themes globally using `styling.codeblocks` in your `docs.json` file. Set simple themes like `system` or `dark`, or configure custom [Shiki themes](https://shiki.style/themes) for light and dark modes. See [Settings](/docs/organize/settings-appearance#styling) for configuration options.

<CodeGroup>
  ```java Syntax highlighting example theme={null}
  class HelloWorld {
      public static void main(String[] args) {
          System.out.println("Hello, World!");
      }
  }
  ```

  ````mdx Format theme={null}
  ```java Syntax highlighting example
  class HelloWorld {
      public static void main(String[] args) {
          System.out.println("Hello, World!");
      }
  }
  ```
  ````
</CodeGroup>

<Accordion title="Custom syntax highlighting theme">
  For custom themes, set your theme in `docs.json` to `"css-variables"` and override syntax highlighting colors using CSS variables with the `--mint-` prefix.

  The following variables are available:

  **Basic colors**

  * `--mint-color-text`: Default text color
  * `--mint-color-background`: Background color

  **Token colors**

  * `--mint-token-constant`: Constants and literals
  * `--mint-token-string`: String values
  * `--mint-token-comment`: Comments
  * `--mint-token-keyword`: Keywords
  * `--mint-token-parameter`: Function parameters
  * `--mint-token-function`: Function names
  * `--mint-token-string-expression`: String expressions
  * `--mint-token-punctuation`: Punctuation marks
  * `--mint-token-link`: Links

  **ANSI colors**

  * `--mint-ansi-black`, `--mint-ansi-black-dim`
  * `--mint-ansi-red`, `--mint-ansi-red-dim`
  * `--mint-ansi-green`, `--mint-ansi-green-dim`
  * `--mint-ansi-yellow`, `--mint-ansi-yellow-dim`
  * `--mint-ansi-blue`, `--mint-ansi-blue-dim`
  * `--mint-ansi-magenta`, `--mint-ansi-magenta-dim`
  * `--mint-ansi-cyan`, `--mint-ansi-cyan-dim`
  * `--mint-ansi-white`, `--mint-ansi-white-dim`
  * `--mint-ansi-bright-black`, `--mint-ansi-bright-black-dim`
  * `--mint-ansi-bright-red`, `--mint-ansi-bright-red-dim`
  * `--mint-ansi-bright-green`, `--mint-ansi-bright-green-dim`
  * `--mint-ansi-bright-yellow`, `--mint-ansi-bright-yellow-dim`
  * `--mint-ansi-bright-blue`, `--mint-ansi-bright-blue-dim`
  * `--mint-ansi-bright-magenta`, `--mint-ansi-bright-magenta-dim`
  * `--mint-ansi-bright-cyan`, `--mint-ansi-bright-cyan-dim`
  * `--mint-ansi-bright-white`, `--mint-ansi-bright-white-dim`

  **Custom syntax highlighting**

  Add syntax highlighting for languages not included in Shiki's default set by providing custom TextMate grammar files. Create a JSON file following the [TextMate grammar format](https://macromates.com/manual/en/language_grammars), then reference it in your `docs.json`. You can add multiple custom languages by including additional paths in the array.

  ```json docs.json theme={null}
  {
    "styling": {
      "codeblocks": {
        "languages": {
          "custom": ["/languages/my-custom-language.json"]
        }
      }
    }
  }
  ```
</Accordion>

### Twoslash

In JavaScript and TypeScript code blocks, use `twoslash` to enable interactive type information. Users can hover over variables, functions, and parameters to see types and errors like in an IDE.

<CodeGroup>
  ```ts twoslash Twoslash example theme={null}
  type Pet = "cat" | "dog" | "hamster";

  function adoptPet(name: string, type: Pet) {
    return `${name} the ${type} is now adopted!`;
  }

  // Hover to see the inferred types
  const message = adoptPet("Mintie", "cat");
  ```

  ````mdx Format theme={null}
  ```ts twoslash Twoslash example
  type Pet = "cat" | "dog" | "hamster";

  function adoptPet(name: string, type: Pet) {
    return `${name} the ${type} is now adopted!`;
  }

  // Hover to see the inferred types
  const message = adoptPet("Mintie", "cat");
  ```
  ````
</CodeGroup>

### Title

Add a title to label your code example. Place the title after the language identifier. Titles can contain multiple words and file paths.

You can set the title two ways:

* **Inline**: Place the title directly after the language identifier.
* **`title` property**: Use `title="Your title"` for titles that need special characters or explicit quoting.

<CodeGroup>
  ```javascript Example title theme={null}
  const hello = "world";
  ```

  ```javascript title="utils/hello.js" theme={null}
  const hello = "world";
  ```

  ````mdx Inline format theme={null}
  ```javascript Example title
  const hello = "world";
  ```
  ````

  ````mdx title property format theme={null}
  ```javascript title="utils/hello.js"
  const hello = "world";
  ```
  ````
</CodeGroup>

### Icon

Add an icon to your code block using the `icon` property. See [Icons](/docs/components/icons) for all available options.

<CodeGroup>
  ```javascript Icon example icon=square-js theme={null}
  const hello = "world";
  ```

  ````mdx Format theme={null}
  ```javascript Icon example icon="square-js"
  const hello = "world";
  ```
  ````
</CodeGroup>

### Line highlighting

Highlight specific lines in your code blocks using `highlight` with the line numbers or ranges you want to highlight.

<CodeGroup>
  ```javascript Line highlighting example {1,2,5} theme={null}
  const greeting = "Hello, World!";
  function sayHello() {
    console.log(greeting);
  }
  sayHello();
  ```

  ````mdx Format theme={null}
  ```javascript Line highlighting example highlight={1-2,5}
  const greeting = "Hello, World!";
  function sayHello() {
    console.log(greeting);
  }
  sayHello();
  ```
  ````
</CodeGroup>

### Line focusing

Focus on specific lines in your code blocks using `focus` with line numbers or ranges.

<CodeGroup>
  ```javascript Line focusing example focus=2,4,5 theme={null}
  const greeting = "Hello, World!";
  function sayHello() {
    console.log(greeting);
  }
  sayHello();
  ```

  ````mdx Format theme={null}
  ```javascript Line focusing example focus={2,4-5}
  const greeting = "Hello, World!";
  function sayHello() {
    console.log(greeting);
  }
  sayHello();
  ```
  ````
</CodeGroup>

### Show line numbers

Display line numbers on the left side of your code block using `lines`.

<CodeGroup>
  ```javascript Show line numbers example lines theme={null}
  const greeting = "Hello, World!";
  function sayHello() {
    console.log(greeting);
  }
  sayHello();
  ```

  ````mdx Format theme={null}
  ```javascript Show line numbers example lines
  const greeting = "Hello, World!";
  function sayHello() {
    console.log(greeting);
  }
  sayHello();
  ```
  ````
</CodeGroup>

### Expandable

Allow users to expand and collapse long code blocks using `expandable`.

<CodeGroup>
  ```python Expandable example expandable theme={null}
  from datetime import datetime, timedelta
  from typing import Dict, List, Optional
  from dataclasses import dataclass

  @dataclass
  class Book:
  title: str
  author: str
  isbn: str
  checked_out: bool = False
  due_date: Optional[datetime] = None

  class Library:
      def __init__(self):
          self.books: Dict[str, Book] = {}
          self.checkouts: Dict[str, List[str]] = {} # patron -> list of ISBNs

      def add_book(self, book: Book) -> None:
          if book.isbn in self.books:
              raise ValueError(f"Book with ISBN {book.isbn} already exists")
          self.books[book.isbn] = book

      def checkout_book(self, isbn: str, patron: str, days: int = 14) -> None:
          if patron not in self.checkouts:
              self.checkouts[patron] = []

          book = self.books.get(isbn)
          if not book:
              raise ValueError("Book not found")

          if book.checked_out:
              raise ValueError("Book is already checked out")

          if len(self.checkouts[patron]) >= 3:
              raise ValueError("Patron has reached checkout limit")

          book.checked_out = True
          book.due_date = datetime.now() + timedelta(days=days)
          self.checkouts[patron].append(isbn)

      def return_book(self, isbn: str) -> float:
          book = self.books.get(isbn)
          if not book or not book.checked_out:
              raise ValueError("Book not found or not checked out")

          late_fee = 0.0
          if datetime.now() > book.due_date:
              days_late = (datetime.now() - book.due_date).days
              late_fee = days_late * 0.50

          book.checked_out = False
          book.due_date = None

          # Remove from patron's checkouts
          for patron, books in self.checkouts.items():
              if isbn in books:
                  books.remove(isbn)
                  break

          return late_fee

      def search(self, query: str) -> List[Book]:
          query = query.lower()
          return [
              book for book in self.books.values()
              if query in book.title.lower() or query in book.author.lower()
          ]

  def main():
      library = Library()

      # Add some books
      books = [
          Book("The Hobbit", "J.R.R. Tolkien", "978-0-261-10295-4"),
          Book("1984", "George Orwell", "978-0-452-28423-4"),
      ]

      for book in books:
          library.add_book(book)

      # Checkout and return example
      library.checkout_book("978-0-261-10295-4", "patron123")
      late_fee = library.return_book("978-0-261-10295-4")
      print(f"Late fee: ${late_fee:.2f}")

  if __name__ == "__main__":
      main()
  ```

  ````text Format theme={null}
  ```python Expandable example expandable
  from datetime import datetime, timedelta
  from typing import Dict, List, Optional
  from dataclasses import dataclass

  # ...

  if __name__ == "__main__":
      main()
  ```
  ````
</CodeGroup>

### Wrap

Enable text wrapping for long lines using `wrap`. This prevents horizontal scrolling and makes long lines easier to read.

<CodeGroup>
  ```javascript Wrap example wrap theme={null}
  const greeting =
    "Hello, World! I am a long line of text that will wrap to the next line.";
  function sayHello() {
    console.log(greeting);
  }
  sayHello();
  ```

  ````mdx Format theme={null}
  ```javascript Wrap example wrap
  const greeting =
    "Hello, World! I am a long line of text that will wrap to the next line.";
  function sayHello() {
    console.log(greeting);
  }
  sayHello();
  ```
  ````
</CodeGroup>

### Diff

Show a visual diff of added or removed lines in your code blocks. The visual diff highlights added lines in green and removed lines in red.

Add `[!code ++]` or `[!code --]` inside a comment at the end of a line to mark it as added or removed. Use your language's comment syntax:

| Language                                       | Added                 | Removed               |
| ---------------------------------------------- | --------------------- | --------------------- |
| JavaScript, TypeScript, Java, C, C++, Go, Rust | `// [!code ++]`       | `// [!code --]`       |
| Python, Ruby, Bash, YAML                       | `# [!code ++]`        | `# [!code --]`        |
| HTML, XML                                      | `<!-- [!code ++] -->` | `<!-- [!code --] -->` |
| CSS                                            | `/* [!code ++] */`    | `/* [!code --] */`    |
| SQL, Lua                                       | `-- [!code ++]`       | `-- [!code --]`       |

For multiple consecutive lines, add a colon and the number of lines:

* `// [!code ++:3]`: Mark the current line plus the next two lines as added.
* `# [!code --:5]`: Mark the current line plus the next four lines as removed.

<CodeGroup>
  ```js JavaScript diff lines theme={null}
  const greeting = "Hello, World!"; // [!code ++]
  function sayHello() {
    console.log("Hello, World!"); // [!code --]
    console.log(greeting); // [!code ++]
  }
  sayHello();
  ```

  ```python Python diff lines theme={null}
  def greet():
      print("Hello, World!")  # [!code --]
      print("Hello, Mintlify!")  # [!code ++]

  greet()
  ```

  ````text JavaScript format theme={null}
  ```js JavaScript diff lines
  const greeting = "Hello, World!"; // [!code ++]
  function sayHello() {
    console.log("Hello, World!"); // [!code --]
    console.log(greeting); // [!code ++]
  }
  sayHello();
  ```
  ````

  ````text Python format theme={null}
  ```python Python diff lines
  def greet():
      print("Hello, World!")  # [!code --]
      print("Hello, Mintlify!")  # [!code ++]

  greet()
  ```
  ````
</CodeGroup>

## CodeBlock component

Use the `<CodeBlock>` component in custom React components to programmatically render code blocks with the same styling and features as markdown code blocks.

### Props

<ResponseField name="language" type="string">
  The programming language for syntax highlighting.
</ResponseField>

<ResponseField name="filename" type="string">
  The filename to display in the code block header.
</ResponseField>

<ResponseField name="icon" type="string">
  The icon to display in the code block header. See [Icons](/docs/components/icons)
  for available options.
</ResponseField>

<ResponseField name="lines" type="boolean">
  Whether to show line numbers.
</ResponseField>

<ResponseField name="wrap" type="boolean">
  Whether to wrap the code block.
</ResponseField>

<ResponseField name="expandable" type="boolean">
  Whether to expand the code block.
</ResponseField>

<ResponseField name="highlight" type="string">
  The lines to highlight. Provide a stringified array of numbers. Example:
  `"[1,3,4,5]"`.
</ResponseField>

<ResponseField name="focus" type="string">
  The lines to focus on. Provide a stringified array of numbers. Example:
  `"[1,3,4,5]"`.
</ResponseField>

### Example

```jsx theme={null}
export const CustomCodeBlock = ({
  filename,
  icon,
  language,
  highlight,
  children,
}) => {
  return (
    <CodeBlock
      filename={filename}
      icon={icon}
      language={language}
      lines
      highlight={highlight}
    >
      {children}
    </CodeBlock>
  );
};
```


# Files
Source: https://www.mintlify.com/docs/create/files

Serve static assets like images, videos, PDFs, and data files from your documentation repository with automatic optimization and CDN delivery.

Mintlify automatically serves static assets from your documentation repository at the appropriate path on your domain. For example, if you have `/images/logo.png` in your repo, the image file is available at `https://docs.your-project.com/images/logo.png`.

You can make any supported file type available to your users, including OpenAPI specifications, images, videos, and more.

Files must be less than 20 MB.

<Note>
  File serving is not supported for documentation sites with authentication enabled. If your site requires authentication, static files are not accessible at their direct URLs.
</Note>

## Supported file types

Supported file types for all plans:

* **Images**: `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.svg`, `.ico`
* **Video**: `.mp4`, `.webm`
* **Audio**: `.mp3`, `.wav`
* **Data**: `.json`, `.yaml`
* **Stylesheet**: `.css`
* **Scripts**: `.js`
* **Fonts**: `.woff`, `.woff2`, `.ttf`, `.eot`

Supported file types for Enterprise plans:

* **Documents**: `.pdf`, `.txt`
* **Data**: `.xml`, `.csv`
* **Archives**: `.zip`

## File organization

Organize your files using folders to keep your repository easy to navigate:

```text theme={null}
/your-project
  |- docs.json
  |- images/
    |- logo.png
    |- screenshots/
      |- dashboard.png
  |- assets/
    |- whitepaper.pdf
    |- demo-video.mp4
```

Mintlify serves files from the root of your domain, so the structure in your repository directly maps to the URL structure. From the previous example, `assets/whitepaper.pdf` would be available at `https://docs.your-project.com/assets/whitepaper.pdf`.


# Images and embeds
Source: https://www.mintlify.com/docs/create/image-embeds

Add images, embed YouTube videos, and include iframes in your MDX pages to enhance documentation with visual and interactive media content.

Add images, embed videos, and include interactive content with iframes to your documentation.

<Frame>
  <img alt="Photograph of a scenic landscape with purple flowers in the foreground, mountains in the background, and a blue sky with scattered clouds." />
</Frame>

## Images

Add images to provide visual context, examples, or decoration to your documentation.

### Basic image syntax

Use [Markdown syntax](https://www.markdownguide.org/basic-syntax/#images) to add images to your documentation:

```mdx theme={null}
![Alt text describing the image](/images/screenshot.png)
```

Image paths are root-relative from your docs repository. For example, if your image is at `images/screenshot.png` in your repository, the path is `/images/screenshot.png`. Relative paths (for example, `./screenshot.png`) are not supported.

<Tip>
  Always include descriptive alt text to improve accessibility and SEO. The alt text should clearly describe what the image shows.
</Tip>

Image files must be less than 20 MB. For larger files, host them on a CDN service like [Amazon S3](https://aws.amazon.com/s3) or [Cloudinary](https://cloudinary.com).

### HTML image embeds

For more control over image display, use HTML `<img>` tags:

```jsx theme={null}
<img 
  src="/images/dashboard.png" 
  alt="Main dashboard interface"
  style={{height: "300px", width: "400px"}}
  className="rounded-lg"
/>
```

#### Resize images with inline styles

Use JSX inline styles with the `style` attribute to resize images:

```jsx theme={null}
<img
  src="/images/architecture.png"
  style={{width: "450px", height: "auto"}}
  alt="Diagram showing the architecture of the system"
/>
```

#### Disable image zoom

To disable the default zoom on click for images, add the `noZoom` property:

```html highlight="4" theme={null}
<img 
  src="/images/screenshot.png" 
  alt="Descriptive alt text"
  noZoom
/>
```

#### Link images

To make an image a clickable link, wrap the image in an anchor tag and add the `noZoom` property:

```html theme={null}
<a href="https://mintlify.com" target="_blank">
  <img 
    src="/images/logo.png" 
    alt="Mintlify logo"
    noZoom
  />
</a>
```

<Note>
  Images within anchor tags automatically display a pointer cursor to indicate they are clickable.
</Note>

#### Copy and download actions

Add copy and download controls to an image with the `actions` property. When enabled, buttons appear as an overlay on hover, focus, or touch, letting readers copy the image to their clipboard or save it to their device.

Set `actions` to `true` to show both buttons, or pass a comma-separated list to enable specific actions:

```html theme={null}
<img
  src="/images/diagram.png"
  alt="System architecture diagram"
  actions
/>
```

```html theme={null}
<img
  src="/images/diagram.png"
  alt="System architecture diagram"
  actions="copy,download"
/>
```

Supported values for `actions`:

* `copy`: Copy the image to the clipboard.
* `download`: Download the image as a file.

Use the `actionsPlacement` property to position the buttons. The default is `bottom-center`.

```html theme={null}
<img
  src="/images/diagram.png"
  alt="System architecture diagram"
  actions="download"
  actionsPlacement="top-right"
/>
```

Supported values for `actionsPlacement`: `bottom-center`, `bottom-left`, `bottom-right`, `top-center`, `top-left`, `top-right`.

#### Light and dark mode images

To display different images for light and dark themes, use Tailwind CSS classes:

```html theme={null}
<!-- Light mode image -->
<img 
  className="block dark:hidden" 
  src="/images/light-mode.png" 
  alt="Light mode interface"
/>

<!-- Dark mode image -->
<img 
  className="hidden dark:block" 
  src="/images/dark-mode.png" 
  alt="Dark mode interface"
/>
```

### SVG images

SVG files that use `foreignObject` elements render differently in production than in local development. Mintlify's image CDN strips `foreignObject` from SVGs as a security measure, which can truncate or hide text and other embedded HTML content.

This commonly affects SVGs exported from tools like [draw.io](https://www.drawio.com) that have HTML text formatting or word wrap turned on. To fix this, disable **Formatted Text** and **Word Wrap** on all labels in your diagram before exporting to SVG. See the [draw.io documentation](https://www.drawio.com/doc/faq/svg-export-text-problems) for more information on SVG exports.

## Videos

Mintlify supports [HTML tags in Markdown](https://www.markdownguide.org/basic-syntax/#html), giving you flexibility to create rich content.

<Tip>
  Always include fallback text content within video elements for browsers that don't support video playback.
</Tip>

### YouTube embeds

Embed YouTube videos using iframe elements:

```html theme={null}
<iframe
  className="w-full aspect-video rounded-xl"
  src="https://www.youtube.com/embed/4KzFe50RQkQ"
  title="YouTube video player"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowFullScreen
></iframe>
```

<Frame>
  <iframe title="YouTube video player" />
</Frame>

### Self-hosted videos

Use the HTML `<video>` element for self-hosted video content:

```html theme={null}
<video
  controls
  className="w-full aspect-video rounded-xl"
  src="link-to-your-video.com"
></video>
```

### Autoplay videos

To autoplay a video, use:

```html theme={null}
<video
  autoPlay
  muted
  loop
  playsInline
  className="w-full aspect-video rounded-xl"
  src="/videos/demo.mp4"
></video>
```

<Note>
  When using JSX syntax, write double-word attributes in camelCase: `autoPlay`, `playsInline`, `allowFullScreen`.
</Note>

## Iframes

Embed external content using iframe elements:

```html theme={null}
<iframe 
  src="https://example.com/embed" 
  title="Embedded content"
  className="w-full h-96 rounded-xl"
></iframe>
```

<Tip>
  Wrap iframes in a [frame](/docs/components/frames) component to keep them within the text column width and prevent overflow.

  ```html theme={null}
  <Frame>
    <iframe 
      src="https://example.com/embed" 
      title="Embedded content"
      className="w-full h-96 rounded-xl"
    ></iframe>
  </Frame>
  ```
</Tip>

## Related resources

<Card title="Frame component reference" icon="frame" href="/components/frames">
  Learn how to use the Frame component for presenting images.
</Card>


# Lists and tables
Source: https://www.mintlify.com/docs/create/list-table

Format structured data in your documentation with Markdown tables, ordered and unordered lists, nested structures, and task list checkboxes.

## Lists

Lists follow the official [Markdown syntax](https://www.markdownguide.org/basic-syntax/#lists-1).

### Ordered list

To create an ordered list, add numbers followed by a period before list items.

1. First item
2. Second item
3. Third item
4. Fourth item

```mdx theme={null}
1. First item
2. Second item
3. Third item
4. Fourth item
```

### Unordered list

To create an unordered list, add dashes (`-`), asterisks (`*`), or plus signs (`+`) before list items.

* First item
* Second item
* Third item
* Fourth item

```mdx theme={null}
- First item
- Second item
- Third item
- Fourth item
```

### Nested list

Indent list items to nest them.

* First item
* Second item
  * Additional item
  * Additional item
* Third item

```mdx theme={null}
- First item
- Second item
  - Additional item
  - Additional item
- Third item
```

## Tables

Tables follow the official [Markdown syntax](https://www.markdownguide.org/extended-syntax/#tables).

To add a table, use three or more hyphens (`---`) to create each column's header, and use pipes (`|`) to separate each column. For compatibility, you should also add a pipe on either end of the row.

| Property | Description                           |
| -------- | ------------------------------------- |
| Name     | Full name of user                     |
| Age      | Reported age                          |
| Joined   | Whether the user joined the community |

```mdx theme={null}
| Property | Description                           |
| -------- | ------------------------------------- |
| Name     | Full name of user                     |
| Age      | Reported age                          |
| Joined   | Whether the user joined the community |
```

### Column alignment

Use colons in the separator row to align column content:

| Left aligned | Center aligned | Right aligned |
| :----------- | :------------: | ------------: |
| Left         |     Center     |         Right |
| Text         |      Text      |          Text |

```mdx theme={null}
| Left aligned | Center aligned | Right aligned |
| :----------- | :------------: | ------------: |
| Left         | Center         | Right         |
| Text         | Text           | Text          |
```


# Personalized content
Source: https://www.mintlify.com/docs/create/personalization

Show personalized content based on identified visitor data, group memberships, and custom variables to tailor documentation per audience.

Customize content for identified visitors while keeping your documentation public. Examples of personalization include prefilling API keys, showing content specific to a user's plan or role, and filtering API reference content based on group membership.

Personalization uses a shared session, JWT, or OAuth to identify visitors without restricting access to your pages.

| Method         | Best for                                                                   | Visitor identification                                                             |
| :------------- | :------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- |
| Shared session | Documentation and an existing application that can share a browser session | Mintlify requests user data from your Info API with the visitor's session cookies. |
| JWT            | An existing login flow that can sign Mintlify user data                    | Your login flow redirects the visitor back with a signed JWT.                      |
| OAuth          | An existing OAuth 2.0 provider                                             | Mintlify completes an OAuth flow and requests user data from your Info API.        |

## Configure personalization

Enable personalization on the [Add-ons](https://app.mintlify.com/settings/deployment/addons) page of your dashboard. Personalization is mutually exclusive with full authentication. JWT and OAuth authentication include personalization features.

1. Navigate to the [Add-ons](https://app.mintlify.com/settings/deployment/addons) page of your dashboard.
2. In the **Personalization** section, select shared session, JWT, or OAuth.
3. Configure your selected personalization method.
4. Click **Save changes**.

### Shared session

Shared session reuses a visitor's existing application session, so they don't need to log in again on your Mintlify site.

1. Select **Shared session** in the **Personalization** settings.
2. Enter an **Info API URL** that returns the current visitor's [user data](#user-data-format).
3. Optionally enter a **Login URL**. Mintlify displays a login link when the Info API does not return user data.
4. Click **Save changes**.

Mintlify sends a `GET` request to the Info API from the visitor's browser with credentials included. Return a successful JSON response for an identified visitor:

```json User data response theme={null}
{
  "expiresAt": 1893456000,
  "content": {
    "firstName": "Jane",
    "plan": "Enterprise"
  },
  "apiPlaygroundInputs": {
    "header": {
      "Authorization": "Bearer user_abc123"
    }
  }
}
```

For a visitor without a valid session, return a non-success response such as `401`. Mintlify leaves the visitor unidentified and keeps public content available.

If the Info API is on a different origin from your documentation, configure it to allow credentialed cross-origin requests from the exact documentation origin. Do not use a wildcard origin with credentials. Prevent browsers and intermediary caches from storing user data by returning `Cache-Control: private, no-store`.

<Warning>
  Values in `apiPlaygroundInputs` are available to the browser so the API playground can send them. Return short-lived, appropriately scoped credentials, and avoid exposing a privileged application session token when a dedicated documentation token is available.
</Warning>

### JWT and OAuth

JWT and OAuth personalization use the same user data format as shared session but don't restrict access to your documentation. Configure these methods in **Add-ons**, not **Authentication**.

For JWT personalization:

1. Enter the URL of your existing login flow.
2. Click **Save changes**.
3. Click **Generate new key** and store the downloaded private key securely.
4. In your login flow, create a JWT containing the identified visitor's [user data](#user-data-format) and sign it with the generated private key using the ES256 algorithm.
5. Redirect the visitor to a page on your documentation site with the signed JWT as the URL fragment. For example, `https://docs.example.com/get-started#{SIGNED_JWT}`. For a custom subpath, include the subpath in this URL.

Set the JWT's `exp` claim to a short duration of 10 seconds or less. Use the user data `expiresAt` field to control how long Mintlify stores the personalization data.

For OAuth personalization:

1. Enter your authorization URL, client ID, scopes, token URL, Info API URL, and any optional settings, then click **Save changes**. OAuth personalization uses the Authorization Code flow with Proof Key for Code Exchange (PKCE) and does not require a client secret.
2. Copy the **Redirect URL** from the dashboard and add it as an authorized redirect URL for your OAuth provider.
3. Configure the Info API to accept a `GET` request with the OAuth access token in the `Authorization: Bearer <access_token>` header and return [user data](#user-data-format).

The OAuth redirect path is `/mintlify-oauth-callback`. On a custom subpath, the dashboard includes the subpath in the redirect URL.

Mintlify exchanges the authorization code and requests user data from the visitor's browser. If the token or Info API endpoint is on a different origin from your documentation, configure it to allow cross-origin requests from the exact documentation origin. The Info API must allow the `Authorization` request header.

## API key prefilling

Automatically populate API playground fields with user-specific values by returning matching field names in your user data. Include the values in the `apiPlaygroundInputs` field of your [user data](/docs/deploy/authentication-setup#user-data-format).

```json theme={null}
{
  "apiPlaygroundInputs": {
    "header": { "X-API-Key": "user_api_key_123" },
    "server": { "subdomain": "acme" }
  }
}
```

The field names must match the names defined in your OpenAPI specification. Mintlify applies only values that match the current endpoint's security scheme.

## Dynamic MDX content

Display content based on user information like name, plan, or organization with the `user` variable in your MDX pages. Include custom data in the `content` field of your [user data](/docs/deploy/authentication-setup#user-data-format).

```json theme={null}
{
  "content": {
    "firstName": "Jane",
    "company": "Acme Corp",
    "plan": "Enterprise"
  }
}
```

Reference these values in your MDX.

```mdx theme={null}
Welcome back, {user.firstName}! Your {user.plan} plan includes 100 seats for members in your {user.company} organization.
```

For conditional rendering based on user data, use the `user` variable in JSX components.

```jsx theme={null}
{
  user.plan === 'enterprise'
    ? <>Contact your admin to enable this feature.</>
    : <>See <a href="https://yoursite.com/pricing">pricing</a> for information about upgrading.</>
}
```

<Note>
  The `user` variable is an empty object for logged-out users. Use optional chaining on all `user` fields to prevent errors. For example, `{user.org?.plan}` instead of `{user.org.plan}`.
</Note>

To read the same user object from a [custom JavaScript file](/docs/customize/custom-scripts#access-personalized-user-data), use `window.mintlify.user` and listen for the `mintlify:user` event.

## Page visibility

Control which pages appear in navigation based on user groups by adding `groups` to page frontmatter.

<Warning>
  With personalization, `groups` control visibility but do not restrict access to a page. A visitor can still open a group-filtered page by navigating directly to its URL. Use [authentication](/docs/deploy/authentication-setup) to restrict access to sensitive content.
</Warning>

```mdx theme={null}
---
title: "Admin settings"
groups: ["admin"]
---
```

## OpenAPI content filtering

Filter API reference content based on user groups with the `x-mint` extension in your OpenAPI specification. You can filter entire endpoints, individual schema properties, `oneOf` variants, and enum values.

### Filter endpoints

Add `x-mint.groups` to an operation or path to show the endpoint in navigation only to specific user groups. With standalone personalization, users not in the listed groups can still open the endpoint page by its direct URL.

<CodeGroup>
  ```json {6-8} Restricted operation theme={null}
  {
    "paths": {
      "/billing": {
        "get": {
          "summary": "Get billing details",
          "x-mint": {
            "groups": ["admin", "billing"]
          },
          "responses": {
            "200": {
              "description": "Billing details"
            }
          }
        }
      }
    }
  }
  ```

  ```json {3-5} Restricted path theme={null}
  {
    "paths": {
      "x-mint": {
        "groups": ["admin", "billing"]
      },
      "/billing": {
        "get": {
          "summary": "Get billing details",
        }
      },
      "/users": {
        "get": {
          "summary": "Get user details",
        }
      }
    }
  }
  ```
</CodeGroup>

### Filter schema properties

Add `x-mint.groups` to individual properties within request bodies, parameters, or responses. Properties without `x-mint.groups` remain visible to all users.

```json {11-13} Restricted property theme={null}
{
  "components": {
    "schemas": {
      "User": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "internal_id": {
            "type": "string",
            "x-mint": {
              "groups": ["admin"]
            }
          }
        }
      }
    }
  }
}
```

In this example, all users see the `name` property. Only users in the `admin` group see the `internal_id` property.

### Filter oneOf variants

Add `x-mint.groups` to individual `oneOf` options to restrict which schema variants a user can see.

```json {7-9} Restricted oneOf variant theme={null}
{
  "schema": {
    "oneOf": [
      {
        "title": "Enterprise config",
        "type": "object",
        "x-mint": {
          "groups": ["enterprise"]
        },
        "properties": {
          "sso_enabled": { "type": "boolean" }
        }
      },
      {
        "title": "Standard config",
        "type": "object",
        "properties": {
          "notifications": { "type": "boolean" }
        }
      }
    ]
  }
}
```

### Filter enum values

Use the `x-mint-enum` extension to restrict individual enum values by group. List each restricted value as a key, with its allowed groups as the value. Enum values not listed in `x-mint-enum` are visible to all users.

```json {4-7} Restricted enum values theme={null}
{
  "type": "string",
  "enum": ["free", "pro", "enterprise"],
  "x-mint-enum": {
    "pro": ["pro", "enterprise"],
    "enterprise": ["enterprise"]
  }
}
```

In this example, all users see `free`. Users in the `pro` or `enterprise` groups see `pro`. Only users in the `enterprise` group see `enterprise`.

<Note>
  `x-mint-enum` is a separate top-level extension on the schema object, not nested under `x-mint`.
</Note>

## User data format

Your identification or authentication system returns user data that controls personalization. The `groups`, `content`, and `apiPlaygroundInputs` fields described on this page are all part of the user data object.

For the full user data format and field reference, see [User data format](/docs/deploy/authentication-setup#user-data-format).

## Logout behavior

Logout occurs on the client side. When users click the logout button, Mintlify clears their stored session data in the browser.

To limit how long personalization data persists, set the `expiresAt` field in your user data.


# Redirects
Source: https://www.mintlify.com/docs/create/redirects

Configure URL redirects in docs.json for moved, renamed, or deleted documentation pages to preserve SEO rankings and prevent broken links.

When you change the path of a file in your docs folder, it also changes the URL path to that page. This may happen when restructuring your docs or changing the sidebar title.

## Redirects

<Note>
  Redirect **sources** cannot include URL anchors like `path#anchor` or query parameters like `path?query=value`. Destinations may include anchors (for example, `/destination/path#section`).
</Note>

Add the `redirects` field to the top level of your `docs.json` file to set up redirects.

```json docs.json theme={null}
{
  "name": "My docs",
  "redirects": [
    {
      "source": "/source/path",
      "destination": "/destination/path"
    }
  ]
}
```

This redirects `/source/path` to `/destination/path`.

By default, redirects are permanent (308). To use a temporary redirect (307), set `permanent` to `false`.

```json theme={null}
"redirects": [
  {
    "source": "/source/path",
    "destination": "/destination/path",
    "permanent": false
  }
]
```

Both 307 and 308 preserve the HTTP method of the original request (unlike 301 and 302), making them suitable for redirecting POST requests.

Use a permanent (308) redirect when a page has moved permanently, such as for renamed slugs, restructured navigation, or removed pages that map to a replacement. Search engines transfer SEO ranking to the destination and browsers cache the redirect.

Use a temporary (307) redirect for short-term rerouting, such as maintenance pages, A/B tests, or campaign links you plan to reuse. Search engines keep the source URL in their index and don't transfer ranking.

### Redirect limits

There is no hard cap on the number of redirects you can define in `docs.json`. Very large redirect arrays (thousands of entries) can slow deploys and make the file harder to review, so consolidate with [wildcard redirects](#wildcard-redirects) where possible.

### Wildcard redirects

To match a wildcard path, use `*` after a parameter. In this example, `/beta/:slug*` matches `/beta/introduction` and redirects it to `/v2/introduction`.

```json theme={null}
"redirects": [
  {
    "source": "/beta/:slug*",
    "destination": "/v2/:slug*"
  }
]
```

### Partial wildcard redirects

Use partial wildcards to match URL segments that start with a specific prefix.

```json theme={null}
"redirects": [
  {
    "source": "/articles/concepts-*",
    "destination": "/collections/overview"
  }
]
```

This matches any URLs with the `/articles/concepts-` path, such as `/articles/concepts-getting-started` and `/articles/concepts-overview`, and redirects them all to `/collections/overview`.

You can also substitute the captured wildcard value in the destination.

```json theme={null}
"redirects": [
  {
    "source": "/old/article-*",
    "destination": "/new/article-*"
  }
]
```

This redirects `/old/article-123` to `/new/article-123`, preserving the captured value after the prefix.

### Avoid infinite redirects

To avoid infinite loops, do not create circular redirects where paths redirect back to each other.

```json theme={null}
"redirects": [
  {
    "source": "/docs/:slug*",
    "destination": "/help/:slug*"
  },
  {
    "source": "/help/:slug*",
    "destination": "/docs/:slug*"
  }
]
```

## When redirects take effect

Redirects in `docs.json` apply at request time on Mintlify's hosting layer, so they go live as soon as your changes deploy. Preview deployments apply redirects too, which lets you verify behavior before merging to your production branch.

To test redirects locally, run `mint dev` and visit the source path in your browser. The local dev server applies the redirects defined in your `docs.json`.

## Check for broken links

Find broken links with the [CLI](/docs/cli).

```bash theme={null}
mint broken-links
```


# Reusable snippets
Source: https://www.mintlify.com/docs/create/reusable-snippets

Create reusable content snippets with variables to maintain consistency across documentation pages and reduce duplication in your MDX files.

One of the core principles of software development is DRY (Don't Repeat Yourself), which applies to documentation too. If you find yourself repeating the same content in multiple places, create a custom snippet for that content. Snippets contain content that you can import into other files to reuse. You control where the snippet appears on a page. If you ever need to update the content, you only need to edit the snippet rather than every file where the snippet appears.

<Note>
  Snippets are not currently supported in the web editor. To use snippets, edit your MDX files locally with the CLI or push snippet imports directly to your repository.
</Note>

## How snippets work

Snippets are any `.mdx`, `.md`, or `.jsx` files imported into another file. You can place snippet files anywhere in your project.

When you import a snippet into another file, the snippet only appears where you import it and does not render as a standalone page. Any file in the `/snippets/` folder is always a snippet even if it is not imported into another file.

## Create snippets

Create a file with the content you want to reuse. Snippets can contain all content types supported by Mintlify and they can import other snippets. See [Nested snippets](#nested-snippets) for where to declare imports when nesting.

## Import snippets into pages

Import snippets into pages using either an absolute or relative path.

* **Absolute imports**: Start with `/` for imports from the root of your project.
* **Relative imports**: Use `./` or `../` to import snippets relative to the current file's location.

The name you use to render an imported snippet as a JSX tag must start with an uppercase letter, such as `MySnippet`. MDX treats lowercase tags such as `<mySnippet />` as literal HTML or custom element names rather than references to imported snippets.

<Tip>
  Relative imports enable IDE navigation. Press <kbd>CMD</kbd> and click a snippet name in your editor to jump directly to the snippet definition.
</Tip>

### Import text

<Steps>
  <Step title="Add content to your snippet file">
    Add the content you want to reuse.

    ```mdx shared/my-snippet.mdx wrap theme={null}
    Hello world! This is my content I want to reuse across pages.
    ```
  </Step>

  <Step title="Import the snippet into your destination file">
    Use either an absolute or relative path.

    <CodeGroup>
      ```mdx Absolute import theme={null}
      ---
      title: "An example page"
      description: "This is an example page that imports a snippet."
      ---

      import MySnippet from "/shared/my-snippet.mdx";

      The snippet content displays beneath this sentence.

      <MySnippet />
      ```

      ```mdx Relative import theme={null}
      ---
      title: "An example page"
      description: "This is an example page that imports a snippet."
      ---

      import MySnippet from "../shared/my-snippet.mdx";

      The snippet content displays beneath this sentence.

      <MySnippet />
      ```
    </CodeGroup>
  </Step>
</Steps>

### Nested snippets

Snippets can import other snippets. Declare the import in the snippet file that uses the nested snippet, not in the page that imports the parent snippet.

Each file resolves its own imports. Imports declared on a page do not apply to the snippets that the page imports. A nested snippet that relies on a page-level import may render as empty content.

<Steps>
  <Step title="Import the nested snippet in the parent snippet file">
    Declare the import where you want to use the nested snippet.

    ```mdx shared/parent-snippet.mdx theme={null}
    import ChildSnippet from "/shared/child-snippet.mdx";

    This snippet renders another snippet beneath this sentence.

    <ChildSnippet />
    ```
  </Step>

  <Step title="Import only the parent snippet in your destination file">
    You do not need to import the nested snippet.

    ```mdx destination-file.mdx theme={null}
    ---
    title: "An example page"
    description: "This is an example page that imports a snippet containing a nested snippet."
    ---

    import ParentSnippet from "/shared/parent-snippet.mdx";

    <ParentSnippet />
    ```
  </Step>
</Steps>

### Import variables

Reference variables from a snippet in a page.

<Steps>
  <Step title="Export variables from a snippet file">
    ```mdx shared/custom-variables.mdx theme={null}
    export const myName = "Ronan";

    export const myObject = { fruit: "strawberries" };

    ;
    ```
  </Step>

  <Step title="Import the snippet from your destination file and use the variable">
    ```mdx destination-file.mdx theme={null}
    ---
    title: "An example page"
    description: "This is an example page that imports a snippet with variables."
    ---

    import { myName, myObject } from "/shared/custom-variables.mdx";

    Hello, my name is {myName} and I like {myObject.fruit}.
    ```
  </Step>
</Steps>

### Import snippets with variables

Use variables to pass data to a snippet when you import it.

<Steps>
  <Step title="Add variables to your snippet">
    Pass in properties when you import it. In this example, the variable is `{word}`.

    ```mdx shared/my-snippet.mdx theme={null}
    My keyword of the day is {word}.
    ```
  </Step>

  <Step title="Import the snippet into your destination file with the variable">
    The passed property replaces the variable in the snippet definition.

    ```mdx destination-file.mdx theme={null}
    ---
    title: "An example page"
    description: "This is an example page that imports a snippet with a variable."
    ---

    import MySnippet from "/shared/my-snippet.mdx";

    <MySnippet word="bananas" />
    ```
  </Step>
</Steps>

Variables also interpolate inside fenced code blocks. This is useful for snippets that include installation commands or other code examples that differ by package name, version, or environment.

````mdx shared/install-snippet.mdx theme={null}
export const InstallSnippet = ({ packageName }) => <></>;

Install the package:

```bash
npm install {packageName}
```
````

```mdx destination-file.mdx theme={null}
import InstallSnippet from "/shared/install-snippet.mdx";

<InstallSnippet packageName="@myorg/sdk" />
```

### Import React components

<Steps>
  <Step title="Create a snippet with a JSX component">
    See [React components](/docs/customize/react-components) for more information.

    ```js components/my-jsx-snippet.jsx theme={null}
    export const MyJSXSnippet = () => {
      return (
        <div>
          <h1>Hello, world!</h1>
        </div>
      );
    };
    ```

    <Note>
      When creating JSX snippets, use arrow function syntax (`=>`) rather than function declarations. The `function` keyword is not supported in snippets.
    </Note>
  </Step>

  <Step title="Import the snippet">
    ```mdx destination-file.mdx theme={null}
    ---
    title: "An example page"
    description: "This is an example page that imports a snippet with a React component."
    ---

    import { MyJSXSnippet } from "/components/my-jsx-snippet.jsx";

    <MyJSXSnippet />
    ```
  </Step>
</Steps>


# Format text
Source: https://www.mintlify.com/docs/create/text

Format text in your documentation with Markdown headings, bold, italic, links, blockquotes, and other inline styling options in MDX pages.

## Headings

Headings organize your content and create navigation anchors. They appear in the table of contents and help users scan your documentation.

### Create headings

Use `#` symbols to create headings of different levels:

```mdx theme={null}
## Main section heading
### Subsection heading
#### Sub-subsection heading
```

Use `##` (H2) through `######` (H6) for content sections. The title set in a page's [frontmatter](/docs/organize/pages) applies a title heading, `#` (H1). Do not use top-level `#` headings inside a page.

<Tip>
  Use descriptive, keyword-rich headings that clearly indicate the content that follows. This improves both user navigation and search engine optimization.
</Tip>

### Automatic anchor IDs

By default, Mintlify generates an anchor ID from the heading text. Generated IDs use the following rules:

* Mintlify converts letters to lowercase and whitespace to hyphens.
* Mintlify converts straight apostrophes to right single quotation marks (`’`) and keeps them in the ID.
* Mintlify converts periods to hyphens and removes parentheses.
* Mintlify converts capital letters within a word to lowercase without adding hyphens.
* Mintlify preserves slashes and ampersands.

When a page has multiple headings that generate the same ID, Mintlify adds `-2`, `-3`, and so on. The counter applies across the entire page, including headings nested inside components such as tabs.

The following examples show how heading text maps to a generated anchor ID:

| Heading text                 | Generated ID             |
| :--------------------------- | :----------------------- |
| `Getting started`            | `getting-started`        |
| `Config.json options`        | `config-json-options`    |
| `What's new`                 | `what’s-new`             |
| `Rate limits (per minute)`   | `rate-limits-per-minute` |
| `Read/write access`          | `read/write-access`      |
| `Fees & billing`             | `fees-&-billing`         |
| `OAuth`                      | `oauth`                  |
| Duplicate `Overview` heading | `overview-2`             |

<Note>
  Mintlify's anchor IDs do not use GitHub-style slugging. Percent-encode non-ASCII characters when constructing a URL programmatically.
</Note>

### Custom heading IDs

To override the generated ID with a custom one, use the `{#custom-id}` syntax.

```mdx theme={null}
## My section {#my-custom-anchor}
### Configuration options {#config}
##### Deep detail {#detail}
```

The custom ID replaces the auto-generated anchor, so you can link to the heading with `#my-custom-anchor` or `#config` instead of the default slugified text.

This is useful when you want stable anchor links that don't change if you update the heading text, or when you need shorter, more memorable anchors.

### Disable anchor links

By default, headings include clickable anchor links that allow users to link directly to specific sections. You can disable these anchor links using the `noAnchor` prop in HTML or React headings.

<CodeGroup>
  ```mdx HTML heading example theme={null}
  <h2 noAnchor>
  Heading without anchor link
  </h2>
  ```

  ```mdx React heading example theme={null}
  <Heading level={2} noAnchor>
  Heading without anchor link
  </Heading>
  ```
</CodeGroup>

When `noAnchor` is used, the heading does not display the anchor chip and clicking the heading text does not copy the anchor link to the clipboard.

## Text formatting

Mintlify supports most Markdown formatting for emphasizing and styling text.

### Basic formatting

Apply these formatting styles to your text:

| Style             | Syntax     | Example                | Result                 |
| ----------------- | ---------- | ---------------------- | ---------------------- |
| **Bold**          | `**text**` | `**important note**`   | **important note**     |
| *Italic*          | `_text_`   | `_emphasis_`           | *emphasis*             |
| ~~Strikethrough~~ | `~text~`   | `~deprecated feature~` | ~~deprecated feature~~ |

### Combine formats

You can combine formatting styles:

```mdx theme={null}
**_bold and italic_**
**~~bold and strikethrough~~**
*~~italic and strikethrough~~*
```

***bold and italic***<br />
**~~bold and strikethrough~~**<br />
*~~italic and strikethrough~~*

### Superscript and subscript

For mathematical expressions or footnotes, use HTML tags:

| Type        | Syntax            | Example               | Result              |
| ----------- | ----------------- | --------------------- | ------------------- |
| Superscript | `<sup>text</sup>` | `example<sup>2</sup>` | example<sup>2</sup> |
| Subscript   | `<sub>text</sub>` | `example<sub>n</sub>` | example<sub>n</sub> |

## Links

Links help users navigate between pages and access external resources. Use descriptive link text to improve accessibility and user experience.

### Internal links

Link to other pages in your documentation using root-relative paths. Omit the file extension (`.mdx` or `.md`). Relative paths and paths with extensions do not work in production.

```mdx theme={null}
[Quickstart](/quickstart)
[Steps](/components/steps)
```

[Quickstart](/docs/quickstart)<br />
[Steps](/docs/components/steps)

### External links

For external resources, include the full URL:

```mdx theme={null}
[Markdown Guide](https://www.markdownguide.org/)
```

[Markdown Guide](https://www.markdownguide.org/)

### Broken links

You can check for broken links in your documentation using the [CLI](/docs/cli):

```bash theme={null}
mint broken-links
```

## Block quotes

Block quotes highlight important information, quotes, or examples within your content.

### Single line block quotes

Add `>` before text to create a block quote:

```mdx theme={null}
> This is text that stands out from the main content.
```

> This is text that stands out from the main content.

### Multi-line block quotes

For longer quotes or multiple paragraphs:

```mdx theme={null}
> This is the first paragraph of a multi-line block quote.
>
> This is the second paragraph, separated by an empty line with `>`.
```

> This is the first paragraph of a multi-line block quote.
>
> This is the second paragraph, separated by an empty line with `>`.

<Tip>
  Use block quotes sparingly to maintain their visual impact and meaning. Consider using [callouts](/docs/components/callouts) for notes, warnings, and other information.
</Tip>

## Mathematical expressions

Mintlify supports LaTeX for rendering mathematical expressions and equations. You can override automated detection by configuring `styling.latex` in your `docs.json` [settings](/docs/organize/settings-appearance#styling).

### Inline math

Use single dollar signs, `$`, for inline mathematical expressions:

```mdx theme={null}
The Pythagorean theorem states that $(a^2 + b^2 = c^2)$ in a right triangle.
```

The Pythagorean theorem states that $(a^2 + b^2 = c^2)$ in a right triangle.

### Block equations

Use double dollar signs, `$$`, for standalone equations:

```mdx theme={null}
$$
E = mc^2
$$
```

$$
E = mc^2
$$

<Info>
  LaTeX support requires proper mathematical syntax. Refer to the [LaTeX documentation](https://www.latex-project.org/help/documentation/) for comprehensive syntax guidelines.
</Info>

## Line breaks and spacing

Control spacing and line breaks to improve content readability.

### Paragraph breaks

Separate paragraphs with blank lines:

```mdx theme={null}
This is the first paragraph.

This is the second paragraph, separated by a blank line.
```

This is the first paragraph.

This is the second paragraph, separated by a blank line.

### Manual line breaks

Use HTML `<br />` tags for forced line breaks within paragraphs:

```mdx theme={null}
This line ends here.<br />
This line starts on a new line.
```

This line ends here.<br />
This line starts on a new line.

<Tip>
  In most cases, paragraph breaks with blank lines provide better readability than manual line breaks.
</Tip>

### Horizontal rules

Use Markdown `---` syntax or HTML `<hr />` tags to add a horizontal rule that visually separates sections of content:

```mdx theme={null}
Content preceding the rule.

<hr />

Content following the rule.
```

Content preceding the rule.

<hr />

Content following the rule.

<Tip>
  Use horizontal rules sparingly. In most cases, headings provide better content separation with the added benefit of navigation anchors.
</Tip>

## Comments

Use MDX-style comments to add notes, reminders, or to-dos in your source files. Comments don't render in the published page.

```mdx theme={null}
{/* This is a comment and won't appear in the published docs. */}

{/*
  Multi-line comments work too.
  Useful for TODOs or reviewer notes.
*/}
```

<Warning>
  HTML-style `<!-- ... -->` comments are not supported in MDX. Always use `{/* ... */}`.
</Warning>

## Escape special characters

MDX treats `{` and `}` as the start and end of JSX expressions, and `<` as the start of a JSX tag. When you want these characters to render as literal text, escape them so MDX does not try to parse them.

| Character   | How to escape                                                                                                                                                     |
| :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{` and `}` | Wrap the character in backticks (`` `{` ``), use the HTML entity (`&#123;` for `{`, `&#125;` for `}`), or write it inside a JSX expression as a string (`{'{'}`). |
| `<`         | Wrap in backticks (`` `<` ``), use the HTML entity `&lt;`, or write `{'<'}`.                                                                                      |
| `` ` ``     | Use a backslash (`` \` ``).                                                                                                                                       |
| `\`         | Use a double backslash (`\\`).                                                                                                                                    |

```mdx Escape examples theme={null}
Use the `{variable}` syntax to interpolate values.

The placeholder &#123;name&#125; renders as literal curly braces.

In JSX, write {'{ key: value }'} to display a literal object.
```

Inside fenced code blocks (` ``` `), MDX does not parse curly braces, so you can write `{variable}` directly without escaping. Escaping is only required in regular prose and inside JSX attributes.

## Best practices

### Content organization

* Use headings to create clear content hierarchy
* Follow proper heading hierarchy (don't skip from H2 to H4)
* Write descriptive, keyword-rich heading text

### Text formatting

* Use bold for emphasis, not for entire paragraphs
* Reserve italics for terms, titles, or subtle emphasis
* Avoid over-formatting that distracts from content

### Links

* Write descriptive link text instead of "click here" or "read more"
* Use root-relative paths for internal links
* Test links regularly to prevent broken references


# Custom 404 page
Source: https://www.mintlify.com/docs/customize/custom-404-page

Customize the title, description, and appearance of your documentation site's 404 error page to match your brand and guide visitors.

All 404 pages automatically suggest relevant pages based on the requested URL. If users land on a 404 page, an agent analyzes the path and retrieves semantically related pages from your documentation to help them find what they're looking for.

You can customize the title and description of the 404 error page. Use the description to add helpful links or guidance.

## Configuration

Configure your 404 page in the `errors.404` section of your `docs.json` file:

```json theme={null}
"errors": {
  "404": {
    "redirect": false,
    "title": "I can't be found",
    "description": "What ever **happened** to this _page_?"
  }
}
```

## Parameters

<ResponseField name="redirect" type="boolean">
  Whether to automatically redirect to the home page when a page is not found.

  Set to `true` to redirect to the home page.

  Set to `false` to show the custom 404 page.
</ResponseField>

<ResponseField name="title" type="string">
  Custom title for the 404 error page. This replaces the default "Page not found" heading.
</ResponseField>

<ResponseField name="description" type="string">
  Custom description for the 404 error page. Supports MDX formatting including links, bold, italic text, and custom components.
</ResponseField>


# Custom domain
Source: https://www.mintlify.com/docs/customize/custom-domain

Host your site at your own domain, subdomain, or subpath with DNS records, automatic TLS certificates, and Mintlify-managed or proxy traffic routing.

Host your documentation at your own domain, like `docs.example.com`, or at a subpath on your domain, like `example.com/docs`.

To host your documentation on a custom domain:

1. Add your domain in your dashboard.
2. Configure DNS settings on your domain provider.
3. Allow time for DNS to propagate and TLS certificates to be automatically provisioned.

## Choose where to host your documentation

You can host your documentation at the root of a domain, a subdomain, or a subpath.

**Domain or subdomain**: Host your documentation at a domain like `example.com` or a subdomain like `docs.example.com`. Mintlify serves all traffic for the domain or subdomain. Hosting at a domain with no subdomain requires a DNS provider that supports CNAME flattening or `ALIAS` records. See [Apex domains](#apex-domains).

**Subpath**: Host your documentation at a path on your domain, like `example.com/docs`. Enable the **Host at** toggle when you add your domain and enter your base path. How traffic reaches Mintlify depends on your DNS:

* If your domain's DNS points to Mintlify, Mintlify serves your documentation at your subpath. Only point your domain at Mintlify if it hosts no other content and Mintlify can receive all paths on the domain.
* If another site runs on your domain, your app or CDN keeps receiving traffic for the domain and proxies only your subpath to Mintlify.

<Note>
  Subpath hosting is not supported for documentation with [authentication](/docs/deploy/authentication-setup) enabled.
</Note>

## Add your custom domain

1. Navigate to the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page in your dashboard.
2. To host at a subpath, enable the **Host at** toggle and enter your base path, like `/docs`.
3. Enter your domain name. For example, `docs.example.com` or `example.com`.
4. Click **Add domain**.

If your domain traffic routes to Mintlify, the dashboard displays the DNS records to add at your domain provider.

If you proxy only your subpath to Mintlify, the dashboard displays reverse proxy setup guides instead. Follow the guide for your provider and see [Host docs at a subpath](/docs/deploy/docs-subpath) for more information.

<Tip>
  You can also add a domain from the terminal with [`mint add-domain <domain>`](/docs/cli/commands#mint-add-domain). The command registers the domain on your deployment and prints the DNS records to configure.
</Tip>

### Base path requirements

Your base path can be any path that meets these requirements:

* Starts with `/` and contains no spaces, query strings, or hashes.
* Is at most 128 characters.
* Is not a path that Mintlify reserves: `/_next`, `/_mintlify`, `/_sites`, `/_live-preview`, `/api`, `/login`, `/logout`, `/mcp`, `/feedback`, `/openapi-specs.download`, `/llms.txt`, `/llms-full.txt`, `/sitemap.xml`, `/robots.txt`, `/skill.md`, and `/.well-known`.

### Change your base path

When you change your base path or subpath, Mintlify rebuilds and redeploys your site. Your site stays live at the current path until the deployment finishes, then traffic switches to the new path. If the deployment fails, your site continues serving from the current path and you can retry the change from your dashboard.

## Configure your DNS

<Tip>
  Each domain provider has different ways to add DNS records. Refer to your domain provider's documentation for specific instructions.
</Tip>

1. On your domain provider's website, navigate to your domain's DNS settings.
2. Create the DNS records shown in your dashboard.

The dashboard displays verification `TXT` records and a `CNAME` record:

```text theme={null}
TXT | _acme-challenge.<your-domain> | <value shown in your dashboard>
TXT | _cf-custom-hostname.<your-domain> | <value shown in your dashboard>
CNAME | <your-domain> | cname.mintlify.builders
```

The `_acme-challenge` record authorizes Let's Encrypt to issue a TLS certificate for your domain, and the `_cf-custom-hostname` record verifies that you control the domain.

<Warning>
  Add your `TXT` records first. Do not add or change your `CNAME` until both verification `TXT` records show as verified in your dashboard. Each appears with a green check when DNS is correct. The dashboard verifies `TXT` records before certificate provisioning can complete. Switching `CNAME` too early commonly breaks HTTPS until provisioning finishes.

  If you migrate an existing domain and want zero downtime, publish the verification `TXT` records first. Wait until they show as verified and TLS has been pre-provisioned before pointing `CNAME` at Mintlify.

  This pre-validation flow does not work for domains proxied through Cloudflare. See [Cloudflare-proxied domains](#cloudflare-proxied-domains).
</Warning>

The dashboard polls DNS in the background and marks each record with a green check once it verifies the expected value. After saving records at your DNS provider, allow a short time for propagation before status updates appear.

### Apex domains

If you host your documentation at an apex domain like `example.com` with no subdomain, your DNS provider must support CNAME flattening or a virtual record type like `ALIAS` or `ANAME`. Standard DNS does not allow a `CNAME` record at the apex of a domain. Providers without this support cannot create the record shown in your dashboard.

Providers that support apex `CNAME` records include Cloudflare (CNAME flattening), Amazon Route 53 (alias records), DNSimple (`ALIAS` records), and Porkbun (`ALIAS` records). If your provider does not support any of these, host your documentation at a subdomain like `docs.example.com` instead.

### DNS propagation

DNS changes typically take 1-24 hours to propagate globally, though it can take up to 48 hours in some cases. Use a tool like [DNSChecker](https://dnschecker.org) to verify your DNS configuration is correct.

Once your DNS records are active, your documentation is first accessible via HTTP. HTTPS is available after Mintlify provisions your TLS certificate.

### Automatic TLS provisioning

After you add your `TXT` records and your DNS records resolve correctly, Mintlify generates a free SSL/TLS certificate for your site using Let's Encrypt.

This typically completes within a few hours of DNS propagation, though it can take up to 24 hours in rare cases. Certificates are automatically renewed before expiration.

### CAA records

If your domain uses CAA (Certification Authority Authorization) records, you must authorize Let's Encrypt to issue certificates for your domain. Add the following CAA record to your DNS settings:

```text theme={null}
0 issue "letsencrypt.org"
```

### Reserved paths

Mintlify reserves the `/.well-known/acme-challenge` path for certificate validation. You cannot redirect or rewrite this path. If you have configured redirects or rewrites for this path, certificate provisioning fails.

### Cloudflare-proxied domains

If your domain is already proxied through Cloudflare (the proxy status shows an orange cloud), the verification `TXT` records cannot show as verified before you update your `CNAME`. This happens even when the records resolve correctly with tools like `dig` or DNSChecker. Cloudflare's proxy prevents the verification from completing until traffic for the hostname routes to Mintlify.

For Cloudflare-proxied domains, follow these steps:

1. Add the verification `TXT` records at your DNS provider.
2. Update your `CNAME` record to point to `cname.mintlify.builders` without waiting for the `TXT` records to show as verified.
3. Wait for verification and TLS provisioning to complete. Your site may briefly serve an invalid certificate during provisioning.

If you need zero downtime during migration, set the `CNAME` record's proxy status to **DNS only** (gray cloud) instead. This allows the standard pre-validation flow to complete before you switch traffic.

### Provider-specific settings

<Accordion title="Cloudflare encryption mode">
  If Cloudflare is your DNS provider, you must enable the "Full (strict)" mode for the SSL/TLS encryption setting. Additionally, disable "Always Use HTTPS" in your Edge Certificates settings. Cloudflare's HTTPS redirect blocks Let's Encrypt from validating your domain during certificate provisioning.
</Accordion>

### Retry validation

`TXT` records typically validate within five minutes. If your domain is still pending validation after adding the verification `TXT` records, manually retry validation from your dashboard.

1. Navigate to the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page in your dashboard.
2. Find your pending custom domain.
3. Click **Retry validation**.

Only retry validation after you confirm that your DNS records are correct. Repeated retries with incorrect records do not speed up validation.

## Remove a custom domain

To remove a custom domain, click the <Icon name="trash-2" /> remove icon next to your domain on the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page and confirm the removal. Existing links to the domain may break, and re-adding the domain may require reconfiguring your DNS records.

Removing a domain also releases it so another Mintlify deployment or organization can claim it. If you cannot add a domain because another deployment holds it, see [Add domain fails with "Domain is already claimed by another organization"](/docs/help-center/domain-already-claimed-by-another-organization).

## Set a canonical URL

After configuring your DNS, set a canonical URL to ensure search engines index your preferred domain. A canonical URL tells search engines which version of your documentation is the primary one. This improves SEO when your documentation is accessible from multiple URLs and prevents issues with duplicate content.

Add the `canonical` meta tag to your `docs.json`:

```json theme={null}
"seo": {
    "metatags": {
        "canonical": "https://www.your-custom-domain-here.com"
    }
}
```

Replace `https://www.your-custom-domain-here.com` with your actual custom domain. For example, if your custom domain is `docs.mintlify.com`, you would use:

```json theme={null}
"seo": {
    "metatags": {
        "canonical": "https://docs.mintlify.com"
    }
}
```


# Custom scripts
Source: https://www.mintlify.com/docs/customize/custom-scripts

Add custom JavaScript and CSS for analytics, widgets, styling, third-party integrations, and API playground server variables on your documentation site.

Use CSS to style HTML elements or add custom CSS and JavaScript to fully customize the look and feel of your documentation.

## Style with Tailwind CSS

Use Tailwind CSS v3 to style HTML elements. You can control layout, spacing, colors, and other visual properties. Some common classes are:

* `w-full` - Full width
* `aspect-video` - 16:9 aspect ratio
* `rounded-xl` - Large rounded corners
* `block`, `hidden` - Display control
* `dark:hidden`, `dark:block` - Dark mode visibility

Tailwind CSS arbitrary values are not supported. For custom values, use the `style` prop instead.

```html theme={null}
<img style={{ width: '350px', margin: '12px auto' }} src="/path/image.jpg" />
```

<Warning>
  Using the `style` prop can cause a layout shift on page load, especially on custom mode pages. Use Tailwind CSS classes or custom CSS files instead to avoid shifts or flickering.
</Warning>

## Add custom CSS

Mintlify includes any `.css` file inside your content directory on every page of your site. You do not need to import or reference the file from `docs.json` or your MDX files.

To add custom styles, create a `.css` file in your content directory. Any class names, ID selectors, or element selectors you define become available across all of your MDX files.

For example, define a class in `style.css`:

```css Example style.css theme={null}
.my-callout {
  border-radius: 1rem;
  background: #f0f9ff;
  padding: 1rem;
}
```

You can combine custom class names with [Tailwind CSS](#style-with-tailwind-css) classes on the same element.

The references and styling of common elements are subject to change. Use custom styling with caution since breaking changes may occur in future updates.

For example, you can add the following `style.css` file to customize the styling of the navbar and footer.

```css theme={null}
#navbar {
  background: #fffff2;
  padding: 1rem;
}

footer {
  margin-top: 2rem;
}
```

Mintlify exposes two types of CSS targeting hooks:

* **ID selectors**: unique page-level elements targeted with `#value { }` in CSS
* **Element selectors**: component and layout elements targeted with `value { }` in CSS (no `#` or `.` prefix)

<Tip>
  Use inspect element to find references to elements you're looking to customize.
</Tip>

### ID selectors

Each ID appears once per page. Use these as `#value` in CSS. For example, `#navbar { background: red; }`.

<AccordionGroup>
  <Accordion title="Page layout">
    * `#body-content`: Outermost wrapper for the page body.
    * `#content-area`: Primary content area, excluding the sidebar and table of contents.
    * `#content`: Inner content element within the content area.
    * `#header`: Page-level header element.
    * `#banner`: Announcement banner displayed above the navbar.
    * `#footer`: Page footer. Also targetable as an element selector: `footer`.
    * `#page-title`: The `<h1>` heading at the top of each page.
    * `#pagination`: Bottom pagination bar with previous and next page links.
    * `#panel`: Floating panel overlay. Also targetable as an element selector: `panel`.
    * `#background-color`: Page background color element.
  </Accordion>

  <Accordion title="Navigation">
    * `#navbar`: Top navigation bar.
    * `#topbar-cta-button`: Call-to-action button in the topbar.
    * `#mobile-nav`: Mobile navigation overlay.
    * `#mobile-nav-content`: Content area within the mobile navigation overlay.
  </Accordion>

  <Accordion title="Sidebar">
    * `#sidebar`: The sidebar navigation panel.
    * `#sidebar-content`: Scrollable content area within the sidebar.
  </Accordion>

  <Accordion title="Table of contents">
    * `#table-of-contents`: Table of contents panel on the right side of the page.
    * `#table-of-contents-layout`: Layout wrapper for the table of contents.
    * `#table-of-contents-content`: Scrollable content within the table of contents.
  </Accordion>

  <Accordion title="Search">
    * `#search-bar-entry`: Search bar trigger in the topbar.
    * `#search-bar-entry-mobile`: Search bar trigger on mobile.
    * `#search-input`: Text input field within the search modal.
  </Accordion>

  <Accordion title="AI assistant">
    * `#assistant-entry`: AI assistant button in the topbar.
    * `#assistant-entry-mobile`: AI assistant button on mobile.
    * `#chat-assistant-sheet`: AI assistant chat panel.
    * `#chat-assistant-textarea`: Text input within the AI assistant panel.
  </Accordion>

  <Accordion title="API reference">
    * `#request-example`: Request example panel in the API playground.
    * `#response-example`: Response example panel in the API playground.
    * `#api-playground-input`: Input section of the API playground.
    * `#endpoints-menu-trigger`: Button that opens the endpoint selector dropdown.
  </Accordion>

  <Accordion title="Code blocks">
    * `#ask-assistant-code-block-button`: "Ask Assistant" button that appears on code blocks.
    * `#code-snippet-feedback-button`: Feedback button on code snippets.
    * `#code-snippet-feedback-textarea`: Text area within the code snippet feedback form.
  </Accordion>

  <Accordion title="Feedback">
    * `#feedback-thumbs-up`: Thumbs-up feedback button at the bottom of a page.
    * `#feedback-thumbs-down`: Thumbs-down feedback button at the bottom of a page.
    * `#feedback-form`: Feedback form shown after a thumbs-down response.
    * `#feedback-form-input`: Text input within the feedback form.
    * `#feedback-form-cancel`: Cancel button within the feedback form.
    * `#feedback-form-submit`: Submit button within the feedback form.
  </Accordion>

  <Accordion title="Page context menu">
    * `#page-context-menu`: Contextual options menu for the current page.
    * `#page-context-menu-button`: Button that triggers the page context menu.
  </Accordion>

  <Accordion title="Localization">
    * `#localization-select-trigger`: Button that opens the language selector.
    * `#localization-select-content`: Dropdown content of the language selector.
    * `#localization-select-item`: Individual language option within the selector.
  </Accordion>

  <Accordion title="Changelog">
    * `#changelog-filters`: Filter controls on a changelog page.
    * `#changelog-filters-content`: Content area within the changelog filter panel.
  </Accordion>

  <Accordion title="Multi-view">
    * `#multi-view-dropdown`: Dropdown for switching between documentation views.
  </Accordion>

  <Accordion title="Text selection">
    * `#text-selection-tooltip`: Tooltip that appears when you select text on a page.
    * `#text-selection-tooltip-button`: Action button within the text selection tooltip.
  </Accordion>
</AccordionGroup>

### Element selectors

Multiple instances of these elements can appear on a page. Use these as `value` in CSS. For example, `accordion { border: 1px solid red; }`.

<AccordionGroup>
  <Accordion title="Content components">
    * `accordion`: Collapsible accordion item.
    * `accordion-group`: Wrapper grouping multiple accordions.
    * `callout`: Callout block (Note, Warning, Tip, etc.).
    * `card`: Individual card element.
    * `card-group`: Wrapper grouping multiple cards. Deprecated in favor of `columns`, but preserved for backward compatibility.
    * `columns`: Multi-column layout wrapper.
    * `code-block`: Code block element.
    * `code-block-icon`: Icon displayed in a code block header.
    * `code-group`: Tabbed group of code blocks.
    * `expandable`: Expandable section element.
    * `frame`: Frame wrapper for images or embedded content.
    * `icon`: Inline icon element.
    * `mermaid`: Mermaid diagram wrapper.
    * `step`: Individual step within a steps sequence.
    * `steps`: Numbered steps container.
    * `tab-icon`: Icon displayed within a tab.
    * `tabs`: Tabbed content container.
    * `tile`: Tile component element.
    * `tooltip`: Tooltip element.
    * `update`: Changelog update entry.
  </Accordion>

  <Accordion title="Page layout">
    * `mdx-content`: Rendered MDX content area.
    * `panel`: Floating panel component. Also targetable as an ID selector: `#panel`.
    * `eyebrow`: Small label displayed above a page title.
    * `link`: Anchor link element.
    * `breadcrumb-list`: Breadcrumb navigation list.
    * `breadcrumb-item`: Individual breadcrumb item.
  </Accordion>

  <Accordion title="Topbar navigation">
    * `nav-logo`: Logo in the navigation bar.
    * `navbar-link`: Link element within the navigation bar.
    * `nav-anchors`: Container for anchor links in the topbar.
    * `nav-anchor`: Individual anchor link in the topbar.
    * `nav-tabs`: Tab bar in the top navigation.
    * `nav-tabs-item`: Individual tab item in the top navigation tab bar.
    * `mobile-nav-tabs-item`: Tab item in the mobile navigation tab bar.
    * `topbar-right-container`: Right section of the topbar.
    * `nav-tag-pill`: Tag pill shown in the navigation.
    * `nav-tag-pill-text`: Text within a navigation tag pill.
  </Accordion>

  <Accordion title="Topbar dropdown">
    * `nav-dropdown-trigger`: Button that opens a navigation dropdown.
    * `nav-dropdown-content`: Content container for a navigation dropdown.
    * `nav-dropdown-item`: Individual item within a navigation dropdown.
    * `nav-dropdown-item-text-container`: Text wrapper within a dropdown item.
    * `nav-dropdown-item-title`: Title text within a dropdown item.
    * `nav-dropdown-item-description`: Description text within a dropdown item.
    * `nav-dropdown-item-icon`: Icon within a dropdown item.
  </Accordion>

  <Accordion title="Products selector">
    * `nav-dropdown-products-selector-trigger`: Button that opens the products selector dropdown.
    * `nav-dropdown-products-selector-content`: Content container for the products selector.
    * `nav-dropdown-products-selector-item`: Individual product in the selector.
    * `nav-dropdown-products-selector-item-title`: Title of a product selector item.
    * `nav-dropdown-products-selector-item-description`: Description of a product selector item.
    * `nav-dropdown-products-selector-item-icon`: Icon of a product selector item.
  </Accordion>

  <Accordion title="Sidebar">
    * `sidebar-group`: Group of related sidebar links.
    * `sidebar-group-icon`: Icon for a sidebar group.
    * `sidebar-group-header`: Header label for a sidebar group.
    * `sidebar-title`: Top-level title in the sidebar.
    * `sidebar-nav-group-divider`: Divider between sidebar navigation groups.
  </Accordion>

  <Accordion title="Table of contents">
    * `toc`: Table of contents container.
    * `toc-item`: Individual heading entry in the table of contents.
  </Accordion>

  <Accordion title="Footer">
    * `footer`: Standard page footer. Also targetable as an ID selector: `#footer`.
    * `advanced-footer`: Extended footer with additional columns or content.
  </Accordion>

  <Accordion title="Pagination">
    * `pagination-prev`: Previous page link in the pagination bar.
    * `pagination-next`: Next page link in the pagination bar.
    * `pagination-title`: Page title shown in the pagination bar.
  </Accordion>

  <Accordion title="API reference">
    * `api-section`: Full section for a single API endpoint.
    * `api-section-heading`: Heading area for an API endpoint section.
    * `api-section-heading-title`: Title within an API endpoint section heading.
    * `api-section-heading-subtitle`: Subtitle within an API endpoint section heading.
    * `field`: Parameter or property field in the API reference.
    * `option-dropdown`: Dropdown for selecting between API options.
    * `tryit-button`: "Try it" button that opens the API playground.
    * `method-pill`: HTTP method badge (GET, POST, etc.) on an endpoint.
    * `method-nav-pill`: HTTP method badge shown in the sidebar navigation.
    * `prompt`: Prompt component in the API reference.
  </Accordion>

  <Accordion title="AI assistant">
    * `chat-assistant-sheet`: AI assistant panel container.
    * `chat-assistant-sheet-header`: Header of the AI assistant panel.
    * `chat-assistant-sheet-content`: Content area of the AI assistant panel.
    * `chat-assistant-input`: Text input within the AI assistant panel.
    * `chat-assistant-floating-input`: Floating input variant of the AI assistant.
    * `chat-assistant-send-button`: Send button in the AI assistant panel.
    * `chat-assistant-disclaimer-text`: Disclaimer text displayed in the AI assistant panel.
    * `chat-assistant-payload-item`: Individual message or result item in the assistant panel.
    * `starter-question-text`: Suggested starter question shown in an empty assistant panel.
  </Accordion>

  <Accordion title="Feedback">
    * `feedback-toolbar`: Toolbar containing page feedback controls.
    * `contextual-feedback-container`: Container for contextual inline feedback.
    * `contextual-feedback-form`: Inline contextual feedback form.
    * `contextual-feedback-form-title`: Title of the contextual feedback form.
    * `contextual-feedback-input`: Text input within the contextual feedback form.
    * `contextual-feedback-button`: Action button within the contextual feedback form.
    * `contextual-feedback-form-submit-button`: Submit button for the contextual feedback form.
  </Accordion>

  <Accordion title="Code snippet feedback">
    * `code-snippet-feedback-popover-content`: Popover content for code snippet feedback.
    * `code-snippet-feedback-form`: Feedback form for a code snippet.
    * `code-snippet-feedback-textarea`: Text area within the code snippet feedback form.
    * `code-snippet-feedback-form-title`: Title of the code snippet feedback form.
    * `code-snippet-feedback-form-description`: Description text in the code snippet feedback form.
    * `code-snippet-feedback-form-submit-button`: Submit button for the code snippet feedback form.
  </Accordion>

  <Accordion title="Authentication">
    * `login-link`: Link that initiates the login flow.
    * `logout-link`: Link that initiates the logout flow.
  </Accordion>

  <Accordion title="Multi-view">
    * `multi-view-item`: Individual view option in a multi-view switcher.
    * `multi-view-dropdown`: Dropdown for selecting between multiple views.
    * `multi-view-dropdown-trigger`: Button that opens the multi-view dropdown.
    * `multi-view-dropdown-content`: Content area of the multi-view dropdown.
    * `multi-view-dropdown-item`: Individual item within the multi-view dropdown.
  </Accordion>

  <Accordion title="Directory">
    * `directory`: Root container for a directory page.
    * `directory-group`: Group of related pages within a directory.
    * `directory-page`: Individual page entry in a directory.
    * `directory-card`: Card-style page entry in a directory.
  </Accordion>

  <Accordion title="404 page">
    * `not-found-container`: Root container of the 404 page.
    * `not-found-status-code`: Status code display on the 404 page.
    * `not-found-title`: Title heading on the 404 page.
    * `not-found-description`: Description text on the 404 page.
    * `not-found-recommended-pages-list`: List of recommended pages shown on the 404 page.
    * `not-found-recommended-page-link`: Individual link in the recommended pages list.
  </Accordion>

  <Accordion title="Color">
    * `color`: Color swatch element.
    * `color-row`: Row grouping color swatches.
    * `color-item`: Individual color item within a color row.
  </Accordion>

  <Accordion title="Tree">
    * `tree`: File tree container.
    * `tree-folder`: Folder entry within a file tree.
    * `tree-file`: File entry within a file tree.
  </Accordion>

  <Accordion title="Data attributes">
    Some elements expose data attributes you can use as CSS selectors.

    Active state (`data-active`):

    * `nav-dropdown-item[data-active]`: Active item in a nav dropdown.
    * `mobile-nav-tabs-item[data-active]`: Active tab in the mobile nav.
    * `sidebar-group[data-active]`: Active sidebar group.
    * `#sidebar-content li[data-active]`: Active sidebar link.
    * `.nav-tabs-item[data-active]`: Active top nav tab. Only applies to simple tabs; tabs with dropdown menus do not receive `data-active`. Note the leading `.`: this targets a class on a standard `<a>` element, unlike most other components which use custom element names.
    * `toc-item[data-active]`: Active table of contents item.
    * `toc-item[data-active-deepest]`: Deepest active table of contents item. Only present on the exact heading currently in view, unlike `data-active` which is also set on its parent headings.

    Component name (`data-component-name`):

    Use `data-component-name` to target specific UI components with a stable selector that persists if internal class names change.

    * `[data-component-name="mermaid-container"]`: Mermaid diagram wrapper, including the zoom controls overlay.
    * `[data-component-name="mermaid-controls-wrapper"]`: Mermaid zoom and pan controls.
    * `[data-component-name="primary-header-button"]`: Primary header button. Sequoia theme only.
    * `[data-component-name="theme-toggle"]`: Theme toggle.

    Component part (`data-component-part`):

    Use `data-component-part` to target sub-elements within a component.

    * `[data-component-part="contact-support-button"]`: The `<a>` wrapper around the contact support link in the assistant panel.
    * `[data-component-part="contact-support-icon"]`: The `<span>` wrapping the icon.
    * `[data-component-part="contact-support-text"]`: The `<p>` element containing the label.

    Badge attributes:

    * `[data-badge]`: Any badge element.
    * `[data-badge][data-color="blue"]`: Badge filtered by color.
    * `[data-badge][data-size="sm"]`: Badge filtered by size.

    Current path (`data-current-path`):

    Use `data-current-path` to style custom CSS on specific pages or subpaths.

    * `html[data-current-path="/"]`: Matches the root page.
    * `html[data-current-path="/quickstart"]`: Matches a specific page.
    * `html[data-current-path^="/api-reference/"]`: Matches any page under a section.
  </Accordion>
</AccordionGroup>

## Custom JavaScript

Custom JavaScript lets you add custom executable code globally. It is the equivalent of adding a `<script>` tag with JavaScript code into every page.

Mintlify includes any `.js` file inside your content directory on every page of your site. Custom JavaScript files run after the page becomes interactive. You cannot scope them to specific pages. When you include multiple `.js` files, they run without a guaranteed order.

To load a third-party script, inject a `<script>` element from your custom JavaScript file instead of adding raw `<script src="...">` tags in MDX:

```js Example third-party script theme={null}
const script = document.createElement('script');
script.src = 'https://example.com/widget.js';
script.async = true;
document.head.appendChild(script);
```

For example, you can add the following `ga.js` file to enable [Google Analytics](https://marketingplatform.google.com/about/analytics) across your entire site.

```js theme={null}
window.dataLayer = window.dataLayer || [];
function gtag() {
  dataLayer.push(arguments);
}
gtag('js', new Date());

gtag('config', 'TAG_ID');
```

<Warning>
  Use with caution to avoid introducing security vulnerabilities.
</Warning>

### Set API playground server variables

Use `window.mintlify.api.playground.setServerVariables` to prefill [OpenAPI server variables](/docs/api-playground/openapi-setup) from custom JavaScript. Use it when values become available after page load. For example, after authentication or a tenant change.

Pass an object of string values. Each call replaces the previous runtime values, which take precedence over OpenAPI defaults and saved values.

```js Set API playground server variables theme={null}
window.mintlify.api.playground.setServerVariables({
  tenantDomain: 'example.us.auth0.com',
});
```

To remove the runtime values, call:

```js Clear API playground server variables theme={null}
window.mintlify.api.playground.clearServerVariables();
```

Calls made before the client initializes queue. Values apply to open and future playgrounds for the current page session and reset after a full-page refresh.

<Warning>
  Do not use server variables for API keys, tokens, or other secrets.
</Warning>

### Access personalized user data

If your site uses [authentication](/docs/deploy/authentication-setup) or [personalization](/docs/create/personalization), custom scripts can read the identified visitor from `window.mintlify.user`. This is the same object exposed to MDX pages as the [`user` variable](/docs/create/personalization#dynamic-mdx-content), so it reflects the `content` field of your user data.

Because custom scripts run before user info resolves, listen for the `mintlify:user` event to identify when the user object is available. The event fires when user info resolves and again on any change. Its `detail` is the user object, or `null` when the visitor is signed out or unidentified.

```js Read the user after it resolves theme={null}
window.addEventListener('mintlify:user', (event) => {
  const user = event.detail;
  if (!user) return; // Signed out or unidentified.

  renderAppLauncher(user);
});
```

If the user has already resolved by the time your script runs, read `window.mintlify.user` directly.

```js Read the current user theme={null}
const user = window.mintlify?.user;
if (user) {
  renderAppLauncher(user);
}
```

`window.mintlify.user` is `undefined` until user info resolves and when the visitor is signed out or unidentified. Use optional chaining when reading nested fields.

<Warning>
  Client-side scripts can access anything you place in the user `content` field. Do not include secrets or credentials that shouldn't be readable in the browser.
</Warning>


# Fonts
Source: https://www.mintlify.com/docs/customize/fonts

Customize typography on your documentation site with Google Fonts or self-hosted font files for headings, body text, and code blocks.

Set a custom font for your entire site or separately for headings and body text. Use Google Fonts, local font files, or externally hosted fonts. The default font varies by theme.

Configure fonts with the [fonts property](/docs/organize/settings-appearance#fonts) in your `docs.json`.

## Google Fonts

Mintlify automatically loads [Google Fonts](https://fonts.google.com) when you specify a font family name in your `docs.json`.

```json docs.json theme={null}
"fonts": {
  "family": "Inter"
}
```

## Local fonts

To use local fonts, place your font files in your project directory and reference them in your `docs.json` configuration.

### Set up local fonts

<Steps>
  <Step title="Add font files to your project">
    For example, create a `fonts` directory and add your font files:

    ```text theme={null}
    your-project/
    ├── fonts/
    │   ├── InterDisplay-Regular.woff2
    │   └── InterDisplay-Bold.woff2
    ├── docs.json
    └── ...
    ```
  </Step>

  <Step title="Configure fonts in docs.json">
    Reference your local fonts using relative paths from your project root:

    ```json docs.json theme={null}
    {
      "fonts": {
        "family": "InterDisplay",
        "source": "/fonts/InterDisplay-Regular.woff2",
        "format": "woff2",
        "weight": 400
      }
    }
    ```
  </Step>
</Steps>

### Local fonts for headings and body

Configure separate local fonts for headings and body text in your `docs.json`:

```json docs.json theme={null}
{
  "fonts": {
    "heading": {
      "family": "InterDisplay",
      "source": "/fonts/InterDisplay-Bold.woff2",
      "format": "woff2",
      "weight": 700
    },
    "body": {
      "family": "InterDisplay",
      "source": "/fonts/InterDisplay-Regular.woff2",
      "format": "woff2",
      "weight": 400
    }
  }
}
```

## Externally hosted fonts

Use externally hosted fonts by referencing a font source URL in your `docs.json`:

```json docs.json theme={null}
{
  "fonts": {
    "family": "Hubot Sans",
    "source": "https://mintlify-assets.b-cdn.net/fonts/Hubot-Sans.woff2",
    "format": "woff2",
    "weight": 400
  }
}
```

## Font configuration reference

<ResponseField name="fonts" type="object">
  Font configuration for your documentation.

  <Expandable title="Fonts">
    <ResponseField name="family" type="string">
      Font family name, such as "Inter" or "Playfair Display."
    </ResponseField>

    <ResponseField name="weight" type="number">
      Font weight, such as 400 or 700. Variable fonts support precise weights such as 550.
    </ResponseField>

    <ResponseField name="source" type="string (uri)">
      URL to your font source, such as `https://mintlify-assets.b-cdn.net/fonts/Hubot-Sans.woff2`, or path to your local font file, such as `/assets/fonts/InterDisplay.woff2`. Google Fonts load automatically when you specify a Google Font `family` name, so you don't need a source URL.
    </ResponseField>

    <ResponseField name="format" type="'woff' | 'woff2'">
      Font file format. Required when using the `source` field.
    </ResponseField>

    <ResponseField name="heading" type="object">
      Override font settings specifically for headings.

      <Expandable title="Heading">
        <ResponseField name="family" type="string">
          Font family name for headings.
        </ResponseField>

        <ResponseField name="weight" type="number">
          Font weight for headings.
        </ResponseField>

        <ResponseField name="source" type="string (uri)">
          URL to your font source, such as `https://mintlify-assets.b-cdn.net/fonts/Hubot-Sans.woff2`, or path to your local font file for headings. Google Fonts load automatically when you specify a Google Font `family` name, so you don't need a source URL.
        </ResponseField>

        <ResponseField name="format" type="'woff' | 'woff2'">
          Font file format for headings. Required when using the `source` field.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="body" type="object">
      Override font settings specifically for body text.

      <Expandable title="Body">
        <ResponseField name="family" type="string">
          Font family name for body text.
        </ResponseField>

        <ResponseField name="weight" type="number">
          Font weight for body text.
        </ResponseField>

        <ResponseField name="source" type="string (uri)">
          URL to your font source, such as `https://mintlify-assets.b-cdn.net/fonts/Hubot-Sans.woff2`, or path to your local font file for body text. Google Fonts load automatically when you specify a Google Font `family` name, so you don't need a source URL.
        </ResponseField>

        <ResponseField name="format" type="'woff' | 'woff2'">
          Font file format for body text. Required when using the `source` field.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>


# React components
Source: https://www.mintlify.com/docs/customize/react-components

Build interactive and reusable elements with custom React components in your Mintlify documentation using JSX, state, and client-side logic.

Build interactive elements in your docs using [React components](https://react.dev) and [hooks](https://react.dev/reference/react/hooks) directly in MDX files.

## Inline components

Declare components directly in your MDX file:

<Counter />

```mdx theme={null}
export const Counter = () => {
  const [count, setCount] = useState(0)
  const increment = () => setCount(count + 1)
  const decrement = () => setCount(count - 1)

  return (
    <div>
      <button onClick={decrement}>-</button>
      <span>{count}</span>
      <button onClick={increment}>+</button>
    </div>
  )
}

<Counter />
```

## Constraints

React components in Mintlify run in a sandboxed MDX environment with the following constraints:

* **React hooks are pre-injected**: `useState`, `useEffect`, `useRef`, `useCallback`, `useMemo`, `useContext`, and `useReducer` are available without importing them.
* **No external npm packages**: You cannot import third-party packages (for example, `lodash`, `axios`, `date-fns`). Use browser built-ins or write the logic inline.
* **No default exports**: Use named exports (`export const MyComponent = ...`). Default exports (`export default`) are not supported.
* **No cross-snippet imports**: Snippet files cannot import other snippet files. Import all dependencies directly in the parent MDX file.
* **No JSON imports**: Importing `.json` files is not supported.
* **No code splitting**: `React.lazy` and dynamic `import()` are not supported. All component code on a page, including imported snippets, compiles into the page and loads with it.

## Import components

Component files must be in the `/snippets/` folder. Learn more about [reusable snippets](/docs/create/reusable-snippets).

<Note>
  Nested imports are not supported. Import all referenced components directly into the parent MDX file.
</Note>

Create a component file in `snippets/`:

```mdx /snippets/color-generator.jsx [expandable] theme={null}
export const ColorGenerator = () => {
  const [hue, setHue] = useState(180)
  const [saturation, setSaturation] = useState(50)
  const [lightness, setLightness] = useState(50)
  const [colors, setColors] = useState([])

  useEffect(() => {
    const newColors = []
    for (let i = 0; i < 5; i++) {
      const l = Math.max(10, Math.min(90, lightness - 20 + i * 10))
      newColors.push(`hsl(${hue}, ${saturation}%, ${l}%)`)
    }
    setColors(newColors)
  }, [hue, saturation, lightness])

  const copyToClipboard = (color) => {
    navigator.clipboard
      .writeText(color)
      .then(() => {
        console.log(`Copied ${color} to clipboard!`)
      })
      .catch((err) => {
        console.error("Failed to copy: ", err)
      })
  }

  return (
    <div className="p-4 border dark:border-zinc-950/80 rounded-xl not-prose">
      <div className="space-y-4">
        <div className="space-y-2">
          <label className="block text-sm text-zinc-950/70 dark:text-white/70">
            Hue: {hue}°
            <input
              type="range"
              min="0"
              max="360"
              value={hue}
              onChange={(e) => setHue(Number.parseInt(e.target.value))}
              className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
              style={{
                background: `linear-gradient(to right, 
                  hsl(0, ${saturation}%, ${lightness}%), 
                  hsl(60, ${saturation}%, ${lightness}%), 
                  hsl(120, ${saturation}%, ${lightness}%), 
                  hsl(180, ${saturation}%, ${lightness}%), 
                  hsl(240, ${saturation}%, ${lightness}%), 
                  hsl(300, ${saturation}%, ${lightness}%), 
                  hsl(360, ${saturation}%, ${lightness}%))`,
              }}
            />
          </label>

          <label className="block text-sm text-zinc-950/70 dark:text-white/70">
            Saturation: {saturation}%
            <input
              type="range"
              min="0"
              max="100"
              value={saturation}
              onChange={(e) => setSaturation(Number.parseInt(e.target.value))}
              className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
              style={{
                background: `linear-gradient(to right, 
                  hsl(${hue}, 0%, ${lightness}%), 
                  hsl(${hue}, 50%, ${lightness}%), 
                  hsl(${hue}, 100%, ${lightness}%))`,
              }}
            />
          </label>

          <label className="block text-sm text-zinc-950/70 dark:text-white/70">
            Lightness: {lightness}%
            <input
              type="range"
              min="0"
              max="100"
              value={lightness}
              onChange={(e) => setLightness(Number.parseInt(e.target.value))}
              className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
              style={{
                background: `linear-gradient(to right, 
                  hsl(${hue}, ${saturation}%, 0%), 
                  hsl(${hue}, ${saturation}%, 50%), 
                  hsl(${hue}, ${saturation}%, 100%))`,
              }}
            />
          </label>
        </div>

        <div className="flex space-x-1">
          {colors.map((color, idx) => (
            <div
              key={idx}
              className="h-16 rounded flex-1 cursor-pointer transition-transform hover:scale-105"
              style={{ backgroundColor: color }}
              title={`Click to copy: ${color}`}
              onClick={() => copyToClipboard(color)}
            />
          ))}
        </div>

        <div className="text-sm font-mono text-zinc-950/70 dark:text-white/70">
          <p>
            Base color: hsl({hue}, {saturation}%, {lightness}%)
          </p>
        </div>
      </div>
    </div>
  )
}
```

Then import and use it:

```mdx theme={null}
import { ColorGenerator } from "/snippets/color-generator.jsx"

<ColorGenerator />
```

<ColorGenerator />

## Considerations

* **SEO**: Search engines may not fully index client-rendered dynamic content.
* **Initial load**: Visitors may see a flash before components render.
* **Accessibility**: Ensure screen readers announce dynamic content changes.
* **Optimize dependency arrays**: Only include necessary dependencies in `useEffect`.
* **Memoize expensive operations**: Use `useMemo` or `useCallback` where appropriate.
* **Reduce re-renders**: Break large components into smaller ones.
* **Lazy loading**: Component code cannot lazy load. All components load with the page. If a component performs resource-intensive operations when it mounts, such as fetching data or heavy computation, use conditional rendering to defer mounting it until user interaction.


# Themes
Source: https://www.mintlify.com/docs/customize/themes

Choose and configure a theme to customize your documentation site's colors, dark mode behavior, layout style, and overall visual appearance.

<div>
  <label>Core Concepts</label>
  <h1>Themes</h1>
  <label>Customize the appearance of your documentation<br /><br />Configure [theme](/docs/organize/settings-appearance#theme) in docs.json using one of the following themes.</label>

  <br />

  <div>
    <ThemeCard title="Mint" description="Classic documentation theme with time-tested layouts and familiar navigation." href="https://mint.mintlify.site" />

    <ThemeCard title="Maple" description="Modern, clean aesthetics perfect for AI and SaaS products." href="https://maple.mintlify.site" />

    <ThemeCard title="Palm" description="Sophisticated fintech theme with deep customization for enterprise documentation." href="https://palm.mintlify.site" />

    <ThemeCard title="Willow" description="Stripped-back essentials for distraction-free documentation." href="https://willow.mintlify.site" />

    <ThemeCard title="Linden" description="Retro terminal vibes with monospace fonts for that 80s hacker aesthetic." href="https://linden.mintlify.site" />

    <ThemeCard title="Almond" description="Card-based organization meets minimalist design for intuitive navigation." href="https://almond.mintlify.site" />

    <ThemeCard title="Aspen" description="Modern documentation crafted for complex navigation and custom components." href="https://aspen.mintlify.site" />

    <ThemeCard title="Sequoia" description="Minimal, elegant layouts designed for large-scale content-focused documentation." href="https://sequoia.mintlify.site" />

    <ThemeCard title="Luma" description="Clean, minimal design for polished documentation." href="https://luma.mintlify.site" />
  </div>
</div>


# Bitbucket Cloud
Source: https://www.mintlify.com/docs/deploy/bitbucket

Connect a Bitbucket Cloud repository to Mintlify for automatic deployments, pull request previews, and continuous synchronization.

<Info>
  Bitbucket Cloud requires an [Enterprise plan](https://mintlify.com/pricing?ref=bitbucket-cloud).
</Info>

Mintlify connects to Bitbucket Cloud through OAuth. After you connect a repository, Mintlify automatically deploys changes pushed to your deployment branch and creates preview deployments for pull requests.

Mintlify supports Bitbucket Cloud repositories hosted on `bitbucket.org`. Bitbucket Data Center, the Slack agent, and automations do not support Bitbucket repositories.

## Requirements

* A Bitbucket Cloud account
* Permission to create a webhook in the repository you want to connect
* Admin access to your Mintlify organization
* A `docs.json` file in your repository

## Set up a new Bitbucket connection

When you open [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) for the first time, a setup wizard guides you through connecting your Bitbucket repository.

<Steps>
  <Step title="Select Bitbucket as your provider">
    1. On the [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) page, click **Connect to Bitbucket**.
    2. Click **Continue**.
  </Step>

  <Step title="Move Mintlify-hosted content">
    If you currently host your content in a Mintlify-managed repository, download it as a zip file. Extract the zip contents and push the files to your Bitbucket repository.

    If your content is already in Bitbucket, click **Continue setup**.
  </Step>

  <Step title="Authorize Bitbucket">
    1. Click **Connect Bitbucket**.
    2. Bitbucket opens a new page. Authorize Mintlify to access the repository you want to connect.

    After authorization, Bitbucket redirects you to your Mintlify Git settings.
  </Step>

  <Step title="Configure the repository">
    Enter the following values:

    * **Workspace**: The slug of the Bitbucket workspace that owns the repository. For example, in `https://bitbucket.org/acme/docs`, `acme` is the workspace slug.
    * **Repository**: The repository slug. For example, in `https://bitbucket.org/acme/docs`, `docs` is the repository slug.
    * **Deploy branch**: The branch that publishes to your production documentation site, such as `main`.
  </Step>

  <Step title="Configure a content directory (optional)">
    1. If your `docs.json` file is in a subdirectory, enable **Docs are in a subdirectory** on your Git settings page.
    2. Enter the path to the directory that contains your `docs.json` file. For example, if your `docs.json` is in the `apps/docs/` directory, enter `apps/docs`.
  </Step>

  <Step title="Connect the repository">
    1. Click **Connect**.
    2. Confirm the change. Mintlify verifies that the authorized Bitbucket account can access your repository and registers the webhook that triggers deployments and pull request previews.
  </Step>
</Steps>

## Update an existing connection

1. Navigate to the [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) page of your Mintlify dashboard.
2. Expand the **Bitbucket OAuth** section.
3. Enable or disable individual repositories. Disabling a repository removes its Mintlify webhook.

Revoking a connection removes the Mintlify webhooks for every repository connected through that account.

## Configure multiple repositories

You can combine content from multiple Bitbucket repositories in one site. Every source in the deployment must use Bitbucket, and you must enable each repository under **Bitbucket OAuth** before you add it as a source.

See [Multi-repository deployments](/docs/deploy/multi-repo) for setup instructions and information about URL paths, base sources, and navigation.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Repository not authorized">
    If Mintlify reports that no connected installation can access your repository, check the following:

    * The workspace and repository values use the correct slugs, not display names.
    * The connected Bitbucket account has the necessary permissions to access the repository.
    * You enabled the repository in the **Bitbucket OAuth** section of your Mintlify Git settings.

    If the repository does not appear, reconnect your Bitbucket account with an account that has access to the repository.
  </Accordion>

  <Accordion title="Deployments do not trigger automatically">
    In Bitbucket, open **Repository settings** > **Webhooks** and verify that an active webhook named **Mintlify** exists. If it is missing, return to your Mintlify Git settings, disable the repository under **Bitbucket OAuth**, then enable it again.

    Verify that the branch in your Mintlify Git settings matches the Bitbucket branch you push changes to.
  </Accordion>

  <Accordion title="Pull request previews do not appear">
    Verify that the Mintlify webhook is active and includes pull request events. If your Bitbucket permissions changed after you connected the repository, reconnect your Bitbucket account and enable the repository again.
  </Accordion>
</AccordionGroup>


# CI checks
Source: https://www.mintlify.com/docs/deploy/ci

Automate documentation quality checks in your CI/CD pipeline with broken link detection, linting, grammar validation, and build previews.

<Info>
  [Pro and Enterprise plans](https://mintlify.com/pricing?ref=docs-ci) include CI checks for GitHub repositories.
</Info>

Use CI checks to lint your docs for errors and provide warnings before you deploy. Mintlify CI checks run on pull requests against a configured deployment branch.

## Installation

To begin, follow the steps on the [GitHub](/docs/deploy/github) page.

## Configuration

Configure the CI checks enabled for a deployment by navigating to the [Add-ons](https://app.mintlify.com/products/addons) page of your dashboard. Enable the checks that you want to run.

When enabling checks, you can choose to run them at a `Warning` or `Blocking` level.

* A `Warning` level check never provides a failure status, even if there is an error or suggestions.
* A `Blocking` level check provides a failure status if there is an error or suggestions.

## Available CI checks

### Broken links

The broken link CI check works like the [CLI link checker](/docs/cli/commands#mint-broken-links). It automatically searches your documentation for broken internal links between pages within your site. It does not check external links to other websites.

To see detailed results for broken links on a pull request, click the **Checks** tab, then click the Mintlify broken links check. The results list any files with broken links found in the pull request.

### Vale

[Vale](https://vale.sh/) is an open source rule-based prose linter which supports a range of document types, including Markdown and MDX. Use Vale to check for consistency of style and tone in your documentation.

Mintlify supports automatically running Vale in a CI check and displaying the results as a check status.

#### Configuration

If you have a `.vale.ini` file in the root content directory of your deployment, the Vale CI check uses that configuration file and any configuration files in your specified `StylesPath`.

If you don't have a Vale config file, the default configuration automatically loads.

<Note>
  The default configuration runs in Mintlify's build environment, where `StylesPath = /app/styles` points to an internal directory. If you create your own `.vale.ini` file, use a relative path within your repository, such as `StylesPath = styles`.

  For security reasons, you cannot use absolute paths or paths containing `..` in your configuration files.
</Note>

```mdx Default vale.ini configuration expandable theme={null}
# Top level styles
StylesPath = /app/styles
MinAlertLevel = suggestion
# Inline HTML tags to ignore (code/tt for code snippets, img/url for links/images, a for anchor tags)
IgnoredScopes = code, tt, img, url, a
SkippedScopes = script, style, pre, figure

# Vocabularies
Vocab = Mintlify

# Parse MDX as MD to avoid fragility with JSX
[formats]
mdx = md

# Only match MDX
[*.mdx]
BasedOnStyles = Vale
Vale.Terms = NO # Enforces really harsh capitalization rules, keep off

# Ignore JSX/MDX-specific syntax patterns
# `import ...`, `export ...`
# `<Component ... />`
# `<Component>...</Component>`
# `{ ... }`
TokenIgnores = (?sm)((?:import|export) .+?$), \
(?<!`)(<\w+ ?.+ ?\/>)(?!`), \
(<[A-Z]\w+>.+?<\/[A-Z]\w+>), \
\{[^}]*\}

# Exclude multiline JSX and curly braces
# `<Component \n ... />`
BlockIgnores = (?sm)^(<\w+\n .*\s\/>)$, \
(?sm)^({.+.*})
```

The default Vale vocabulary includes the following words.

```text Default Vale vocabulary expandable theme={null}
Mintlify
mintlify
VSCode
openapi
OpenAPI
GitHub
APIs

repo
npm
dev

Lorem
ipsum
impsum
amet

const
myName
myObject
bearerAuth
favicon
topbar
url
borderRadius
args
modeToggle
ModeToggle
isHidden
autoplay

_italic_
Strikethrough
Blockquotes
Blockquote
Singleline
Multiline

onboarding

async
await
boolean
enum
func
impl
init
instanceof
typeof
params
stdin
stdout
stderr
stdout
stdin
var
const
let
null
undefined
struct
bool

cors
csrf
env
xhr
xhr2
jwt
oauth
websocket
localhost
middleware
runtime
webhook
stdin
stdout

json
yaml
yml
md
txt
tsx
jsx
css
scss
html
png
jpg
svg

cdn
cli
css
dom
dto
env
git
gui
http
https
ide
jvm
mvc
orm
rpc
sdk
sql
ssh
ssl
tcp
tls
uri
url
ux
ui

nodejs
npm
yarn
pnpm
eslint
pytest
golang
rustc
kubectl
mongo
postgres
redis

JavaScript
TypeScript
Python
Ruby
Rust
Go
Golang
Java
Kotlin
Swift
Node.js
NodeJS
Deno

React
Vue
Angular
Next.js
Nuxt
Express
Django
Flask
Spring
Laravel
Redux
Vuex
TensorFlow
PostgreSQL
MongoDB
Redis
PNPM

Docker
Kubernetes
AWS
Azure
GCP
Terraform
Jenkins
CircleCI
GitLab
Heroku

Git
git
GitHub
GitLab
Bitbucket
VSCode
Visual Studio Code
IntelliJ
WebStorm
ESLint
eslint
Prettier
prettier
Webpack
webpack
Vite
vite
Babel
babel
Jest
jest
Mocha
Cypress
Postman

HTTP
HTTPS
OAuth
JWT
GraphQL
REST
WebSocket
TCP/IP

NPM
Yarn
PNPM
Pip
PIP
Cargo
RubyGems

Swagger
OpenAPI
Markdown
MDX
Storybook
TypeDoc
JSDoc

MySQL
PostgreSQL
MongoDB
Redis
Elasticsearch
DynamoDB

Linux
Unix
macOS
iOS

Firefox
Chromium
WebKit

config
ctx
desc
dir
elem
err
len
msg
num
obj
prev
proc
ptr
req
res
str
tmp
val
vars

todo
href
lang
nav
prev
next
toc
```

To add your own vocabulary for the default configuration, create a `styles/config/vocabularies/Mintlify` directory with `accept.txt` and `reject.txt` files.

* `accept.txt`: Words that the Vale linter should ignore. For example, product names or uncommon terms.
* `reject.txt`: Words that the Vale linter should flag as errors. For example, jargon or words that are not appropriate for the tone of your documentation.

```text Example Vale file structure theme={null}
/your-project
  |- docs.json
  |- .vale.ini
  |- styles/
    |- config/
      |- vocabularies/
        |- Mintlify/
          |- accept.txt
          |- reject.txt
  |- example-page.mdx
```

```text Example monorepo Vale file structure theme={null}
/your-monorepo
  |- main.ts
  |- docs/
    |- docs.json
    |- .vale.ini
    |- styles/
      |- config/
        |- vocabularies/
          |- Mintlify/
            |- accept.txt
            |- reject.txt
    |- example-page.mdx
  |- test/
```

#### Packages

Vale supports a range of [packages](https://vale.sh/docs/keys/packages) that check for spelling and style errors. Any packages you include in your repository under the correct `StylesPath` automatically install and run with your Vale configuration.

For packages not included in your repository, you can specify any packages from the [Vale package registry](https://vale.sh/explorer), and they're automatically downloaded and used in your Vale configuration.

<Note>
  For security reasons, you cannot automatically download packages that aren't from the [Vale package registry](https://vale.sh/explorer).
</Note>

#### Vale with `MDX`

<Note>
  MDX native support requires Vale 3.10.0 or later. Check your Vale version with `vale --version`.
</Note>

To use Vale's in-document comments in MDX files, use MDX-style comments `{/* ... */}`:

```mdx theme={null}
{/* vale off */}

Vale ignores this text

{/* vale on */}
```

Vale automatically recognizes and respects these comments in MDX files without additional configuration. Use comments to skip lines or sections that you want the linter to ignore.

<Warning>
  Do not place `{/* vale off */}` or similar MDX expression comments as direct children of a JSX component between sibling elements. For example, between two `<Step>` elements inside a `<Steps>` component.

  Place comments inside a specific element's content or restructure the content to avoid needing comments.
</Warning>


# Deploy at a subpath with Cloudflare Workers
Source: https://www.mintlify.com/docs/deploy/cloudflare

Deploy your Mintlify documentation at a subpath on your domain using Cloudflare Workers with step-by-step setup and DNS configuration.

To host your documentation at a subpath such as `yoursite.com/docs` using Cloudflare, you must create and configure a Cloudflare Worker.

<Info>
  Before you begin, you need a Cloudflare account and a domain name (managed on or off Cloudflare).
</Info>

## Set your base path

1. Navigate to the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page in your dashboard.
2. Enable the **Host at** toggle.
3. Enter your domain.
4. Enter your base path. For example, `/docs` or `/help`.
5. Click **Add domain**.

The dashboard displays a Cloudflare Worker script with your subdomain, domain, and base path filled in. Use this script in the [Configure routing](#configure-routing) step instead of manually replacing the placeholder values in the example script.

## Set up a Worker

Create a Cloudflare Worker by following the [Cloudflare Workers getting started guide](https://developers.cloudflare.com/workers/get-started/dashboard/), if you have not already.

<Tip>
  If your DNS provider is Cloudflare, disable proxying for the CNAME record to avoid potential configuration issues.
</Tip>

### Proxies with Vercel deployments

If you use Cloudflare as a proxy with Vercel deployments, you must ensure proper configuration to avoid conflicts with Vercel's domain verification and SSL certificate provisioning.

Improper proxy configuration can prevent Vercel from provisioning Let's Encrypt SSL certificates and cause domain verification failures.

#### Required path allowlist

Your Cloudflare Worker must allow traffic to these specific paths without blocking or redirecting:

* `/.well-known/acme-challenge/*`: Required for Let's Encrypt certificate verification.
* `/.well-known/vercel/*`: Required for Vercel domain verification.

While Cloudflare automatically handles many verification rules, creating additional custom rules may inadvertently block this critical traffic.

#### Header forwarding requirements

Ensure that your Worker sets the `Host` header to your `<subdomain>.mintlify.site` target, as shown in the example script, rather than passing through the original request's `Host` header. Incorrect `Host` headers cause verification requests to fail.

### Configure routing

In your Cloudflare dashboard, click **Edit Code** and add the script from your [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page, which has your values filled in, or copy the following example script. See the [Cloudflare documentation](https://developers.cloudflare.com/workers-ai/get-started/dashboard/#development) for more information on editing a Worker.

<Tip>
  If you use the example script, replace `[SUBDOMAIN]` with your unique subdomain, `[YOUR_DOMAIN]` with your website's base URL, and `/docs` with your desired subpath if different.
</Tip>

```javascript theme={null}
addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  try {
    const urlObject = new URL(request.url);
    
    // If the request is to a Vercel verification path, allow it to pass through
    if (urlObject.pathname.startsWith('/.well-known/')) {
      return await fetch(request);
    }
    
    // If the request is to the docs subpath or a Mintlify asset or API path
    if (
      /^\/docs/.test(urlObject.pathname) ||
      /^\/mintlify-assets\//.test(urlObject.pathname) ||
      /^\/_mintlify\//.test(urlObject.pathname)
    ) {
      // Then Proxy to Mintlify
      const DOCS_URL = "[SUBDOMAIN].mintlify.site";
      const CUSTOM_URL = "[YOUR_DOMAIN]";

      let url = new URL(request.url);
      url.hostname = DOCS_URL;

      let proxyRequest = new Request(url, request);

      proxyRequest.headers.set("Host", DOCS_URL);
      proxyRequest.headers.set("X-Forwarded-Host", CUSTOM_URL);
      proxyRequest.headers.set("X-Forwarded-Proto", "https");
      // If deploying to Vercel, preserve client IP
      proxyRequest.headers.set("CF-Connecting-IP", request.headers.get("CF-Connecting-IP"));

      return await fetch(proxyRequest);
    }
  } catch (error) {
    // If no action found, serve the regular request
    return await fetch(request);
  }
}
```

<Warning>
  In addition to your subpath, your Worker must proxy `/mintlify-assets/*`, which serves the CSS, JavaScript, and favicons for your documentation, and `/_mintlify/*`, which handles API playground requests.

  If you route traffic to your Worker with route patterns instead of a custom domain, add routes for `yoursite.com/mintlify-assets/*` and `yoursite.com/_mintlify/*` alongside your subpath route. These paths must originate from the root of your domain, not your subpath.
</Warning>

Click **Deploy** and wait for the changes to propagate.

<Note>
  After you deploy your changes, your documentation is usually available at your subpath within a few minutes. If your setup includes DNS changes, propagation can take 1-4 hours, and in rare cases up to 48 hours. If your documentation is not immediately available, wait before troubleshooting.
</Note>

### Test your Worker

After your code deploys, test your Worker to ensure it routes to your Mintlify docs.

1. Test using the Worker's preview URL: `your-worker.your-subdomain.workers.dev/docs`
2. Verify the Worker routes to your Mintlify docs and your website.

### Add a custom domain

1. In your [Cloudflare dashboard](https://dash.cloudflare.com/), navigate to your Worker.
2. Go to **Settings > Domains & Routes > Add > Custom Domain**.
3. Add your domain.

<Tip>
  Add your domain both with and without `www.` prepended.
</Tip>

See [Add a custom domain](https://developers.cloudflare.com/workers/configuration/routing/custom-domains/#add-a-custom-domain) in the Cloudflare documentation for more information.

### Resolve DNS conflicts

If your domain already points to another service, you must remove the existing DNS record. Your Cloudflare Worker must control all traffic for your domain.

1. Delete the existing DNS record for your domain. See [Delete DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#delete-dns-records) in the Cloudflare documentation for more information.
2. Return to your Worker and add your custom domain.

## Webflow custom routing

If you use Webflow to host your main site and want to serve Mintlify docs at `/docs` on the same domain, configure custom routing through Cloudflare Workers. The Worker proxies all non-docs traffic to your main site.

<Warning>
  Set up your main site on a landing page before deploying this Worker, or visitors to your main site may see errors.
</Warning>

1. In Webflow, set up a landing page for your main site like `landing.yoursite.com`. This is the page that visitors see when they visit your site.
2. Deploy your main site to the landing page. This ensures that your main site remains accessible while you configure the Worker.
3. To avoid conflicts, update any absolute URLs in your main site to be relative.
4. In Cloudflare, click **Edit Code** and add the following script into your Worker's code.

<Tip> Replace `[SUBDOMAIN]` with your unique subdomain, `[YOUR_DOMAIN]` with your website's base URL, `[LANDING_DOMAIN]` with your landing page URL, and `/docs` with your desired subpath if different. </Tip>

```javascript theme={null}
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
try {
  const urlObject = new URL(request.url);
  
  // If the request is to a Vercel verification path, allow it to pass through
  if (urlObject.pathname.startsWith('/.well-known/')) {
    return await fetch(request);
  }
  
  // If the request is to the docs subpath or a Mintlify asset or API path
  if (
    /^\/docs/.test(urlObject.pathname) ||
    /^\/mintlify-assets\//.test(urlObject.pathname) ||
    /^\/_mintlify\//.test(urlObject.pathname)
  ) {
    // Proxy to Mintlify
    const DOCS_URL = "[SUBDOMAIN].mintlify.site";
    const CUSTOM_URL = "[YOUR_DOMAIN]";
    let url = new URL(request.url);
    url.hostname = DOCS_URL;
    let proxyRequest = new Request(url, request);
    proxyRequest.headers.set("Host", DOCS_URL);
    proxyRequest.headers.set("X-Forwarded-Host", CUSTOM_URL);
    proxyRequest.headers.set("X-Forwarded-Proto", "https");
    // If deploying to Vercel, preserve client IP
    proxyRequest.headers.set("CF-Connecting-IP", request.headers.get("CF-Connecting-IP"));
    return await fetch(proxyRequest);
  }
  // Route everything else to main site
  const MAIN_SITE_URL = "[LANDING_DOMAIN]";
  if (MAIN_SITE_URL && MAIN_SITE_URL !== "[LANDING_DOMAIN]") {
    let mainSiteUrl = new URL(request.url);
    mainSiteUrl.hostname = MAIN_SITE_URL;
    return await fetch(mainSiteUrl, {
      method: request.method,
      headers: request.headers,
      body: request.body
    });
  }
} catch (error) {
  // If no action found, serve the regular request
  return await fetch(request);
}
}
```

5. Click **Deploy** and wait for the changes to propagate.

<Note>
  After you deploy your changes, your documentation is usually available at your subpath within a few minutes. If your setup includes DNS changes, propagation can take 1-4 hours, and in rare cases up to 48 hours. If your documentation is not immediately available, wait before troubleshooting.
</Note>


# Content Security Policy (CSP) configuration
Source: https://www.mintlify.com/docs/deploy/csp-configuration

Configure Content Security Policy headers to allow Mintlify resources while maintaining security for reverse proxies and strict network policies.

Content Security Policy (CSP) is a security standard that helps prevent cross-site scripting (XSS) attacks by controlling which resources a web page can load. Mintlify serves a default CSP that protects most sites. If you host your documentation behind a reverse proxy or firewall that overwrites the default CSP, you may need to configure CSP headers for features to function properly.

## CSP directives

The following CSP directives control which resources a page can load:

* `script-src`: Controls which scripts can run
* `style-src`: Controls which stylesheets can load
* `font-src`: Controls which fonts can load
* `img-src`: Controls which images, icons, and logos can load
* `connect-src`: Controls which URLs can connect to for API calls and WebSocket connections
* `frame-src`: Controls which URLs can embed in frames or iframes
* `default-src`: Fallback for other directives when not explicitly set

## Domain allowlist

| Domain                                | Purpose                                   | CSP directive                                                                         | Required |
| :------------------------------------ | :---------------------------------------- | :------------------------------------------------------------------------------------ | :------- |
| `d4tuoctqmanu0.cloudfront.net`        | KaTeX CSS, fonts                          | `style-src`, `font-src`                                                               | Required |
| `*.mintlify.site`                     | Documentation content                     | `connect-src`, `frame-src`                                                            | Required |
| `*.mintlify.com`                      | Dashboard, API, analytics proxy           | `connect-src`                                                                         | Required |
| `leaves.mintlify.com`                 | Assistant API                             | `connect-src`                                                                         | Required |
| `d3gk2c5xim1je2.cloudfront.net`       | Icons, images, logos                      | `img-src`                                                                             | Required |
| `d1ctpt7j8wusba.cloudfront.net`       | Mint version and release files            | `connect-src`                                                                         | Required |
| `mintcdn.com`                         | Images, favicons                          | `img-src`, `connect-src`                                                              | Required |
| `*.mintcdn.com`                       | Images, favicons                          | `img-src`, `connect-src`                                                              | Required |
| `cdn.jsdelivr.net`                    | Emoji assets for OG images                | `script-src`, `img-src`                                                               | Required |
| `mintlify.s3.us-west-1.amazonaws.com` | S3-hosted images                          | `img-src`                                                                             | Required |
| `hcaptcha.com`                        | hCaptcha CAPTCHA verification             | `script-src`, `frame-src`, `style-src`, `connect-src`, `unsafe-eval`, `unsafe-inline` | Required |
| `*.hcaptcha.com`                      | hCaptcha CAPTCHA verification             | `script-src`, `frame-src`, `style-src`, `connect-src`, `unsafe-eval`, `unsafe-inline` | Required |
| `fonts.googleapis.com`                | Google Fonts                              | `style-src`, `font-src`                                                               | Optional |
| `www.googletagmanager.com`            | Google Analytics/Google Tag Manager (GTM) | `script-src`, `connect-src`                                                           | Optional |
| `cdn.segment.com`                     | Segment analytics                         | `script-src`, `connect-src`                                                           | Optional |
| `plausible.io`                        | Plausible analytics                       | `script-src`, `connect-src`                                                           | Optional |
| `us.posthog.com`                      | PostHog analytics                         | `connect-src`                                                                         | Optional |
| `tag.clearbitscripts.com`             | Clearbit tracking                         | `script-src`                                                                          | Optional |
| `cdn.heapanalytics.com`               | Heap analytics                            | `script-src`                                                                          | Optional |
| `chat.cdn-plain.com`                  | Plain chat widget                         | `script-src`                                                                          | Optional |
| `chat-assets.frontapp.com`            | Front chat widget                         | `script-src`                                                                          | Optional |
| `browser.sentry-cdn.com`              | Sentry error tracking                     | `script-src`, `connect-src`                                                           | Optional |
| `js.sentry-cdn.com`                   | Sentry JavaScript SDK                     | `script-src`                                                                          | Optional |

## Example CSP configuration

<Note>
  Only include domains for services that you use. Remove any analytics domains that you have not configured for your documentation.
</Note>

```text wrap theme={null}
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval' cdn.jsdelivr.net www.googletagmanager.com cdn.segment.com plausible.io
us.posthog.com tag.clearbitscripts.com cdn.heapanalytics.com chat.cdn-plain.com chat-assets.frontapp.com
browser.sentry-cdn.com js.sentry-cdn.com hcaptcha.com *.hcaptcha.com;
style-src 'self' 'unsafe-inline' d4tuoctqmanu0.cloudfront.net fonts.googleapis.com hcaptcha.com *.hcaptcha.com;
font-src 'self' d4tuoctqmanu0.cloudfront.net fonts.googleapis.com;
img-src 'self' data: blob: d3gk2c5xim1je2.cloudfront.net mintcdn.com *.mintcdn.com cdn.jsdelivr.net mintlify.s3.us-west-1.amazonaws.com;
connect-src 'self' *.mintlify.site *.mintlify.com d1ctpt7j8wusba.cloudfront.net mintcdn.com *.mintcdn.com
www.googletagmanager.com cdn.segment.com plausible.io us.posthog.com browser.sentry-cdn.com hcaptcha.com *.hcaptcha.com;
frame-src 'self' *.mintlify.site hcaptcha.com *.hcaptcha.com;
```

## Common configurations by proxy type

Most reverse proxies support adding custom headers.

### Cloudflare configuration

Create a Response Header Transform Rule:

1. In your Cloudflare dashboard, go to **Rules > Overview**.
2. Click **Create rule > Response Header Transform Rule**.
3. Configure the rule:

* **Modify response header**: Set static
* **Header name**: `Content-Security-Policy`
* **Header value**:
  ```text wrap theme={null}
  default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' cdn.jsdelivr.net hcaptcha.com *.hcaptcha.com; style-src 'self' 'unsafe-inline' d4tuoctqmanu0.cloudfront.net fonts.googleapis.com hcaptcha.com *.hcaptcha.com; font-src 'self' d4tuoctqmanu0.cloudfront.net fonts.googleapis.com; img-src 'self' data: blob: d3gk2c5xim1je2.cloudfront.net mintcdn.com *.mintcdn.com cdn.jsdelivr.net mintlify.s3.us-west-1.amazonaws.com; connect-src 'self' *.mintlify.site *.mintlify.com d1ctpt7j8wusba.cloudfront.net mintcdn.com *.mintcdn.com hcaptcha.com *.hcaptcha.com; frame-src 'self' *.mintlify.site hcaptcha.com *.hcaptcha.com;
  ```

4. Deploy your rule.

### AWS CloudFront configuration

Add a response headers policy in CloudFront:

```json theme={null}
{
"ResponseHeadersPolicy": {
    "Name": "MintlifyCSP",
    "Config": {
    "SecurityHeadersConfig": {
        "ContentSecurityPolicy": {
        "ContentSecurityPolicy": "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' cdn.jsdelivr.net hcaptcha.com *.hcaptcha.com; style-src 'self' 'unsafe-inline' d4tuoctqmanu0.cloudfront.net fonts.googleapis.com hcaptcha.com *.hcaptcha.com; font-src 'self' d4tuoctqmanu0.cloudfront.net fonts.googleapis.com; img-src 'self' data: blob: d3gk2c5xim1je2.cloudfront.net mintcdn.com *.mintcdn.com cdn.jsdelivr.net mintlify.s3.us-west-1.amazonaws.com; connect-src 'self' *.mintlify.site *.mintlify.com d1ctpt7j8wusba.cloudfront.net mintcdn.com *.mintcdn.com hcaptcha.com *.hcaptcha.com; frame-src 'self' *.mintlify.site hcaptcha.com *.hcaptcha.com;",
        "Override": true
        }
      }
    }
  }
}
```

### Vercel configuration

Add to your `vercel.json`:

```json theme={null}
{
"headers": [
    {
    "source": "/(.*)",
    "headers": [
        {
        "key": "Content-Security-Policy",
        "value": "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' cdn.jsdelivr.net hcaptcha.com *.hcaptcha.com; style-src 'self' 'unsafe-inline' d4tuoctqmanu0.cloudfront.net fonts.googleapis.com hcaptcha.com *.hcaptcha.com; font-src 'self' d4tuoctqmanu0.cloudfront.net fonts.googleapis.com; img-src 'self' data: blob: d3gk2c5xim1je2.cloudfront.net mintcdn.com *.mintcdn.com cdn.jsdelivr.net mintlify.s3.us-west-1.amazonaws.com; connect-src 'self' *.mintlify.site *.mintlify.com d1ctpt7j8wusba.cloudfront.net mintcdn.com *.mintcdn.com hcaptcha.com *.hcaptcha.com; frame-src 'self' *.mintlify.site hcaptcha.com *.hcaptcha.com;"
        }
      ]
    }
  ]
}
```

## Troubleshooting

Identify CSP violations in your browser console:

1. Open your browser's Developer Tools.
2. Go to the **Console** tab.
3. Look for errors starting with:
   * `Content Security Policy: The page's settings blocked the loading of a resource`
   * `Refused to load the script/stylesheet because it violates the following Content Security Policy directive`
   * `Refused to connect to because it violates the following Content Security Policy directive`


# Deployments
Source: https://www.mintlify.com/docs/deploy/deployments

Manage documentation deployments in the Mintlify dashboard, including viewing deployment history, monitoring build status, and troubleshooting.

Your documentation site automatically deploys when you push changes to your connected repository. This requires the Mintlify GitHub app to be properly installed and connected.

If your latest changes are not appearing on your live site, first check that the GitHub account or organization that owns your docs repository has the GitHub App installed. See [GitHub troubleshooting](/docs/deploy/github#troubleshooting) for more information.

If you have the GitHub App installed, but changes are still not deploying, manually trigger a deployment from your dashboard.

## Manually trigger a deployment

<Steps>
  <Step title="Verify your latest commit was successful.">
    Check that your latest commit appears in your docs repository and did not encounter any errors.
  </Step>

  <Step title="Manually trigger a deployment.">
    Go to your [dashboard](https://app.mintlify.com) and click the deploy button.

    <Frame>
      <img alt="The manual update button emphasized with an orange rectangle." />

      <img alt="The manual update button emphasized with an orange rectangle." />
    </Frame>
  </Step>
</Steps>

## Delete a deployment

You can permanently delete a deployment from the [Danger zone](https://app.mintlify.com/settings/organization/danger-zone) in your dashboard settings. This action is irreversible and removes all deployment data, including any associated preview deployments.

<Steps>
  <Step title="Navigate to the Danger zone.">
    Go to the [Danger zone](https://app.mintlify.com/settings/organization/danger-zone) in the settings page of your dashboard.
  </Step>

  <Step title="Delete the deployment.">
    1. In the **Delete my deployment** section, provide a reason for deletion.
    2. Click the delete button and confirm that you want to delete the deployment.
  </Step>
</Steps>

<Warning>
  Deleting a deployment is permanent and cannot be undone. If you have an active subscription, you'll receive a prorated credit for any unused time remaining in your billing period.
</Warning>

If you have multiple deployments, Mintlify redirects you to another deployment after deletion. If you delete your only deployment, Mintlify redirects you to the Mintlify homepage. When you delete a deployment, the organization admin receives an email notification confirming the deletion.


# Host docs at a subpath
Source: https://www.mintlify.com/docs/deploy/docs-subpath

Host your Mintlify documentation at a subpath like /docs on your main domain using Cloudflare Workers, Vercel rewrites, or an nginx reverse proxy.

Host your documentation at a subpath like `your-domain.com/docs` to keep your docs on your main domain. This makes them easier to find and maintains a cohesive brand experience for your users.

## Let Mintlify manage your domain

If your domain hosts nothing else, Mintlify can serve your documentation at your subpath without a proxy. In your dashboard, open the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page. Enable the **Host at** toggle, enter your base path, and add your domain. Then configure the DNS records shown in your dashboard to point your domain at Mintlify. See [Custom domain](/docs/customize/custom-domain) for setup instructions.

Only use this option if Mintlify can receive all paths on the domain.

## Set up by hosting provider

If another site runs on your domain, configure your hosting provider to proxy your subpath to Mintlify. Choose your hosting provider and follow the setup instructions.

* [Cloudflare](/docs/deploy/cloudflare): Set up Cloudflare Workers for your domain to serve your documentation at your subpath.
* [AWS Route 53 and CloudFront](/docs/deploy/route53-cloudfront): Deploy your documentation at your subpath using AWS with Route 53 DNS and CloudFront CDN.
* [Vercel](/docs/deploy/vercel): Use rewrites to deploy your documentation at your subpath.
* [Custom reverse proxy](/docs/deploy/reverse-proxy): For other hosting platforms, set up a reverse proxy to deploy your documentation at your subpath.

### Additional configuration for strict security policies

If you proxy all traffic on your custom domain, you may need to configure your proxy or firewall rules to add the correct [headers](/docs/deploy/csp-configuration). This ensures that your documentation displays properly.


# GitHub Enterprise Server
Source: https://www.mintlify.com/docs/deploy/ghes

Install and configure the Mintlify GitHub App on your GitHub Enterprise Server instance for automated documentation deployments and syncing.

This guide walks you through setting up the Mintlify GitHub App on your GitHub Enterprise Server (GHES) installation. To connect a GHES instance to Mintlify, you must create a local version of our app within your self-hosted environment that communicates with our remote server.

If you use a cloud-hosted GitHub instance, see the [GitHub](/docs/deploy/github) page for setup instructions.

## Prerequisites

* Admin privileges on your GitHub Enterprise Server organization where you want to install the app
* Access to your organization's repositories where you want to install the app
* Network connectivity to communicate with our external services (see [Network requirements](#network-requirements) section below)

### Network requirements

#### Outbound connectivity

Your GitHub Enterprise Server must be able to reach:

* Mintlify's API endpoints ([https://leaves.mintlify.com](https://leaves.mintlify.com))
* Webhook receivers (port 443)

#### Firewall configuration

Allow the following outbound connections:

* Connections from Mintlify's static IP: `54.242.90.151`
* HTTPS (port 443) to Mintlify's service domains
* DNS resolution for Mintlify's service domains

## Step 1: register the GitHub App

See [Registering a GitHub App](https://docs.github.com/en/enterprise-server@3.18/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) in the GitHub documentation for detailed instructions.

<Steps>
  <Step title="Navigate to your organization settings">
    1. In the upper-right corner of any page on GitHub, click your profile picture.
    2. Click **Your organizations**.
    3. Click **Settings** next to the organization that you want to create the app for.
  </Step>

  <Step title="Create a new GitHub App">
    1. In the left sidebar, click **Developer settings**.
    2. Click **GitHub Apps**.
    3. Click **New GitHub App**.
  </Step>

  <Step title="Configure basic app information">
    Set the following:

    * **GitHub App name:** `Mintlify`
    * **Description:** `Integration with Mintlify services`
    * **Homepage URL:** `https://mintlify.com`
    * **User authorization callback URL:** `https://your-github-server.com/` (replace with your actual GHES domain)
  </Step>
</Steps>

## Step 2: configure app permissions

<Steps>
  <Step title="Set repository permissions">
    Set the following permissions for the app. The app needs no Organization, Account, or Enterprise permissions:

    * **Checks:** Read and write
    * **Contents:** Read and write
    * **Deployments:** Read and write
    * **Metadata:** Read-only
    * **Pull Requests:** Read and write
  </Step>

  <Step title="Subscribe to events">
    Select the following webhook events:

    * Installation
    * Installation Target
    * Create
    * Delete
    * Public
    * Pull Request
    * Push
    * Repository
  </Step>
</Steps>

## Step 3: generate and secure credentials

<Steps>
  <Step title="Create the app">
    Click **Create GitHub App**.

    GitHub redirects you to the app's settings page.
  </Step>

  <Step title="Generate private key">
    1. Scroll down to the **Private keys** section.
    2. Click **Generate a private key**.
    3. Download the `.pem` file and securely store it.
  </Step>

  <Step title="Note app credentials">
    Record the following:

    * **App ID** (visible at the top of the settings page)
    * **Client ID** (in the "About" section)
    * **Client Secret** (generate and record it securely)
  </Step>
</Steps>

## Step 4: install the app

<Steps>
  <Step title="Navigate to app installation">
    1. From the app settings page, click **Install App** in the left sidebar.
    2. Select your organization from the list.
  </Step>

  <Step title="Choose installation scope">
    Select either:

    * **All repositories** (for organization-wide access)
    * **Only select repositories** (choose specific repositories)
  </Step>

  <Step title="Complete the installation">
    1. Click **Install**.
    2. Record the installation ID from the URL. For example, in `https://your-github-server.com/settings/installations/12345`, the string `12345` is the installation ID.
  </Step>
</Steps>

## Step 5: configure webhook URL

<Steps>
  <Step title="Return to app settings">
    1. Go back to your app's settings page.
    2. Scroll to the **Webhook** section.
  </Step>

  <Step title="Set webhook URL">
    Configure the following:

    * **Webhook URL:** `https://leaves.mintlify.com/github-enterprise/:subdomain` (replace `:subdomain` with the URL that we provide you with)
    * **Webhook secret:** Generate a random string (32+ characters) and record it securely. Mintlify can also generate this and provide it to you.
  </Step>
</Steps>

## Share credentials with us

Share the following information with our team using your secure information transfer method of choice.

### Required credentials

* GitHub Enterprise Server base URL: [https://your-github-server.com](https://your-github-server.com)
* App ID: (from step 3)
* App client ID: (from step 3)
* App client secret: (from step 3)
* Installation ID: (from step 4)
* Installation owner: The name of the GitHub organization that owns the app installation
* Private key: The entire contents of the `.pem` file (share it via secure file transfer)
* Webhook secret: (from step 5)

### Optional credentials for troubleshooting

* Repository names: Specific repositories where you installed the app
* GitHub Enterprise Server version: Found in your site admin dashboard

## Mintlify connection

We take the credentials you provide us and store them, encrypted, in a secure location. Then we work with you to either:

* Integrate your GHES environment with an existing Mintlify deployment.
* Integrate your GHES environment with a new Mintlify deployment that we provision for you.

After you integrate your GHES environment with a Mintlify deployment, you are ready to enable webhooks for your GitHub App.

<Note>
  The webhook URL may change based on our configuration. We test the integration and provide you with the new URL.
</Note>

## Test the integration

<Steps>
  <Step title="Verify webhook delivery">
    1. Go to your GitHub App settings.
    2. Click the **Advanced** tab.
    3. Check "Recent Deliveries" for successful webhook deliveries.
    4. Look for HTTP 200 responses.
  </Step>

  <Step title="Test repository access">
    1. Create a test issue or pull request in an installed repository.
    2. Verify that Mintlify responds appropriately.
  </Step>
</Steps>

## FAQ and troubleshooting

<AccordionGroup>
  <Accordion title="The app installation is failing with permission errors.">
    Ensure you have:

    * Site admin privileges for app creation
    * Organization owner or admin rights for app installation.
    * Proper repository permissions if installing on specific repositories.
  </Accordion>

  <Accordion title="Webhooks aren't being delivered">
    * Verify the webhook URL is correct and accessible.
    * Ensure your firewall allows outbound HTTPS connections.
    * Check the webhook secret matches what you configured.
    * Review webhook delivery logs in the "Advanced" tab of your GitHub App settings.
  </Accordion>

  <Accordion title="I'm getting SSL/TLS certificate errors">
    Your GHES might use self-signed certificates. Our services cannot verify your server's certificate.

    **Solution:** Ensure your GHES has a valid SSL certificate.
  </Accordion>

  <Accordion title="The app installs, but doesn't respond to events.">
    * Ensure our server receives and acknowledges webhooks with response code 200.
    * You granted the required permissions during installation.
  </Accordion>

  <Accordion title="Can I limit which repositories the app accesses?">
    Yes, during installation you can select "Only select repositories" and choose specific ones. You can modify this later in your organization's installed apps settings. This is the recommended form of installation.
  </Accordion>

  <Accordion title="How do I update app permissions later?">
    * Go to the app settings as a site admin.
    * Modify permissions as needed.
    * The app needs to be re-approved by organization owners.
    * Notify us of any permission changes so we can advise on any additional steps you may need.
  </Accordion>

  <Accordion title="Our GHES is behind a corporate firewall, nginx proxy, or similar setup.">
    You must:

    * Add our service domains to your firewall allowlist.
    * Ensure outbound HTTPS (port 443) connectivity.
    * If direct internet access is not allowed, set up a proxy.
  </Accordion>

  <Accordion title="Can this work with GHES in air-gapped environments?">
    No, your GHES must be able to communicate with our cloud-hosted server.
  </Accordion>

  <Accordion title="Who should I contact if I need help?">
    Reach out to your customer success representative at Mintlify, or contact our support team at <a href="mailto:support@mintlify.com">[support@mintlify.com](mailto:support@mintlify.com)</a> with:

    * Your GitHub Enterprise Server version.
    * Specific error messages.
    * Screenshots of any issues.
    * Network/firewall configuration details (if relevant).
  </Accordion>
</AccordionGroup>


# GitHub
Source: https://www.mintlify.com/docs/deploy/github

Connect your GitHub repository to Mintlify for automated deployments, pull request preview builds, and continuous documentation synchronization.

Mintlify uses a GitHub App to automatically sync your documentation with your GitHub repository.

<Tip>
  **Do you need the GitHub App?**

  * **Mintlify-hosted repository** in the `mintlify-community` organization: No. The GitHub App is already configured.
  * **Your own repository**: Yes. Install the GitHub App to enable automatic deployments when you push changes.

  See your repository in the [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) page of your dashboard.
</Tip>

If your repository is in a private repository owned by the Mintlify organization, the GitHub App is automatically configured and managed by Mintlify. You can use the web editor to make changes to your documentation. If you want to work on your documentation locally, clone the repository to your own organization and update your Git settings to use your own repository.

## Clone to your own repository

If you skipped connecting your own Git repository during onboarding, your documentation lives in a private repository owned by the Mintlify organization. To move it to your own account or organization, go to [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) in your dashboard. A setup wizard guides you through the process with two options:

<AccordionGroup>
  <Accordion title="One-click clone (recommended)">
    The clone option automatically creates a copy of your documentation in your GitHub account.

    1. Select **GitHub** as your provider.
    2. Click **Clone**.
    3. Authorize with GitHub when prompted.
    4. Select the GitHub organization where you want to create the repository.
    5. Confirm the clone. Mintlify copies your documentation files into a new repository.
    6. Optionally install the Mintlify GitHub App for automatic deployments.
  </Accordion>

  <Accordion title="Manual setup">
    <Warning>
      This process permanently deletes your content from the Mintlify-hosted repository.

      Download your documentation from the setup wizard before completing the manual setup process.
    </Warning>

    If you prefer to set up your repository manually:

    1. Download your documentation as a zip file so that you have a backup of your files.
    2. Select **GitHub** as your provider.
    3. Click **Continue setup**.
    4. Authorize with GitHub when prompted.
    5. Select your organization, repository, and branch.
    6. Optionally specify a subdirectory if your docs are not at the repository root.
    7. Save your settings.
  </Accordion>
</AccordionGroup>

After completing either path, install the GitHub App by following the steps in [Install the GitHub App](#install-the-github-app).

## Install the GitHub App

<Note>
  You must have organization ownership or administrator permissions in a repository to install the app. If you lack the necessary permissions, the repository owner must approve the installation request.
</Note>

Install the Mintlify GitHub App on the [Git settings](https://app.mintlify.com/settings/deployment/git-settings) page of your dashboard.

<Frame>
  <img alt="Mintlify GitHub App installation page with the 'Only select repositories' option selected." />
</Frame>

## Permissions

When you install the GitHub App, grant the following permissions.

Read permissions:

* `metadata`: Basic repository information

Read and write permissions:

* `checks`: Create status checks on pull requests
* `code`: Read file changes when you commit to your docs branch
* `deployments`: Generate preview deployments for pull requests
* `pull requests`: Create branches and pull requests from the web editor

<Info>
  The app only accesses repositories that you explicitly grant it access to. If you have branch protection rules enabled, the app can't push directly to protected branches.
</Info>

## Manage repository access

When installing the GitHub App, you can grant access to all of your repositories or specific ones. Grant access only to your documentation repository and any repositories that you want to provide as context for the agent or workflows. You can modify this selection anytime in your [GitHub App settings](https://github.com/apps/mintlify/installations/new).

## Configure docs source

Change the organization, repository, or branch that your documentation builds from in the [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) section of your dashboard.

## GitHub Enterprise with IP allowlists

If your GitHub Enterprise Cloud organization has an IP allowlist enabled, you need to add Mintlify's egress IP address (`54.242.90.151`) to your allowlist for the GitHub App to function properly.

Follow [GitHub's documentation](https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization) to configure your IP allowlist.

## Troubleshooting

### Deployment not triggering automatically

If pushes to your repository don't trigger deployments, check the following possible problems.

<AccordionGroup>
  <Accordion title="Verify GitHub App installation">
    Check that the correct repository has the app installed.

    1. Navigate to the [Git settings](https://app.mintlify.com/settings/deployment/git-settings) page in your dashboard.
    2. Check that your repository is on the active app installations list.
  </Accordion>

  <Accordion title="Check deployment branch">
    Ensure that you're pushing to the correct branch.

    1. Go to [Git Settings](https://app.mintlify.com/settings/deployment/git-settings)
    2. Verify the branch in your dashboard matches the branch that you're pushing to.
  </Accordion>
</AccordionGroup>

### GitHub App connection issues

If you encounter problems with the GitHub App, resetting the connection can solve most problems.

<Steps>
  <Step title="Uninstall the Mintlify app through GitHub.">
    1. In GitHub, go to [installations](https://github.com/settings/installations) and click **Configure** next to the Mintlify app. Scroll down and click **Uninstall**.
    2. Go to [Authorized GitHub Apps](https://github.com/settings/apps/authorizations) and click **Revoke** next to the Mintlify app.
  </Step>

  <Step title="Reinstall the Mintlify app.">
    1. In your Mintlify dashboard, go to [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) and install the GitHub App.
    2. Authorize your account in the [My Profile](https://app.mintlify.com/settings/account) section of your dashboard.
  </Step>
</Steps>


# GitLab
Source: https://www.mintlify.com/docs/deploy/gitlab

Connect your GitLab repository to Mintlify for automated documentation deployments, merge request previews, and continuous synchronization.

Mintlify uses access tokens and webhooks to authenticate and sync changes between GitLab and Mintlify.

* Mintlify uses access tokens to pull information from GitLab.
* GitLab uses webhooks to notify Mintlify when you make changes, which enables preview deployments for merge requests.

## Set up the connection

When you open [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) for the first time, a setup wizard guides you through connecting your GitLab repository.

<Steps>
  <Step title="Select GitLab as your provider">
    On the [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) page, click **Connect to GitLab** and then click **Continue**.
  </Step>

  <Step title="Download your content">
    <Tip>
      If you already have a GitLab repository with your documentation, you can skip the download and click **Continue setup** directly.
    </Tip>

    If your documentation is hosted by Mintlify, download it as a zip file.

    * Create a new repository in GitLab.
    * Extract the zip contents.
    * Push the contents to your repository.

    Click **Continue setup** to proceed.
  </Step>

  <Step title="Find your project ID">
    In your GitLab project, navigate to **Settings** > **General** and locate your **Project ID**.

    <Frame>
      <img alt="The General Settings page in the GitLab dashboard. The Project ID is highlighted." />
    </Frame>
  </Step>

  <Step title="Generate an access token">
    Navigate to **Settings** > **Access Tokens** and click **Add new token**.

    Configure the token with these settings:

    * **Name**: Mintlify
    * **Role**: Maintainer (required for private repos)
    * **Scopes**: `api` and `read_api`

    Click **Create project access token** and copy the token.

    <Note>
      If Project Access Tokens are not available, you can use a Personal Access Token instead. Note that Personal Access Tokens expire and must be updated.
    </Note>

    <Frame>
      <img alt="The Access tokens page in the GitLab dashboard. The settings to configure for Mintlify are highlighted." />
    </Frame>
  </Step>

  <Step title="Connect your repository">
    Back in the setup wizard, fill in the following fields:

    * **GitLab instance URL**: Leave blank for `gitlab.com`, or enter your self-hosted instance URL (for example, `https://gitlab.your-domain.com`). Your instance must be publicly accessible for Mintlify to reach it.
    * **Project ID**: The project ID from your GitLab project settings.
    * **GitLab deployment token**: The access token you generated.
    * **Branch**: Select the branch to deploy your documentation from.

    Click **Connect**.

    <Frame>
      <img alt="The GitLab configuration panel in the Git Settings page of the Mintlify dashboard." />

      <img alt="The GitLab configuration panel in the Git Settings page of the Mintlify dashboard." />
    </Frame>
  </Step>
</Steps>

## Update an existing connection

To modify your GitLab connection settings after the initial setup, go to [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) and update your project ID, access token, branch, or instance URL directly.

## Revalidate Git settings

If your deployment shows unexpected behavior, such as missing branch options or stale configuration, you can force Mintlify to refresh your Git source.

<Steps>
  <Step title="Navigate to Git Settings">
    Go to [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) in your dashboard.
  </Step>

  <Step title="Revalidate your settings">
    Click the green **Active** badge in the corner of the GitLab settings box to revalidate your Git source.
  </Step>
</Steps>

## Create the webhook

Webhooks notify Mintlify when you push changes so that deployments trigger
automatically.

<Steps>
  <Step title="Add new webhook">
    1. In GitLab, navigate to **Settings** > **Webhooks**.
    2. Click **Add new webhook**.

    <Frame>
      <img alt="Screenshot of the Webhooks page in the GitLab dashboard." />
    </Frame>
  </Step>

  <Step title="Set up URL and webhook">
    Name the webhook **Mintlify**.

    In the **URL** field, enter the endpoint `https://leaves.mintlify.com/gitlab-webhook`.
  </Step>

  <Step title="Get webtoken">
    In your Mintlify dashboard, click **Show Webtoken**. Copy the webtoken.

    <Frame>
      <img alt="Screenshot of the GitLab connection in the Mintlify dashboard." />

      <img alt="Screenshot of the GitLab connection in the Mintlify dashboard." />
    </Frame>
  </Step>

  <Step title="Paste webtoken">
    In GitLab, paste the webtoken from your Mintlify dashboard in the **Secret token** field.
  </Step>

  <Step title="Select events">
    Select the following events to trigger the webhook:

    * **Push events** (All branches)
    * **Merge requests events**
  </Step>

  <Step title="Verify the webhook">
    You should see the following settings after configuring the webhook:

    * **Name**: Mintlify
    * **URL**: `https://leaves.mintlify.com/gitlab-webhook`
    * **Secret token**: The webtoken from your Mintlify dashboard
    * **Events**: **Push events** (All branches) and **Merge requests events**

    Add the webhook.

    <Frame>
      <img alt="The Webhook page in the GitLab dashboard. The settings to configure for Mintlify are highlighted." />
    </Frame>
  </Step>

  <Step title="Test the webhook">
    After you create the webhook, click the **Test** dropdown. Click **Push events** to send a sample payload. If the test returns `Hook executed successfully: HTTP 200`, you configured the webhook correctly.

    <Frame>
      <img alt="Screenshot of the GitLab Webhooks page. The 'Push events' menu item is highlighted in the 'Test' menu." />
    </Frame>
  </Step>
</Steps>


# Monorepo setup
Source: https://www.mintlify.com/docs/deploy/monorepo

Configure the documentation path and content directory in a monorepo project so Mintlify deploys only from your designated docs folder.

Configure Mintlify to deploy documentation from a specific directory within a monorepo. This setup lets you maintain documentation alongside your code in repositories that contain multiple projects or services.

<Note>
  A monorepo deployment uses a single repository with a subdirectory of docs. To combine content from more than one repository into one site, see [Multi-repository deployments](/docs/deploy/multi-repo).
</Note>

A typical monorepo structure might look like this:

```text theme={null}
your-repo/
├── apps/
│   ├── web/
│   └── api/
├── docs/
│   ├── docs.json
│   └── quickstart.mdx
└── package.json
```

In this example, you'd set your documentation path to `/docs`.

## Prerequisites

* Admin access to your Mintlify project.
* Documentation files organized in a dedicated directory within your monorepo.
* A valid `docs.json` in your documentation directory.

## Configure monorepo deployment

<Steps>
  <Step title="Access Git settings">
    Navigate to [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) in your dashboard.

    <Frame>
      <img alt="The project settings panel in the Git Settings menu, showing the docs.json is in a subdirectory toggle enabled and a path to the /docs directory specified." />

      <img alt="The project settings panel in the Git Settings menu, showing the docs.json is in a subdirectory toggle enabled and a path to the /docs directory specified." />
    </Frame>
  </Step>

  <Step title="Set your documentation path">
    1. Enable the **docs.json is in a subdirectory** toggle.
    2. Enter the relative path to your docs directory. For example, if your docs are in the `docs` directory, enter `/docs`.

    <Note>
      Do not include a trailing slash in the path.
    </Note>

    3. Click **Save changes**. Saving triggers a new deployment from the configured path.
  </Step>
</Steps>


# Multi-repository deployments
Source: https://www.mintlify.com/docs/deploy/multi-repo

Combine multiple Git repositories into one Mintlify site, with a dedicated URL path for each source repo's content and navigation.

<Info>
  Multi-repository deployments are available on [Enterprise plans](https://mintlify.com/pricing?ref=multi-repo).
</Info>

Use a multi-repository deployment when one site needs content from more than one Git repository. When you configure multiple repositories as sources for the same Mintlify project, content from each repository has its own URL path.

For example, you can combine separate repositories for product documentation, API reference, and SDK guides into one site:

```text theme={null}
docs.example.com/product
docs.example.com/api
docs.example.com/sdks
```

One source in a multi-repository deployment can use a root URL path (`/`). Mintlify serves content from that source at the root of the site with no path prefix, while other sources are at their configured URL paths. Use a root URL path if one repository holds the main documentation and other repositories add sections like an API reference or SDK guides.

## How multi-repository deployments work

Each repository in a multi-repository deployment has its own:

* Git provider connection
* Branch
* Optional content directory
* URL path
* `docs.json`

During deployment, Mintlify reads each repository and combines the configured sources into one site. Each source appears under its configured URL path.

One repository acts as the **base source** for the deployment. Its `docs.json` is the root `docs.json` and controls site-level configuration, including theme, colors, logo, site name, top-level navigation, integrations, SEO, and other top-level fields. Every other source contributes only its own navigation and content under its configured URL path. The first repository you configure is the base source by default, and you can [change which source is the base](#change-the-base-source) at any time.

<Note>
  Multi-repository deployments are different from a [monorepo setup](/docs/deploy/monorepo). Use a monorepo setup when you store all content in a subdirectory alongside source code in a single repository. Use multi-repository deployments when you store content across separate repositories.
</Note>

## Requirements

* An Enterprise plan
* Admin access to your Mintlify project
* A `docs.json` file in each repository source
* All repository sources must use the same Git provider (all GitHub, all GitLab, or all Bitbucket). Adding a source from a different provider removes all existing sources of the other type

<Warning>
  URL paths must be unique and cannot overlap. For example, do not configure one source at `/docs` and another source at `/docs/api`. Only one source can use the root URL path (`/`).
</Warning>

## Configure multiple repositories

<Steps>
  <Step title="Open Git settings">
    Navigate to [Git settings](https://app.mintlify.com/settings/deployment/git-settings) in your dashboard.

    <Frame>
      <img alt="The Git settings page in the Mintlify dashboard. The Add repository button is visible at the bottom." />

      <img alt="The Git settings page in the Mintlify dashboard. The Add repository button is visible at the bottom." />
    </Frame>
  </Step>

  <Step title="Add another repository">
    Click **Add repository**.
  </Step>

  <Step title="Configure the repository source">
    Select the repository, branch, and any required Git provider-specific fields (GitHub, GitLab, or Bitbucket).

    <Frame>
      <img alt="The repository configuration panel in the Git settings page. The repository, branch, and GitHub-specific fields are visible." />

      <img alt="The repository configuration panel in the Git settings page. The repository, branch, and GitHub-specific fields are visible." />
    </Frame>

    For GitHub sources, the Mintlify GitHub App must have access to the repository. For GitLab sources, provide the project ID and a deploy token with `read_repository` scope. For Bitbucket sources, connect your Bitbucket account through OAuth and enable the repository. See [Bitbucket](/docs/deploy/bitbucket) for setup instructions.

    If the repository's `docs.json` is in a subdirectory rather than the root, enable **docs.json is in a subdirectory** and enter the path to that directory.
  </Step>

  <Step title="Set the URL path">
    Enter a **URL path** for the repository source.

    The URL path determines where the content from that repository appears on your docs site. For example, a URL path of `api` serves the content under `docs.example.com/api`.

    To serve a source at the root of your site with no path prefix, leave the URL path empty or set it to `/`. Only one source per deployment can use the root URL path.

    <Note>
      You can enter the path with or without leading slashes. Mintlify normalizes the value when you save.
    </Note>
  </Step>

  <Step title="Save changes">
    Click **Save changes**. Mintlify saves the configuration and queues a deployment of the combined site.
  </Step>
</Steps>

## Change the base source

The base source provides the site-wide configuration for your multi-repository deployment. Change the base source when you want a different repository's `docs.json` to control settings like theme, colors, site name, and top-level navigation.

<Steps>
  <Step title="Open Git settings">
    Navigate to [Git settings](https://app.mintlify.com/settings/deployment/git-settings) in your dashboard.

    The current base source shows a **Base** badge next to the repository name.
  </Step>

  <Step title="Set a new base source">
    On the repository you want to use as the base, click **Set as base**.

    Mintlify updates the base source immediately and queues a deployment using the new base repository's `docs.json` for site-level configuration.
  </Step>
</Steps>

<Warning>
  Changing the base source replaces site-level settings such as theme, colors, logo, site name, and top-level navigation with the values from the new base repository's `docs.json`. This change doesn't affect URL paths or content from other sources.
</Warning>

## Example repository layout

In this example, each source has its own repository and its own `docs.json`.

```text theme={null}
acme/product-docs
├── docs.json
├── overview.mdx
└── guides/

acme/api-docs
├── docs.json
├── introduction.mdx
└── reference/

acme/sdk-docs
├── docs.json
├── quickstart.mdx
└── javascript/
```

Configure each repository with a URL path:

| Repository          | URL path  | Published path |
| ------------------- | --------- | -------------- |
| `acme/product-docs` | `product` | `/product`     |
| `acme/api-docs`     | `api`     | `/api`         |
| `acme/sdk-docs`     | `sdks`    | `/sdks`        |

## Navigation behavior

Mintlify combines the navigation from each repository into one site navigation. Each repository source becomes a top-level product section under the configured URL path.

The name of each product section comes from the `name` field in the corresponding repository's `docs.json`. For example, if a repository's `docs.json` sets `"name": "API Reference"`, its product section appears as "API Reference" in the combined navigation.

Keep each source's navigation scoped to that repository. For example, pages in the API repository should reference only files that live in the API repository. Similarly, pages in the SDK repository should reference only files that live in the SDK repository.

Nested `navigation.products` configurations are not supported inside individual source repositories.

### Link between sources

Relative Markdown links can't resolve across repositories because each source only sees its own files at build time. To link from one source to a page in another source, use a root-relative URL path that includes the destination source's URL path:

```mdx theme={null}
See the [API reference](/api/reference/authentication) for details.
```

In this example, `/api` is the URL path configured for the API repository source. The link resolves at the published site level to `docs.example.com/api/reference/authentication`.

Do not use full `https://` URLs for internal cross-source links. Root-relative paths keep previews and custom domains working correctly.

### Avoid path conflicts across sources

When one source uses the root URL path, its pages can share the same final URL as pages in another source. If two sources produce the same page path, Mintlify serves the page from the source with the more specific URL path and logs a conflict warning in the deployment update. To avoid conflicts, keep filenames in the root source from overlapping with URL paths configured for other sources.

## Reference navigation from another source

Use `sourceRef` to place another repository's navigation at a specific location in the base source's `docs.json`. If you don't use `sourceRef`, Mintlify adds each repository as a separate top-level product section.

### Requirements

* Configure the referenced repository as a source in the same multi-repository deployment.
* `sourceRef` values must use `owner/repo` format. Mount paths and repository names by themselves are not supported.
* The referenced source must define a similar navigation pattern as the main source. For example, a `sourceRef` inside `anchors` requires the referenced source to define `navigation.anchors`.
* `sourceRef` entries cannot form a cycle. A source cannot reference itself, and two sources cannot reference each other.
* `sourceRef` must appear inside a navigation array. It is not valid at the top level of `navigation`.

### Usage

Add a `sourceRef` entry to a navigation array in the base source's `docs.json`. The value must be the repository's `owner/repo` identifier.

```json theme={null}
{ "sourceRef": "acme/api-docs" }
```

Mintlify supports `sourceRef` inside `anchors`, `tabs`, `groups`, `pages`, `products`, `menu`, and arrays under `navigation.global`.

When you place `sourceRef` inside a tab's `menu` array, Mintlify replaces the entry with the menu items the referenced source declares under `navigation.groups[*].menu` and prefixes each item's page paths with the referenced source's URL path. If the referenced source doesn't define any menu items under `navigation.groups`, the deployment fails.

For example, to combine anchors from multiple repositories into a single anchor navigation:

```json theme={null}
{
  "navigation": {
    "anchors": [
      {
        "anchor": "Guides",
        "pages": ["quickstart"]
      },
      {
        "sourceRef": "acme/api-docs"
      }
    ]
  }
}
```

If `acme/api-docs` defines its own `navigation.anchors`, Mintlify replaces the `sourceRef` entry with those anchors and prefixes their paths with the referenced source's URL path.

## Removing a repository source

You can remove a repository source from the [Git settings page](https://app.mintlify.com/settings/deployment/git-settings) in your dashboard. When only one repository source remains, Mintlify removes the source URL path and treats the remaining repository as the root source for the deployment.


# Preview deployments
Source: https://www.mintlify.com/docs/deploy/preview-deployments

Get unique preview URLs for each pull request so reviewers can see documentation changes in a live environment before merging to production.

<Info>
  Preview deployments require a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=preview-deployments).
</Info>

Preview deployments let you see how changes to your docs look before merging to production. Each preview creates a shareable URL that updates automatically as you push new changes.

Preview URLs are publicly viewable by default. Share a preview link with anyone who needs to review your changes.

## Create preview deployments

Create preview deployments automatically through pull requests or manually from your dashboard.

### Automatic previews

<Note>
  Automatic previews are only created for pull requests targeting your [deployment branch](/docs/guides/git-concepts#deployment-branch).
</Note>

When you create a pull request, the Mintlify bot automatically adds a link to view the preview deployment in your pull request. The preview updates each time you push new commits to the branch.

<Frame>
  <img alt="Link to view deployment in the pull request timeline" />

  <img alt="Link to view deployment in the pull request timeline" />
</Frame>

### Fork pull requests

Pull requests opened from a fork do not generate preview deployments. The Mintlify GitHub App must be installed on a repository to generate a preview, so it cannot read a fork or build a preview against it.

A maintainer with write access to the main repository can preview changes from a fork. They can push the forked contributor's branch to a branch in the main repository or merge the fork into an integration branch. The GitHub App can then build a preview for a pull request opened from that branch.

### Manual previews

You can manually create a preview for any branch.

1. Go to your [dashboard](https://app.mintlify.com/).
2. Click **Previews**.
3. Click **Create custom preview**.
4. Enter the name of the branch you want to preview.
5. Click **Create preview**.

### API

You can also create preview deployments programmatically using the [Trigger preview deployment](/docs/api/preview/trigger) API endpoint. This is useful for integrating preview creation into continuous integration and continuous delivery (CI/CD) pipelines or custom tooling.

## Redeploy a preview

Redeploy a preview to refresh content or retry after a failed deployment.

1. Click the preview from your [dashboard](https://app.mintlify.com/).
2. Click **Redeploy**.

<Frame>
  <img alt="The Previews menu with the deploy button emphasized by an orange rectangle." />

  <img alt="The Previews menu with the deploy button emphasized by an orange rectangle." />
</Frame>

## Preview widget

The preview widget appears on preview deployments to help you navigate and review updated pages. The widget is a floating button in the bottom-right corner of your preview deployment.

<Frame>
  <img alt="Preview widget expanded to show list of changed files." />

  <img alt="Preview widget expanded to show list of changed files." />
</Frame>

1. Click the widget to show all added, modified, or removed files in the preview.
2. Click a file to view the changes on the corresponding page.
3. Use the search bar to filter the list of changed files.
4. Hover over a file and click the **Open in editor** icon to edit the file directly in the web editor.

The widget only appears on preview deployments, not on your live site or local previews.

## Restrict access to preview deployments

By default, preview deployments are publicly accessible to anyone with the URL. You can restrict access by requiring organization authentication for all previews or by password-protecting individual previews.

### Require organization authentication

Restrict preview access to authenticated members of your Mintlify organization.

1. Navigate to the **Previews** section in the [Add-ons](https://app.mintlify.com/products/addons) page of your dashboard.
2. Click the **Preview authentication** toggle to enable or disable preview authentication.

<Frame>
  <img alt="The preview authentication toggle in the Add-ons page" />

  <img alt="The preview authentication toggle in the Add-ons page" />
</Frame>

### Password-protect an individual preview

Password-protect a specific preview to share it with external reviewers without adding them to your Mintlify organization. This option is available when creating a manual preview and is not shown when organization authentication is already enabled for your deployment.

1. Go to your [dashboard](https://app.mintlify.com/).
2. Click **Previews**.
3. Click **Create custom preview**.
4. Enter the name of the branch you want to preview.
5. Toggle **Make private** on and enter a password. Passwords must be at least 8 characters.

<Frame>
  <img alt="The Create a custom preview modal with the Make private toggle enabled and a password field." />

  <img alt="The Create a custom preview modal with the Make private toggle enabled and a password field." />
</Frame>

6. Click **Create preview**.

## Preview lifetime

Preview deployments stay live as long as their source branch exists in your repository and continue to receive updates on every push.

* **Automatic previews**: The preview for a pull request remains available while the PR is open and after it's merged or closed, as long as the source branch still exists. When you delete the branch, the next dashboard sync removes the preview.
* **Manual previews**: Manual previews stay live until you delete them. Redeploying a manual preview refreshes its content against the latest commit on the specified branch.
* **Delete a preview**: In your [dashboard](https://app.mintlify.com/), go to **Previews**, open the preview, and click **Delete** to remove it immediately.

Preview URLs are unique per branch. If you delete a preview and later recreate one for the same branch, Mintlify may issue a new URL.

Mintlify generates preview URLs automatically. The subdomain and domain are not configurable, and custom domains only apply to your production deployment.

## Troubleshooting preview deployments

If your preview deployment fails, try these troubleshooting steps.

* **View the build logs**: In your [dashboard](https://app.mintlify.com/), go to **Previews** and click the failed preview. The deployment logs show errors that caused failures.
* **Check your configuration**:
  * Missing `docs.json` at the configured content root. If your `docs.json` is in a subdirectory, confirm the **docs.json is in a subdirectory** setting points to the correct path.
  * Invalid `docs.json` syntax (for example, an empty file or a stray trailing comma that breaks JSON parsing).
  * Schema errors in `docs.json` such as an invalid `theme`, malformed `navigation`, or unresolved `$ref` values.
  * Missing or incorrect file paths referenced in your navigation.
  * Invalid frontmatter in MDX files.
  * Broken image links or missing image files.
* **Validate locally**: Run `mint dev` and `mint validate` locally to catch configuration and build errors before pushing to the repository.
* **Check recent changes**: Review the most recent commits in your branch to identify what changes caused the build to fail.


# Reverse proxy
Source: https://www.mintlify.com/docs/deploy/reverse-proxy

Configure a custom reverse proxy with nginx or a similar tool to serve your Mintlify documentation at a subpath on your own domain.

To serve your documentation through a custom reverse proxy, you must configure routing rules, caching policies, and header forwarding.

When you implement a reverse proxy, monitor for potential issues with domain verification, SSL certificate provisioning, authentication flows, performance, and analytics tracking.

## Set your base path

Set your base path on the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page in your dashboard. Then configure your reverse proxy to route that path to Mintlify. The default base path is `/docs`, but you can use any base path you choose, like `/help` or `/resources`.

In all configurations, use `mintlify.site` as the proxy target.

## Host at `/docs` subpath

Use this configuration when you want to serve documentation at the `/docs` path on your domain.

Before configuring your reverse proxy:

1. Navigate to [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) in your dashboard.
2. Enable the **Host at** toggle.
3. Enter your domain.
4. Enter `docs` as your base path.
5. Click **Add domain**.

<Warning>
  When you host at a subpath, your canonical docs URL becomes `<your-subdomain>.mintlify.site<your-base-path>`, like `<your-subdomain>.mintlify.site/docs`. Proxy to `<your-subdomain>.mintlify.site` so cache invalidation and updates take effect.
</Warning>

### Routing configuration

Proxy these paths to your Mintlify subdomain:

| Path                                     | Destination                                                      | Caching  |
| ---------------------------------------- | ---------------------------------------------------------------- | -------- |
| `/docs`                                  | `<your-subdomain>.mintlify.site/docs`                            | No cache |
| `/docs/*`                                | `<your-subdomain>.mintlify.site/docs/*`                          | No cache |
| `/.well-known/vercel/*`                  | `<your-subdomain>.mintlify.site/.well-known/vercel/*`            | No cache |
| `/.well-known/skills/*` (optional)       | `<your-subdomain>.mintlify.site/docs/.well-known/skills/*`       | No cache |
| `/.well-known/agent-skills/*` (optional) | `<your-subdomain>.mintlify.site/docs/.well-known/agent-skills/*` | No cache |
| `/skill.md` (optional)                   | `<your-subdomain>.mintlify.site/docs/skill.md`                   | No cache |
| `/llms.txt` (optional)                   | `<your-subdomain>.mintlify.site/docs/llms.txt`                   | No cache |
| `/llms-full.txt` (optional)              | `<your-subdomain>.mintlify.site/docs/llms-full.txt`              | No cache |

Your proxy must forward all HTTP methods on documentation paths. Mintlify sends analytics events as `POST` requests to `/docs/_mintlify/api/v1/e`. A proxy that only allows `GET` and `HEAD` requests silently breaks the analytics in your dashboard.

Mintlify serves these files under your base path, like `<your-subdomain>.mintlify.site/docs/llms.txt`. They are available on your domain under your subpath, like `your-domain.com/docs/llms.txt`, through your main subpath route.

The `/.well-known/skills/*`, `/.well-known/agent-skills/*`, `/skill.md`, `/llms.txt`, and `/llms-full.txt` routes are optional. Include them only if you also want to serve these files at root paths on your domain, like `your-domain.com/llms.txt`. Each root path maps to the file under your base path on your Mintlify subdomain.

### Required header configuration

Configure your reverse proxy with these header requirements:

* **Origin**: Contains the target subdomain `<your-subdomain>.mintlify.site`.
* **X-Forwarded-For**: Preserves client IP information.
* **X-Forwarded-Proto**: Preserves the original protocol (HTTP/HTTPS).
* **X-Real-IP**: Forwards the real client IP address.
* **User-Agent**: Forwards the user agent.

<Warning>
  Do not forward the `Host` header.
</Warning>

### Example nginx configuration

```nginx theme={null}
server {
    listen 80;
    server_name <your-domain>.com;

    # Vercel verification paths
    location ~ ^/\.well-known/vercel/ {
        proxy_pass https://<your-subdomain>.mintlify.site;
        proxy_set_header Origin <your-subdomain>.mintlify.site;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header User-Agent $http_user_agent;

        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # AI skills paths
    location ^~ /.well-known/skills/ {
        proxy_pass https://<your-subdomain>.mintlify.site/docs/.well-known/skills/;
        proxy_set_header Origin <your-subdomain>.mintlify.site;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header User-Agent $http_user_agent;

        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # Agent-skills discovery paths
    location ^~ /.well-known/agent-skills/ {
        proxy_pass https://<your-subdomain>.mintlify.site/docs/.well-known/agent-skills/;
        proxy_set_header Origin <your-subdomain>.mintlify.site;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header User-Agent $http_user_agent;

        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # Skill manifest (optional)
    location = /skill.md {
        proxy_pass https://<your-subdomain>.mintlify.site/docs/skill.md;
        proxy_set_header Origin <your-subdomain>.mintlify.site;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header User-Agent $http_user_agent;

        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # LLM index files (optional)
    location = /llms.txt {
        proxy_pass https://<your-subdomain>.mintlify.site/docs/llms.txt;
        proxy_set_header Origin <your-subdomain>.mintlify.site;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header User-Agent $http_user_agent;

        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    location = /llms-full.txt {
        proxy_pass https://<your-subdomain>.mintlify.site/docs/llms-full.txt;
        proxy_set_header Origin <your-subdomain>.mintlify.site;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header User-Agent $http_user_agent;

        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # Documentation root
    location = /docs {
        proxy_pass https://<your-subdomain>.mintlify.site;
        proxy_set_header Origin <your-subdomain>.mintlify.site;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header User-Agent $http_user_agent;

        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # All documentation paths
    location /docs/ {
        proxy_pass https://<your-subdomain>.mintlify.site/docs/;
        proxy_set_header Origin <your-subdomain>.mintlify.site;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header User-Agent $http_user_agent;

        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
}
```

## Custom subpath

To use a subpath other than `/docs` (such as `/help` or `/resources`):

1. Navigate to the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page in your dashboard.
2. Enable the **Host at** toggle.
3. Enter your domain.
4. Enter your base path. For example, `/docs` or `/help`.
5. Click **Add domain**.

Mintlify rebuilds your documentation to serve at your base path, so `<your-subdomain>.mintlify.site<your-base-path>` serves your content.

Configure your reverse proxy using the same [routing configuration](#routing-configuration), [header requirements](#required-header-configuration), and nginx patterns as the `/docs` subpath, replacing `/docs` with your base path.

## Troubleshooting

### Changes not appearing

**Symptoms**: You publish documentation updates, but the changes don't appear on your site.

**Cause**: Your reverse proxy points to an outdated hostname.

**Solution**: Update your reverse proxy configuration to point to `<your-subdomain>.mintlify.site`.

### 404 error

**Symptoms**: Documentation loads, but features don't work. API calls fail.

**Cause**: The reverse proxy forwards the `Host` header or the `Origin` header is missing.

**Solution**:

* Remove `Host` header forwarding.
* Set the `Origin` header to your Mintlify subdomain (`<your-subdomain>.mintlify.site`).

### Performance issues

**Symptoms**: Slow page loads and layout shifts.

**Cause**: Incorrect caching configuration.

**Solution**: Disable caching for documentation paths. If you proxy `/mintlify-assets/_next/static/*` paths, enable caching only for those static assets.


# Deploy at a subpath with AWS Route 53 and CloudFront
Source: https://www.mintlify.com/docs/deploy/route53-cloudfront

Deploy your Mintlify documentation at a subpath on AWS by combining Route 53 DNS routing, a CloudFront distribution, and cache behaviors.

To host your documentation at a subpath such as `yoursite.com/docs` using AWS Route 53 and CloudFront, configure your DNS provider to point to your CloudFront distribution.

Before configuring AWS, set your base path in your dashboard:

1. Navigate to the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page in your dashboard.
2. Enable the **Host at** toggle.
3. Enter your domain.
4. Enter your base path. For example, `/docs` or `/help`.
5. Click **Add domain**.

## Overview

<Note>
  The following examples use the `/docs` base path. If you use a different base path, replace `/docs` with your base path.
</Note>

Route traffic to these paths with a Cache Policy of **CachingDisabled**:

* `/.well-known/acme-challenge/*` - Required for Let's Encrypt certificate verification
* `/.well-known/vercel/*` - Required for domain verification
* `/docs/*` - Required for subpath routing
* `/docs/` - Required for subpath routing
* `/_mintlify/*` - Required for API playground requests

Route traffic to these paths with a Cache Policy of **CachingEnabled**:

* `/mintlify-assets/*` - Required for CSS, JavaScript, and favicons
* `Default (*)` - Your website's landing page

All Behaviors must have an **origin request policy** of `AllViewerExceptHostHeader`.

The behaviors for your subpath must allow all HTTP methods. CloudFront only allows `GET` and `HEAD` requests by default. This blocks the `POST` requests that Mintlify uses for analytics and other interactive features.

<img alt="CloudFront &#x22;Behaviors&#x22; page with 4 behaviors: /docs/*, /docs, Default, and /.well-known/*." />

## Create CloudFront distribution

1. Navigate to [CloudFront](https://aws.amazon.com/cloudfront) inside the AWS console.
2. Click **Create distribution**.

<Frame>
  <img alt="CloudFront Distributions page with the &#x22;Create distribution&#x22; button emphasized." />
</Frame>

3. For the Origin domain, input `[SUBDOMAIN].mintlify.site` where `[SUBDOMAIN]` is your project's unique subdomain.

<Frame>
  <img alt="CloudFront &#x22;Create distribution&#x22; page showing &#x22;acme.mintlify.site&#x22; as the origin domain." />
</Frame>

4. For "Web Application Firewall (WAF)," enable security protections.

<Frame>
  <img alt="Web Application Firewall (WAF) options with &#x22;Enable security protections&#x22; selected." />
</Frame>

<Note>
  WAF rules can block the `POST` requests that Mintlify uses for analytics and other interactive features. If analytics stop appearing in your dashboard after enabling WAF, check your WAF logs. Look for blocked requests to paths under `/docs/_mintlify/`.
</Note>

5. The remaining settings should be default.
6. Click **Create distribution**.

## Add default origin

1. After creating the distribution, navigate to the "Origins" tab.

<Frame>
  <img alt="A CloudFront distribution with the &#x22;Origins&#x22; tab highlighted." />
</Frame>

2. Find your staging URL that mirrors the main domain. This varies depending on your landing page host. For example, the Mintlify staging URL is [mintlify-landing-page.vercel.app](https://mintlify-landing-page.vercel.app).

<Info>
  If Webflow hosts your landing page, use Webflow's staging URL. It would look like `.webflow.io`.

  If you use Vercel, use the `.vercel.app` domain available for every project.
</Info>

3. Create a new Origin and add your staging URL as the "Origin domain."

<Frame>
  <img alt="CloudFront &#x22;Create origin&#x22; page with a &#x22;Origin domain&#x22; input field highlighted." />
</Frame>

You should now have two Origins: one with `[SUBDOMAIN].mintlify.site` and another with your staging URL.

<Frame>
  <img alt="CloudFront &#x22;Origins&#x22; page with two origins: One for mintlify and another for mintlify-landing-page." />
</Frame>

## Set behaviors

Behaviors in CloudFront enable control over the subpath logic. At a high level, you create the following logic:

* **If a user lands on your custom subpath**, go to `[SUBDOMAIN].mintlify.site`.
* **If a user lands on any other page**, go to the current landing page.

1. Navigate to the "Behaviors" tab of your CloudFront distribution.

<Frame>
  <img alt="CloudFront &#x22;Behaviors&#x22; tab highlighted." />
</Frame>

2. Click the **Create behavior** button and create the following behaviors.

### `/.well-known/*`

Create behaviors for Vercel domain verification paths with a **Path pattern** of `/.well-known/*` and set **Origin and origin groups** to your docs URL.

For "Cache policy," select **CachingDisabled** to ensure these verification requests pass through without caching.

<Frame>
  <img alt="CloudFront &#x22;Create behavior&#x22; page with a &#x22;Path pattern&#x22; of &#x22;/.well-known/*&#x22; and &#x22;Origin and origin groups&#x22; pointing to the staging URL." />
</Frame>

<Info>
  If `.well-known/*` is too generic, narrow it down to at least 2 behaviors for Vercel:

  * `/.well-known/vercel/*` - Required for Vercel domain verification
  * `/.well-known/acme-challenge/*` - Required for Let's Encrypt certificate verification
</Info>

### Your subpath

Create a behavior with a **Path pattern** of your chosen subpath, for example `/docs`. Set **Origin and origin groups** to the `.mintlify.site` URL (for example, `acme.mintlify.site`).

* Set "Cache policy" to **CachingDisabled**.
* Set "Origin request policy" to **AllViewerExceptHostHeader**.
* Set "Viewer protocol policy" to **Redirect HTTP to HTTPS**.
* Set "Allowed HTTP methods" to **GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE**.

<Warning>
  CloudFront only allows `GET` and `HEAD` requests by default. If you don't allow all HTTP methods, CloudFront rejects the `POST` requests that Mintlify uses for analytics. Your dashboard won't show any page views even though your docs load normally.
</Warning>

<Frame>
  <img alt="CloudFront &#x22;Create behavior&#x22; page with a &#x22;Path pattern&#x22; of &#x22;/docs/*&#x22; and &#x22;Origin and origin groups&#x22; pointing to the acme.mintlify.site URL." />
</Frame>

### Your subpath with wildcard

Create a behavior with a **Path pattern** of your chosen subpath followed by `/*`, for example `/docs/*`, and **Origin and origin groups** pointing to the same `.mintlify.site` URL.

These settings should exactly match your base subpath behavior, with the exception of the **Path pattern**.

* Set "Cache policy" to **CachingDisabled**.
* Set "Origin request policy" to **AllViewerExceptHostHeader**.
* Set "Viewer protocol policy" to **Redirect HTTP to HTTPS**.
* Set "Allowed HTTP methods" to **GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE**.

### `/mintlify-assets/*`

Create a behavior with a **Path pattern** of `/mintlify-assets/*` and set **Origin and origin groups** to the `.mintlify.site` URL. This path serves the CSS, JavaScript, and favicons for your documentation from the root of your domain.

* Set "Cache policy" to **CachingOptimized**.
* Set "Origin request policy" to **AllViewerExceptHostHeader**.
* Set "Viewer protocol policy" to **Redirect HTTP to HTTPS**.

### `/_mintlify/*`

Create a behavior with a **Path pattern** of `/_mintlify/*` and set **Origin and origin groups** to the `.mintlify.site` URL. This path handles API playground requests from the root of your domain.

* Set "Cache policy" to **CachingDisabled**.
* Set "Origin request policy" to **AllViewerExceptHostHeader**.
* Set "Viewer protocol policy" to **Redirect HTTP to HTTPS**.
* Set "Allowed HTTP methods" to **GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE**.

### `Default (*)`

Edit the `Default (*)` behavior.

<Frame>
  <img alt="A CloudFront distribution with the &#x22;Default (*)&#x22; behavior selected and the Edit button emphasized." />
</Frame>

1. Change the default behavior's **Origin and origin groups** to the staging URL (for example, `mintlify-landing-page.vercel.app`).

<Frame>
  <img alt="CloudFront &#x22;Edit behavior&#x22; page with the &#x22;Origin and origin groups&#x22; input field highlighted." />
</Frame>

2. Click **Save changes**.

### Check that you set up behaviors correctly

If you follow the preceding steps, your behaviors should look like this:

<Frame>
  <img alt="CloudFront &#x22;Behaviors&#x22; page with 4 behaviors: /docs/*, /docs, Default, and /.well-known/*." />
</Frame>

## Preview distribution

To test your distribution, go to the "General" tab and visit the **Distribution domain name** URL.

<Frame>
  <img alt="CloudFront &#x22;General&#x22; tab with the &#x22;Distribution domain name&#x22; URL highlighted." />
</Frame>

All pages should route to your main landing page. When you append your chosen subpath, for example `/docs`, the URL should serve your Mintlify documentation.

## Connect with Route 53

Next, connect the CloudFront distribution to your primary domain.

<Note>
  For this section, you can also refer to AWS's official guide on [Configuring
  Amazon Route 53 to route traffic to a CloudFront
  distribution](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-cloudfront-distribution.html#routing-to-cloudfront-distribution-config).
</Note>

1. Navigate to [Route53](https://aws.amazon.com/route53) inside the AWS console.
2. Navigate to the "Hosted zone" for your primary domain.
3. Click **Create record**.

<Frame>
  <img alt="Route 53 &#x22;Records&#x22; page with the &#x22;Create record&#x22; button emphasized." />
</Frame>

4. Toggle `Alias` and then **Route traffic to** the `Alias to CloudFront distribution` option.

<Frame>
  <img alt="Route 53 &#x22;Create record&#x22; page with the &#x22;Alias&#x22; toggle and the &#x22;Route traffic to&#x22; menu highlighted." />
</Frame>

5. Click **Create records**.

<Note>
  You may need to remove the existing A record if one currently exists.
</Note>

Your documentation is now live at your chosen subpath for your primary domain.

<Note>
  After you deploy your changes, your documentation is usually available at your subpath within a few minutes. If your setup includes DNS changes, propagation can take 1-4 hours, and in rare cases up to 48 hours. If your documentation is not immediately available, wait before troubleshooting.
</Note>


# Self-host
Source: https://www.mintlify.com/docs/deploy/self-host

Run Mintlify inside your own cloud or on-premises environment, on AWS or any Kubernetes platform including Azure, Google Cloud, Oracle Cloud, and OpenShift.

<Info>
  Self-hosting requires an [Enterprise plan](https://mintlify.com/pricing?ref=self-host). Reach out to your account team to scope a deployment.
</Info>

Self-hosting runs Mintlify inside your own cloud account or data center, so your content, build pipeline, analytics, and logs stay within your network boundary. It's designed for teams with data-residency, compliance, or air-gap requirements that a cloud-hosted deployment can't meet.

Every self-hosted deployment is a scoped engagement with your account team, not a self-serve install. This page describes what you provision, how the deployment runs, and the tradeoffs against cloud hosting so you can evaluate self-hosting before committing to it.

## Platform support

| Platform                                                                                                                                                                                   | Method                                                     |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
| <Icon icon="https://mintcdn.com/mintlify/Q7oFaERE0J2m9ZuP/images/logos/aws-mark.svg?fit=max&auto=format&n=Q7oFaERE0J2m9ZuP&q=85&s=58f3dda751b77b17ab6cced2cebd2e58" /> Amazon Web Services | AWS Cloud Development Kit (CDK) app                        |
| <Icon icon="https://mintcdn.com/mintlify/Q7oFaERE0J2m9ZuP/images/logos/azure.svg?fit=max&auto=format&n=Q7oFaERE0J2m9ZuP&q=85&s=4876869c714a175f00a6a4e901cb3773" /> Microsoft Azure        | Helm chart on Azure Kubernetes Service (AKS)               |
| <Icon icon="https://mintcdn.com/mintlify/Q7oFaERE0J2m9ZuP/images/logos/gcp.svg?fit=max&auto=format&n=Q7oFaERE0J2m9ZuP&q=85&s=6dbbcc45c5c496930feed71d98abecc6" /> Google Cloud             | Helm chart on Google Kubernetes Engine (GKE)               |
| <Icon icon="https://mintcdn.com/mintlify/Q7oFaERE0J2m9ZuP/images/logos/oracle-mark.svg?fit=max&auto=format&n=Q7oFaERE0J2m9ZuP&q=85&s=e762372bf1a32cd569d62fd6d05f6cab" /> Oracle Cloud     | Helm chart on Oracle Container Engine for Kubernetes (OKE) |
| <Icon icon="https://mintcdn.com/mintlify/Q7oFaERE0J2m9ZuP/images/logos/openshift.svg?fit=max&auto=format&n=Q7oFaERE0J2m9ZuP&q=85&s=bd02374a3dc706827faa493ae3144a94" /> Red Hat OpenShift  | Helm chart                                                 |
| <Icon icon="https://mintcdn.com/mintlify/Q7oFaERE0J2m9ZuP/images/logos/kubernetes.svg?fit=max&auto=format&n=Q7oFaERE0J2m9ZuP&q=85&s=eac35dd976d4b34b4afc0ab2be08f4d5" /> Any Kubernetes    | Helm chart                                                 |

## How self-hosting compares to cloud hosting

Authoring works the same way in both hosting models. Your team maintains content with the editor or their Git workflow, and every change flows through your repository's review process. What changes is who operates the platform and where data resides.

| Area             | Cloud-hosted                  | Self-hosted                                                                                                                                         |
| ---------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| Time to launch   | Same day                      | Scoped engagement, typically weeks                                                                                                                  |
| Infrastructure   | Mintlify operates everything  | You operate the cluster, network, and data stores. Mintlify ships versioned releases with upgrade guides and supports the application tier          |
| Platform updates | Continuous, automatic         | Versioned releases that you review and deploy on your own schedule                                                                                  |
| Data boundary    | Processed in Mintlify's cloud | Content, builds, analytics, and logs stay inside your network with no third-party egress                                                            |
| AI features      | On by default                 | Ship disabled until your security or AI governance team approves them. Can run against your own model endpoint, your own API key, or Mintlify cloud |
| Integrations     | Full catalog                  | Integrations that depend on Mintlify cloud services are unavailable                                                                                 |
| Monitoring       | Managed by Mintlify           | You connect your own observability stack                                                                                                            |

Self-hosted deployments usually start narrow and expand. A common path is to start with public documentation, then add authenticated content, the web editor, and AI features as you complete security reviews.

## Features

Everything core to authoring, building, and serving documentation ships in a self-hosted deployment.

| Feature                                   |         Availability         | Notes                                                                                                        |
| ----------------------------------------- | :--------------------------: | ------------------------------------------------------------------------------------------------------------ |
| Documentation site                        | <Icon icon="circle-check" /> | Full rendering, components, and theming                                                                      |
| Web editor                                | <Icon icon="circle-check" /> | Browser-based authoring                                                                                      |
| Git-backed workflow                       | <Icon icon="circle-check" /> | GitHub, GitHub Enterprise Server, GitLab including self-managed, Bitbucket, or an internally owned proxy API |
| Search                                    | <Icon icon="circle-check" /> | Runs inside your deployment. The index rebuilds on publish                                                   |
| Authenticated content                     | <Icon icon="circle-check" /> | Access control through your identity provider                                                                |
| Dashboard SSO                             | <Icon icon="circle-check" /> | OIDC or SAML                                                                                                 |
| Analytics                                 | <Icon icon="circle-check" /> | Collected and stored inside your network                                                                     |
| Third-party analytics and support widgets | <Icon icon="circle-check" /> | Configured with your own keys, served from the docs site                                                     |
| Static export                             | <Icon icon="circle-check" /> | Self-contained bundles for air-gapped serving                                                                |
| Versioned releases and rollback           | <Icon icon="circle-check" /> | Each release pins image versions. Roll back by redeploying the previous version                              |
| AI assistant and agent                    |           Optional           | Ships disabled. Runs against your own model endpoint, your own API key, or Mintlify cloud                    |

Only smaller surfaces that depend on Mintlify-operated services are cloud-only: the Slack app, third-party connectors for agent automations, and SDK generation integrations.

## Architecture

A self-hosted deployment is a set of services with clear dependencies. Provision the data stores first, then the services that depend on them, then the edge.

```mermaid theme={null}
flowchart TD
  U[Users] --> CDN[CDN and WAF]
  CDN --> ING[Load balancer or ingress]
  ING --> WEB[Docs site]
  ING --> API[Dashboard and API]
  API --> BUILD[Build workers]
  BUILD --> GIT[Git source]
  WEB --> OBJ[(Object storage)]
  BUILD --> OBJ
  API --> MONGO[(MongoDB)]
  API --> PG[(PostgreSQL)]
  API --> REDIS[(Redis)]
  API --> SEARCH[Search and indexing]
  API --> IDP[Identity provider]
  API -. optional .-> AI[AI assistant services]
```

| Resource                 | Purpose                                                      |           Required           |
| ------------------------ | ------------------------------------------------------------ | :--------------------------: |
| Load balancer or ingress | TLS termination and routing                                  | <Icon icon="circle-check" /> |
| Docs site                | Serves rendered documentation                                | <Icon icon="circle-check" /> |
| Dashboard and API        | Admin, auth, and build orchestration                         | <Icon icon="circle-check" /> |
| Build workers            | Build and publish documentation sites                        | <Icon icon="circle-check" /> |
| MongoDB                  | Content store                                                | <Icon icon="circle-check" /> |
| PostgreSQL               | Deployment and user metadata                                 | <Icon icon="circle-check" /> |
| Redis                    | Build queue and caching                                      | <Icon icon="circle-check" /> |
| Object storage           | Built site bundles and static exports                        | <Icon icon="circle-check" /> |
| Search and indexing      | Docs search. The index rebuilds on publish                   | <Icon icon="circle-check" /> |
| Identity provider        | OIDC or SAML SSO for the dashboard and authenticated content | <Icon icon="circle-check" /> |
| AI assistant services    | Assistant and agent features                                 |           Optional           |

Your documentation source can be GitHub, GitHub Enterprise Server, GitLab (including self-managed), or Bitbucket.

If your organization can't grant repository credentials to a third-party service, front your Git hosting with an internally owned proxy API instead. Fully air-gapped environments use [static export](/docs/api/static-export/overview) with no Git connection at all.

### Sizing

As a starting point, a production deployment runs on roughly 45 to 60 vCPU, 160 to 220 GB of memory, and about 1 TB of solid-state storage across services. Non-production environments run at about half that. Your account team sizes the deployment with you based on page count, traffic, and which features you enable.

## Set up your platform

<Tabs>
  <Tab title="AWS" icon="https://mintcdn.com/mintlify/Q7oFaERE0J2m9ZuP/images/logos/aws-mark.svg?fit=max&auto=format&n=Q7oFaERE0J2m9ZuP&q=85&s=58f3dda751b77b17ab6cced2cebd2e58">
    AWS deployments use an AWS CDK app that provisions and updates the full stack in your account. The CDK app pins container images to specific versions, so every deployment is reproducible and reviewable.

    ### What you provide

    | Component       | Requirement                                                    | Notes                                    |
    | --------------- | -------------------------------------------------------------- | ---------------------------------------- |
    | Compute         | Amazon ECS cluster                                             | Runs the Mintlify services               |
    | Content store   | Amazon DocumentDB                                              | MongoDB-compatible                       |
    | Metadata store  | Amazon RDS for PostgreSQL                                      | Deployment and user metadata             |
    | Cache and queue | Amazon ElastiCache for Redis                                   | Build queue and caching                  |
    | Object storage  | Amazon S3                                                      | Built site bundles and static exports    |
    | CDN             | Amazon CloudFront                                              | Serves the docs site at the edge         |
    | Networking      | VPC with public and private subnets, Application Load Balancer | Isolates workloads                       |
    | TLS and DNS     | AWS Certificate Manager, Amazon Route 53                       | HTTPS and routing for your domain        |
    | Secrets         | AWS Secrets Manager                                            | Database credentials and signing secrets |
    | Identity        | OIDC or SAML provider                                          | Dashboard SSO                            |

    ### Setup

    <Steps>
      <Step title="Scope the deployment">
        Your account team reviews your network topology, Git hosting, identity provider, and compliance requirements, then delivers the CDK app and access to versioned container images.
      </Step>

      <Step title="Configure and deploy">
        Set your domain, certificate, and networking in the CDK context, review the change set, and deploy.

        ```bash theme={null}
        cdk diff
        cdk deploy --all
        ```
      </Step>

      <Step title="Connect Git and SSO">
        Grant the deployment access to your documentation repositories and connect your identity provider.
      </Step>

      <Step title="Cut over">
        Verify builds and search on your staging domain, then point your production DNS at the deployment.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Kubernetes" icon="https://mintcdn.com/mintlify/Q7oFaERE0J2m9ZuP/images/logos/kubernetes.svg?fit=max&auto=format&n=Q7oFaERE0J2m9ZuP&q=85&s=eac35dd976d4b34b4afc0ab2be08f4d5">
    Kubernetes deployments use the Mintlify enterprise Helm chart and run on any certified Kubernetes cluster. The same chart covers managed Kubernetes on any cloud and on-premises clusters:

    * **Azure**: AKS, with Microsoft Entra ID for SSO and Azure managed data services.
    * **Google Cloud**: GKE, with Cloud SQL, Memorystore, and Cloud Storage.
    * **Oracle Cloud**: OKE, with OCI managed databases and OCI Object Storage.
    * **OpenShift**: ships OpenShift-compatible security contexts and uses Routes for ingress.

    ### What you provide

    | Component       | Requirement                                    | Notes                                       |
    | --------------- | ---------------------------------------------- | ------------------------------------------- |
    | Cluster         | Kubernetes or OpenShift cluster                | Hosts the Helm release                      |
    | Content store   | MongoDB                                        | Managed or in-cluster                       |
    | Metadata store  | PostgreSQL                                     | Managed or in-cluster                       |
    | Cache and queue | Redis                                          | Build queue and caching                     |
    | Object storage  | S3-compatible bucket                           | Built site bundles and static exports       |
    | Ingress         | Ingress controller or OpenShift Route with TLS | Serves HTTPS. A WAF in front is recommended |
    | Registry        | Private container registry                     | Hosts the delivered images                  |
    | Identity        | OIDC or SAML provider                          | Dashboard SSO                               |

    ### Setup

    <Steps>
      <Step title="Scope the deployment">
        Your account team reviews your cluster, Git hosting, identity provider, and compliance requirements, then delivers the Helm chart, a values template, and versioned container images for your registry.
      </Step>

      <Step title="Provision data stores">
        Stand up MongoDB, PostgreSQL, Redis, and object storage, managed by your cloud provider or in-cluster.
      </Step>

      <Step title="Configure and install">
        Point the values file at your data stores, ingress, and registry, then install the release.

        ```bash theme={null}
        helm upgrade --install mintlify ./mintlify-enterprise \
          --namespace mintlify --create-namespace -f values.yaml
        ```
      </Step>

      <Step title="Connect Git and SSO, then cut over">
        Grant the deployment access to your documentation repositories, connect your identity provider, verify on staging, and point production DNS at the deployment.
      </Step>
    </Steps>
  </Tab>
</Tabs>

## Updates

Platform updates and content updates move independently. You control when the platform changes, and your documentation stays current on its own.

### Platform updates

Mintlify ships versioned releases with upgrade guides and release notes from your account team. Each release pins specific image versions, so you can test a release in a non-production environment before deploying it and roll back to the previous version if needed.

<CodeGroup>
  ```bash AWS (CDK) theme={null}
  # review the change set for the new release, then roll it out
  cdk diff
  cdk deploy --all
  ```

  ```bash Kubernetes (Helm) theme={null}
  # upgrade to a delivered release, or roll back
  helm upgrade mintlify ./mintlify-enterprise \
    --namespace mintlify -f values.yaml
  helm rollback mintlify
  ```
</CodeGroup>

Updates roll out with no downtime. New tasks or pods start, pass health checks, and replace the old ones.

### Content updates

Content flows through your Git source, not through platform releases. When you push to your documentation repository, the build workers rebuild the site and publish it to object storage automatically. Content changes never require a platform deploy.

## Air-gapped deployments

Environments with no Git webhook path serve documentation as [static export bundles](/docs/api/static-export/overview). Self-contained builds of your site are published to object storage and served through your CDN. Regenerate the bundle when content changes, or automate the loop with a GitHub Action. AI features that require outbound network access are disabled in air-gapped deployments.

## Next steps

<Columns>
  <Card title="Talk to your account team" icon="messages-square" href="https://www.mintlify.com/enterprise">
    Scope a self-hosted deployment on your platform and plan your launch.
  </Card>

  <Card title="Static export" icon="package" href="/api/static-export/overview">
    Generate self-contained bundles of your documentation for air-gapped serving.
  </Card>
</Columns>


# Deploy at a subpath with Vercel
Source: https://www.mintlify.com/docs/deploy/vercel

Serve your Mintlify site at a subpath on your main domain using Vercel rewrites, with a step-by-step vercel.json configuration walkthrough.

Configure your `vercel.json` file to proxy requests from your main domain to your documentation at a subpath.

## The vercel.json file

The `vercel.json` file configures how your project builds and deploys. It sits in your project's root directory and controls various aspects of your deployment, including routing, redirects, headers, and build settings.

Mintlify uses the `rewrites` configuration in your `vercel.json` file to proxy requests from your main domain to your documentation.

Rewrites map incoming requests to different destinations without changing the URL in the browser. When someone visits `yoursite.com/docs`, Vercel internally fetches content from `your-subdomain.mintlify.site/docs`, but the user still sees `yoursite.com/docs` in their browser. This is different from redirects, which send users to another URL entirely.

## Configuration

### Host at `/docs` subpath

1. Navigate to [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) in your dashboard.
2. Enable the **Host at** toggle.
3. Enter your domain.
4. Enter `docs` as your base path.
5. Click **Add domain**.
6. Add the following rewrites to your `vercel.json` file. Replace `[subdomain]` with your subdomain, which appears at the end of your dashboard URL. For example, `app.mintlify.com/your-organization/your-subdomain` has a domain identifier of `your-subdomain`.

   ```json theme={null}
   {
     "rewrites": [
       {
         "source": "/docs",
         "destination": "https://[subdomain].mintlify.site/docs"
       },
       {
         "source": "/docs/:match*",
         "destination": "https://[subdomain].mintlify.site/docs/:match*"
       }
     ]
   }
   ```

The `rewrites` configuration maps the `/docs` subpath on your domain to the `/docs` subpath on your documentation.

* **`source`**: The path pattern on your domain that triggers the rewrite.
* **`destination`**: Where the request should be proxied to.
* **`:match*`**: A wildcard that captures any path segments after your subpath.

For more information, see [Configuring projects with vercel.json: Rewrites](https://vercel.com/docs/projects/project-configuration#rewrites) in the Vercel documentation.

### Host at custom subpath

To use a custom subpath (any path other than `/docs`):

1. Navigate to the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page in your dashboard.
2. Enable the **Host at** toggle.
3. Enter your domain.
4. Enter your base path. For example, `/docs` or `/help`.
5. Click **Add domain**.

Then use the generator below to create your rewrites configuration and add the rewrites to your `vercel.json` file.

Mintlify rebuilds your documentation to serve at your base path, so your documentation files do not need to be in a directory that matches your subpath.

<VercelJsonGenerator />


# External proxies with Vercel
Source: https://www.mintlify.com/docs/deploy/vercel-external-proxies

Configure external reverse proxies like Cloudflare or Nginx in front of your Vercel deployment to serve Mintlify docs at a custom subpath.

If you have an external proxy like Cloudflare or AWS CloudFront in front of your Vercel deployment, configure it properly. This avoids conflicts with Vercel's domain verification and SSL certificate provisioning.

Improper proxy configuration can prevent Vercel from provisioning Let's Encrypt SSL certificates and cause domain verification failures.

See the [supported providers](https://vercel.com/guides/how-to-setup-verified-proxy#supported-providers-verified-proxy-lite) in the Vercel documentation.

## Required path allowlist

Your external proxy must allow traffic to these specific paths without blocking, redirecting, or heavily caching:

* `/.well-known/acme-challenge/*`: Required for Let's Encrypt certificate verification.
* `/.well-known/vercel/*`: Required for Vercel domain verification.
* `/mintlify-assets/_next/static/*`: Required for static assets.

Your proxy should pass these paths directly to your Vercel deployment without modification.

## Header forwarding requirements

Ensure that your proxy correctly forwards the `Host` header. Without proper header forwarding, verification requests fail.

## Test your proxy setup

To verify your proxy is correctly configured:

1. Test that `https://[yourdomain].com/.well-known/vercel/` returns a response.
2. Ensure SSL certificates are provisioning correctly in your Vercel dashboard.
3. Check that domain verification completes successfully.


# Ask agent
Source: https://www.mintlify.com/docs/editor/agent

Use the editor's built-in AI agent to write content, edit pages, leave comments and suggestions, search your site, upload files, and configure settings.

The editor includes a built-in agent that can edit pages, reorganize navigation, update `docs.json`, search across your entire repository, and manage dashboard settings.

The editor agent makes changes directly in your current branch.

## Open the agent

Click **Ask agent** in the editor toolbar, or press <kbd>Cmd</kbd> + <kbd>I</kbd> (macOS) or <kbd>Ctrl</kbd> + <kbd>I</kbd> (Windows).

To close the panel, click the **X** button in the panel header or press <kbd>Cmd</kbd> + <kbd>I</kbd> again.

## Send a message

Type your request in the chat box at the bottom of the panel and press <kbd>Enter</kbd> or click the <Icon icon="arrow-up" /> send button.

Type <kbd>@</kbd> to mention a specific page. The agent focuses on that page when processing your request. If you don't mention a page, the agent uses the page you currently have open.

Example prompts:

* `simplify the introduction page`
* `fix all grammar errors across my content`
* `add a new page that explains authentication`
* `rename every mention of "Acme Pro" to "Acme Team" across all pages`
* `update docs.json to add a new group called "Guides"`

## Attach files

Click the paperclip icon in the chat box, or drag and drop files onto the panel. The agent reads attached files as context for your request.

Supported file types:

* **Images**: JPG, PNG, GIF, WebP, SVG
* **Documents**: PDF
* **Code and text**: `.js`, `.ts`, `.jsx`, `.tsx`, `.mdx`, `.md`, `.json`, `.yaml`, `.html`, `.css`, Python, Go, Rust, Ruby, Java, Swift, C, C++, SQL, shell scripts, and more

Maximum size: 5 MB per file. Maximum: 10 files per message.

## Add a selection to the agent

In visual mode, select text on a page. A floating toolbar appears over the selection. Click **Add to agent** to send the selected text to the agent as context.

## Ask for comments and suggestions

The agent edits content directly by default. To get feedback without immediately changing the page, explicitly ask the agent to review the page, leave comments, or make suggestions.

* [Suggestions](/docs/editor/suggestions) propose a specific replacement that you can accept or reject. The original text remains visible with a strikethrough until you decide, and the agent can include an explanation in the suggestion thread.
* [Comments](/docs/editor/comments) leave feedback or a question anchored to specific text without changing the page.

Example prompts:

* `review this page and leave suggestions`
* `comment on anything that needs more context`
* `suggest ways to make the introduction more concise`

The agent uses the page you currently have open unless you name another page. It can annotate rendered page text, including prose inside components. It cannot annotate frontmatter, page metadata, configuration, or raw MDX component tags and attributes.

## Review what the agent changed

As the agent edits your pages, a **Changed files** panel appears in the chat. Expand it to see a list of every file modified in the session. Click any file to open it in diff view and compare the agent's changes against the original.

## What the agent can do

### Edit pages

The agent can write, rewrite, expand, and reorganize content on any page. It reads your existing content to match your style and structure.

### Search and navigate your content

The agent can search across your entire repository, not just the page you have open. Use it to find information, check for inconsistencies, or verify that content exists before adding it.

### Update navigation and docs.json

The agent can add, rename, reorder, and delete navigation elements, the same changes you'd make manually in the navigation panel. It can also update `docs.json` configuration directly, including adding new groups, adjusting settings, and configuring redirects.

Example: `add a "Quickstart" group under the Getting Started tab and move the quickstart page into it`

### Run bash commands

The agent can run `grep`, `rg`, and other bash commands against your repository. Use this for bulk operations that span many files.

Example: `find every page that mentions the deprecated /v1/auth endpoint`

### Configure your site (code mode)

For requests that go beyond editing pages (setting up authentication, managing workflows, or changing deployment settings), the agent switches into code mode. It writes and runs a script against your Mintlify dashboard on your behalf.

Code mode respects your dashboard permissions. If you don't have access to a setting in the dashboard, the agent can't change it either.

Example prompts that use code mode:

* `enable JWT authentication for my site`
* `create a workflow that updates my site when I merge a PR`
* `add a custom domain`

### Continue an automation run

When you open the editor from a completed automation run by clicking **View changes**, the agent panel opens automatically with context on what the automation did. A **Changed pages** card at the top of the chat lists every page the automation modified. Click any page to open a diff view.

The agent has context on the automation's prompt, a summary of the changes it made, and which pages it modified. You can ask it to refine or extend the automation's work without re-explaining the background.

For example: `The new section on rate limits is too long. Trim it to three sentences.`

## Session history

Click the clock icon in the panel header to see your previous chat sessions. Click any session to reopen it and see what the agent changed.

## AI instructions

To give the agent persistent guidance like voice rules, terminology, or formatting conventions, configure AI instructions in [Editor settings](/docs/editor/settings#ai-instructions). The agent follows these instructions on every request without you needing to repeat them.


# Branching and publishing
Source: https://www.mintlify.com/docs/editor/branching-and-publishing

Understand how branches and protection rules determine what happens when you publish, and how to manage the full review and deployment workflow.

The web editor autosaves everything as you type, but your changes are only live when you choose to publish them.

What happens when you publish depends on two things: **which branch you're on** and **whether that branch requires pull requests**.

## Saving versus publishing

**Saving** happens automatically. Mintlify stores your edits on its servers and persists them across browser tabs, devices, and network interruptions.

**Publishing** commits your changes to your Git repository. Click **Publish** in the toolbar to open the publish menu, save your changes as a Git commit, and create a pull request.

The editor tracks the following as pending changes:

* Content edits in pages
* New or deleted pages
* Navigation structure changes
* Media uploads
* Configuration updates

## What happens when you publish

The actions available when you click the publish button depend on your current branch and whether it has branch protection rules that require pull requests.

| Branch type                          | Branch protection      | Available actions                                 |
| ------------------------------------ | ---------------------- | ------------------------------------------------- |
| <Tooltip>Deployment branch</Tooltip> | None                   | **Publish** directly to your live site            |
| Deployment branch                    | Pull requests required | **Create branch** to move changes to a new branch |
| <Tooltip>Feature branch</Tooltip>    | None                   | **Save in branch**, **Create pull request**       |
| Feature branch                       | Pull requests required | **Save in branch**, **Create pull request**       |

* **Publish**: Commits and deploys your changes to your live site immediately.
* **Save in branch**: Commits your changes to the feature branch without merging to your deployment branch.
* **Create branch**: Moves your pending changes to a new feature branch when you're on a protected deployment branch.
* **Create pull request**: Opens a pull request targeting your deployment branch.

If there are no pending changes, the editor disables the publish and save actions.

<Note>
  Your live site updates after Mintlify builds and deploys your changes. This typically takes 30 seconds to a few minutes. Check the deployment status on your [dashboard](https://app.mintlify.com).
</Note>

## When to use a branch

**Edit directly on your deployment branch** if you do not use a Git-based workflow.

**Create a branch** when you use a branch-based workflow where you make each change to your content on a separate branch.

## Create and switch branches

### Create a branch

1. Click the branch name in the editor toolbar.
2. Click **Create new branch**.
3. If you have pending changes, choose whether to bring them to the new branch or leave them on the current branch.
4. Enter a name and click **Create branch**.

<Tip>
  Use descriptive branch names so you can identify them and other people understand what each branch is for.
</Tip>

### Switch branches

1. Click the branch name in the toolbar.
2. Search for or scroll to the branch you want.
3. Click the branch to switch to it.

<Note>
  Switching branches while you have unpublished changes prompts you to bring those changes to the new branch or leave them behind. Changes left behind remain on your original branch.
</Note>

<Tip>
  To copy a branch name, hover over the branch in the dropdown and click the copy icon. This is useful when sharing the branch with teammates or referencing it in a pull request.
</Tip>

## Preview your changes

Every time you save changes to a feature branch, Mintlify builds a preview deployment, a temporary URL where your changes render exactly as they look when published.

### Access and share a preview

1. Click **Publish** in the editor toolbar.
2. In the publish menu, click the preview URL. The URL format is `organization-branch-name.mintlify.site`.

   <Frame>
     <img alt="Preview URL emphasized in the publish menu." />

     <img alt="Preview URL emphasized in the publish menu." />
   </Frame>

Copy the URL and send it to reviewers. The preview updates automatically each time you save to the branch.

### Restrict access to previews

Preview URLs are publicly accessible by default. To restrict access to members of your Mintlify organization, enable preview authentication in the [Add-ons](https://app.mintlify.com/products/addons) page of your dashboard.

### Share editor links

To invite a teammate to a specific page on a branch, copy the URL from your browser's address bar and share it. Anyone with access to your Mintlify organization can open the link directly in their editor session.

The URL format is:

```text theme={null}
https://app.mintlify.com/{org}/{project}/editor/{branch}/~/{filepath}
```

For example: `https://app.mintlify.com/acme/docs/editor/main/~/guides/quickstart.mdx`

## Review and merge pull requests

When a pull request is open for the current branch, the publish menu shows a review panel with:

* The pull request title, description, and whether it is a draft.
* The source and target branches.
* The number of changed files.
* The approval requirement on the deployment branch: **Approval required**, **Code owner required**, or no requirement.
* The current review status: **Approved**, **Changes requested**, or **Awaiting review**.

Click the pull request link to open it in GitHub, GitLab, or Bitbucket.

After a reviewer approves a pull request, click **Merge and publish** to merge and deploy directly from the editor. The editor switches to your deployment branch after merging.

### Approve pull requests from the editor

For GitHub repositories, reviewers can approve open pull requests in the editor. When a pull request is open, an **Approve pull request** button appears in the review panel if your account has permission to review it. Click **Approve pull request** when the changes are ready to merge. The review status updates to **Approved** and the **Merge and publish** action becomes available.

If you use GitLab or Bitbucket, open the pull request in your Git provider to approve it.

<Tip>
  Configure branch protection rules in your Git provider to require pull requests. See [About protected branches](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches) in the GitHub help or [Protected branches](https://docs.gitlab.com/user/project/repository/branches/protected/) in the GitLab help.
</Tip>

### Review changes before merging

Click any changed file in the publish menu to open it in diff view and compare your branch against the published version. In visual mode you see a visual diff. In source mode you see a text diff. Files that can't display a diff, such as images or deleted files, appear in the list but aren't clickable.

The file tree highlights changed pages so you can see at a glance which files an [automation](/docs/automations) or teammate touched. Unlisted pages that appear in the branch diff are also openable from the publish menu, even though they don't appear in your site navigation.

### Open an automation run in the editor

When an [automation](/docs/automations) opens a pull request, you can jump straight from the run review UI or its Slack notification into the editor on the automation's branch:

* From the **Automation Runs** page in your dashboard, click **Open in editor** on a completed run.
* From a Slack notification, click the **View changes** link.

Either entry point opens the editor on the automation's branch with the changed pages preselected in the publish menu. You can review the diff and merge or request changes without leaving the editor.

### Simultaneous publishing

Only one publish can happen at a time per branch. If another team member publishes to the same branch, wait for the current publish to complete before trying again.

### Pull request titles and descriptions

If your organization requires pull requests, you can enter a title and description when you publish. If you leave either blank, the editor uses a default message that lists the files you created, updated, moved, or deleted.

## Resolve conflicts

Conflicts occur when your branch and the deployment branch have incompatible changes to the same files. For example, when you and a teammate edited the same lines in a file or moved a file to different locations.

The editor displays a warning when conflicts block publishing. Follow the prompts to choose which version of each conflicting section to keep.

## Collaborate in real time

When multiple people open the same page on the same branch, they edit together in real time. Each person's cursor and edits are visible to everyone, with avatars shown in the toolbar.

* Changes from all collaborators merge automatically. Two people editing the same section won't create conflicts.
* Undo only affects your own edits.
* If you lose your connection, edits save locally and sync when you reconnect.

When the [Mintlify agent](/docs/agent) edits a page through the API or MCP, it appears in the editor like any other collaborator. You see the agent's avatar in the toolbar and a live cursor at its most recent edit location. The cursor clears automatically after the agent finishes.

## Git sync

When someone pushes changes to your repository from outside the editor, the editor incorporates those changes automatically.

Non-overlapping changes apply automatically. If a remote change and your local edit affect the same part of a page, the editor highlights the conflict so you can resolve it.

## Commit signing

Sign commits with your GitHub account by authorizing it in your [account settings](https://app.mintlify.com/settings/account). Without authorization, the Mintlify GitHub App signs commits made in the web editor.

For a reference of how editor actions map to Git operations, see [Git essentials](/docs/editor/git-essentials#how-the-editor-maps-to-git).


# Comment on pages in the editor
Source: https://www.mintlify.com/docs/editor/comments

Leave inline comments on pages in the editor to give feedback, ask questions, mention teammates, and resolve threads before you publish changes.

Comments let you and your team leave feedback on specific text in a page without editing the content. Use comments to ask questions, flag issues, or discuss changes before you publish them.

Comments live only inside the editor. They are never included in the published site or committed to your repository.

All [roles](/docs/dashboard/roles)—viewers, editors, and admins—can leave and reply to comments. Only editors and admins can resolve comment threads.

If your branch has an open pull request, Mintlify adds a summary of unresolved comment threads to the pull request description. The summary lists the files with open comments, the first comment in each thread, and a link to navigate to the comment in the editor.

The summary updates when you add, resolve, or delete a comment.

## Add a comment

1. Highlight the text you want to comment on.
2. Click the <Icon icon="message-square-text" /> **Comment** icon in the toolbar.
3. Type your comment and press <kbd>Enter</kbd> to submit.

<Frame>
  <img alt="The comment button in the floating toolbar above selected text in the web editor." />

  <img alt="The comment button in the floating toolbar above selected text in the web editor." />
</Frame>

## Reply to a comment

To open a comment thread, click the highlighted text or click the thread in the comment sidebar. Type your reply and press <kbd>Enter</kbd> to submit.

<Frame>
  <img alt="A comment thread opened in the web editor and two comment threads in the sidebar." />

  <img alt="A comment thread opened in the web editor and two comment threads in the sidebar." />
</Frame>

## Mention a teammate

Type `@` in a comment or reply to mention a teammate. People must be a member of your organization for you to mention them.

Mentioned teammates receive an email notification.

## Resolve a comment

Editors and admins can resolve threads when a discussion is complete.

Click the checkmark icon to resolve a thread. Resolving a thread removes it from the comment sidebar and clears the highlight from the page.

<Frame>
  <img alt="A comment thread opened in the web editor with the checkmark icon to resolve the thread highlighted." />

  <img alt="A comment thread opened in the web editor with the checkmark icon to resolve the thread highlighted." />
</Frame>

## Delete a comment

Click the trashcan icon beside a comment to delete it. Deleting the first comment in a thread deletes the entire thread.

You can delete your own comments. Admins can delete any comment.


# Configurations
Source: https://www.mintlify.com/docs/editor/configurations

Edit site branding, appearance, navigation, and feature settings from the Configurations panel in the Mintlify web editor, with real-time team sync.

Configure your site's branding, appearance, and features from the **Site configurations** panel in the web editor. Configuration changes sync in real time with other editors on the same branch, so your team always sees the latest settings.

To open the panel, click the <Icon icon="sliders-horizontal" /> configurations icon in the editor toolbar.

<Frame>
  <img alt="Configurations menu in the editor." />

  <img alt="Configurations menu in the editor." />
</Frame>

The panel groups settings into sections that map to the top-level properties in your [`docs.json`](/docs/organize/settings).

## General

Set your site's identity and how it appears to visitors.

* **Name**: The name of your project. Appears in browser tabs and search results.
* **Description**: Brief overview of your project. Used for SEO and answer engine optimization (AEO).

## Branding

Upload the marks that identify your site.

* **Logo**: Your brand logo. Upload PNG or JPG files. Set separate light and dark versions and an optional click-through URL. To use an SVG logo, add the file to your repository and reference its path in your [`docs.json`](/docs/organize/settings-appearance#logos).
* **Favicon**: Small icon that appears in browser tabs. Upload ICO, PNG, GIF, or JPG files. Set separate light and dark versions if needed.

## Styling

Control your site's visual identity and color scheme.

* **Theme**: Choose a [theme](/docs/customize/themes) for your site's overall appearance.
* **Primary color**: The main accent color used throughout your site for links, buttons, and highlights.
* **Light color**: Accent color used in dark mode. How themes apply this varies by theme.
* **Dark color**: Accent color used in light mode. How themes apply this varies by theme.
* **Background color**: Custom background colors for light and dark modes.
* **Icon library**: Icon library used for all icon properties. Defaults to `fontawesome`.
* **Strict appearance**: Lock the site to a single appearance mode and hide the theme toggle.
* **Default appearance**: Whether your site loads in `system`, `light`, or `dark` mode by default.
* **Background decoration**: Apply a visual style (`gradient`, `grid`, or `windows`) to your background.
* **Background image**: Optional background image. Set a single image or separate light and dark versions.

## Typography

Replace default fonts with your brand's typography.

* **Font family**: Any [Google Fonts](https://fonts.google.com/) family works out of the box. For a self-hosted font, provide a source URL and format (`woff` or `woff2`).
* **Weight**: Typically `400` for regular and `700` for bold. Variable fonts support precise weights like `550`.
* **Heading font**: Optional override applied to all headings (`h1` through `h6`).
* **Body font**: Optional override applied to body text and the remainder of the page.

## Navbar

Add navigation elements to the top of your site.

* **Primary button**: The main call-to-action in your header. Set the type, label, and destination URL.
* **Navbar links**: Additional navigation links in your header. Each link includes text and a URL.

## Footer

Add links and social media handles to your site footer.

* **Social links**: Profiles on platforms like GitHub, X, LinkedIn, Discord, YouTube, and Slack.
* **Footer columns**: Enable to organize footer links into up to four columns with custom headings.

## Banner

Display an announcement bar across the top of every page.

* **Content**: The banner text. Supports basic MDX formatting like links, bold, and italic. Custom components are not supported.
* **Dismissible**: Show a dismiss button on the right side of the banner.
* **Type**: Visual style. `info` uses the primary brand color, `warning` uses an amber background, and `critical` uses a red background. Defaults to `info`.
* **Color**: Override the banner background color with a custom hex color. Set separate light and dark values for theme-aware colors.

## Thumbnail

Customize page thumbnails and social previews.

* **Background**: Custom background image for thumbnails.
* **Appearance**: Render thumbnails in `light` or `dark` mode. When unset, thumbnails are auto-generated from your theme colors.
* **Font**: Custom font for text in thumbnails.

## Content

Customize how content appears on your site.

* **Page eyebrow**: Show small labels preceding page titles. Choose `section` or `breadcrumbs`.
* **Timestamps**: Show the date the content was last modified on all pages.
* **LaTeX**: Load LaTeX (KaTeX) stylesheets for mathematical notation rendering.

## Code blocks

Configure syntax highlighting and code block behavior.

* **Code block theme**: Match the site light/dark mode with `system`, always use a dark theme with `dark`, or pick a custom [Shiki](https://shiki.style/) theme.
* **Custom code languages**: Register additional syntax highlighting languages.

## Context menu

Configure the quick actions surfaced in the page context menu.

* **Options**: Multi-select dropdown of actions like `copy`, `view`, and opening the page in `chatgpt`, `claude`, `cursor`, and other AI assistants.
* **Display**: Where to display the options. `header` (default) shows them in the top-of-page context menu; `toc` shows them in the table of contents sidebar.

## Navigation

Tune navigation behavior across your site.

* **Drilldown**: Auto-navigate to the first page when a user clicks a navigation group.

## Search

Customize the search experience and feedback.

* **Search placeholder**: The text that appears in the search box before users type. Default is `Search or ask`.
* **Feedback**: Show thumbs-up and thumbs-down buttons or a "Suggest edits" link on every page.

## API reference

Document your API endpoints.

* **OpenAPI specs**: Add OpenAPI specification files to generate API reference pages.
* **AsyncAPI specs**: Add AsyncAPI specification files to generate API reference pages.
* **MDX server**: Custom MDX server endpoints for the API playground.
* **Playground display**: Show the interactive API playground, the simple API playground, or no API playground.
* **Proxy server**: Enable or disable the proxy server for API requests.
* **MDX schema**: Whether to render the schema section on API reference pages.

## Redirects

Use the **Redirects** section to add, edit, search, and remove redirects without manually editing your `docs.json` file. Redirects send users from old URLs to new ones, which is useful when you rename pages or restructure your site. For more information, see [Redirects](/docs/create/redirects).

Each redirect has the following fields:

* **Source**: The path to redirect from, like `/old-path`. Supports wildcards.
* **Destination**: The path to redirect to, like `/new-path`. Supports wildcards.
* **Status**: The HTTP status code for the redirect.
  * `308`: Permanent redirect. Use this for content that has moved permanently. This is the default status.
  * `307`: Temporary redirect. Use this when the move is temporary.

<Frame>
  <img alt="Redirects menu in the editor." />

  <img alt="Redirects menu in the editor." />
</Frame>

To add a redirect:

1. Click **Add redirect**.
2. Enter the source and destination.
3. Click **Save**.

To edit or remove an existing redirect, hover over the row and use the inline edit icon or the **X** to remove it.

## SEO

Configure metatags and indexing for search engines.

* **Metatags**: Custom `<meta>` tags applied across your site. Add key-value pairs for tags like `og:image` or `twitter:card`.
* **Indexing**: Choose whether to index hidden pages.

## Analytics

Connect analytics platforms to track visitor behavior. Supported providers include Amplitude, Mixpanel, Heap, Google Analytics, Google Tag Manager, PostHog, Plausible, Fathom, Segment, Hightouch, Hotjar, LogRocket, Microsoft Clarity, Intercom, Clearbit, and more.

Each entry renders as an inline row. Use the **X** icon to remove an integration.

## 404 page

Customize the experience when a user lands on a missing page.

* **Redirect to home**: When on, missing pages redirect to your home page. When off, the site shows a 404 page and you can customize the title and description below.
* **Title**: Heading shown on the 404 page.
* **Description**: Subheading shown on the 404 page.

## Variables

Define custom variables that can be re-used throughout your content. Each variable is a key-value pair. Use the **X** icon to remove a variable.


# Git essentials for the editor
Source: https://www.mintlify.com/docs/editor/git-essentials

Understand the Git version control concepts behind the Mintlify editor, including branches, commits, pull requests, and merge workflows.

Git lets you control and track changes to files. It's the version control system behind branch-based workflows, where you manage content the same way you would any other codebase.

The web editor handles Git operations for you. Understanding a few key concepts helps you get the most out of the editor and collaborate effectively with your team.

## What Git does for your content

Git tracks every change made to your content. It records what changed, who changed it, when they changed it, and why. This means you can:

* See the full history of any page.
* Undo changes by reverting to a previous version.
* Work on updates without affecting your live site.
* Review changes before they go live.

Your repository is the collection of files and their history that makes up your site. The editor connects to this repository to sync and publish your content.

## Key concepts

These are the Git concepts you'll encounter most often when using the web editor.

<AccordionGroup>
  <Accordion title="Commit">
    A saved snapshot of your changes at a specific point in time. Each commit includes a message describing what changed and creates a permanent record in your project history.

    When you publish changes, the web editor creates a commit in your Git repository.
  </Accordion>

  <Accordion title="Branch">
    A separate line of work in your repository. Sometimes called a **feature branch**.

    Your live site builds from a **deployment branch**, usually called `main`. Other branches let you work on changes independently without affecting your live site. Nothing on a branch goes live until you merge it into your deployment branch with a pull request.

    Switch between branches using the branch dropdown in the editor toolbar. If you have unpublished changes, the editor lets you bring them to the new branch or leave them on your current branch.
  </Accordion>

  <Accordion title="Deployment branch">
    The branch that builds your live site, typically called `main`. Changes merged into this branch automatically deploy to your site.
  </Accordion>

  <Accordion title="Pull request">
    A proposal to merge changes from one branch into another. Pull requests let your team review and discuss changes before they go live.

    When you publish changes on a feature branch (or when your repository requires pull requests), the web editor creates a pull request. Your team reviews and merges the pull request in your Git provider (GitHub, GitLab, or Bitbucket).
  </Accordion>

  <Accordion title="Merge">
    Combining changes from one branch into another. After your team reviews and approves a pull request, merging the branch incorporates your changes into the deployment branch and publishes them.
  </Accordion>

  <Accordion title="Conflict">
    Occurs when two branches have incompatible changes to the same files. The editor helps you resolve conflicts when they occur.
  </Accordion>

  <Accordion title="Diff">
    A comparison showing the differences between two versions of a file. The editor shows a visual diff of your pending changes before you publish so you can review exactly what gets committed.
  </Accordion>
</AccordionGroup>

## How the editor maps to Git

Every action in the web editor corresponds to a Git operation. Here is the full reference:

| Action in the editor              | Git operation                                                                |
| --------------------------------- | ---------------------------------------------------------------------------- |
| Edit a page                       | Changes auto-save to Mintlify servers. No Git commit yet.                    |
| Publish on your deployment branch | `git commit` and `git push`. Triggers a deployment.                          |
| Save in branch                    | `git commit` to the current feature branch.                                  |
| Create pull request               | `git push` and opens a pull request against your deployment branch.          |
| Merge and publish                 | Merges the pull request and triggers a deployment.                           |
| Create a branch                   | `git checkout -b <branch-name>`                                              |
| Switch branches                   | `git checkout <branch-name>`                                                 |
| External push or CLI update       | Incoming changes sync into the editor automatically using a three-way merge. |


# Editor overview
Source: https://www.mintlify.com/docs/editor/index

Create, edit, and publish content in your browser with real-time team collaboration, automatic saving, live previews, and continuous Git sync.

<Card title="New to the editor? Start with the tutorial." icon="graduation-cap" href="/editor/tutorial">
  A step-by-step walkthrough: create a branch, make a change, share a preview, and publish.
</Card>

## Open the editor

Open the editor from the [Editor](https://app.mintlify.com/editor) tab in your Mintlify dashboard. Any member of your organization can open the editor, but what you can do inside depends on your [role](/docs/dashboard/roles). Admins and editors can edit and publish, and viewers can browse content and leave [comments](/docs/editor/comments) or [suggestions](/docs/editor/suggestions).

## How the editor works

**Changes save automatically.** As you type, the editor saves your work. Your changes persist across tabs, devices, and network interruptions. Changes only go live when you publish them.

**Git stays in sync.** When someone else pushes changes to your repository from outside the editor, those changes appear in the editor automatically. You don't need to pull or refresh. The editor merges non-conflicting changes and highlights anything that needs your attention.

<Tip>
  If the editor ever appears out of sync with your repository, use [Reset editor](/docs/editor/settings#reset-editor) to force a resync from Git. For example, the file tree is empty or shows `Unable to find docs.json` even though the file is present on your deployment branch.
</Tip>

**Publishing writes to Git.** When you publish, the editor commits your changes to your repository. On a deployment branch, this updates your live site immediately. On a feature branch, it creates a pull request.

**Your team edits together.** Multiple people can edit the same page simultaneously. Live cursors show who is editing and where.

## The editor layout

<Frame>
  <img alt="Screenshot of the editor showing the branch selector, ask agent button, publish button, navigation sidebar, and top bar." />

  <img alt="Screenshot of the editor showing the branch selector, ask agent button, publish button, navigation sidebar, and top bar." />
</Frame>

* **Top bar**: Use the top bar to control what branch you work on, access the agent, preview, and publish changes.
* **Navigation sidebar**: Select a page to edit, create new pages, and manage the site structure.

## Explore the editor

<Card title="Branching and publishing" icon="git-branch" href="/editor/branching-and-publishing">
  How branches and protection rules determine what happens when you publish, and how to manage the pull request review process.
</Card>

<Card title="Comments" icon="message-square" href="/editor/comments">
  Leave feedback, ask questions, and discuss changes with your team.
</Card>

<Card title="Suggestions" icon="pen-line" href="/editor/suggestions">
  Propose changes that teammates can review, accept, or reject.
</Card>

<Card title="Ask agent" icon="sparkles" href="/editor/agent">
  Edit pages, search your content, modify settings, and configure your site from a chat interface.
</Card>

<Card title="Create and edit pages" icon="notebook-pen" href="/editor/pages">
  Add new and update existing pages.
</Card>

<Card title="Organize navigation" icon="list-tree" href="/editor/navigation">
  Reorder pages and manage site structure.
</Card>

<Card title="Live preview" icon="play" href="/editor/live-preview">
  Preview your site in real time as you edit without waiting for a build.
</Card>

<Card title="Configurations" icon="sliders-horizontal" href="/editor/configurations">
  Configure your site's branding, colors, and features.
</Card>

<Card title="Settings" icon="settings" href="/editor/settings">
  Configure AI instructions and publishing defaults for your deployment.
</Card>

<Card title="Git essentials" icon="git-merge" href="/editor/git-essentials">
  Understand the Git concepts behind the editor: branches, commits, pull requests, and merges.
</Card>

<Card title="Keyboard shortcuts" icon="keyboard" href="/editor/keyboard-shortcuts">
  Save time with keyboard shortcuts.
</Card>


# Keyboard shortcuts
Source: https://www.mintlify.com/docs/editor/keyboard-shortcuts

View the complete list of keyboard shortcuts for the Mintlify web editor, including text formatting, navigation, and editing commands.

Use keyboard shortcuts to navigate and edit faster in the web editor. The editor supports common shortcuts like copy, paste, undo, and select all, along with the shortcuts listed below.

## Editor-wide

These shortcuts work regardless of which mode you're in.

| Command                                         | macOS                                            | Windows                                           |
| :---------------------------------------------- | :----------------------------------------------- | :------------------------------------------------ |
| **Search files and content**                    | <kbd>Cmd</kbd> + <kbd>K</kbd>                    | <kbd>Ctrl</kbd> + <kbd>K</kbd>                    |
| **Toggle AI assistant** (when not editing text) | <kbd>Cmd</kbd> + <kbd>I</kbd>                    | <kbd>Ctrl</kbd> + <kbd>I</kbd>                    |
| **Switch between visual and source mode**       | <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd> |
| **Toggle diff view**                            | <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>D</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>D</kbd> |
| **Switch between Navigation and Files tree**    | <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>F</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>F</kbd> |
| **Hide/show sidebar**                           | <kbd>Cmd</kbd> + <kbd>\\</kbd>                   | <kbd>Ctrl</kbd> + <kbd>\\</kbd>                   |

## Visual mode

Use these shortcuts when editing in visual mode.

### Text formatting

| Command           | macOS                                            | Windows                                           |
| :---------------- | :----------------------------------------------- | :------------------------------------------------ |
| **Bold**          | <kbd>Cmd</kbd> + <kbd>B</kbd>                    | <kbd>Ctrl</kbd> + <kbd>B</kbd>                    |
| **Italic**        | <kbd>Cmd</kbd> + <kbd>I</kbd>                    | <kbd>Ctrl</kbd> + <kbd>I</kbd>                    |
| **Underline**     | <kbd>Cmd</kbd> + <kbd>U</kbd>                    | <kbd>Ctrl</kbd> + <kbd>U</kbd>                    |
| **Strikethrough** | <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>X</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>X</kbd> |
| **Code**          | <kbd>Cmd</kbd> + <kbd>E</kbd>                    | <kbd>Ctrl</kbd> + <kbd>E</kbd>                    |
| **Subscript**     | <kbd>Cmd</kbd> + <kbd>,</kbd>                    | <kbd>Ctrl</kbd> + <kbd>,</kbd>                    |
| **Superscript**   | <kbd>Cmd</kbd> + <kbd>.</kbd>                    | <kbd>Ctrl</kbd> + <kbd>.</kbd>                    |

### Headings

| Command       | macOS                                             | Windows                                         |
| :------------ | :------------------------------------------------ | :---------------------------------------------- |
| **Text**      | <kbd>Cmd</kbd> + <kbd>Option</kbd> + <kbd>0</kbd> | <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>0</kbd> |
| **Heading 1** | <kbd>Cmd</kbd> + <kbd>Option</kbd> + <kbd>1</kbd> | <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>1</kbd> |
| **Heading 2** | <kbd>Cmd</kbd> + <kbd>Option</kbd> + <kbd>2</kbd> | <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>2</kbd> |
| **Heading 3** | <kbd>Cmd</kbd> + <kbd>Option</kbd> + <kbd>3</kbd> | <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>3</kbd> |
| **Heading 4** | <kbd>Cmd</kbd> + <kbd>Option</kbd> + <kbd>4</kbd> | <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>4</kbd> |

### Lists and blocks

| Command            | macOS                                            | Windows                                           |
| :----------------- | :----------------------------------------------- | :------------------------------------------------ |
| **Unordered list** | <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>8</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>8</kbd> |
| **Blockquote**     | <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>B</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>B</kbd> |

### Content actions

| Command                         | macOS                                            | Windows                                           |
| :------------------------------ | :----------------------------------------------- | :------------------------------------------------ |
| **Add link** to selected text   | <kbd>Cmd</kbd> + <kbd>K</kbd>                    | <kbd>Ctrl</kbd> + <kbd>K</kbd>                    |
| **Add line break**              | <kbd>Cmd</kbd> + <kbd>Enter</kbd>                | <kbd>Ctrl</kbd> + <kbd>Enter</kbd>                |
| **Comment on highlighted text** | <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>M</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>M</kbd> |
| **Toggle suggesting mode**      | <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd> | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd> |
| **Component menu**              | <kbd>/</kbd>                                     | <kbd>/</kbd>                                      |
| **Emoji picker**                | <kbd>:</kbd> + keyword                           | <kbd>:</kbd> + keyword                            |

### Smart substitutions

The editor automatically converts certain character sequences into typographic symbols as you type. The editor skips substitutions inside code blocks and inline code.

| Type | Result |
| :--- | :----- |
| `->` | →      |
| `<-` | ←      |
| `=>` | ⇒      |
| `<=` | ≤      |
| `>=` | ≥      |
| `!=` | ≠      |

## Source mode

Source mode uses the Monaco editor, which supports standard VS Code keyboard shortcuts.

### Search and navigation

| Command          | macOS                         | Windows                        |
| :--------------- | :---------------------------- | :----------------------------- |
| **Search files** | <kbd>Cmd</kbd> + <kbd>K</kbd> | <kbd>Ctrl</kbd> + <kbd>K</kbd> |
| **Find**         | <kbd>Cmd</kbd> + <kbd>F</kbd> | <kbd>Ctrl</kbd> + <kbd>F</kbd> |

### Editing

| Command            | macOS                                               | Windows                                          |
| :----------------- | :-------------------------------------------------- | :----------------------------------------------- |
| **Toggle comment** | <kbd>Cmd</kbd> + <kbd>/</kbd>                       | <kbd>Ctrl</kbd> + <kbd>/</kbd>                   |
| **Indent line**    | <kbd>Tab</kbd>                                      | <kbd>Tab</kbd>                                   |
| **Outdent line**   | <kbd>Shift</kbd> + <kbd>Tab</kbd>                   | <kbd>Shift</kbd> + <kbd>Tab</kbd>                |
| **Move line up**   | <kbd>Option</kbd> + <kbd>↑</kbd>                    | <kbd>Alt</kbd> + <kbd>↑</kbd>                    |
| **Move line down** | <kbd>Option</kbd> + <kbd>↓</kbd>                    | <kbd>Alt</kbd> + <kbd>↓</kbd>                    |
| **Duplicate line** | <kbd>Shift</kbd> + <kbd>Option</kbd> + <kbd>↓</kbd> | <kbd>Shift</kbd> + <kbd>Alt</kbd> + <kbd>↓</kbd> |

### Multiple cursors

| Command              | macOS                                             | Windows                                         |
| :------------------- | :------------------------------------------------ | :---------------------------------------------- |
| **Add cursor**       | <kbd>Option</kbd> + Click                         | <kbd>Alt</kbd> + Click                          |
| **Add cursor above** | <kbd>Cmd</kbd> + <kbd>Option</kbd> + <kbd>↑</kbd> | <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>↑</kbd> |
| **Add cursor below** | <kbd>Cmd</kbd> + <kbd>Option</kbd> + <kbd>↓</kbd> | <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>↓</kbd> |


# Live preview
Source: https://www.mintlify.com/docs/editor/live-preview

Preview your site in real time as you edit, with continuous updates that render content, navigation, and configuration changes instantly.

Preview your site while you edit. Live previews render pages exactly as they look when published, and update as you make changes to content, navigation, and configuration.

## Open live preview

Click the <Icon icon="play" /> live preview button in the top bar.

<Frame>
  <img alt="The live preview button in the toolbar." />

  <img alt="The live preview button in the toolbar." />
</Frame>

## Edit site settings in live preview

Edit your site settings in the live preview to see how they affect the rendered content.

1. Open the live preview in the editor.
2. Click **Site settings** in the preview toolbar.
3. Select a configuration section and edit the settings.

If you set the live preview to open in a new tab, the preview site settings menu is unavailable. Disable **Open live preview in new tab** in [editor settings](/docs/editor/settings) to use the site settings menu.

## Ask the agent in live preview

Click **Ask agent** in the preview toolbar to open the [editor agent](/docs/editor/agent) beside the live preview. Only editors and admins can use the agent in live previews.

<Note>
  Live preview works for public sites and sites protected by Mintlify authentication.
</Note>

## Live preview versus preview deployments

|                  | Live preview                    | Preview deployment                |
| ---------------- | ------------------------------- | --------------------------------- |
| **Speed**        | Instant                         | Requires a build                  |
| **Access**       | Local URL                       | Shareable URL                     |
| **Use when**     | Reviewing changes while editing | Sharing with your team for review |
| **Availability** | While the editor is open        | As long as the branch exists      |

Use live preview for immediate feedback while editing. When you need to share changes with your team or test on a different device, use a [preview deployment](/docs/editor/branching-and-publishing#preview-your-changes).


# Organize navigation
Source: https://www.mintlify.com/docs/editor/navigation

Reorder pages, add groups, and manage your documentation sidebar structure using drag-and-drop in the Mintlify web editor—no docs.json edits needed.

Use the navigation sidebar to organize your documentation. The editor syncs your changes to your repository when you publish. You don't need to edit `docs.json` manually.

## Add navigation elements

Click **Add new** at the bottom of the navigation tree to add a new element at the root level. To nest an element inside another, click the <Icon icon="plus" /> plus button next to that element.

Drag and drop elements to reorder or nest them. Hover over an element and click the gear icon to configure its properties.

Right-click a **page** to open its settings or delete it.

Right-click a **navigation element** to open its settings or convert it to a different element type. You can also duplicate it, add a page or group inside it, ungroup it, or delete it.

<Note>
  Some elements cannot nest inside other elements. For example, tabs cannot nest inside groups. The editor prevents you from creating invalid combinations.
</Note>

## Navigation elements

Choose the right structure for your content:

* **Pages**—Individual documentation files. The core building block of navigation.
* **Groups**—Collapsible sections that cluster related pages together. Can nest within other groups.
* **Tabs**—Top-level sections with horizontal navigation at the top of your site. Use tabs when you have distinct areas like API Reference and Guides.
* **Anchors**—Persistent items at the top of your sidebar. Useful for quick access to external resources or top-level sections. Can be global to appear on every page.
* **Dropdowns**—Expandable menus at the top of your sidebar. A lighter alternative to tabs for multiple related sections.
* **Menus**—Dropdown navigation items within a tab for direct links to specific pages.
* **Products**—A switcher for multiple distinct product documentation sets, each with its own navigation structure.
* **Versions**—A switcher for multiple simultaneous documentation versions.
* **Languages**—A switcher for documentation in multiple languages.

## Configure elements

Hover over any navigation element and click the gear icon to set:

* **Title**: The label shown in the sidebar.
* **Icon**: A visual marker next to the label.
* **Tag**: A badge like "NEW" or "BETA" to highlight the item.


# Create and edit pages
Source: https://www.mintlify.com/docs/editor/pages

Create pages, edit content, upload images and video, and manage files in the Mintlify web editor with rich-text editing and search across your content.

## Navigate files

The left panel has two views: **Navigation** and **Files**.

**Navigation** shows your sidebar structure as visitors see it. Click a page to open it.

**Files** shows the full file tree of your repository, including files that aren't in your navigation. Click any file to open it.

To switch between views, click the <Icon icon="folder-open" /> file icon or press <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>F</kbd> (macOS) or <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>F</kbd> (Windows). To search by filename or page content, click the search icon or press <kbd>Cmd</kbd> + <kbd>K</kbd> (macOS) or <kbd>Ctrl</kbd> + <kbd>K</kbd> (Windows).

## Manage files and folders

Use the Files view to organize your content:

* **Create a folder**: Click the <Icon icon="folder-plus" /> new folder button at the top of the file tree, or right-click an existing folder and select **New folder**.
* **Rename a file or folder**: Right-click the item and select **Rename**.
* **Open unlisted files**: Click any file in the tree to open it, even if it isn't included in your navigation.

Files that aren't in your navigation remain unlisted. They exist in your repository but won't appear in the published sidebar.

## Create new pages

### Add a page to navigation

1. Click the <Icon icon="plus" /> plus button in the navigation element where you want to add a page.
2. Click **Add a page**.
3. Enter a filename. The editor adds the `.mdx` extension automatically.

### Create an unlisted page

Unlisted pages exist in your repository but don't appear in navigation. They're useful for draft content, reusable snippets, or pages you plan to add to navigation later.

Right-click any folder in the Files view and select **New file**. Enter a filename and the editor creates the page without adding it to navigation. You can add it to navigation later from the **Navigation** tab.

## Edit content

Switch between visual and source mode using the mode toggle in the toolbar below the top bar. To switch to visual mode, click the <Icon icon="eye" /> eye icon or press <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd> (macOS) or <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd> (Windows). To switch to source mode, click the <Icon icon="code" /> code icon or press the same shortcut.

**Visual mode** shows a real-time preview as you type. Press <kbd>/</kbd> to open the component menu and insert components, images, videos, and other content. You can also drag and drop media files directly onto the page from your computer or from the navigation tree. Other shortcuts:

* **Insert a link**: Select text and press <kbd>Cmd</kbd> + <kbd>K</kbd> (macOS) or <kbd>Ctrl</kbd> + <kbd>K</kbd> (Windows). You can also drag a page from the navigation tree into the editor to create a link with the page title.
* **Link to another page**: Right-click a page in the navigation tree, click **Copy link**, then paste the link into your content. The editor recognizes internal links to other pages and converts them.
* **Insert media from your project**: Drag an image or video from the navigation tree into the page to embed it inline. Supported formats include PNG, JPG, JPEG, GIF, WebP, SVG, MP4, and WebM.
* **Insert an emoji**: Type <kbd>:</kbd> followed by a keyword to open the emoji picker.
* **Edit a table**: When your cursor is inside a table, use the floating toolbar to add or remove rows and columns, or merge cells.

**Source mode** gives you direct access to the MDX source. Use it for precise control over component properties and frontmatter.

For a full list of components, see [Components](/docs/components). For MDX syntax, see [Format text](/docs/create/text) and [Format code](/docs/create/code).

### Task lists

In visual mode, type `/task` and select **Task List** to add an interactive checklist. You can also type `- [ ]` followed by a space to turn a list item into a task. Click the checkbox beside a task to mark it complete.

Press <kbd>Enter</kbd> at the end of a task to add another unchecked task. Press <kbd>Enter</kbd> again on an empty task to exit the list.

In source mode, use `- [ ]` for an incomplete task or `- [x]` for a completed task.

### Diff view

To compare your current page against the last published version, click the <Icon icon="file-diff" /> **View diff** button in the toolbar, or press <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>D</kbd> (macOS) or <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>D</kbd> (Windows). In visual mode, this shows a visual diff. In source mode, it shows a text diff. Click **Exit diff** or press the shortcut again to return to editing.

You can also open a diff from the publish menu. Click **Publish** then click any changed file in the list.

### Version history

Use version history to review saved versions of the page you edit. Version history isn't available for `docs.json` files.

The version history groups entries by date. Each entry shows the author and save time. The editor marks the most recent entry as **Current**.

The editor records a new entry when content differs from the latest recorded version. If you save unchanged content, the editor doesn't create a duplicate entry.

To open version history:

1. Open a page in the editor.
2. Click <Icon icon="ellipsis" /> **More options** in the top-right corner of the page.
3. Click **Version history**.

If you enable version history for pages, you can click the **Edited** timestamp on the page to open version history.

Public page history only includes the current branch. Private page history includes entries across branches. Click **Show more versions** to load older entries.

Older versions include a **Restore** action when you have permission to edit the page. If you restore an older version, you overwrite any unsaved changes. Viewers can review and compare saved versions of private pages. Editors and managers can restore them.

For public pages, the editor restores the page on your current branch. For private pages, it updates the shared private content.

To compare an older saved version with the current page, click its row. The editor opens diff view with the older version as the baseline and the current page content as the comparison. To exit comparison and return to editing, click the active row again.

### Block actions

In visual mode, hover over any block to reveal a drag handle on the left. Click the handle to open a context menu with actions for that block:

* **Turn into**: Convert the block to a different type: text, headings, blockquote, or list.
* **Duplicate**: Insert a copy of the block immediately after it.
* **Delete**: Remove the block.

<Frame>
  <img alt="The block actions menu in visual mode." />

  <img alt="The block actions menu in visual mode." />
</Frame>

### Table of contents

In visual mode, the editor shows a minimap on the right side of the page that reflects the heading structure of your document. Hover over the minimap to expand it into a full table of contents. Click any heading to scroll to that section.

### Code block options

When editing a code block in visual mode, you can:

* **Highlight or focus lines**: Select text within the code block, then use the toolbar that appears to mark lines as highlighted or focused. Highlighting visually emphasizes lines. Focusing lines dims everything else.
* **Mark diff lines**: Select lines and use the toolbar to mark them as additions (`+`) or removals (`-`).
* **Wrap**: Toggle line wrapping in the code block settings.
* **Expandable**: Make the code block collapsible so readers can expand it on demand.

## Manage pages

* **Move**: Drag and drop pages to reorder them in navigation.
* **Rename**: Right-click a page and select **Rename**.
* **Duplicate**: Right-click a page and select **Duplicate**.
* **Delete**: Right-click a page and select **Delete**. The editor removes the page from navigation automatically.

### Move private pages to the workspace

To turn a private page or folder into workspace content, drag the private content from the **Private** section to a folder in your workspace. You can also right-click the private content and select **Move to workspace**.

When you move a private folder, all pages in the folder move to your workspace. Any content you move to your workspace immediately becomes available to your workspace collaborators, but it is not added to your site navigation.

<Warning>
  You can't move workspace content back to the **Private** section.
</Warning>

### Pages deleted via Git

If a teammate deletes a page through Git while you have it open, the editor enters read-only mode and shows a banner. The editor preserves your content so you can copy it before navigating away.

## Configure pages

Hover over a page and click the gear icon, or right-click and select **Settings**, to configure:

* **Title**, **Slug**, and **Sidebar title**: Control how the page appears in navigation and its URL.
* **Description** and **Keywords**: Improve search and SEO.
* **Layout**: Choose from standard, wide, centered, or custom.

For details on each setting, see [Pages](/docs/organize/pages).

## Add media

### Images and videos

Type <kbd>/image</kbd> to upload a new image or select an existing one from your repository. Type <kbd>/video</kbd> to upload or select a video.

You can also drag and drop files from your computer directly onto a page. In visual mode, the file inserts inline. In source mode, the editor inserts the file path at your cursor position. Images save to your `images/` folder and videos to `videos/`.

To reuse media that already lives in your project, drag an image or video file from the navigation tree onto the page. The editor embeds the asset inline.

### Light and dark image variants

After inserting an image in visual mode, hover over it to reveal the image toolbar. Use **Light/dark variants** to upload separate images for light and dark mode.

### Embed external media

Type <kbd>/embed</kbd> and paste a YouTube, Loom, or Vimeo URL. The editor detects the provider and generates the iframe. Searching the slash menu for `youtube`, `yt`, `loom`, or `vimeo` also surfaces the **Embed** command.

For other embeds, type <kbd>/embed</kbd> and toggle **Manual embed** to write custom HTML.

For more on formatting images and using the Frame component, see [Images and embeds](/docs/create/image-embeds).


# Editor settings for AI and publishing
Source: https://www.mintlify.com/docs/editor/settings

Configure AI instructions, pull request defaults, and the default merge method to control how the Mintlify web editor publishes changes.

The web editor has two layers of settings:

* **Your settings** apply only to you and control how the editor's AI assists with your edits.
* **Publishing settings** apply to everyone on a deployment and shape what happens when you commit changes and turn them into pull requests.

You can configure both from the settings panel. To open it, click the <Icon icon="settings" /> settings icon in the editor toolbar.

## AI instructions

AI instructions are persistent guidance that the editor sends to the AI alongside your request. Use them to capture style and tone rules you don't want to repeat every time, like voice, terminology, or formatting conventions.

Your instructions apply to:

* **Edit with AI** actions on a selection, such as rewrite, expand, or fix.
* **Agent sessions** started from the editor.

Each teammate maintains their own instructions, scoped to their user account.

### When to use AI instructions

Add AI instructions when you find yourself repeating the same guidance in prompts, for example:

* Enforcing second-person voice or sentence case headings.
* Preferring specific product names or terminology.
* Banning marketing language or filler phrases.
* Requiring certain components, like always using `<Note>` for callouts.

Keep instructions short and specific. The AI follows them on every request, so vague or contradictory rules degrade results.

### Configure AI instructions

1. Click the <Icon icon="settings" /> settings icon in the editor toolbar.
2. In the **AI instructions** field, enter the guidance you want the AI to follow.
3. Save your changes.

Example:

```text theme={null}
- Use second person ("you") and active voice.
- Use sentence case for all headings.
- Refer to the product as "Acme" — never "Acme Inc." or "the platform".
- Wrap notes and warnings in <Note> or <Warning> components.
- Do not add introductory filler like "In this guide" or "Let's explore".
```

Leave the field empty to remove your instructions.

## Publishing settings

You configure publishing settings per deployment, and they apply to everyone who publishes from the editor. They control how the editor generates, opens, and merges pull requests and commits.

You need admin access to your Mintlify deployment to change publishing settings.

### Lock the deployment branch

To make your deployment branch (usually `main`) read-only in the editor, lock the deployment branch.

Use this setting when your team wants all editor changes to create pull requests from feature branches.

### Pull request instructions

Pull request instructions guide the AI when it generates a pull request title and description. They apply whenever the editor opens a pull request on your behalf, including from **Create pull request** and **Merge and publish** flows.

Use pull request instructions to standardize what reviewers see, for example:

* Required sections like **Summary** and **Changes**.
* A description template that links to a tracking system.
* Tone or length requirements for titles.

Example:

```text theme={null}
Title: imperative mood, under 70 characters, no trailing period.
Description: include a "## Summary" section (one sentence) and a
"## Changes" section as a bulleted list. Link any referenced page
using its relative path.
```

### Main branch autocommits

When you enable main branch autocommits, the editor commits changes shortly after you stop typing.

Use this setting when your team edits the deployment branch directly and wants updates to reach Git without a manual publish step. If you want to review changes before they publish to your sire, do not use autocommits.

Edits on feature branches created from the editor autocommit regardless of this setting. Changes on a feature branch never publish unless you merge them into your deployment branch.

### Create pull requests as drafts by default

Turn this on to have the editor open every new pull request in draft state. You can't merge a draft pull request until you mark it ready for review. This is useful when:

* Your team requires a manual review pass before a pull request is open for approval.
* You want to share preview URLs without signaling that the change is ready to merge.

You can still mark a pull request as ready for review from your Git provider.

### Default merge method

Choose how the editor merges pull requests when you click **Merge and publish**:

* **Merge**: Creates a merge commit that preserves the full branch history.
* **Squash**: Combines all commits in the branch into a single commit on your deployment branch.
* **Rebase**: Replays each commit from the branch onto your deployment branch without a merge commit.

The editor uses the selected method by default. If you pass an explicit merge method through the API or your Git provider's UI, that choice takes precedence.

<Tip>
  Match your default merge method to your Git provider's branch protection settings. If your deployment branch only allows squash merges, set the default to **Squash** to avoid failed merges from the editor.
</Tip>

## Danger zone

The **Danger zone** section of the editor settings panel contains actions that can't be undone. Click the <Icon icon="settings" /> settings icon in the editor toolbar then scroll to **Danger zone**.

### Reset editor

**Reset editor** forces the editor to discard its local state and sync with your Git repository. If the editor gets stuck out of sync with your repo, reset the editor. Reset the editor if the file tree is empty or shows errors like `Unable to find docs.json`. This can happen even though the file exists on your deployment branch and your live site builds normally.

<Warning>
  If you reset the editor, you discard any unpublished changes that you haven't committed to Git. If you have pending edits you want to keep, publish them first.
</Warning>

To reset the editor:

1. Click the <Icon icon="settings" /> settings icon in the editor toolbar.
2. Scroll to **Danger zone**.
3. Click **Reset editor** and confirm.

The editor reloads and pulls the latest state from your repository.

## Related

* [Branching and publishing](/docs/editor/branching-and-publishing)
* [Configurations](/docs/editor/configurations)


# Suggest changes in the editor
Source: https://www.mintlify.com/docs/editor/suggestions

Propose text changes as suggestions that teammates can review, accept, or reject in the editor without modifying the current page content.

Suggestions let you propose changes to text while preserving the current content. Teammates can review, accept, or reject your suggestions.

Suggesting mode applies to page text. Editors and admins can accept or reject any suggestion, but viewers cannot. See [roles](/docs/dashboard/roles) for details.

Pending suggestions appear as highlighted text in the editor. The sidebar lists them alongside comments so reviewers can find them.

## Make suggestions

1. Highlight any text on the page.
2. Click the <Icon icon="pen" /> **Switch to Suggesting** button in the toolbar.
3. In suggesting mode, edit any text. Deletions and insertions appear with highlighting so that reviewers can identify the changes you propose.
4. To exit suggesting mode, click the <Icon icon="pen" /> **Switch to Editing** button in the floating toolbar or the **X** on the **Suggesting** pill in the top bar.

<Note>
  [Viewers](/docs/dashboard/roles) are always in suggesting mode. Suggesting mode activates automatically when a viewer opens the editor. The **Suggesting** pill is visible but not interactive for viewers, so they remain in suggesting mode. This lets viewers propose changes without directly editing content.
</Note>

<Frame>
  <img alt="The switch to suggesting button in the floating toolbar above selected text in the editor." />

  <img alt="The switch to suggesting button in the floating toolbar above selected text in the editor." />
</Frame>

## Accept a suggestion

1. Click the highlighted suggestion text.
2. Click the <Icon icon="check" /> **Accept** button to apply the suggested change.

Accepting a suggestion resolves and deletes the suggestion thread. The accepted change becomes part of your current branch and goes live the next time you [publish](/docs/editor/branching-and-publishing).

## Reject a suggestion

1. Click the highlighted suggestion text.
2. Click the <Icon icon="trash-2" /> **Reject** button to discard the proposed change.

Rejecting a suggestion resolves and deletes the suggestion thread.


# How to use the editor
Source: https://www.mintlify.com/docs/editor/tutorial

Step-by-step walkthrough of the Mintlify editor: create a branch, edit pages, share a preview deployment for review, and publish your changes.

This tutorial walks you through a complete content update using the editor. You'll create a branch, make a change, share a preview for review, and publish your changes.

<Steps>
  <Step title="Create a branch">
    A branch is a temporary copy of your content. It's where you make your changes without affecting your live site. You can merge a branch into your live site or safely discard it if you choose not to make the changes.

    Working on a branch keeps your edits separate from your live site until you're ready to share the content with your users.

    1. In the editor toolbar, click the branch name (usually `main`).

       <Frame>
         <img alt="Branch name emphasized in the editor toolbar." />

         <img alt="Branch name emphasized in the editor toolbar." />
       </Frame>
    2. Click **Create new branch**.
    3. Enter a name that describes your change, like `update-quickstart`.
    4. Click **Create branch**.

    The editor switches to your new branch. Any changes you make are only on the branch. They only appear on your live site if you complete the publishing process.
  </Step>

  <Step title="Make your changes">
    Edit an existing page or create a new one.

    **To edit a page**: Click the page name in the navigation sidebar to open it. Type directly in the editor to add content. Press <kbd>/</kbd> to insert components, images, or other content.

    **To create a page**: Click the <Icon icon="plus" /> plus button next to the navigation group where you want to add the page, then click **Add a page** and enter a filename.

    <Frame>
      <img alt="The add page menu opened beside a group in the editor." />

      <img alt="The add page menu opened beside a group in the editor." />
    </Frame>
  </Step>

  <Step title="Publish your branch">
    When you're ready for review, create a pull request from your branch. A pull request is a proposal to merge your changes into the branch that builds your live site. Your changes only go live after someone approves and merges the pull request.

    1. Click **Publish** in the toolbar to open the publish menu.

       <Frame>
         <img alt="The publish menu opened in the editor toolbar." />

         <img alt="The publish menu opened in the editor toolbar." />
       </Frame>
    2. Optionally, click any changed file in the list to view and compare your edits against the published version.
    3. Click **Create pull request**. Add a title and description, then click **Publish pull request**.

    <Note>
      You can also click **Save in branch** to commit your changes without opening a pull request yet. This is useful if you want to keep editing before requesting review.
    </Note>

    After you create the pull request, a preview deployment builds automatically. The publish menu shows the preview URL, a temporary link where your changes render exactly as they would on your live site. Share this URL with your reviewers.
  </Step>

  <Step title="Get your pull request approved">
    Share the pull request with your team. Reviewers can open the pull request in GitHub, GitLab, or Bitbucket to leave comments, request changes, or approve it.

    If a reviewer requests changes, make the edits in the editor on the same branch. Your updates push to the existing pull request automatically. You don't need to create a new one.

    When all required reviewers have approved, the pull request is ready to merge.
  </Step>

  <Step title="Merge and publish">
    With the pull request approved, click **Publish** in the toolbar to reopen the publish menu. The menu now shows the pull request status and an option to merge.

    Click **Merge and publish**. The editor merges the pull request and switches you back to your deployment branch. Mintlify builds and deploys your changes. Your live site updates in about 30 seconds to a few minutes.
  </Step>
</Steps>


# Introduction
Source: https://www.mintlify.com/docs/index

Mintlify is an AI-native documentation platform built for developers, with beautiful defaults, interactive API playgrounds, and smart search.

<div>
  <div>
    <img alt="Decorative background image." />

    <img alt="Decorative background image." />
  </div>

  <div>
    <h1>
      Documentation
    </h1>

    <div>
      Meet the next generation of documentation. AI-native, beautiful out-of-the-box, and built for developers and teams.
    </div>

    <div>
      <HeroCard title="Quickstart" description="Deploy your first docs site in minutes with our step-by-step guide" href="/quickstart" />

      <HeroCard title="CLI installation" description="Install the CLI to preview and develop your docs locally" href="/installation" />

      <HeroCard title="Web editor" description="Make quick updates and manage content with our browser-based editor" href="/editor/index" />

      <HeroCard title="Components" description="Build rich, interactive documentation with our ready-to-use components" href="/components/accordions" />
    </div>
  </div>
</div>


# Migrate to Mintlify
Source: https://www.mintlify.com/docs/migration

Migrate your documentation to Mintlify from Docusaurus, ReadMe, GitBook, or another platform with step-by-step instructions and CLI tooling.

This guide helps you move your existing documentation to Mintlify. Choose automated migration for supported platforms or manual migration for complete control over the process.

## Choose your migration path

* If you currently use Docusaurus or ReadMe -> **Automated migration**
* If you have a public GitHub repository -> **Auto-generated migration**
* If you are migrating from any other platform -> **Manual migration**

<Tabs>
  <Tab title="Automated migration">
    Migrate your documentation using the [@mintlify/scraping package](https://www.npmjs.com/package/@mintlify/scraping). The package scrapes your content and converts it to use Mintlify components.

    ### Supported platforms

    <Columns>
      <Card
        title="Docusaurus"
        icon={<svg className="h-6 w-6" width="36" height="36" viewBox="0 -19 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
<g>
		<rect fill="#FFFFFF" x="126.030769" y="45.9487179" width="110.276923" height="44.6358974">

</rect>
		<path d="M26.2564103,191.671795 C16.5441641,191.671795 8.0830359,186.385067 3.54067692,178.54359 C1.30231795,182.408533 0,186.883938 0,191.671795 C0,206.17321 11.7549949,217.928205 26.2564103,217.928205 L52.5128205,217.928205 L52.5128205,191.671795 L26.2564103,191.671795 Z" fill="#3ECC5F">

</path>
		<path d="M144.384656,53.006441 L236.308349,47.2615385 L236.308349,34.1333333 C236.308349,19.6319179 224.552041,7.87692308 210.051938,7.87692308 L91.8980923,7.87692308 L88.616041,2.19241026 C87.1561846,-0.334769231 83.5104821,-0.334769231 82.0519385,2.19241026 L78.7698872,7.87692308 L75.4878359,2.19241026 C74.0279795,-0.334769231 70.3822769,-0.334769231 68.9237333,2.19241026 L65.6416821,7.87692308 L62.3596308,2.19241026 C60.8997744,-0.334769231 57.2540718,-0.334769231 55.7955282,2.19241026 L52.5134769,7.87692308 C52.4845949,7.87692308 52.4570256,7.88086154 52.4281436,7.88086154 L46.990441,2.44447179 C44.928,0.382030769 41.4070154,1.3246359 40.6508308,4.14326154 L38.8548923,10.8438974 L32.0374154,9.01645128 C29.2187897,8.26157949 26.6404103,10.839959 27.3965949,13.6585846 L29.2227282,20.4760615 L22.5234051,22.2706872 C19.7047795,23.0268718 18.7608615,26.5491692 20.8233026,28.6116103 L26.2596923,34.0493128 C26.2596923,34.0768821 26.2570667,34.1044513 26.2570667,34.1333333 L20.571241,37.4153846 C18.0453744,38.8739282 18.0453744,42.5209436 20.571241,43.9794872 L26.2570667,47.2615385 L20.571241,50.5435897 C18.0453744,52.0021333 18.0453744,55.6491487 20.571241,57.1076923 L26.2570667,60.3897436 L20.571241,63.6717949 C18.0453744,65.1303385 18.0453744,68.7773538 20.571241,70.2358974 L26.2570667,73.5179487 L20.571241,76.8 C18.0453744,78.2585436 18.0453744,81.905559 20.571241,83.3641026 L26.2570667,86.6461538 L20.571241,89.9282051 C18.0453744,91.3867487 18.0453744,95.0337641 20.571241,96.4923077 L26.2570667,99.774359 L20.571241,103.05641 C18.0453744,104.514954 18.0453744,108.161969 20.571241,109.620513 L26.2570667,112.902564 L20.571241,116.184615 C18.0453744,117.643159 18.0453744,121.290174 20.571241,122.748718 L26.2570667,126.030769 L20.571241,129.312821 C18.0453744,130.771364 18.0453744,134.418379 20.571241,135.876923 L26.2570667,139.158974 L20.571241,142.441026 C18.0453744,143.899569 18.0453744,147.546585 20.571241,149.005128 L26.2570667,152.287179 L20.571241,155.569231 C18.0453744,157.027774 18.0453744,160.67479 20.571241,162.133333 L26.2570667,165.415385 L20.571241,168.697436 C18.0453744,170.155979 18.0453744,173.802995 20.571241,175.261538 L26.2570667,178.54359 L20.571241,181.825641 C18.0453744,183.284185 18.0453744,186.9312 20.571241,188.389744 L26.2570667,191.671795 C26.2570667,206.17321 38.0120615,217.928205 52.5134769,217.928205 L210.051938,217.928205 C224.552041,217.928205 236.308349,206.17321 236.308349,191.671795 L236.308349,86.6461538 L144.384656,80.9012513 C137.019733,80.4404513 131.282708,74.3332103 131.282708,66.9538462 C131.282708,59.5744821 137.019733,53.467241 144.384656,53.006441" fill="#3ECC5F">

</path>
		<polygon fill="#3ECC5F" points="183.794872 217.928205 223.179487 217.928205 223.179487 165.415385 183.794872 165.415385">

</polygon>
		<path d="M249.435897,185.107692 C249.14839,185.107692 248.87401,185.156267 248.597005,185.191713 C248.547118,184.99479 248.499856,184.796554 248.444718,184.599631 C250.815672,183.609764 252.481641,181.272944 252.481641,178.54359 C252.481641,174.917579 249.543549,171.979487 245.917538,171.979487 C244.423549,171.979487 243.062154,172.499364 241.958072,173.339569 C241.812349,173.191221 241.666626,173.044185 241.518277,172.898462 C242.341415,171.800944 242.845538,170.45399 242.845538,168.977067 C242.845538,165.351056 239.907446,162.412964 236.281436,162.412964 C233.570462,162.412964 231.244144,164.057928 230.243774,166.405251 C230.049477,166.350113 229.853867,166.304164 229.659569,166.254277 C229.695015,165.977272 229.74359,165.702892 229.74359,165.415385 C229.74359,161.789374 226.805497,158.851282 223.179487,158.851282 C219.553477,158.851282 216.615385,161.789374 216.615385,165.415385 C216.615385,165.702892 216.663959,165.977272 216.699405,166.254277 C216.505108,166.304164 216.309497,166.350113 216.1152,166.405251 C215.114831,164.057928 212.788513,162.412964 210.077538,162.412964 C206.451528,162.412964 203.513436,165.351056 203.513436,168.977067 C203.513436,170.45399 204.017559,171.800944 204.840697,172.898462 C199.960944,177.666626 196.923077,184.31081 196.923077,191.671795 C196.923077,206.17321 208.678072,217.928205 223.179487,217.928205 C235.439918,217.928205 245.707487,209.513026 248.597005,198.151877 C248.87401,198.187323 249.14839,198.235897 249.435897,198.235897 C253.061908,198.235897 256,195.297805 256,191.671795 C256,188.045785 253.061908,185.107692 249.435897,185.107692" fill="#44D860">

</path>
		<polygon fill="#3ECC5F" points="196.923077 139.158974 236.307692 139.158974 236.307692 112.902564 196.923077 112.902564">

</polygon>
		<path d="M249.435897,129.312821 C251.248903,129.312821 252.717949,127.843774 252.717949,126.030769 C252.717949,124.217764 251.248903,122.748718 249.435897,122.748718 C249.2928,122.748718 249.154954,122.773662 249.017108,122.790728 C248.990851,122.692267 248.968533,122.593805 248.940964,122.495344 C250.125128,122.00041 250.958769,120.830687 250.958769,119.466667 C250.958769,117.653662 249.489723,116.184615 247.676718,116.184615 C246.929723,116.184615 246.248369,116.443241 245.696985,116.864656 C245.624779,116.789826 245.551262,116.716308 245.476431,116.644103 C245.888656,116.096656 246.140718,115.421867 246.140718,114.682749 C246.140718,112.871056 244.671672,111.400697 242.858667,111.400697 C241.502523,111.400697 240.339364,112.223836 239.839179,113.397497 C238.714092,113.083733 237.533867,112.902564 236.307692,112.902564 C229.058297,112.902564 223.179487,118.781374 223.179487,126.030769 C223.179487,133.280164 229.058297,139.158974 236.307692,139.158974 C237.533867,139.158974 238.714092,138.977805 239.839179,138.664041 C240.339364,139.837703 241.502523,140.660841 242.858667,140.660841 C244.671672,140.660841 246.140718,139.190482 246.140718,137.37879 C246.140718,136.639672 245.888656,135.964882 245.476431,135.417436 C245.551262,135.345231 245.624779,135.271713 245.696985,135.196882 C246.248369,135.618297 246.929723,135.876923 247.676718,135.876923 C249.489723,135.876923 250.958769,134.407877 250.958769,132.594872 C250.958769,131.230851 250.125128,130.061128 248.940964,129.566195 C248.968533,129.469046 248.990851,129.369272 249.017108,129.27081 C249.154954,129.287877 249.2928,129.312821 249.435897,129.312821" fill="#44D860">

</path>
		<path d="M78.7692308,50.5435897 C76.9562256,50.5435897 75.4871795,49.0745436 75.4871795,47.2615385 C75.4871795,41.8317128 71.0708513,37.4153846 65.6410256,37.4153846 C60.2112,37.4153846 55.7948718,41.8317128 55.7948718,47.2615385 C55.7948718,49.0745436 54.3258256,50.5435897 52.5128205,50.5435897 C50.6998154,50.5435897 49.2307692,49.0745436 49.2307692,47.2615385 C49.2307692,38.2122667 56.5917538,30.8512821 65.6410256,30.8512821 C74.6902974,30.8512821 82.0512821,38.2122667 82.0512821,47.2615385 C82.0512821,49.0745436 80.5822359,50.5435897 78.7692308,50.5435897" fill="#000000">

</path>
		<path d="M131.282051,217.928205 L210.051282,217.928205 C224.552697,217.928205 236.307692,206.17321 236.307692,191.671795 L236.307692,99.774359 L157.538462,99.774359 C143.037046,99.774359 131.282051,111.529354 131.282051,126.030769 L131.282051,217.928205 Z" fill="#FFFF50">

</path>
		<path d="M216.640985,140.471795 L150.948759,140.471795 C150.222769,140.471795 149.635938,139.884964 149.635938,139.158974 C149.635938,138.432985 150.222769,137.846154 150.948759,137.846154 L216.640985,137.846154 C217.366974,137.846154 217.953805,138.432985 217.953805,139.158974 C217.953805,139.884964 217.366974,140.471795 216.640985,140.471795" fill="#000000">

</path>
		<path d="M216.640985,166.728205 L150.948759,166.728205 C150.222769,166.728205 149.635938,166.141374 149.635938,165.415385 C149.635938,164.689395 150.222769,164.102564 150.948759,164.102564 L216.640985,164.102564 C217.366974,164.102564 217.953805,164.689395 217.953805,165.415385 C217.953805,166.141374 217.366974,166.728205 216.640985,166.728205" fill="#000000">

</path>
		<path d="M216.640985,192.984615 L150.948759,192.984615 C150.222769,192.984615 149.635938,192.397785 149.635938,191.671795 C149.635938,190.945805 150.222769,190.358974 150.948759,190.358974 L216.640985,190.358974 C217.366974,190.358974 217.953805,190.945805 217.953805,191.671795 C217.953805,192.397785 217.366974,192.984615 216.640985,192.984615" fill="#000000">

</path>
		<path d="M216.640985,127.587118 L150.948759,127.587118 C150.222769,127.587118 149.635938,126.998974 149.635938,126.274297 C149.635938,125.548308 150.222769,124.961477 150.948759,124.961477 L216.640985,124.961477 C217.366974,124.961477 217.953805,125.548308 217.953805,126.274297 C217.953805,126.998974 217.366974,127.587118 216.640985,127.587118" fill="#000000">

</path>
		<path d="M216.640985,153.6 L150.948759,153.6 C150.222769,153.6 149.635938,153.013169 149.635938,152.287179 C149.635938,151.56119 150.222769,150.974359 150.948759,150.974359 L216.640985,150.974359 C217.366974,150.974359 217.953805,151.56119 217.953805,152.287179 C217.953805,153.013169 217.366974,153.6 216.640985,153.6" fill="#000000">

</path>
		<path d="M216.640985,179.85641 L150.948759,179.85641 C150.222769,179.85641 149.635938,179.269579 149.635938,178.54359 C149.635938,177.8176 150.222769,177.230769 150.948759,177.230769 L216.640985,177.230769 C217.366974,177.230769 217.953805,177.8176 217.953805,178.54359 C217.953805,179.269579 217.366974,179.85641 216.640985,179.85641" fill="#000000">

</path>
		<path d="M236.307692,58.5666297 C236.291938,58.5666297 236.27881,58.5587528 236.263056,58.5600656 C232.206441,58.6979118 230.287097,62.75584 228.593559,66.3359015 C226.826503,70.0761272 225.459856,72.5100964 223.220185,72.4365785 C220.740267,72.3473067 219.322421,69.5457477 217.820554,66.5800862 C216.095508,63.1759426 214.126277,59.3136246 209.992205,59.4580349 C205.993354,59.5945682 204.067446,63.1260554 202.368656,66.2413785 C200.560903,69.5601887 199.33079,71.5779938 196.958523,71.4847836 C194.428718,71.3928862 193.08439,69.1151426 191.528697,66.478999 C189.794462,63.5435323 187.789785,60.2431015 183.735795,60.3560041 C179.80521,60.4912246 177.874051,63.487081 176.17001,66.1324144 C174.367508,68.9287221 173.104574,70.6327631 170.702113,70.5316759 C168.111918,70.4384656 166.774154,68.5493169 165.226338,66.3608451 C163.488164,63.9019323 161.529436,61.1187528 157.487262,61.2539733 C153.643323,61.3852554 151.712164,63.8389169 150.009436,66.0037579 C148.392041,68.0570092 147.129108,69.682281 144.457518,69.579881 C143.732841,69.550999 143.125005,70.1194503 143.098749,70.84544 C143.071179,71.5688041 143.638318,72.1779528 144.362995,72.2055221 C148.323774,72.3381169 150.329764,69.8411323 152.071877,67.6277169 C153.617067,65.6637374 154.950892,63.9688862 157.576533,63.8796144 C160.105026,63.7719631 161.290503,65.3434092 163.083815,67.8771528 C164.786544,70.2848656 166.719015,73.0155323 170.60759,73.1560041 C174.681272,73.2925374 176.641313,70.2481067 178.376862,67.554199 C179.928615,65.1464862 181.267692,63.0682913 183.825067,62.9803323 C186.178954,62.8923733 187.460267,64.75264 189.266708,67.8128246 C190.969436,70.6970913 192.897969,73.9647015 196.864,74.1091118 C200.966564,74.2508964 202.94761,70.6682092 204.673969,67.4990605 C206.169272,64.7578913 207.580554,62.1676964 210.081477,62.0823631 C212.435364,62.0272246 213.662851,64.1763118 215.478482,67.7668759 C217.174646,71.1185067 219.097928,74.9151836 223.125662,75.0609067 C223.200492,75.0635323 223.27401,75.0648451 223.347528,75.0648451 C227.37001,75.0648451 229.278851,71.0279221 230.968451,67.4583631 C232.463754,64.2944656 233.878974,61.3130503 236.307692,61.1922708 L236.307692,58.5666297 Z" fill="#000000">

</path>
		<polygon fill="#3ECC5F" points="105.025641 217.928205 157.538462 217.928205 157.538462 165.415385 105.025641 165.415385">

</polygon>
		<path d="M183.794872,185.107692 C183.507364,185.107692 183.232985,185.156267 182.955979,185.191713 C182.906092,184.99479 182.858831,184.796554 182.803692,184.599631 C185.174646,183.609764 186.840615,181.272944 186.840615,178.54359 C186.840615,174.917579 183.902523,171.979487 180.276513,171.979487 C178.782523,171.979487 177.421128,172.499364 176.317046,173.339569 C176.171323,173.191221 176.0256,173.044185 175.877251,172.898462 C176.70039,171.800944 177.204513,170.45399 177.204513,168.977067 C177.204513,165.351056 174.266421,162.412964 170.64041,162.412964 C167.929436,162.412964 165.603118,164.057928 164.602749,166.405251 C164.408451,166.350113 164.212841,166.304164 164.018544,166.254277 C164.05399,165.977272 164.102564,165.702892 164.102564,165.415385 C164.102564,161.789374 161.164472,158.851282 157.538462,158.851282 C153.912451,158.851282 150.974359,161.789374 150.974359,165.415385 C150.974359,165.702892 151.022933,165.977272 151.058379,166.254277 C150.864082,166.304164 150.668472,166.350113 150.474174,166.405251 C149.473805,164.057928 147.147487,162.412964 144.436513,162.412964 C140.810503,162.412964 137.87241,165.351056 137.87241,168.977067 C137.87241,170.45399 138.376533,171.800944 139.199672,172.898462 C134.319918,177.666626 131.282051,184.31081 131.282051,191.671795 C131.282051,206.17321 143.037046,217.928205 157.538462,217.928205 C169.798892,217.928205 180.066462,209.513026 182.955979,198.151877 C183.232985,198.187323 183.507364,198.235897 183.794872,198.235897 C187.420882,198.235897 190.358974,195.297805 190.358974,191.671795 C190.358974,188.045785 187.420882,185.107692 183.794872,185.107692" fill="#44D860">

</path>
		<polygon fill="#3ECC5F" points="105.025641 139.158974 157.538462 139.158974 157.538462 112.902564 105.025641 112.902564">

</polygon>
		<path d="M170.666667,129.312821 C172.479672,129.312821 173.948718,127.843774 173.948718,126.030769 C173.948718,124.217764 172.479672,122.748718 170.666667,122.748718 C170.523569,122.748718 170.385723,122.773662 170.247877,122.790728 C170.221621,122.692267 170.199303,122.593805 170.171733,122.495344 C171.355897,122.00041 172.189538,120.830687 172.189538,119.466667 C172.189538,117.653662 170.720492,116.184615 168.907487,116.184615 C168.160492,116.184615 167.479138,116.443241 166.927754,116.864656 C166.855549,116.789826 166.782031,116.716308 166.7072,116.644103 C167.119426,116.096656 167.371487,115.421867 167.371487,114.682749 C167.371487,112.871056 165.902441,111.400697 164.089436,111.400697 C162.733292,111.400697 161.570133,112.223836 161.069949,113.397497 C159.944862,113.083733 158.764636,112.902564 157.538462,112.902564 C150.289067,112.902564 144.410256,118.781374 144.410256,126.030769 C144.410256,133.280164 150.289067,139.158974 157.538462,139.158974 C158.764636,139.158974 159.944862,138.977805 161.069949,138.664041 C161.570133,139.837703 162.733292,140.660841 164.089436,140.660841 C165.902441,140.660841 167.371487,139.190482 167.371487,137.37879 C167.371487,136.639672 167.119426,135.964882 166.7072,135.417436 C166.782031,135.345231 166.855549,135.271713 166.927754,135.196882 C167.479138,135.618297 168.160492,135.876923 168.907487,135.876923 C170.720492,135.876923 172.189538,134.407877 172.189538,132.594872 C172.189538,131.230851 171.355897,130.061128 170.171733,129.566195 C170.199303,129.469046 170.221621,129.369272 170.247877,129.27081 C170.385723,129.287877 170.523569,129.312821 170.666667,129.312821" fill="#44D860">

</path>
		<path d="M183.794872,32.4923077 C183.584821,32.4923077 183.361641,32.4660513 183.15159,32.4266667 C182.941538,32.3872821 182.730174,32.321641 182.534564,32.2428718 C182.337641,32.1641026 182.153846,32.0590769 181.968738,31.9409231 C181.798072,31.8227692 181.628718,31.678359 181.469867,31.5339487 C181.326769,31.3764103 181.182359,31.2188718 181.064205,31.0350769 C180.946051,30.8512821 180.841026,30.6674872 180.760944,30.4705641 C180.683487,30.273641 180.617846,30.0635897 180.578462,29.8535385 C180.539077,29.6434872 180.512821,29.4203077 180.512821,29.2102564 C180.512821,29.0002051 180.539077,28.7770256 180.578462,28.5669744 C180.617846,28.3569231 180.683487,28.16 180.760944,27.9499487 C180.841026,27.7530256 180.946051,27.5692308 181.064205,27.3854359 C181.182359,27.2147692 181.326769,27.0441026 181.469867,26.8865641 C181.628718,26.7421538 181.798072,26.5977436 181.968738,26.4795897 C182.153846,26.3614359 182.337641,26.2564103 182.534564,26.177641 C182.730174,26.0988718 182.941538,26.0332308 183.15159,25.9938462 C183.571692,25.9019487 184.004923,25.9019487 184.438154,25.9938462 C184.646892,26.0332308 184.858256,26.0988718 185.055179,26.177641 C185.25079,26.2564103 185.435897,26.3614359 185.619692,26.4795897 C185.790359,26.5977436 185.959713,26.7421538 186.118564,26.8865641 C186.262974,27.0441026 186.407385,27.2147692 186.525538,27.3854359 C186.643692,27.5692308 186.748718,27.7530256 186.827487,27.9499487 C186.906256,28.16 186.971897,28.3569231 187.011282,28.5669744 C187.049354,28.7770256 187.076923,29.0002051 187.076923,29.2102564 C187.076923,30.0767179 186.721149,30.9300513 186.118564,31.5339487 C185.959713,31.678359 185.790359,31.8227692 185.619692,31.9409231 C185.435897,32.0590769 185.25079,32.1641026 185.055179,32.2428718 C184.858256,32.321641 184.646892,32.3872821 184.438154,32.4266667 C184.228103,32.4660513 184.004923,32.4923077 183.794872,32.4923077" fill="#000000">

</path>
		<path d="M210.051282,30.8512821 C209.184821,30.8512821 208.344615,30.4968205 207.726277,29.8929231 C207.583179,29.7353846 207.438769,29.5647179 207.320615,29.3940513 C207.202462,29.2102564 207.097436,29.0264615 207.017354,28.8295385 C206.939897,28.6326154 206.874256,28.4225641 206.834872,28.2125128 C206.795487,28.0024615 206.769231,27.7792821 206.769231,27.5692308 C206.769231,26.7027692 207.123692,25.8625641 207.726277,25.2455385 C207.885128,25.1011282 208.054482,24.9567179 208.225149,24.8385641 C208.410256,24.7204103 208.594051,24.6153846 208.790974,24.5366154 C208.986585,24.4578462 209.197949,24.3922051 209.408,24.3528205 C209.828103,24.2609231 210.274462,24.2609231 210.694564,24.3528205 C210.903303,24.3922051 211.114667,24.4578462 211.31159,24.5366154 C211.5072,24.6153846 211.692308,24.7204103 211.876103,24.8385641 C212.046769,24.9567179 212.216123,25.1011282 212.374974,25.2455385 C212.977559,25.8625641 213.333333,26.7027692 213.333333,27.5692308 C213.333333,27.7792821 213.305764,28.0024615 213.267692,28.2125128 C213.228308,28.4225641 213.162667,28.6326154 213.083897,28.8295385 C212.992,29.0264615 212.900103,29.2102564 212.781949,29.3940513 C212.663795,29.5647179 212.519385,29.7353846 212.374974,29.8929231 C212.216123,30.0373333 212.046769,30.1817436 211.876103,30.2998974 C211.692308,30.4180513 211.5072,30.5230769 211.31159,30.6018462 C211.114667,30.6806154 210.903303,30.7462564 210.694564,30.785641 C210.484513,30.8250256 210.261333,30.8512821 210.051282,30.8512821" fill="#000000">

</path>
</g>
</svg>}
      />

      <Card
        title="ReadMe"
        icon={<svg fill="#177fc4" className="h-6 w-6" width="36" height="36" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path d="M29.35 4.361h-7.767c-2.672 0-4.994 1.85-5.578 4.461-0.589-2.611-2.906-4.461-5.578-4.461h-7.761c-1.472 0-2.667 1.194-2.667 2.667v13.656c0 1.472 1.194 2.667 2.667 2.667h4.983c5.678 0 7.372 1.355 8.183 4.167 0.039 0.156 0.289 0.156 0.333 0 0.817-2.811 2.511-4.167 8.183-4.167h4.983c1.472 0 2.667-1.194 2.667-2.667v-13.65c0-1.467-1.183-2.661-2.65-2.672zM13.444 19.105c0 0.106-0.083 0.194-0.194 0.194h-8.906c-0.105 0-0.194-0.083-0.194-0.194v-1.272c0-0.105 0.083-0.194 0.194-0.194h8.911c0.105 0 0.194 0.083 0.194 0.194v1.272zM13.444 15.722c0 0.105-0.083 0.194-0.194 0.194h-8.906c-0.105 0-0.194-0.083-0.194-0.194v-1.272c0-0.106 0.083-0.194 0.194-0.194h8.911c0.105 0 0.194 0.083 0.194 0.194v1.272zM13.444 12.339c0 0.105-0.083 0.194-0.194 0.194h-8.906c-0.105 0-0.194-0.083-0.194-0.194v-1.272c0-0.105 0.083-0.194 0.194-0.194h8.911c0.105 0 0.194 0.083 0.194 0.194v1.272zM27.85 19.1c0 0.105-0.083 0.194-0.194 0.194h-8.906c-0.105 0-0.194-0.083-0.194-0.194v-1.272c0-0.105 0.083-0.194 0.194-0.194h8.911c0.106 0 0.194 0.083 0.194 0.194v1.272zM27.85 15.717c0 0.106-0.083 0.194-0.194 0.194h-8.906c-0.105 0-0.194-0.083-0.194-0.194v-1.272c0-0.105 0.083-0.194 0.194-0.194h8.911c0.106 0 0.194 0.083 0.194 0.194v1.272zM27.85 12.333c0 0.105-0.083 0.194-0.194 0.194h-8.906c-0.105 0-0.194-0.083-0.194-0.194v-1.267c0-0.105 0.083-0.194 0.194-0.194h8.911c0.106 0 0.194 0.083 0.194 0.194v1.267z"/>
</svg>}
      />
    </Columns>

    If you host your documentation on another platform, see the manual migration steps.

    ### Install the scraper

    Install the `@mintlify/scraping` package to get started.

    ```bash theme={null}
    npm install @mintlify/scraping@latest -g
    ```

    ### Scrape pages and sections

    The migration tool automatically detects your documentation platform and converts your content. It saves prepared files locally in the `./docs` folder by default.

    For large documentation sites, migrate smaller sections one at a time rather than the entire site at once.

    **Migrate entire sections:**

    ```bash theme={null}
    mintlify-scrape section https://your-docs-site.com/docs
    ```

    **Migrate single pages:**

    ```bash theme={null}
    mintlify-scrape page https://your-docs-site.com/docs/getting-started
    ```

    **Filter specific paths:**

    Use the `--filter` (or `-f`) option to scrape only URLs matching a specific path prefix.

    ```bash theme={null}
    mintlify-scrape section https://your-docs-site.com --filter=/docs
    ```

    The filter matches the specified path and all nested paths. For example, `--filter=/docs` matches `/docs`, `/docs/getting-started`, `/docs/api/reference`, and so on.

    **Migrate OpenAPI specifications:**

    ```bash theme={null}
    mintlify-scrape openapi-file [openApiFilename]
    ```

    ### Add prepared content to your Mintlify project

    After scraping your existing documentation platform, you are ready to build your docs on Mintlify.

    Confirm that you scraped all of your pages. Then add these files to the documentation repository that you created during the onboarding process. This is usually a GitHub repository.
  </Tab>

  <Tab title="Auto-generated migration">
    Mintlify can generate a complete documentation site for any public GitHub repository, whether it already contains documentation or just code.

    Replace `github.com` with `mintlify.com` in any public repository URL:

    ```text theme={null}
    https://mintlify.com/github-owner/repository-name
    ```

    Mintlify analyzes your repository and generates a complete documentation site that you can further customize.
  </Tab>

  <Tab title="Manual migration">
    Migrate your documentation from any platform with full control over the process.

    ### Content migration

    To migrate your content to Mintlify, you need:

    * A valid `docs.json` for your site settings and navigation. See [Global settings](/docs/organize/settings) and [Navigation](/docs/organize/navigation) for more information.
    * A Markdown file (`.md` or `.mdx`) for each page of your documentation. MDX is the recommended format. See [Pages](/docs/organize/pages) for more information.
    * (Optional) An OpenAPI specification for your API endpoint pages. See [OpenAPI setup](/docs/api-playground/openapi-setup) for more information.

    1. If your content is already in Markdown format, copy the content to your Mintlify project. Otherwise, convert your content to MDX format.
    2. Create your `docs.json` referencing the paths to your Markdown pages.
    3. If you have OpenAPI specifications, add them to your `docs.json` and configure the API playground. You can also generate MDX pages from your spec using the [`@mintlify/scraping`](https://www.npmjs.com/package/@mintlify/scraping) package:

    ```bash theme={null}
    npx @mintlify/scraping@latest openapi-file <openApiFilename> -o <folder-name>
    ```

    <Tip>
      If you migrate your content as `.md` files, convert them to `.mdx` to support interactive features like React components.
    </Tip>

    ### Asset migration

    1. Copy assets to your repository's `images/` directory.
    2. Update references in your Markdown files:
       ```mdx theme={null}
       ![Alt text](/images/screenshot.png)
       ```
  </Tab>
</Tabs>

## Post-migration checklist

After completing your migration (automated or manual), check the following:

* All pages render
* Navigation works as intended
* Internal links resolve properly
* Images and assets load correctly
* Code blocks display with proper syntax highlighting
* Search works
* Correct deployment branch


# Collect page feedback from users and AI agents
Source: https://www.mintlify.com/docs/optimize/feedback

Enable feedback widgets, page ratings, contextual notes, code snippet reactions, and agent feedback to find and fix documentation gaps.

<Info>
  Feedback requires a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=feedback).
</Info>

The feedback section of the [analytics](https://app.mintlify.com/analytics) page displays quantitative thumbs-up and thumbs-down votes for your pages. It also displays any qualitative feedback users provide. A bar chart shows feedback over time, and the views below it list specific feedback items. Use this information to gauge the quality of your content and make improvements.

Review your feedback data to:

* **Identify successful content**: Pages with the most positive feedback show what works well in your documentation.
* **Prioritize improvements**: Pages with the most negative feedback indicate what content might need attention.
* **Take action**: Make documentation updates based on direct user feedback.

<Frame>
  <img alt="Feedback tab in the Analytics page." />

  <img alt="Feedback tab in the Analytics page." />
</Frame>

## Enable feedback

<Note>
  If you disable telemetry in your `docs.json` file, you cannot enable feedback features.
</Note>

To collect and view feedback from users, you must enable feedback from the [Add-ons](https://app.mintlify.com/products/addons) page in your dashboard.

1. Navigate to the [Add-ons](https://app.mintlify.com/products/addons) page.
2. Enable your desired feedback types.

* **Thumbs rating**: Simple thumbs up/down voting to gauge overall satisfaction with pages.
* **Edit suggestions**: Allow users to suggest edits to your documentation. Only available for public repositories.
* **Raise issues**: Allow users to create issues directly from your site. Only available for public repositories.
* **Contextual feedback**: Free-form feedback about the content of a page. Optionally, enable email collection to allow users to provide their email address when submitting feedback.
* **Code snippet feedback**: Feedback specifically on code snippets.

<Frame>
  <img alt="Feedback toggles in the Add-ons page." />

  <img alt="Feedback toggles in the Add-ons page." />
</Frame>

## Manage feedback

You can set the status of a piece of feedback and add internal notes to track your work resolving user feedback. To analyze feedback outside the dashboard, [export it to CSV](/docs/analytics/export).

### Change feedback status

Select the status beside a piece of feedback to mark it as **Pending**, **In Progress**, **Resolved**, or **Dismissed**.

Best practices for setting feedback statuses:

* **Pending**: Feedback is awaiting review.
* **In Progress**: Work is in progress to address the feedback.
* **Resolved**: You resolved the feedback.
* **Dismissed**: Feedback is irrelevant or inaccurate.

### Filter by status

Use the **Filters** menu to control which feedback displays. Clear a status to hide all feedback with that status. By default, all feedback types display.

### Filter by type

Select between **Ratings by page**, **Detailed feedback**, and **Code snippets** depending on the information you want to analyze.

* **Ratings by page**: See which pages have the most positive and negative feedback. Use this quantitative data to identify pages that users find most and least helpful.
* **Detailed feedback**: Review the open feedback users leave on pages to identify targeted improvements to specific pages. Detailed feedback only displays feedback that includes additional information. Submissions that use only the thumbs up or thumbs down rating without selecting an additional feedback option do not appear in the detailed view.
* **Code snippets**: Review the open feedback users leave on code snippets to identify targeted improvements to specific blocks of code.

### Add internal notes

Click a piece of feedback to add an internal note. These notes are only visible to people with access to your dashboard.

Use notes to add information for collaboration, link relevant support or engineering tickets, or remember any other useful information.

## Agent feedback

<Note>
  Agent feedback is in beta and subject to change.
</Note>

Third-party AI agents can submit structured feedback about pages they find incorrect, outdated, or difficult to use.

This feedback appears in the **Detailed feedback** section identified by an **Agent** badge. Manage agent feedback the same way as human feedback.

### How agent feedback works

Connect an agent to your site's [search MCP server](/docs/ai/model-context-protocol). The server exposes a `submit_feedback` tool that requires the page path and a description of the problem.

<Note>
  Web search and web fetch tools do not connect an agent to the search MCP server. Connect the agent to the server so it can discover and call the `submit_feedback` tool.
</Note>

Mintlify records each submission as unhelpful feedback for the specified page. The feedback appears in the dashboard alongside human feedback.

### Retrieve agent feedback via API

Use the [analytics feedback endpoint](/docs/api/analytics/feedback) to retrieve agent feedback programmatically. Filter by `source=agent` to return only agent feedback.

Agent feedback responses include:

* `comment`: The feedback text submitted by the agent.
* `path`: The path of the page the feedback is about.


# Hidden pages
Source: https://www.mintlify.com/docs/organize/hidden-pages

Hide documentation pages from the sidebar navigation while keeping them accessible via direct URL, search, or AI assistant for special use cases.

Hidden pages don't appear in your site's navigation, but anyone who knows the URL can still access them. For example, if you create a hidden page like `guides/hidden-page.mdx`, visitors can reach it at `docs.yoursite.com/guides/hidden-page`.

Use hidden pages for content you want users to access or reference as context for AI tools, but don't want listed in the navigation.

<Warning>
  Hidden pages are not private. Anyone with the URL can view them, and links shared externally still work. Hiding a page only removes it from the rendered navigation.

  If your content requires strict access control, you must configure [authentication](/docs/deploy/authentication-setup). To restrict pages to specific user groups, set up [group-based access control](/docs/deploy/authentication-setup#control-access-with-groups).
</Warning>

See an [example of a hidden page](/docs/organize/hidden-page-example).

<Note>
  Some navigation elements like sidebars, dropdowns, and tabs may appear empty or shift layout on hidden pages.
</Note>

## Hide a page

To hide a page, set `hidden: true` in the page's [frontmatter](/docs/organize/pages) or remove it from your `docs.json` navigation.

### Set `hidden: true` in frontmatter

Add `hidden: true` to a page's frontmatter to remove it from the rendered navigation while still including it in your `docs.json` configuration.

```yaml theme={null}
---
title: "My hidden page"
hidden: true
---
```

To make a page visible again, remove the `hidden` field entirely. Do not set `hidden: false` as it results in undefined behavior.

<Note>
  By default, `hidden: true` excludes a page from search engine indexing, sitemaps, and AI context.

  To include it anyway, set `seo.indexing: "all"` in `docs.json`. See [Search, SEO, and AI indexing](#search-seo-and-ai-indexing) for details.

  `noindex: true` only affects indexing—it does not hide the page from navigation. See [Disable indexing](/docs/optimize/seo#disable-indexing) for more information.
</Note>

### Remove the page from navigation

If you don't include a page in your `docs.json` navigation, you hide it. This method works well for pages that you don't want to appear in navigation at all.

## Hide a group of pages

To hide a group of pages, set the `hidden` property to `true` for the group in your `docs.json` file:

```json highlight={4} theme={null}
"groups": [
  {
    "group": "Getting started",
    "hidden": true,
    "pages": [
      "index",
      "quickstart"
    ]
  },
  {
    "group": "Guides",
    "pages": [
      "guides/hidden-page.mdx",
      "guides/hidden-groups.mdx"
    ]
  }
]
```

In this example, the `Getting started` group stays hidden and the `Guides` group remains visible.

### Hide a tab

To hide a tab, add the `hidden` property for the tab in your `docs.json` file:

```json highlight={4} theme={null}
"tabs": [
  {
    "tab": "Home",
    "hidden": true,
    "pages": [
      "index",
      "quickstart"
    ]
  }
]
```

## Search, SEO, and AI indexing

By default, hidden pages don't appear in indexing for search engines, documentation site search, or as AI assistant context. You have two ways to include hidden content in search and indexing.

The following table summarizes how each property affects page visibility and indexing:

| Property                                 | Sidebar navigation | Site search | Sitemap  | Search engine indexing | AI assistant context |
| ---------------------------------------- | ------------------ | ----------- | -------- | ---------------------- | -------------------- |
| `hidden: true`                           | Hidden             | Excluded    | Excluded | Excluded               | Excluded             |
| `noindex: true`                          | Visible            | Excluded    | Excluded | Excluded               | Excluded             |
| `searchable: false` (page frontmatter)   | Visible            | Excluded    | Included | Included               | Excluded             |
| `searchable: true` (on hidden tab/group) | Hidden             | Included    | Included | Included               | Included             |
| `seo.indexing: "all"` (in `docs.json`)   | Hidden             | Included    | Included | Included               | Included             |

### Include all hidden pages

To include every hidden page across your site in search, sitemaps, and AI context, add the `seo` property to your `docs.json`:

```json theme={null}
"seo": {
    "indexing": "all"
}
```

### Include pages under specific hidden tabs or groups

To include only the pages under a specific hidden tab or group, set `searchable: true` on that tab or group in your `docs.json`. Use this option when you hide tabs or groups to control navigation layout but still want descendant pages discoverable.

```json highlight={5} theme={null}
"tabs": [
  {
    "tab": "Storage",
    "hidden": true,
    "searchable": true,
    "groups": [
      {
        "group": "Buckets",
        "pages": ["products/storage/buckets/create-bucket"]
      }
    ]
  }
]
```

With `searchable: true`, descendant pages remain in:

* Documentation site search
* `sitemap.xml`
* AI assistant context
* MCP server search results
* Search engine indexing (the `noindex` meta tag is not applied)

The tab or group itself stays hidden from the rendered navigation.

A page's own `hidden: true` frontmatter always takes precedence. To re-exclude a descendant group, set `hidden: true` on it without `searchable: true`.

### Page-level `searchable`

At the page frontmatter level, `searchable` only accepts `false`. Use it to keep a page indexable by external search engines while excluding it from in-product search and AI assistant context. See [Exclude a page from search](/docs/optimize/search#exclude-a-page-from-search) for an example.

Page-level `searchable` does not override `hidden: true` on the same page. To make a hidden page discoverable, leave `searchable` unset and either move it under a hidden tab or group with `searchable: true`, or set `seo.indexing: "all"` in `docs.json`.

### Understanding hidden versus noindex

The relationship between `hidden` and `noindex` is one-directional:

* **`hidden: true` → automatically applies `noindex`**: Hidden pages are automatically excluded from search engines, sitemaps, and AI context.
* **`noindex: true` → does NOT apply `hidden`**: Pages with `noindex: true` remain visible in navigation. They don't appear in site search, sitemaps, search engine indexing, or AI assistant context.

To exclude a specific page from search and indexing while keeping it visible in navigation, add `noindex: true` to its frontmatter. To hide a page from navigation as well, use `hidden: true`. To exclude a page only from your in-product search and AI assistant context while keeping it indexable by external search engines, use [`searchable: false`](/docs/optimize/search#exclude-a-page-from-search) instead.


# Exclude files from publishing
Source: https://www.mintlify.com/docs/organize/mintignore

Exclude specific files and directories from your published documentation using a .mintignore file with glob patterns, similar to .gitignore syntax.

The `.mintignore` file lets you exclude specific files and directories in your documentation repository from processing and publishing to your documentation site.

Use `.mintignore` to keep drafts, internal notes, and source files out of your public documentation while maintaining them in your repository.

## Create a .mintignore file

Create a `.mintignore` file in the root of your docs directory. This file uses the same pattern syntax as `.gitignore`.

```plaintext .mintignore theme={null}
# Exclude draft documents
drafts/
*.draft.mdx

# Exclude internal documentation
internal/

# Exclude specific files
private-notes.md
```

When Mintlify builds your documentation, it reads the `.mintignore` file and excludes any matching files or directories from processing.

Excluded files:

* Don't appear in your published documentation.
* Aren't indexed for search.
* Aren't accessible to visitors.
* Don't have their outgoing links checked by [`mint broken-links`](/docs/cli/commands#mint-broken-links).
* Cause any links pointing to them from other pages to appear as broken by `mint broken-links` checks.

## Default ignored patterns

Mintlify automatically ignores the following directories and files without requiring any configuration:

* `.git`
* `.github`
* `.claude`
* `.agents`
* `.idea`
* `.vscode`
* `node_modules`
* `build`
* `dist`
* `coverage`
* `.cache`
* `tmp`
* `temp`
* `README.md`
* `LICENSE.md`
* `CHANGELOG.md`
* `CONTRIBUTING.md`

You don't need to add these to your `.mintignore` file.

<Note>
  Unlike [hidden pages](/docs/organize/hidden-pages), `.mintignore` completely removes
  matching files from your site. Visitors cannot access them by URL.
</Note>

## Pattern syntax

The `.mintignore` file follows `.gitignore` syntax. Some common patterns include:

| Pattern            | Description                                    |
| ------------------ | ---------------------------------------------- |
| `drafts/`          | Excludes the entire `drafts` directory         |
| `*.draft.mdx`      | Excludes all files ending in `.draft.mdx`      |
| `private-notes.md` | Excludes a specific file                       |
| `**/internal/**`   | Excludes any `internal` directory at any level |
| `!important.mdx`   | Negates a previous pattern (includes the file) |


# Navigation
Source: https://www.mintlify.com/docs/organize/navigation

Configure your documentation site navigation with groups, pages, dropdowns, tabs, and anchors in docs.json to build a sidebar structure.

The [navigation](/docs/organize/settings-structure#navigation) property in `docs.json` controls the structure and information hierarchy of your documentation.

With proper navigation configuration, you can organize your content so that users can find exactly what they're looking for.

Choose one primary organizational pattern at the root level of your navigation. Once you've chosen your primary pattern, you can nest other navigation elements within it.

## Choose a primary pattern

Use the pattern that matches how you want visitors to move between top-level sections of your content.

| Pattern                 | Use when                                                                                                                | Example                                                                           |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| [Groups](#groups)       | Your content fits in one linear sidebar and you don't need a second axis of navigation.                                 | A single-product SDK reference.                                                   |
| [Tabs](#tabs)           | You have parallel sections that share the same audience.                                                                | Guides, API reference, and SDKs tabs for one product.                             |
| [Anchors](#anchors)     | You want persistent links to a small number of top-level destinations (external or internal) visible at all times.      | Community, status page, or another link alongside your product documentation.     |
| [Dropdowns](#dropdowns) | Similar to tabs, but you want to use a dropdown menu for navigation.                                                    | Switching between product documentation, API reference, and partner integrations. |
| [Products](#products)   | You maintain documentation for multiple distinct products under one deployment, and each product has its own full site. | A platform with separate content for Payments, Identity, and Analytics.           |
| [Versions](#versions)   | You publish multiple versions of the same content in parallel.                                                          | Maintaining `v1` and `v2` API docs simultaneously.                                |
| [Languages](#languages) | You publish translated versions of the same content.                                                                    | English, Spanish, and Japanese documentation for one product.                     |

## Pages

Pages are the most fundamental navigation component. Each page is an MDX file in your documentation repository.

<img alt="Decorative graphic of pages." />

<img alt="Decorative graphic of pages." />

In the `navigation` object, `pages` is an array. Each entry must reference the path to a [page file](/docs/organize/pages).

```json theme={null}
{
  "navigation": {
    "pages": [
      "settings",
      "pages",
      "navigation",
      "themes",
      "custom-domain"
    ]
  }
}
```

## Groups

Use groups to organize your sidebar navigation into sections. You can nest groups within each other, label them with tags, and style them with icons.

<img alt="Decorative graphic of groups." />

<img alt="Decorative graphic of groups." />

In the `navigation` object, `groups` is an array. Each entry is an object that requires a `group` field and a `pages` field. The `icon`, `tag`, `root`, and `expanded` fields are optional.

```json theme={null}
{
  "navigation": {
    "groups": [
      {
        "group": "Getting started",
        "icon": "play",
        "pages": [
          "quickstart",
          {
            "group": "Editing",
            "expanded": false,
            "icon": "pencil",
            "pages": [
              "installation",
              "editor"
            ]
          }
        ]
      },
      {
        "group": "Writing content",
        "icon": "notebook-text",
        "tag": "NEW",
        "pages": [
          "writing-content/page",
          "writing-content/text"
        ]
      }
    ]
  }
}
```

### Root page

Use the `root` property to designate a main page for a group. When a group has a root page, clicking the group title in the sidebar navigation opens the root page. Root pages work for top-level and nested groups.

```json Example group with a root page theme={null}
{
  "navigation": {
    "groups": [
      {
        "group": "API pages",
        "root": "api-overview",
        "pages": [
          "api-reference/get",
          "api-reference/post",
          "api-reference/delete"
        ]
      }
    ]
  }
}
```

### Directory listings

Use the `directory` property to automatically render a directory of child pages and groups on group root pages. Set `directory` on any object within the `navigation` tree in `docs.json`. Groups with a `root` page matching or beneath that object display a listing of their pages and groups below their page contents.

The `directory` property accepts three values:

| Value         | Behavior                                                       |
| :------------ | :------------------------------------------------------------- |
| `"none"`      | No directory listing. Default value.                           |
| `"accordion"` | Displays child pages in a collapsible list grouped by section. |
| `"card"`      | Displays child pages in a horizontal card layout.              |

The `directory` value inherits recursively through the navigation tree. Set it anywhere within the navigation object and all descendant groups inherit the same value. Any descendant can override the inherited value by setting `directory` to a different value.

You can set `directory` anywhere in the navigation object in your `docs.json` file, including on tabs, anchors, dropdowns, products, versions, languages, and individual groups.

```json theme={null}
{
  "navigation": {
    "groups": [
      {
        "group": "Help Center",
        "root": "help/index",
        "directory": "accordion",
        "pages": [
          {
            "group": "Getting Started",
            "root": "help/getting-started/index",
            "pages": [
              "help/getting-started/quickstart",
              "help/getting-started/install"
            ]
          },
          {
            "group": "API Reference",
            "root": "help/api/index",
            "directory": "none",
            "pages": [
              "help/api/overview",
              "help/api/endpoints"
            ]
          }
        ]
      }
    ]
  }
}
```

In this example:

* **Help Center** uses `"accordion"` and its root page displays a directory listing.
* **Getting Started** inherits `"accordion"` from its parent and also displays a directory listing.
* **API Reference** overrides with `"none"`, so its root page does not display a directory listing.

<Note>
  The `directory` property only affects groups that have a `root` page. Groups without a `root` page are not affected.
</Note>

### Default expanded state

Use the `expanded` property to control the default state of a nested group in the navigation sidebar.

* `expanded: true`: Expands the group by default.
* `expanded: false` or omitted: Collapses the group by default.

<Note>
  The `expanded` property only affects nested groups—groups within groups. Top-level groups always expand and you cannot collapse them.
</Note>

```json theme={null}
{
  "group": "Getting started",
  "pages": [
    "quickstart",
    {
      "group": "Advanced",
      "expanded": false,
      "pages": ["installation", "configuration"]
    }
  ]
}
```

## Tabs

Tabs create distinct sections of your documentation with separate URL paths. Tabs create a horizontal navigation bar at the top of your documentation that lets users switch between sections.

<img alt="Decorative graphic of a tab navigation." />

<img alt="Decorative graphic of a tab navigation." />

In the `navigation` object, `tabs` is an array. Each entry is an object that requires a `tab` field and can contain other navigation fields, such as groups, pages, icons, or links to external pages.

```json theme={null}
{
  "navigation": {
    "tabs": [
      {
        "tab": "API reference",
        "icon": "square-terminal",
        "pages": [
          "api-reference/get",
          "api-reference/post",
          "api-reference/delete"
        ]
      },
      {
        "tab": "SDKs",
        "icon": "code",
        "pages": [
          "sdk/fetch",
          "sdk/create",
          "sdk/delete"
        ]
      },
      {
        "tab": "Blog",
        "icon": "newspaper",
        "href": "https://external-link.com/blog"
      }
    ]
  }
}
```

### Menus

Menus add dropdown navigation items to a tab. Use menus to help users go directly to specific pages within a tab.

In the `navigation` object, `menu` is an array. Each entry is an object that requires an `item` field and can contain other navigation fields, such as groups, pages, icons, or links to external pages.

A menu item can hold pages, an external link via `href`, or any navigation division (`groups`, `tabs`, `anchors`, `dropdowns`, `products`, `languages`, or `versions`). Use a division inside a menu item when you want that column to render the same kind of nested navigation that the division provides at the top level.

```json theme={null}
{
  "navigation": {
    "tabs": [
      {
        "tab": "Developer tools",
        "icon": "square-terminal",
        "menu": [
          {
            "item": "API reference",
            "icon": "rocket",
            "groups": [
              {
                "group": "Core endpoints",
                "icon": "square-terminal",
                "pages": [
                  "api-reference/get",
                  "api-reference/post",
                  "api-reference/delete"
                ]
              }
            ]
          },
          {
            "item": "SDKs",
            "icon": "code",
            "description": "SDKs are used to interact with the API.",
            "pages": [
              "sdk/fetch",
              "sdk/create",
              "sdk/delete"
            ]
          }
        ]
      }
    ]
  }
}
```

## Anchors

Anchors add persistent navigation items to the top of your sidebar. Use anchors to section your content, provide quick access to external resources, or create prominent calls to action.

<img alt="Decorative graphic of an anchor navigation." />

<img alt="Decorative graphic of an anchor navigation." />

In the `navigation` object, `anchors` is an array. Each entry is an object that requires an `anchor` field and can contain other navigation fields, such as groups, pages, icons, or links to external pages.

```json theme={null}
{
  "navigation": {
    "anchors": [
      {
        "anchor": "Documentation",
        "icon": "book-open",
        "pages": [
          "quickstart",
          "development",
          "navigation"
        ]
      },
      {
        "anchor": "API reference",
        "icon": "square-terminal",
        "pages": [
          "api-reference/get",
          "api-reference/post",
          "api-reference/delete"
        ]
      },
      {
        "anchor": "Blog",
        "href": "https://external-link.com/blog"
      }
    ]
  }
}
```

### Global anchors

Use global anchors for links that should appear on all pages, regardless of which section of your navigation the user is viewing. Global anchors are useful for linking to resources outside your documentation, such as a blog, community forum, or support portal. They also provide consistent access to important internal pages, such as a changelog or status page.

Global anchors support both external URLs and relative paths to pages within your documentation.

```json theme={null}
{
  "navigation": {
    "global":  {
      "anchors": [
        {
          "anchor": "Changelog",
          "icon": "list",
          "href": "/changelog"
        },
        {
          "anchor": "Blog",
          "icon": "pencil",
          "href": "https://mintlify.com/blog"
        }
      ]
    },
    "tabs": /*...*/
  }
}
```

## Products

<img alt="Decorative graphic of a product switcher." />

<img alt="Decorative graphic of a product switcher." />

Products create a dedicated navigation division for organizing product-specific documentation. Use products to separate different offerings, services, or major feature sets within your documentation.

In the `navigation` object, `products` is an array. Each entry is an object that requires a `product` field and can contain other navigation fields, such as groups, pages, a [menu](#menus), icons, or links to external pages.

```json theme={null}
{
  "navigation": {
    "products": [
      {
        "product": "Core API",
        "description": "Core API description",    
        "icon": "api",
        "groups": [
          {
            "group": "Getting started",
            "pages": [
              "core-api/quickstart",
              "core-api/authentication"
            ]
          },
          {
            "group": "Endpoints",
            "pages": [
              "core-api/users",
              "core-api/orders"
            ]
          }
        ]
      },
      {
        "product": "Analytics Platform",
        "description": "Analytics Platform description",
        "icon": "chart-bar",
        "pages": [
          "analytics/overview",
          "analytics/dashboard",
          "analytics/reports"
        ]
      },
      {
        "product": "Mobile SDK",
        "description": "Mobile SDK description",
        "icon": "smartphone",
        "href": "https://mobile-sdk-docs.example.com"
      }
    ]
  }
}
```

### Product menus

Add a `menu` array to a product to render its product switcher entry as a multi-column dropdown. Each menu item requires an `item` field and can contain pages, an external link via `href`, or any navigation division (`groups`, `tabs`, `anchors`, `dropdowns`, `products`, `languages`, or `versions`). This is the same `menu` shape supported under [tabs](#menus), and is useful when a product has several distinct content areas that you want to surface from the product switcher.

```json theme={null}
{
  "navigation": {
    "products": [
      {
        "product": "Core API",
        "icon": "api",
        "menu": [
          {
            "item": "Guides",
            "icon": "book-open",
            "groups": [
              {
                "group": "Getting started",
                "pages": [
                  "core-api/quickstart",
                  "core-api/authentication"
                ]
              }
            ]
          },
          {
            "item": "API reference",
            "icon": "square-terminal",
            "pages": [
              "core-api/users",
              "core-api/orders"
            ]
          },
          {
            "item": "Changelog",
            "icon": "list",
            "href": "https://example.com/changelog"
          }
        ]
      }
    ]
  }
}
```

## Dropdowns

Dropdowns are an expandable menu at the top of your sidebar navigation. Each item in a dropdown directs to a section of your documentation.

<img alt="Decorative graphic of a dropdown navigation." />

<img alt="Decorative graphic of a dropdown navigation." />

In the `navigation` object, `dropdowns` is an array. Each entry is an object that requires a `dropdown` field and can contain other navigation fields, such as groups, pages, icons, or links to external pages.

```json theme={null}
{
  "navigation": {
    "dropdowns": [
      {
        "dropdown": "Documentation",
        "icon": "book-open",
        "pages": [
          "quickstart",
          "development",
          "navigation"
        ]
      },
      {
        "dropdown": "API reference",
        "icon": "square-terminal",
        "pages": [
          "api-reference/get",
          "api-reference/post",
          "api-reference/delete"
        ]
      },
      {
        "dropdown": "Blog",
        "href": "https://external-link.com/blog"
      }
    ]
  }
}
```

## OpenAPI

Integrate OpenAPI specifications directly into your navigation structure to automatically generate API documentation. Create dedicated API sections or place endpoint pages within other navigation components.

Set a default OpenAPI specification at any level of your navigation hierarchy. Child elements inherit the specification unless they define their own.

<Note>
  When you add the `openapi` property to a navigation element, such as an anchor, tab, or group, without specifying any pages, Mintlify automatically generates pages for **all endpoints** defined in your OpenAPI specification.

  To control which endpoints appear, explicitly list the desired endpoints in a `pages` array.
</Note>

For more information about referencing OpenAPI endpoints in your docs, see the [OpenAPI setup](/docs/api-playground/openapi-setup).

```json theme={null}
{
  "navigation": {
    "groups": [
      {
        "group": "API reference",
        "openapi": "/path/to/openapi-v1.json",
        "pages": [
          "overview",
          "authentication",
          "GET /users",
          "POST /users",
          {
            "group": "Products",
            "openapi": "/path/to/openapi-v2.json",
            "pages": [
              "GET /products",
              "POST /products"
            ]
          }
        ]
      }
    ]
  }
}
```

## SDK references

Generate SDK reference pages from the build artifacts of your documentation tools. Add an `sdk` property to a tab with the artifact `format` (`typedoc`, `docfx`, `javadoc`, `sphinx`, or `phpdoc`) and a `source` path or HTTPS URL. You can also add an optional `directory` for the URL prefix of generated pages.

Mintlify parses the artifact and generates navigation groups and pages for every class, interface, module, and function in the library.

For more information about generating artifacts and configuring sources, see the [SDK reference setup](/docs/api-playground/sdk-reference-setup).

```json theme={null}
{
  "navigation": {
    "tabs": [
      {
        "tab": "TypeScript SDK",
        "sdk": {
          "format": "typedoc",
          "source": "sdk-artifacts/typedoc.json",
          "directory": "sdk/typescript"
        }
      }
    ]
  }
}
```

## Versions

Partition your navigation into different versions. Versions are selectable from a dropdown menu.

<img alt="Decorative graphic of a version switcher." />

<img alt="Decorative graphic of a version switcher." />

In the `navigation` object, `versions` is an array. Each entry is an object that requires a `version` field and can contain any other navigation fields.

```json theme={null}
{
  "navigation": {
    "versions": [
      {
        "version": "1.0.0",
        "groups": [
          {
            "group": "Getting started",
            "pages": ["v1/overview", "v1/quickstart", "v1/development"]
          }
        ]
      },
      {
        "version": "2.0.0",
        "groups": [
          {
            "group": "Getting started",
            "pages": ["v2/overview", "v2/quickstart", "v2/development"]
          }
        ]
      }
    ]
  }
}
```

### Default version

Mintlify uses the first version in the `versions` array as the default. Use the `default` field to specify a different version as the default.

```json theme={null}
{
  "navigation": {
    "versions": [
      {
        "version": "1.0.0",
        "groups": [
          {
            "group": "Getting started",
            "pages": ["v1/overview", "v1/quickstart"]
          }
        ]
      },
      {
        "version": "2.0.0",
        "default": true,
        "groups": [
          {
            "group": "Getting started",
            "pages": ["v2/overview", "v2/quickstart"]
          }
        ]
      }
    ]
  }
}
```

### Version tags

Add a badge label to version entries in the version selector dropdown using the optional `tag` field. Use tags to highlight specific versions such as "Latest," "Recommended," or "Beta."

```json theme={null}
{
  "navigation": {
    "versions": [
      {
        "version": "2026_03",
        "tag": "Latest",
        "groups": [
          {
            "group": "Getting started",
            "pages": ["getting-started", "quickstart"]
          }
        ]
      },
      {
        "version": "2025_12",
        "tag": "Recommended",
        "groups": [
          {
            "group": "Getting started",
            "pages": ["2025_12/getting-started", "2025_12/quickstart"]
          }
        ]
      },
      {
        "version": "2025_09",
        "tag": "Deprecated",
        "groups": [
          {
            "group": "Getting started",
            "pages": ["2025_09/getting-started", "2025_09/quickstart"]
          }
        ]
      }
    ]
  }
}
```

## Languages

Partition your navigation into different languages. Languages are selectable from a dropdown menu.

<img alt="Decorative graphic of a language switcher." />

<img alt="Decorative graphic of a language switcher." />

In the `navigation` object, `languages` is an array. Each entry is an object that requires a `language` field and can contain any other navigation fields, including language-specific banner, footer, and navbar configurations.

Mintlify supports the following languages for localization:

| Language              | Code      |
| --------------------- | --------- |
| Arabic                | `ar`      |
| Catalan               | `ca`      |
| Chinese               | `cn`      |
| Chinese (Traditional) | `zh-Hant` |
| Czech                 | `cs`      |
| Danish                | `da`      |
| Dutch                 | `nl`      |
| English               | `en`      |
| Finnish               | `fi`      |
| French                | `fr`      |
| German                | `de`      |
| Hebrew                | `he`      |
| Hindi                 | `hi`      |
| Hungarian             | `hu`      |
| Indonesian            | `id`      |
| Italian               | `it`      |
| Japanese              | `jp`      |
| Korean                | `ko`      |
| Latvian               | `lv`      |
| Norwegian             | `no`      |
| Polish                | `pl`      |
| Portuguese (Brazil)   | `pt-BR`   |
| Romanian              | `ro`      |
| Russian               | `ru`      |
| Spanish               | `es`      |
| Swedish               | `sv`      |
| Turkish               | `tr`      |
| Ukrainian             | `uk`      |
| Uzbek                 | `uz`      |
| Vietnamese            | `vi`      |

```json theme={null}
{
  "navigation": {
    "languages": [
      {
        "language": "en",
        "banner": {
          "content": "🚀 Version 2.0 is now live! See our [changelog](/en/changelog) for details.",
          "dismissible": true
        },
        "footer": {
          "socials": {
            "x": "https://x.com/mintlify"
          },
          "links": [
            {
              "header": "Resources",
              "items": [
                { "label": "Documentation", "href": "/en/docs" },
                { "label": "Blog", "href": "https://mintlify.com/blog" }
              ]
            }
          ]
        },
        "navbar": {
          "links": [
            { "label": "Docs", "href": "/en/docs" }
          ],
          "primary": {
            "type": "button",
            "label": "Get Started",
            "href": "/en/quickstart"
          }
        },
        "groups": [
          {
            "group": "Getting started",
            "pages": ["en/overview", "en/quickstart", "en/development"]
          }
        ]
      },
      {
        "language": "es",
        "banner": {
          "content": "🚀 ¡La versión 2.0 ya está disponible! Consulta nuestro [registro de cambios](/es/changelog).",
          "dismissible": true
        },
        "footer": {
          "socials": {
            "x": "https://x.com/mintlify"
          },
          "links": [
            {
              "header": "Recursos",
              "items": [
                { "label": "Documentación", "href": "/es/docs" },
                { "label": "Blog", "href": "https://mintlify.com/blog" }
              ]
            }
          ]
        },
        "navbar": {
          "links": [
            { "label": "Documentación", "href": "/es/docs" }
          ],
          "primary": {
            "type": "button",
            "label": "Comenzar",
            "href": "/es/quickstart"
          }
        },
        "groups": [
          {
            "group": "Getting started",
            "pages": ["es/overview", "es/quickstart", "es/development"]
          }
        ]
      }
    ]
  }
}
```

For automated translations, [set up an automation](/docs/automations) to run the agent on a schedule or in response to repository pushes.

### Route visitors to their preferred language

If you publish in multiple languages, you can redirect visitors from the root of your site to the language that matches their browser's `Accept-Language` header.

1. Navigate to the [Add-ons](https://app.mintlify.com/settings/deployment/addons) page in your dashboard.
2. Enable **Auto-route to preferred language**.

If a visitor selects a language with the language switcher, Mintlify remembers their choice and stops auto-routing them. If no published language matches the visitor's browser preferences, Mintlify serves your default language.

## Nesting

You can nest navigation elements within each other to create complex hierarchies. You must have one root-level parent navigation element such as tabs, groups, or a dropdown. You can nest other types of navigation elements within your primary navigation pattern.

Each navigation element can contain one type of child element at each level of your navigation hierarchy. For example, a tab can contain anchors that contain groups, but a tab cannot contain both anchors and groups at the same level.

Mixing incompatible child types at the same level fails schema validation. Run [`mint validate`](/docs/cli/commands#mint-validate) locally before publishing to catch these errors.

<CodeGroup>
  ```json Tabs containing anchors theme={null}
  {
    "navigation": {
      "tabs": [
        {
          "tab": "Documentation",
          "anchors": [
            {
              "anchor": "Guides",
              "icon": "book-open",
              "pages": ["quickstart", "tutorial"]
            },
            {
              "anchor": "API Reference",
              "icon": "code",
              "pages": ["api/overview", "api/endpoints"]
            }
          ]
        },
        {
          "tab": "Resources",
          "groups": [
            {
              "group": "Help",
              "pages": ["support", "faq"]
            }
          ]
        }
      ]
    }
  }
  ```

  ```json Anchors containing tabs theme={null}
  {
    "navigation": {
      "anchors": [
        {
          "anchor": "Documentation",
          "icon": "book-open",
          "tabs": [
            {
              "tab": "Guides",
              "pages": ["quickstart", "tutorial"]
            },
            {
              "tab": "API",
              "pages": ["api/overview", "api/endpoints"]
            }
          ]
        },
        {
          "anchor": "Community",
          "icon": "users",
          "href": "https://community.example.com"
        }
      ]
    }
  }
  ```

  ```json Products containing tabs theme={null}
  {
    "navigation": {
      "products": [
        {
          "product": "Platform",
          "icon": "server",
          "tabs": [
            {
              "tab": "Documentation",
              "groups": [
                {
                  "group": "Getting started",
                  "pages": ["platform/quickstart"]
                }
              ]
            },
            {
              "tab": "API Reference",
              "pages": ["platform/api"]
            }
          ]
        },
        {
          "product": "Mobile SDK",
          "icon": "mobile",
          "pages": ["mobile/overview"]
        }
      ]
    }
  }
  ```

  ```json Multi-product SaaS with tabs and menu theme={null}
  {
    "navigation": {
      "products": [
        {
          "product": "Platform",
          "icon": "cloud",
          "tabs": [
            {
              "tab": "Documentation",
              "menu": [
                {
                  "item": "Getting Started",
                  "icon": "rocket",
                  "groups": [
                    {
                      "group": "Setup",
                      "pages": ["platform/install", "platform/config"]
                    },
                    {
                      "group": "Core Concepts",
                      "pages": ["platform/concepts/auth", "platform/concepts/data"]
                    }
                  ]
                },
                {
                  "item": "Guides",
                  "icon": "book",
                  "pages": ["platform/guides/deployment", "platform/guides/scaling"]
                }
              ]
            },
            {
              "tab": "API Reference",
              "groups": [
                {
                  "group": "REST API",
                  "pages": ["platform/api/users", "platform/api/projects"]
                },
                {
                  "group": "GraphQL",
                  "pages": ["platform/api/graphql/queries", "platform/api/graphql/mutations"]
                }
              ]
            }
          ]
        },
        {
          "product": "Analytics",
          "icon": "chart-bar",
          "tabs": [
            {
              "tab": "Documentation",
              "groups": [
                {
                  "group": "Getting Started",
                  "pages": ["analytics/quickstart", "analytics/setup"]
                }
              ]
            },
            {
              "tab": "API",
              "pages": ["analytics/api/events", "analytics/api/reports"]
            }
          ]
        }
      ]
    }
  }
  ```

  ```json Versioned docs with tabs theme={null}
  {
    "navigation": {
      "versions": [
        {
          "version": "v2.0",
          "tabs": [
            {
              "tab": "Documentation",
              "groups": [
                {
                  "group": "Getting Started",
                  "pages": ["v2/quickstart", "v2/migration-from-v1"]
                },
                {
                  "group": "Features",
                  "pages": ["v2/features/auth", "v2/features/api"]
                }
              ]
            },
            {
              "tab": "API Reference",
              "pages": ["v2/api/overview", "v2/api/endpoints"]
            }
          ]
        },
        {
          "version": "v1.0",
          "tabs": [
            {
              "tab": "Documentation",
              "groups": [
                {
                  "group": "Getting Started",
                  "pages": ["v1/quickstart"]
                }
              ]
            },
            {
              "tab": "API Reference",
              "pages": ["v1/api/overview"]
            }
          ]
        }
      ]
    }
  }
  ```
</CodeGroup>

## Breadcrumbs

Breadcrumbs display the full navigation path at the top of pages. Some themes have breadcrumbs enabled by default and others do not. You can control whether breadcrumbs display on your site using the `styling` property in your `docs.json`.

<CodeGroup>
  ```json Display full breadcrumbs theme={null}
  "styling": {
    "eyebrows": "breadcrumbs"
  }
  ```

  ```json Display parent section only theme={null}
  "styling": {
    "eyebrows": "section"
  }
  ```
</CodeGroup>

## Interaction configuration

Control how users interact with navigation elements using the `interaction` property in your `docs.json`.

### Enable auto-navigation for groups

When a user expands a navigation group, some themes automatically navigate to the first page in the group. You can override a theme's default behavior using the `drilldown` option.

* Set to `true` to force automatic navigation to the first page when a user selects a navigation group.
* Set to `false` to prevent navigation and only expand or collapse the group when a user selects a navigation group.
* Leave unset to use the theme's default behavior.

<CodeGroup>
  ```json Force navigation theme={null}
  "interaction": {
    "drilldown": true  // Force navigation to first page when a user expands a dropdown
  }
  ```

  ```json Prevent navigation theme={null}
  "interaction": {
    "drilldown": false // Never navigate, only expand or collapse the group
  }
  ```
</CodeGroup>


# Pages
Source: https://www.mintlify.com/docs/organize/pages

Configure page metadata, titles, descriptions, icons, and layout modes using YAML frontmatter properties at the top of your MDX documentation.

Each page is a Markdown file. You can use either `.mdx` or `.md` file types for your pages. Use MDX, which combines Markdown with React components for rich, interactive documentation. Plain Markdown (`.md`) can expedite migration from other platforms, but switching to MDX enables more features.

## Page metadata

Every page begins with frontmatter, the YAML metadata enclosed by `---` at the top of a file. This metadata controls how your page appears and behaves.

All frontmatter fields are optional. If you omit `title`, Mintlify generates one from the file path. You can skip the frontmatter block entirely on pages that don't need custom metadata.

Use frontmatter to control:

* Page titles and descriptions
* Sidebar titles, icons, and tags
* Page layouts
* SEO meta tags
* Custom metadata

<ResponseField name="title" type="string">
  The title of your page that appears in navigation and browser tabs.

  If omitted, Mintlify generates a title from the path. The last segment of the path becomes the title, with dashes and underscores replaced by spaces and the first letter capitalized. For example, `guides/getting-started.md` becomes **Getting started**.
</ResponseField>

<ResponseField name="description" type="string">
  A brief description of what this page covers. Displays under the title and improves SEO.
</ResponseField>

<ResponseField name="sidebarTitle" type="string">
  A short title that displays in the sidebar navigation.
</ResponseField>

<ResponseField name="icon" type="string">
  The icon to display.

  Options:

  * [Font Awesome icon](https://fontawesome.com/icons) name
  * [Lucide icon](https://lucide.dev/icons) name
  * [Tabler icon](https://tabler.io/icons) name
  * URL to an externally hosted icon
  * Path to an icon file in your project
</ResponseField>

<ResponseField name="iconType" type="string">
  For [Font Awesome](https://fontawesome.com/icons) icons only. The style of the icon.

  Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
</ResponseField>

<ResponseField name="tag" type="string">
  A tag that appears next to your page title in the sidebar.
</ResponseField>

<ResponseField name="hidden" type="boolean">
  Set to `true` to remove the page from the sidebar navigation. Users can still access the page via its URL, but search engines do not index it. To make a page visible again, remove this field entirely. **Do not** set to `false` as it results in undefined behavior. See [Hidden pages](/docs/organize/hidden-pages) for details.
</ResponseField>

<ResponseField name="noindex" type="boolean">
  Set to `true` to exclude the page from site search, sitemaps, search engine indexing, and AI assistant context. The page remains visible in navigation. See [Disable indexing](/docs/optimize/seo#disable-indexing) for details. All pages with `hidden: true` in their frontmatter receive `noindex: true` automatically.
</ResponseField>

<ResponseField name="searchable" type="boolean">
  Defaults to `true`. Pages are searchable unless you opt out. Set to `false` to exclude the page from your documentation site's search results and the AI assistant context. The page stays indexable by external search engines, listed in your sitemap, and visible in navigation. See [Exclude a page from search](/docs/optimize/search#exclude-a-page-from-search) for details.
</ResponseField>

<ResponseField name="boost" type="number">
  Multiply the page's in-product search ranking by this factor. Use values greater than `1` to prioritize the page and values between `0` and `1` to de-prioritize it. See [Search](/docs/optimize/search#boost-search-ranking) for details. `boost` has no effect when `searchable: false`, since the page doesn't appear in in-product search results.
</ResponseField>

<ResponseField name="deprecated" type="boolean">
  Set to `true` to display a "deprecated" label next to the page title. Use this to mark outdated content or legacy features while keeping the page accessible.
</ResponseField>

<ResponseField name="hideFooterPagination" type="boolean">
  Set to `true` to hide the previous/next page navigation links at the bottom of the page. Use this for standalone pages like landing pages or reference pages where sequential navigation does not apply.
</ResponseField>

<ResponseField name="related" type="array or boolean">
  A list of related pages to show in the **Related topics** section at the bottom of the page, or `false` to hide the section entirely. Overrides the deployment's automatic suggestions. Requires enabling the [Related pages](/docs/organize/related-pages) add-on.
</ResponseField>

<ResponseField name="hideApiMarker" type="boolean">
  Set to `true` to hide the HTTP method badge (such as GET or POST) next to the page title in the sidebar. Use this for API pages where you want a cleaner sidebar appearance.
</ResponseField>

<ResponseField name="contextual" type="object">
  Override the site-wide [contextual menu](/docs/ai/contextual-menu) for this page. Accepts the same `options` array and `display` value as the `contextual` field in `docs.json`. Omit the field to inherit the global configuration, or set `options: []` to disable the contextual menu on this page.
</ResponseField>

<ResponseField name="groups" type="string[]">
  Restrict the page to users in specific groups. Users must belong to at least one listed group to access the page. You must configure [authentication](/docs/deploy/authentication-setup) first. See [Control access with groups](/docs/deploy/authentication-setup#control-access-with-groups) for more information.
</ResponseField>

<ResponseField name="<custom>" type="string">
  Any valid YAML frontmatter. For example, `product: "API"` or `version: "1.0.0"`.
</ResponseField>

```yaml Example YAML frontmatter wrap theme={null}
---
title: "About frontmatter"
description: "Frontmatter is the metadata that controls how your page appears and behaves"
sidebarTitle: "Frontmatter"
icon: "book"
tag: "NEW"
---
```

## Page mode

Control your page's layout with the `mode` setting.

### Default

If you do not define a mode, the page uses a standard layout with sidebar navigation and table of contents.

```yaml theme={null}
---
title: "Default page title"
---
```

### Wide

Wide mode hides the side panel, which includes the table of contents, `<Panel>` components, and API request and response examples. Use this mode for pages without headings or if you want extra horizontal space. Every theme supports wide mode.

```yaml theme={null}
---
title: "Wide page title"
mode: "wide"
---
```

### Custom

Custom mode provides a minimalist layout and removes all elements except for the top navbar. This mode hides the sidebar, table of contents, and footer. Treat custom mode as a blank canvas to build landing pages or unique layouts with minimal navigation. All themes support custom mode.

```yaml theme={null}
---
title: "Custom page title"
mode: "custom"
---
```

<Warning>
  The `style` property may cause a layout shift on page load. Prefer [Tailwind CSS or custom CSS](/docs/customize/custom-scripts) to avoid this issue.
</Warning>

### Frame

Frame mode provides a layout similar to custom mode but keeps the sidebar navigation. Use this mode to include custom HTML and components while preserving the default navigation experience. Aspen, Almond, Luma, and Sequoia themes support frame mode.

```yaml theme={null}
---
title: "Frame page title"
mode: "frame"
---
```

### Center

Center mode removes the sidebar and table of contents, and centers the content. Use center mode for changelogs or other pages where you want to place focus on the content. Mint, Linden, Willow, and Maple themes support center mode.

```yaml theme={null}
---
title: "Center page title"
mode: "center"
---
```

### Assistant

Assistant mode renders the page as a full-screen [assistant](/docs/assistant) experience. A chat interface replaces all page content. Use this mode to create a dedicated page for users to interact with the assistant, such as an "Ask AI" page. Every theme supports assistant mode.

To use assistant mode, you must enable the [assistant](/docs/assistant) on your deployment. If you don't enable the assistant, the assistant page mode shows a disabled search field.

```yaml theme={null}
---
title: "Ask AI"
description: "Ask questions about how to get started and use the product"
mode: "assistant"
---
```

## API pages

To create an interactive API playground, add an API specification to your frontmatter by setting `api` or `openapi`.

```yaml theme={null}
---
openapi: "GET /endpoint"
---
```

Learn more about building [API documentation](/docs/api-playground/overview).

## External links

Link to external sites directly from your navigation with the `url` metadata.

```yaml theme={null}
---
title: "npm Package"
url: "https://www.npmjs.com/package/mint"
---
```

## Search engine optimization

Mintlify automatically generates most SEO meta tags. You can set SEO meta tags manually to customize your approach to SEO, social sharing, and browser compatibility.

<Note>
  Always wrap meta tags with colons in quotes.
</Note>

```yaml theme={null}
---
"twitter:image": "/images/social-preview.jpg"
---
```

See [SEO](/docs/optimize/seo) for the full list of SEO metadata options.

## Internal search keywords

Help users discover a specific page in search results by providing `keywords` in your metadata. These keywords don't appear in page content. If users search for the keywords, the page appears in the search results.

```yaml theme={null}
---
keywords: ['configuration', 'setup', 'getting started']
---
```

## Last modified timestamp

To display a "Last modified on \[date]" timestamp on all pages, enable `metadata.timestamp` in your [global settings](/docs/organize/settings-seo#metadata). This timestamp uses the date of the last Git commit that modified the page's source file.

```json docs.json theme={null}
"metadata": {
  "timestamp": true
}
```

To override the global timestamp setting for an individual page, use the `timestamp` frontmatter field. Use this field to show or hide timestamps on specific pages.

```yaml theme={null}
---
title: "Page title"
timestamp: false
---
```

If you set `timestamp: true`, the page always shows the timestamp even if the global setting is `false`. If you set `timestamp: false`, the page hides the timestamp even if the global setting is `true`.

To display a specific date instead of the Git commit date for an individual page, use the `lastUpdatedDate` frontmatter field. Use this field when your Git history doesn't reflect when the content changed, such as content imported or synced from another system. Use a date-only value or an ISO 8601 timestamp.

```yaml theme={null}
---
title: "Page title"
lastUpdatedDate: "2026-08-13"
---
```

Mintlify determines the displayed date in the following order:

1. The `lastUpdatedDate` frontmatter field, if set on the page.
2. For deployments backed by Git, the date of the last commit that modified the page's source file.
3. The most recent deployment timestamp.


# Related topics
Source: https://www.mintlify.com/docs/organize/related-pages

Add a related topics section at the bottom of each page using automatic recommendations or manually curated links defined in page frontmatter.

Add related topics to the bottom of each page to help readers discover relevant content. Suggested pages can come from automated recommendations, links you curate in page frontmatter, or both.

## Enable related topics

1. Navigate to the [Add-ons](https://app.mintlify.com/settings/deployment/addons) page in your dashboard.
2. In the "Related topics" section, enable **Show related topics**.
3. Select a mode and, optionally, set a limit on how many pages to show.

## Modes

<ResponseField name="Automatic" type="mode">
  Mintlify generates suggestions from your contents' search index using the current page's title. Frontmatter overrides still take precedence over automatic suggestions. Use this mode when you want related pages to update automatically as you add content.
</ResponseField>

<ResponseField name="Manual" type="mode">
  Only pages listed in a page's `related` frontmatter are shown. Pages without a `related` field display no **Related topics** section. Use this mode when you want full editorial control.
</ResponseField>

### Limit

Set how many related pages to display. The default is `5` and the maximum is `10`.

## Configure per page with frontmatter

Use the `related` frontmatter field to override or supply the list of related pages for a single page. This works in both **Automatic** and **Manual** modes.

<ResponseField name="related" type="array | false">
  A list of related pages, or `false` to hide the **Related topics** section on this page.

  Each entry can be:

  * A root-relative path to another page in your docs: `/api-playground/overview`
  * An absolute URL to an external site: `https://example.com/docs`
  * A `Title: link` object to set an explicit label

  If you don't explicitly set titles and icons for internal paths, Mintlify infers them. External links open in a new tab.
</ResponseField>

### Examples

Curate a list of internal pages:

```mdx theme={null}
---
title: "Authentication"
related:
  - /api-playground/overview
  - /deploy/authentication-setup
  - /organize/hidden-pages
---
```

Mix internal pages, external links, and custom titles:

```mdx theme={null}
---
title: "Authentication"
related:
  - Overview: /api-playground/overview
  - Set up auth: /deploy/authentication-setup
  - OAuth 2.0 spec: https://oauth.net/2/
---
```

Hide the **Related topics** section on a specific page:

```mdx theme={null}
---
title: "Changelog"
related: false
---
```

## How suggestions are generated

In **Automatic** mode, Mintlify generates related pages from your docs' search index using the current page's title as the query. It filters results by the page's language and version when applicable, and excludes the current page.

For deployments with [end-user authentication](/docs/deploy/authentication-setup), Mintlify disables automatic suggestions to avoid leaking content across user contexts. Use the `related` frontmatter field to show curated suggestions on user-authenticated deployments.


# Global settings
Source: https://www.mintlify.com/docs/organize/settings

Configure your Mintlify documentation site with docs.json, the required configuration file that controls navigation, appearance, integrations, and more.

The `docs.json` file is the central configuration file for your Mintlify documentation site. It controls your site's global settings, including visual branding, navigation structure, integrations, API settings, and more. Think of it as the blueprint for your site.

## File location

Store your `docs.json` file at the root of your documentation repository. If you have a monorepo, store your `docs.json` at the root of your documentation directory.

## Required fields

You must define four fields to build a working site.

| Field            | Description                                         |
| ---------------- | --------------------------------------------------- |
| `name`           | Your project or organization name                   |
| `theme`          | The layout [theme](/docs/customize/themes) for your site |
| `colors.primary` | Primary brand color as a hex code                   |
| `navigation`     | Your content structure                              |

All other fields are optional. Add them as you customize and refine your site.

## Minimal configuration

For the best editing experience, include the `$schema` reference at the top of your `docs.json`. This enables autocomplete, validation, and inline documentation in most editors.

```json docs.json theme={null}
{
  "$schema": "https://mintlify.com/docs.json",
  "theme": "mint",
  "name": "Your project name",
  "colors": {
    "primary": "#ff0000"
  },
  "navigation": {
    "groups": [
      {
        "group": "Home",
        "pages": ["index"]
      }
    ]
  }
}
```

## Settings

<CardGroup>
  <Card title="Appearance and branding" icon="palette" href="/organize/settings-appearance">
    Customize the visual appearance of your site including theme, colors, logo, favicon, fonts, and background.
  </Card>

  <Card title="Site structure" icon="layout-panel-left" href="/organize/settings-structure">
    Design the information architecture and user experience (UX) of your site, including the navbar, footer, banner, navigation, and redirects.
  </Card>

  <Card title="API settings" icon="square-terminal" href="/organize/settings-api">
    Control the display and behavior of API documentation including OpenAPI and AsyncAPI specs, API playground, and code examples.
  </Card>

  <Card title="Integrations" icon="plug" href="/organize/settings-integrations">
    Connect your site to third-party services for analytics, chat, and more.
  </Card>

  <Card title="SEO & search" icon="search" href="/organize/settings-seo">
    Control how search engines index your site including meta tags, search, and page timestamps.
  </Card>

  <Card title="Schema reference" icon="code" href="/organize/settings-reference">
    Complete reference for all `docs.json` properties.
  </Card>
</CardGroup>

## Split configuration with `$ref`

As your configuration grows, you can break `docs.json` into smaller files using `$ref` references. Each reference points to a separate JSON file that gets resolved at build time.

Add a `$ref` property with a relative file path anywhere in your `docs.json`. Mintlify replaces the `$ref` object with the contents of the referenced file.

```json docs.json theme={null}
{
  "$schema": "https://mintlify.com/docs.json",
  "theme": "mint",
  "name": "Acme Docs",
  "colors": {
    "primary": "#1a73e8"
  },
  "navigation": {
    "$ref": "./config/navigation.json"
  }
}
```

```json config/navigation.json theme={null}
{
  "groups": [
    {
      "group": "Get started",
      "pages": ["index", "quickstart"]
    },
    {
      "group": "Guides",
      "pages": ["guides/first-steps", "guides/advanced"]
    }
  ]
}
```

* Referenced files can contain their own `$ref` references. Nested paths resolve relative to the file that contains them, not relative to `docs.json`.
* References must point to valid JSON files.
* Paths must be relative and stay within the project root. Path traversal (for example, `../../outside`) is not allowed.
* Circular references cause a build error.

### Merge sibling keys

When a `$ref` resolves to an object, Mintlify merges sibling keys from the same block on top of the referenced content. These keys take precedence over matching keys in the reference. When a `$ref` resolves to a non-object value such as an array, Mintlify ignores any sibling keys.

```json docs.json theme={null}
{
  "appearance": {
    "$ref": "./config/appearance.json",
    "strict": true
  }
}
```

## Upgrade from `mint.json`

If your project uses the deprecated `mint.json` file, use the [CLI](/docs/cli) to upgrade to `docs.json`.

<Steps>
  <Step title="Install or update the CLI">
    If you haven't installed the [CLI](/docs/cli/install), install it now:

    <CodeGroup>
      ```bash npm theme={null}
      npm i -g mint
      ```

      ```bash yarn theme={null}
      yarn global add mint
      ```

      ```bash pnpm theme={null}
      pnpm add -g mint
      ```
    </CodeGroup>

    If you already have the CLI installed, make sure it is up to date:

    ```bash theme={null}
    mint update
    ```
  </Step>

  <Step title="Create your docs.json file">
    In your docs repository, run:

    ```bash theme={null}
    mint dev
    ```

    This command creates a `docs.json` file from your existing `mint.json`. Review the generated file to ensure all settings are correct.
  </Step>

  <Step title="Delete your mint.json file">
    After verifying your `docs.json` is configured correctly, you can safely delete your old `mint.json` file.
  </Step>
</Steps>


# API settings
Source: https://www.mintlify.com/docs/organize/settings-api

Configure OpenAPI and AsyncAPI specs, the interactive API playground, SDK code examples, and authentication settings in your docs.json file.

Use the `api` field in `docs.json` to configure what API specifications generate API pages, the interactive API playground for testing endpoints, and how to generate and display code examples.

## Settings

### `api`

**Type:** `object`

Define all API-related settings under the `api` key.

<ResponseField name="api.openapi" type="string or array or object">
  OpenAPI specification files for generating API reference pages. Accepts a single path or URL, an array of paths and URLs, or an object specifying a source and directory.

  <Expandable title="api.openapi object">
    <ResponseField name="source" type="string">
      URL or path to your OpenAPI specification file. Minimum length: 1.
    </ResponseField>

    <ResponseField name="directory" type="string">
      Directory to search for OpenAPI files. Do not include a leading slash.
    </ResponseField>
  </Expandable>

  <CodeGroup>
    ```json Single file theme={null}
    "openapi": "openapi.json"
    ```

    ```json Multiple files theme={null}
    "openapi": [
      "openapi/v1.json",
      "openapi/v2.json",
      "https://api.example.com/openapi.yaml"
    ]
    ```

    ```json Directory theme={null}
    "openapi": {
      "source": "openapi.json",
      "directory": "api-reference"
    }
    ```
  </CodeGroup>
</ResponseField>

<ResponseField name="api.asyncapi" type="string or array or object">
  AsyncAPI specification files for generating event-driven API reference pages. Accepts a single path or URL, an array of paths and URLs, or an object specifying a source and directory.

  <Expandable title="api.asyncapi object">
    <ResponseField name="source" type="string">
      URL or path to your AsyncAPI specification file. Minimum length: 1.
    </ResponseField>

    <ResponseField name="directory" type="string">
      Directory to search for AsyncAPI files. Do not include a leading slash.
    </ResponseField>
  </Expandable>

  <CodeGroup>
    ```json Single file theme={null}
    "asyncapi": "asyncapi.json"
    ```

    ```json Multiple files theme={null}
    "asyncapi": [
      "asyncapi/events.yaml",
      "asyncapi/webhooks.yaml"
    ]
    ```

    ```json Directory theme={null}
    "asyncapi": {
      "source": "asyncapi.json",
      "directory": "websockets"
    }
    ```
  </CodeGroup>
</ResponseField>

<ResponseField name="api.playground" type="object">
  Interactive API playground settings.

  <Expandable title="api.playground">
    <ResponseField name="display" type="&#x22;interactive&#x22; | &#x22;simple&#x22; | &#x22;none&#x22; | &#x22;auth&#x22;">
      The display mode for the playground. Defaults to `interactive`.

      * `interactive` — Full interactive playground with request builder
      * `simple` — Simplified view without the request builder
      * `none` — Hide the playground entirely
      * `auth` — Show the playground only to authenticated users
    </ResponseField>

    <ResponseField name="proxy" type="boolean">
      Whether to route API requests through a proxy server. Defaults to `true`.
    </ResponseField>

    <ResponseField name="credentials" type="boolean">
      Whether to include cookies and authentication headers for cross-origin requests when `proxy` is `false`. Defaults to `false`. Has no effect when `proxy` is `true`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="api.params" type="object">
  Display settings for API parameters.

  <Expandable title="api.params">
    <ResponseField name="expanded" type="&#x22;all&#x22; | &#x22;closed&#x22;">
      Whether to expand all parameters by default. Defaults to `closed`.
    </ResponseField>

    <ResponseField name="post" type="array of string">
      OpenAPI spec field keys to surface as post pills next to every parameter name in API reference pages and the playground. For each key you list, Mintlify reads the value from the schema and renders it as a pill:

      * String values render as the verbatim string.
      * `true` renders the key name as the pill label. `false`, `null`, and empty strings render nothing.
      * Number values render the stringified number.
      * Arrays of strings or numbers render one pill per element.
      * Objects and other values are skipped.

      Use this to expose custom OpenAPI fields—such as `x-internal`, `nullable`, or vendor extensions—as visual annotations on each parameter without per-property configuration.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="api.url" type="&#x22;full&#x22;">
  Display mode for the base URL in the endpoint header. Set to `full` to always show the complete base URL on every endpoint page. By default, the base URL is only shown when there are multiple base URLs to select from.
</ResponseField>

<ResponseField name="api.examples" type="object">
  Settings for autogenerated API code examples.

  <Expandable title="api.examples">
    <ResponseField name="languages" type="array of string">
      Languages for autogenerated code snippets. See [supported languages](/docs/api-playground/overview#all-supported-languages) for the full list of available languages and aliases.
    </ResponseField>

    <ResponseField name="defaults" type="&#x22;required&#x22; | &#x22;all&#x22;">
      Whether to include optional parameters in generated examples. Defaults to `all`.
    </ResponseField>

    <ResponseField name="prefill" type="boolean">
      Whether to prefill the playground with example values from your OpenAPI specification. Defaults to `false`.
    </ResponseField>

    <ResponseField name="autogenerate" type="boolean">
      Whether to generate code samples for endpoints from your API specification. Defaults to `true`. When set to `false`, only manually written code samples (from `x-codeSamples` in OpenAPI or `<RequestExample>` components in MDX) appear in the playground.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="api.mdx" type="object">
  Settings for API pages built from MDX files rather than OpenAPI specs.

  <Expandable title="api.mdx">
    <ResponseField name="auth" type="object">
      Authentication configuration for MDX-based API requests.

      <Expandable title="auth">
        <ResponseField name="method" type="&#x22;bearer&#x22; | &#x22;basic&#x22; | &#x22;key&#x22; | &#x22;cobo&#x22;">
          Authentication method for API requests.
        </ResponseField>

        <ResponseField name="name" type="string">
          Authentication parameter name for API requests.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="server" type="string or array">
      Base URL prepended to relative paths in page-level `api` frontmatter fields. Not used when the frontmatter contains a full URL.
    </ResponseField>
  </Expandable>
</ResponseField>

## Example

```json docs.json theme={null}
{
  "api": {
    "openapi": ["openapi/v1.json", "openapi/v2.json"],
    "playground": {
      "display": "interactive"
    },
    "params": {
      "expanded": "all",
      "post": ["nullable", "x-internal"]
    },
    "url": "full",
    "examples": {
      "languages": ["curl", "python", "javascript", "go"],
      "defaults": "required",
      "prefill": true,
      "autogenerate": true
    }
  }
}
```


# Appearance and branding
Source: https://www.mintlify.com/docs/organize/settings-appearance

Configure theme, colors, logo, favicon, fonts, and background in docs.json to control the visual identity of your documentation site.

Use these `docs.json` settings to control your documentation site's visual identity—layout theme, brand colors, logo, typography, and background.

## Settings

### `theme` - <Badge>required</Badge>

The layout theme for your site.

One of: `mint`, `maple`, `palm`, `willow`, `linden`, `almond`, `aspen`, `sequoia`, `luma`.

See [Themes](/docs/customize/themes) for previews and details.

***

### `name` - <Badge>required</Badge>

**Type:** `string`

The name of your project, organization, or product. Appears in the browser tab title and other places throughout your site.

***

### `colors` - <Badge>required</Badge>

**Type:** `object`

The colors used in your documentation. Colors appear differently across themes. If you only provide a primary color, it applies to all color elements.

<ResponseField name="colors.primary" type="string">
  The primary color for your documentation. Generally used for emphasis in light mode, with some variation by theme.

  Must be a hex code beginning with `#`. Example: `"#0D9373"`.
</ResponseField>

<ResponseField name="colors.light" type="string">
  The color used for emphasis in dark mode.

  Must be a hex code beginning with `#`.
</ResponseField>

<ResponseField name="colors.dark" type="string">
  The color used for buttons and hover states across both light and dark modes, with some variation by theme.

  Must be a hex code beginning with `#`.
</ResponseField>

```json docs.json theme={null}
"colors": {
  "primary": "#0D9373",
  "light": "#55D799",
  "dark": "#0D9373"
}
```

***

### `logo`

**Type:** `string` or `object`

Your site logo. Provide a single image path or separate images for light and dark mode.

<ResponseField name="logo.light" type="string">
  Path to your logo file for light mode. Include the file extension. Example: `/logo/light.svg`.
</ResponseField>

<ResponseField name="logo.dark" type="string">
  Path to your logo file for dark mode. Include the file extension. Example: `/logo/dark.svg`.
</ResponseField>

<ResponseField name="logo.href" type="string (uri)">
  The URL to redirect to when clicking the logo. If not provided, the logo links to the first page of the currently selected locale for [internationalized docs](/docs/guides/internationalization), or to your homepage for single-language sites. Example: `https://yoursite.com`.
</ResponseField>

```json docs.json theme={null}
"logo": {
  "light": "/logo/light.svg",
  "dark": "/logo/dark.svg",
  "href": "https://yoursite.com"
}
```

***

### `favicon`

**Type:** `string` or `object`

Path to your favicon file, including the file extension. Automatically resized to appropriate favicon sizes. Provide a single file or separate files for light and dark mode.

<ResponseField name="favicon.light" type="string">
  Path to your favicon for light mode. Include the file extension. Example: `/favicon.png`.
</ResponseField>

<ResponseField name="favicon.dark" type="string">
  Path to your favicon for dark mode. Include the file extension. Example: `/favicon-dark.png`.
</ResponseField>

```json docs.json theme={null}
"favicon": "/favicon.svg"
```

***

### `appearance`

**Type:** `object`

Light/dark mode settings.

<ResponseField name="appearance.default" type="&#x22;system&#x22; | &#x22;light&#x22; | &#x22;dark&#x22;">
  Default color mode. Choose `system` to match the user's OS setting, or `light` or `dark` to force a specific mode. Defaults to `system`.
</ResponseField>

<ResponseField name="appearance.strict" type="boolean">
  When `true`, hides the light/dark mode toggle so users cannot switch modes. Defaults to `false`.
</ResponseField>

```json docs.json theme={null}
"appearance": {
  "default": "dark",
  "strict": true
}
```

***

### `fonts`

**Type:** `object`

Custom fonts for your documentation. The default font varies by theme. Supports [Google Fonts](https://fonts.google.com) and self-hosted fonts.

<ResponseField name="fonts.family" type="string">
  Font family name, such as `"Inter"` or `"Open Sans"`. Supports [Google Fonts](https://fonts.google.com) family names—these load automatically without a `source` required.
</ResponseField>

<ResponseField name="fonts.weight" type="number">
  Font weight, such as `400` or `700`. Variable fonts support fractional weights such as `550`.
</ResponseField>

<ResponseField name="fonts.source" type="string (uri)">
  URL to a hosted font or a path to a local font file. Not needed for Google Fonts.

  * Hosted: `https://example.com/fonts/MyFont.woff2`
  * Local: `/fonts/MyFont.woff2`
</ResponseField>

<ResponseField name="fonts.format" type="&#x22;woff&#x22; | &#x22;woff2&#x22;">
  Font file format. Required when using the `source` field.
</ResponseField>

<ResponseField name="fonts.heading" type="object">
  Override font settings for headings only.

  Accepts the same `family`, `weight`, `source`, and `format` fields as the top-level `fonts` object.
</ResponseField>

<ResponseField name="fonts.body" type="object">
  Override font settings for body text only.

  Accepts the same `family`, `weight`, `source`, and `format` fields as the top-level `fonts` object.
</ResponseField>

```json docs.json theme={null}
"fonts": {
  "family": "Inter",
  "heading": {
    "family": "Playfair Display"
  }
}
```

***

### `icons`

**Type:** `object`

Icon library settings. You can only use one icon library per project. All icon names in your docs must come from the selected library.

<ResponseField name="icons.library" type="&#x22;fontawesome&#x22; | &#x22;lucide&#x22; | &#x22;tabler&#x22;">
  Icon library to use throughout your documentation. Defaults to `fontawesome`.

  <Note>
    You can specify a URL to an externally hosted icon or a path to an icon file in your project for any individual icon, regardless of the library setting.
  </Note>
</ResponseField>

```json docs.json theme={null}
"icons": {
  "library": "lucide"
}
```

***

### `background`

**Type:** `object`

Background image, decoration, and color settings.

<ResponseField name="background.decoration" type="&#x22;gradient&#x22; | &#x22;grid&#x22; | &#x22;windows&#x22;">
  A decorative background pattern for your theme.
</ResponseField>

<ResponseField name="background.color" type="object">
  Custom background colors for light and dark modes.

  <Expandable title="background.color">
    <ResponseField name="light" type="string">
      Background color for light mode. Must be a hex code beginning with `#`.
    </ResponseField>

    <ResponseField name="dark" type="string">
      Background color for dark mode. Must be a hex code beginning with `#`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="background.image" type="string or object">
  Background image for your site. Provide a single path or separate paths for light and dark mode.

  <Expandable title="background.image">
    <ResponseField name="light" type="string">
      Path to your background image for light mode. Example: `/background.png`.
    </ResponseField>

    <ResponseField name="dark" type="string">
      Path to your background image for dark mode. Example: `/background-dark.png`.
    </ResponseField>
  </Expandable>
</ResponseField>

```json docs.json theme={null}
"background": {
  "decoration": "gradient",
  "color": {
    "light": "#F8FAFC",
    "dark": "#0F172A"
  }
}
```

***

### `styling`

**Type:** `object`

Fine-grained visual styling controls.

<ResponseField name="styling.eyebrows" type="&#x22;section&#x22; | &#x22;breadcrumbs&#x22;">
  The style of the page eyebrow (the label shown at the top of the page). Choose `section` to show the section name or `breadcrumbs` to show the full navigation path. Defaults to `section`.
</ResponseField>

<ResponseField name="styling.latex" type="boolean">
  Controls whether LaTeX stylesheets load. By default, Mintlify automatically detects LaTeX usage in your content and loads the necessary stylesheets.

  * Set to `true` to force-load LaTeX stylesheets when auto-detection fails.
  * Set to `false` to prevent loading LaTeX stylesheets for better performance if you don't use math expressions.
</ResponseField>

<ResponseField name="styling.codeblocks" type="&#x22;system&#x22; | &#x22;dark&#x22; | string | object">
  Code block theme. Defaults to `"system"`.

  * `"system"`: Matches the current site mode (light or dark)
  * `"dark"`: Always uses dark mode
  * A [Shiki theme](https://shiki.style/themes) name string: applies that theme to all code blocks
  * An object with `light` and `dark` keys: applies separate Shiki themes per mode

  <Expandable title="styling.codeblocks object">
    <ResponseField name="theme" type="string">
      A single Shiki theme for both modes.

      ```json theme={null}
      "styling": {
        "codeblocks": {
          "theme": "dracula"
        }
      }
      ```
    </ResponseField>

    <ResponseField name="theme" type="object">
      Separate Shiki themes for light and dark modes.

      <Expandable title="theme">
        <ResponseField name="light" type="string">
          Shiki theme name for light mode.
        </ResponseField>

        <ResponseField name="dark" type="string">
          Shiki theme name for dark mode.
        </ResponseField>
      </Expandable>

      ```json theme={null}
      "styling": {
        "codeblocks": {
          "theme": {
            "light": "github-light",
            "dark": "github-dark"
          }
        }
      }
      ```
    </ResponseField>

    <ResponseField name="languages" type="object">
      Custom language configuration for code blocks.

      <Expandable title="languages">
        <ResponseField name="custom" type="array of string">
          Paths to JSON files describing custom Shiki languages. Use this to add syntax highlighting for languages not in Shiki's default set. Each file must follow the [TextMate grammar format](https://macromates.com/manual/en/language_grammars).

          ```json theme={null}
          "styling": {
            "codeblocks": {
              "languages": {
                "custom": ["/languages/my-language.json"]
              }
            }
          }
          ```
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

***

### `thumbnails`

**Type:** `object`

Thumbnail customization for social media and page previews.

<ResponseField name="thumbnails.appearance" type="&#x22;light&#x22; | &#x22;dark&#x22;">
  Visual theme for thumbnails. If not set, thumbnails use your site's color scheme defined by `colors`.
</ResponseField>

<ResponseField name="thumbnails.background" type="string">
  Background image for thumbnails. Can be a relative path or absolute URL.
</ResponseField>

<ResponseField name="thumbnails.fonts" type="object">
  Font configuration for thumbnails. Only supports Google Fonts family names.

  <Expandable title="thumbnails.fonts">
    <ResponseField name="family" type="string">
      Font family name, such as `"Open Sans"` or `"Playfair Display"`. Supports [Google Fonts](https://fonts.google.com) family names.
    </ResponseField>
  </Expandable>
</ResponseField>

## Example

```json docs.json theme={null}
{
  "$schema": "https://mintlify.com/docs.json",
  "theme": "maple",
  "name": "Example Co.",
  "colors": {
    "primary": "#3B82F6",
    "light": "#93C5FD",
    "dark": "#1D4ED8"
  },
  "logo": {
    "light": "/logo/light.svg",
    "dark": "/logo/dark.svg",
    "href": "https://example.com"
  },
  "favicon": "/favicon.svg",
  "appearance": {
    "default": "system"
  },
  "fonts": {
    "family": "Inter"
  },
  "icons": {
    "library": "lucide"
  },
  "background": {
    "decoration": "gradient"
  }
}
```


# Integrations
Source: https://www.mintlify.com/docs/organize/settings-integrations

Connect analytics platforms, chat widgets, and third-party services to your Mintlify documentation site through the docs.json integrations config.

Use the `integrations` field in `docs.json` to connect third-party analytics platforms, chat tools, and other services to your documentation site.

## Settings

Configure all integrations as properties of the `integrations` object in your `docs.json` file:

```json docs.json theme={null}
"integrations": {
  "ga4": {
    "measurementId": "G-XXXXXXXXXX"
  }
}
```

### Analytics

<ResponseField name="integrations.adobe" type="object">
  Adobe Analytics integration.

  <Expandable title="integrations.adobe">
    <ResponseField name="launchUrl" type="string (uri)">
      Your Adobe Analytics launch URL.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.amplitude" type="object">
  Amplitude analytics integration.

  <Expandable title="integrations.amplitude">
    <ResponseField name="apiKey" type="string">
      Your Amplitude API key.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.clarity" type="object">
  Microsoft Clarity session recording and heatmap integration.

  <Expandable title="integrations.clarity">
    <ResponseField name="projectId" type="string">
      Your Microsoft Clarity project ID.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.fathom" type="object">
  Fathom analytics integration.

  <Expandable title="integrations.fathom">
    <ResponseField name="siteId" type="string">
      Your Fathom site ID.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.ga4" type="object">
  Google Analytics 4 integration.

  <Expandable title="integrations.ga4">
    <ResponseField name="measurementId" type="string matching ^G">
      Your Google Analytics 4 measurement ID. Must begin with `G`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.gtm" type="object">
  Google Tag Manager integration.

  <Expandable title="integrations.gtm">
    <ResponseField name="tagId" type="string matching ^G">
      Your Google Tag Manager container ID. Must begin with `G`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.heap" type="object">
  Heap analytics integration.

  <Expandable title="integrations.heap">
    <ResponseField name="appId" type="string">
      Your Heap app ID.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.hightouch" type="object">
  Hightouch data activation integration.

  <Expandable title="integrations.hightouch">
    <ResponseField name="writeKey" type="string">
      Your Hightouch write key.
    </ResponseField>

    <ResponseField name="apiHost" type="string">
      Your Hightouch API host.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.hotjar" type="object">
  Hotjar heatmap and session recording integration.

  <Expandable title="integrations.hotjar">
    <ResponseField name="hjid" type="string">
      Your Hotjar site ID.
    </ResponseField>

    <ResponseField name="hjsv" type="string">
      Your Hotjar script version.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.logrocket" type="object">
  LogRocket session replay integration.

  <Expandable title="integrations.logrocket">
    <ResponseField name="appId" type="string">
      Your LogRocket app ID.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.mixpanel" type="object">
  Mixpanel product analytics integration.

  <Expandable title="integrations.mixpanel">
    <ResponseField name="projectToken" type="string">
      Your Mixpanel project token.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.pirsch" type="object">
  Pirsch privacy-friendly analytics integration.

  <Expandable title="integrations.pirsch">
    <ResponseField name="id" type="string">
      Your Pirsch site ID.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.plausible" type="object">
  Plausible privacy-friendly analytics integration.

  <Expandable title="integrations.plausible">
    <ResponseField name="domain" type="string">
      Your Plausible domain.
    </ResponseField>

    <ResponseField name="server" type="string">
      Your Plausible server, if self-hosting.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.posthog" type="object">
  PostHog product analytics integration.

  <Expandable title="integrations.posthog">
    <ResponseField name="apiKey" type="string matching ^phc_">
      Your PostHog API key. Must begin with `phc_`.
    </ResponseField>

    <ResponseField name="apiHost" type="string (uri)">
      Your PostHog API host. Required if self-hosting PostHog.
    </ResponseField>

    <ResponseField name="sessionRecording" type="boolean">
      Whether to enable session recording. Defaults to `false`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.segment" type="object">
  Segment customer data platform integration.

  <Expandable title="integrations.segment">
    <ResponseField name="key" type="string">
      Your Segment write key.
    </ResponseField>
  </Expandable>
</ResponseField>

### Chat and support

<ResponseField name="integrations.frontchat" type="object">
  Front chat widget integration.

  <Expandable title="integrations.frontchat">
    <ResponseField name="snippetId" type="string">
      Your Front chat snippet ID. Minimum length: 6.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.intercom" type="object">
  Intercom customer messaging integration.

  <Expandable title="integrations.intercom">
    <ResponseField name="appId" type="string">
      Your Intercom app ID. Minimum length: 6.
    </ResponseField>
  </Expandable>
</ResponseField>

### Data enrichment

<ResponseField name="integrations.clearbit" type="object">
  Clearbit visitor data enrichment integration.

  <Expandable title="integrations.clearbit">
    <ResponseField name="publicApiKey" type="string">
      Your Clearbit public API key.
    </ResponseField>
  </Expandable>
</ResponseField>

### Platform settings

<ResponseField name="integrations.telemetry" type="object">
  Mintlify telemetry settings.

  <Expandable title="integrations.telemetry">
    <ResponseField name="enabled" type="boolean">
      Whether to enable Mintlify telemetry. When set to `false`, feedback features are also disabled and do not appear on your documentation pages.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="integrations.cookies" type="object">
  Cookie settings for your documentation site.

  <Expandable title="integrations.cookies">
    <ResponseField name="key" type="string">
      Cookie key name.
    </ResponseField>

    <ResponseField name="value" type="string">
      Cookie value.
    </ResponseField>
  </Expandable>
</ResponseField>

## Example

```json docs.json theme={null}
"integrations": {
  "ga4": {
    "measurementId": "G-XXXXXXXXXX"
  },
  "posthog": {
    "apiKey": "phc_XXXXXXXXXX"
  },
  "intercom": {
    "appId": "abc12345"
  },
  "telemetry": {
    "enabled": true
  }
}
```


# docs.json schema reference
Source: https://www.mintlify.com/docs/organize/settings-reference

Complete reference for every docs.json configuration property with types, default values, descriptions, and usage examples for your docs site.

Required fields have a <Badge>required</Badge> badge. All other fields are optional.

For context on what each group of settings does, see the topic pages:

* [Appearance and branding](/docs/organize/settings-appearance)
* [Site structure](/docs/organize/settings-structure)
* [API settings](/docs/organize/settings-api)
* [Integrations](/docs/organize/settings-integrations)
* [SEO and search](/docs/organize/settings-seo)

## Quick reference

| Property                     | Type                                                  | Required | Default         |
| ---------------------------- | ----------------------------------------------------- | -------- | --------------- |
| `$ref`                       | string (file path)                                    | No       | None            |
| `theme`                      | string                                                | Yes      | None            |
| `name`                       | string                                                | Yes      | None            |
| `colors.primary`             | string (hex)                                          | Yes      | None            |
| `navigation`                 | object                                                | Yes      | None            |
| `description`                | string                                                | No       | None            |
| `logo`                       | string or object                                      | No       | None            |
| `favicon`                    | string or object                                      | No       | None            |
| `appearance.default`         | `"system"` \| `"light"` \| `"dark"`                   | No       | `"system"`      |
| `appearance.strict`          | boolean                                               | No       | `false`         |
| `fonts.family`               | string                                                | No       | Theme default   |
| `icons.library`              | `"fontawesome"` \| `"lucide"` \| `"tabler"`           | No       | `"fontawesome"` |
| `background.decoration`      | `"gradient"` \| `"grid"` \| `"windows"`               | No       | None            |
| `styling.eyebrows`           | `"section"` \| `"breadcrumbs"`                        | No       | `"section"`     |
| `styling.latex`              | boolean                                               | No       | Auto-detected   |
| `styling.codeblocks`         | `"system"` \| `"dark"` \| string \| object            | No       | `"system"`      |
| `thumbnails.appearance`      | `"light"` \| `"dark"`                                 | No       | Site default    |
| `navbar.links`               | array                                                 | No       | None            |
| `navbar.primary`             | object                                                | No       | None            |
| `footer.socials`             | object                                                | No       | None            |
| `footer.links`               | array                                                 | No       | None            |
| `banner.content`             | string                                                | No       | None            |
| `banner.dismissible`         | boolean                                               | No       | `false`         |
| `banner.type`                | `"info"` \| `"warning"` \| `"critical"`               | No       | `"info"`        |
| `banner.color`               | object \| string                                      | No       | None            |
| `interaction.drilldown`      | boolean                                               | No       | Theme default   |
| `contextual.options`         | array                                                 | No       | None            |
| `contextual.display`         | `"header"` \| `"toc"`                                 | No       | `"header"`      |
| `redirects`                  | array                                                 | No       | None            |
| `variables`                  | object                                                | No       | None            |
| `metadata.timestamp`         | boolean                                               | No       | `false`         |
| `errors.404.redirect`        | boolean                                               | No       | `true`          |
| `errors.404.title`           | string                                                | No       | None            |
| `errors.404.description`     | string                                                | No       | None            |
| `api.openapi`                | string or array or object                             | No       | None            |
| `api.asyncapi`               | string or array or object                             | No       | None            |
| `api.playground.display`     | `"interactive"` \| `"simple"` \| `"none"` \| `"auth"` | No       | `"interactive"` |
| `api.playground.proxy`       | boolean                                               | No       | `true`          |
| `api.playground.credentials` | boolean                                               | No       | `false`         |
| `api.params.expanded`        | `"all"` \| `"closed"`                                 | No       | `"closed"`      |
| `api.params.post`            | array of string                                       | No       | None            |
| `api.url`                    | `"full"`                                              | No       | None            |
| `api.examples.languages`     | array of string                                       | No       | None            |
| `api.examples.defaults`      | `"required"` \| `"all"`                               | No       | `"all"`         |
| `api.examples.prefill`       | boolean                                               | No       | `false`         |
| `api.examples.autogenerate`  | boolean                                               | No       | `true`          |
| `markdown.schema`            | boolean                                               | No       | `true`          |
| `markdown.instructions`      | string or array of strings                            | No       | None            |
| `seo.indexing`               | `"navigable"` \| `"all"`                              | No       | `"navigable"`   |
| `seo.metatags`               | object                                                | No       | None            |
| `seo.organization`           | object                                                | No       | None            |
| `search.prompt`              | string                                                | No       | None            |
| `integrations.*`             | object                                                | No       | None            |

## Full property reference

### `$ref`

Load configuration from another JSON file. Use `$ref` at any level of your `docs.json` to split configuration across multiple files.

**Type:** string—relative file path to a `.json` file

* When `$ref` resolves to an object, Mintlify merges any sibling keys in the same block on top of the referenced content. Those keys take precedence over matching keys in the reference.
* When `$ref` resolves to a non-object value such as an array, Mintlify ignores any sibling keys.
* Referenced files can contain their own `$ref` entries, resolved relative to that file.
* Paths must stay within the project root. Circular references cause a build error.

```json Example theme={null}
{
  "navigation": { "$ref": "./navigation.json" }
}
```

See [Split configuration with `$ref`](/docs/organize/settings#split-configuration-with-%24ref) for more examples.

***

### `theme` - <Badge>required</Badge>

The layout theme for your site.

**Type:** string
**Options:** `mint`, `maple`, `palm`, `willow`, `linden`, `almond`, `aspen`, `sequoia`, `luma`

See [Themes](/docs/customize/themes) for previews.

***

### `name` - <Badge>required</Badge>

The name of your project, organization, or product.

**Type:** string

***

### `colors` - <Badge>required</Badge>

The colors used in your documentation.

**Type:** object

#### `colors.primary`

<Badge>required</Badge>

The primary color. Generally used for emphasis in light mode.

**Type:** string—hex code matching `^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$`

#### `colors.light`

The color used for emphasis in dark mode.

**Type:** string—hex code matching `^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$`

#### `colors.dark`

The color used for buttons and hover states across both modes.

**Type:** string—hex code matching `^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$`

***

### `navigation` - <Badge>required</Badge>

The navigation structure of your content.

**Type:** object

See [Navigation](/docs/organize/navigation) for complete documentation.

#### `navigation.global`

Global navigation elements that appear across all pages and locales.

**Type:** object

##### `navigation.global.tabs`

Top-level navigation tabs.

**Type:** array of object—each with: `tab` (string, required), `icon` (string), `iconType` (string), `hidden` (boolean), `href` (string uri, required)

##### `navigation.global.anchors`

Sidebar anchor links.

**Type:** array of object—each with: `anchor` (string, required), `icon` (string), `iconType` (string), `color.light` (string hex), `color.dark` (string hex), `hidden` (boolean), `href` (string uri, required)

##### `navigation.global.dropdowns`

Dropdown menus.

**Type:** array of object—each with: `dropdown` (string, required), `icon` (string), `iconType` (string), `hidden` (boolean), `href` (string uri, required)

##### `navigation.global.languages`

Language switcher in the global nav.

**Type:** array of object—each with: `language` (string, required), `default` (boolean), `hidden` (boolean), `href` (string uri, required)

**Supported language codes:** `ar`, `ca`, `cn`, `cs`, `da`, `de`, `en`, `es`, `fr`, `fr-CA`, `he`, `hi`, `hu`, `id`, `it`, `ja`, `ja-JP`, `jp`, `ko`, `lv`, `nl`, `no`, `pl`, `pt`, `pt-BR`, `ro`, `ru`, `sv`, `tr`, `uk`, `uz`, `vi`, `zh`, `zh-CN`, `zh-Hans`, `zh-Hant`, `zh-TW`

##### `navigation.global.versions`

Version switcher in the global nav.

**Type:** array of object—each with: `version` (string, required, min length 1), `default` (boolean), `hidden` (boolean), `href` (string uri, required)

##### `navigation.global.products`

Product switcher in the global nav.

**Type:** array of object—each with: `product` (string, required), `description` (string), `icon` (string), `iconType` (string)

#### `navigation.languages`

Language switcher for multi-language sites. Each entry can include language-specific `banner`, `footer`, and `navbar` overrides.

**Type:** array of object—each with: `language` (string, required), `default` (boolean), `hidden` (boolean), `banner` (object), `footer` (object), `navbar` (object)

**Supported language codes:** `ar`, `ca`, `cn`, `cs`, `da`, `de`, `en`, `es`, `fr`, `fr-CA`, `he`, `hi`, `hu`, `id`, `it`, `ja`, `ja-JP`, `jp`, `ko`, `lv`, `nl`, `no`, `pl`, `pt`, `pt-BR`, `ro`, `ru`, `sv`, `tr`, `uk`, `uz`, `vi`, `zh`, `zh-CN`, `zh-Hans`, `zh-Hant`, `zh-TW`

#### `navigation.versions`

Version switcher for multi-version sites.

**Type:** array of object—each with: `default` (boolean), `tag` (string)

#### `navigation.tabs`

Top-level navigation tabs.

**Type:** array of object—see `navigation.global.tabs` for shape.

#### `navigation.anchors`

Sidebar anchor links.

**Type:** array of object—see `navigation.global.anchors` for shape.

#### `navigation.dropdowns`

Dropdown menus.

**Type:** array of object—see `navigation.global.dropdowns` for shape.

#### `navigation.products`

Product switcher. Each entry requires a `product` field. It can contain groups, pages, a `menu` array (same shape as `navigation.tabs[].menu`, for multi-column product dropdowns), icons, or external links.

**Type:** array of object—each with: `product` (string, required), `description` (string), `icon` (string), `iconType` (string), `href` (string uri), `groups` (array), `pages` (array), `menu` (array)

#### `navigation.groups`

Groups for organizing content into labeled sections.

**Type:** array of object

##### `navigation.groups[].boost`

Numeric multiplier applied to the in-product search ranking of every page in this group. Pages inherit the boost factor from the nearest ancestor group that sets one. Use values greater than `1` to prioritize pages. Use values between `0` and `1` to de-prioritize them. See [Search](/docs/optimize/search#boost-search-ranking).

**Type:** number

#### `navigation.pages`

Individual pages in your documentation.

**Type:** array of string or object

#### `navigation.directory`

Directory layout for root pages in navigation groups. Inherits recursively. Descendants can override. See [Directory listings](/docs/organize/navigation#directory-listings).

**Type:** `"none"` | `"accordion"` | `"card"`—default `"none"`

***

### `description`

Site description for SEO and AI indexing.

**Type:** string

***

### `logo`

Site logo. Provide a path string or separate `light` and `dark` objects.

**Type:** string or object

#### `logo.light`

<Badge>required</Badge> (when using object form)

Path to the logo for light mode. Example: `/logo/light.svg`.

**Type:** string

#### `logo.dark`

<Badge>required</Badge> (when using object form)

Path to the logo for dark mode. Example: `/logo/dark.svg`.

**Type:** string

#### `logo.href`

URL to redirect to when clicking the logo.

**Type:** string (uri)

***

### `favicon`

Site favicon. Automatically resized. Provide a path string or separate `light` and `dark` objects.

**Type:** string or object

#### `favicon.light`

<Badge>required</Badge> (when using object form)

Path to the favicon for light mode. Example: `/favicon.png`.

**Type:** string

#### `favicon.dark`

<Badge>required</Badge> (when using object form)

Path to the favicon for dark mode. Example: `/favicon-dark.png`.

**Type:** string

***

### `appearance`

Light/dark mode settings.

**Type:** object

#### `appearance.default`

Default color mode.

**Type:** `"system"` | `"light"` | `"dark"`
**Default:** `"system"`

#### `appearance.strict`

When `true`, hides the light/dark mode toggle.

**Type:** boolean
**Default:** `false`

***

### `fonts`

Custom fonts. Supports [Google Fonts](https://fonts.google.com) and self-hosted fonts.

**Type:** object

#### `fonts.family`

<Badge>required</Badge> (when using `fonts`)

Font family name. Google Fonts family names load automatically.

**Type:** string

#### `fonts.weight`

Font weight. Variable fonts support fractional values such as `550`.

**Type:** number

#### `fonts.source`

URL to a hosted font or path to a local font file. Not needed for Google Fonts.

**Type:** string (uri)

#### `fonts.format`

Font file format. Required when using `fonts.source`.

**Type:** `"woff"` | `"woff2"`

#### `fonts.heading`

Override font settings for headings. Accepts the same `family`, `weight`, `source`, and `format` fields.

**Type:** object

#### `fonts.body`

Override font settings for body text. Accepts the same `family`, `weight`, `source`, and `format` fields.

**Type:** object

***

### `icons`

Icon library settings.

**Type:** object

#### `icons.library`

<Badge>required</Badge>

Icon library to use throughout your documentation. All icon names in your docs must come from the selected library.

**Type:** `"fontawesome"` | `"lucide"` | `"tabler"`
**Default:** `"fontawesome"`

***

### `background`

Background image, decoration, and color settings.

**Type:** object

#### `background.decoration`

Decorative background pattern.

**Type:** `"gradient"` | `"grid"` | `"windows"`

#### `background.color`

Custom background colors.

**Type:** object

##### `background.color.light`

Background color for light mode.

**Type:** string—hex code matching `^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$`

##### `background.color.dark`

Background color for dark mode.

**Type:** string—hex code matching `^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$`

#### `background.image`

Background image. Provide a path string or separate `light` and `dark` objects.

**Type:** string or object

##### `background.image.light`

<Badge>required</Badge> (when using object form)

Background image path for light mode.

**Type:** string

##### `background.image.dark`

<Badge>required</Badge> (when using object form)

Background image path for dark mode.

**Type:** string

***

### `styling`

Visual styling controls.

**Type:** object

#### `styling.eyebrows`

Page eyebrow style shown at the top of the page.

**Type:** `"section"` | `"breadcrumbs"`
**Default:** `"section"`

#### `styling.latex`

Whether to load LaTeX stylesheets. By default, Mintlify auto-detects LaTeX usage.

**Type:** boolean

#### `styling.codeblocks`

Code block theme configuration.

**Type:** `"system"` | `"dark"` | string (Shiki theme name) | object
**Default:** `"system"`

When an object:

##### `styling.codeblocks.theme`

A single Shiki theme name for both modes, or an object with `light` and `dark` Shiki theme names.

**Type:** string or object

##### `styling.codeblocks.languages`

Custom language configuration.

**Type:** object

###### `styling.codeblocks.languages.custom`

Paths to JSON files describing custom Shiki languages in [TextMate grammar format](https://macromates.com/manual/en/language_grammars).

**Type:** array of string

***

### `thumbnails`

Social media thumbnail customization.

**Type:** object

#### `thumbnails.appearance`

Visual theme for thumbnails.

**Type:** `"light"` | `"dark"`
**Default:** Site color scheme

#### `thumbnails.background`

Background image for thumbnails. Can be a relative path or absolute URL.

**Type:** string

#### `thumbnails.fonts`

Font configuration for thumbnails.

**Type:** object

##### `thumbnails.fonts.family`

<Badge>required</Badge> (when using `thumbnails.fonts`)

Font family name. Supports [Google Fonts](https://fonts.google.com) only.

**Type:** string

***

### `navbar`

Top navigation bar configuration.

**Type:** object

#### `navbar.links`

Links displayed in the navbar.

**Type:** array of object—each with:

| Field      | Type                      | Required    | Description                          |
| ---------- | ------------------------- | ----------- | ------------------------------------ |
| `type`     | `"github"` \| `"discord"` | No          | Link type. Omit for a standard link. |
| `label`    | string                    | Conditional | Required when `type` is omitted.     |
| `href`     | string (uri)              | Yes         | Link destination.                    |
| `icon`     | string                    | No          | Icon name, URL, path, or SVG.        |
| `iconType` | string                    | No          | Font Awesome icon style only.        |

#### `navbar.primary`

Primary call-to-action button in the navbar.

**Type:** object

| Field   | Type                                    | Required    | Description                         |
| ------- | --------------------------------------- | ----------- | ----------------------------------- |
| `type`  | `"button"` \| `"github"` \| `"discord"` | Yes         | Button style.                       |
| `label` | string                                  | Conditional | Required when `type` is `"button"`. |
| `href`  | string (uri)                            | Yes         | Button destination.                 |

***

### `footer`

Footer content and social links.

**Type:** object

#### `footer.socials`

Social media profiles. Each key is a platform name, each value is your profile URL.

**Type:** object

**Valid keys:** `x`, `website`, `facebook`, `youtube`, `discord`, `slack`, `github`, `linkedin`, `instagram`, `hacker-news`, `medium`, `telegram`, `twitter`, `x-twitter`, `earth-americas`, `bluesky`, `threads`, `reddit`, `podcast`

#### `footer.links`

Link columns in the footer. Maximum 4 columns.

**Type:** array of object (max 4)—each with: `header` (string), `items` (array of `{ label: string, href: string }`, required)

***

### `banner`

Site-wide banner displayed at the top of every page.

**Type:** object

#### `banner.content`

<Badge>required</Badge> (when using `banner`)

Banner text. Supports basic MDX formatting including links, bold, and italic. Custom components are not supported.

**Type:** string

#### `banner.dismissible`

Whether to show a dismiss button.

**Type:** boolean
**Default:** `false`

#### `banner.type`

Visual style for the banner background. Use `info` for general announcements, `warning` for cautionary notices, and `critical` for urgent issues.

**Type:** `"info"` | `"warning"` | `"critical"`
**Default:** `"info"`

#### `banner.color`

Custom background color override. Takes precedence over `type`. Banner text is white, so choose a background that remains legible.

**Type:** object with `light` (string) and `dark` (string) hex values, or a single hex string applied to both modes.

***

### `interaction`

Navigation interaction settings.

**Type:** object

#### `interaction.drilldown`

Controls automatic navigation when a user clicks a navigation group. Set to `true` to navigate to the first page when a user clicks a group. Set to `false` to only expand/collapse the group without navigating.

**Type:** boolean
**Default:** Theme default

***

### `contextual`

Contextual menu for page actions and AI tool integrations.

**Type:** object

#### `contextual.options`

<Badge>required</Badge>

Actions available in the contextual menu. The first item is the default action.

**Type:** array of `"assistant"` | `"copy"` | `"view"` | `"download-pdf"` | `"download-spec"` | `"chatgpt"` | `"claude"` | `"perplexity"` | `"grok"` | `"aistudio"` | `"devin"` | `"devin-desktop"` | `"mcp"` | `"add-mcp"` | `"cursor"` | `"vscode"` | `"devin-mcp"` | object

Custom option object fields:

| Field         | Type             | Required | Description                                                       |
| ------------- | ---------------- | -------- | ----------------------------------------------------------------- |
| `title`       | string           | Yes      | Display title.                                                    |
| `description` | string           | Yes      | Description text.                                                 |
| `icon`        | string           | No       | Icon name, URL, path, or SVG.                                     |
| `href`        | string or object | Yes      | Link destination. Supports `$page`, `$path`, `$mcp` placeholders. |

#### `contextual.display`

Where to show the contextual menu.

**Type:** `"header"` | `"toc"`
**Default:** `"header"`

<Note>
  The contextual menu is only available on preview and production deployments.
</Note>

***

### `redirects`

Redirects for moved, renamed, or deleted pages.

**Type:** array of object—each with:

| Field         | Type    | Required | Description                                       |
| ------------- | ------- | -------- | ------------------------------------------------- |
| `source`      | string  | Yes      | Path to redirect from. Example: `/old-page`       |
| `destination` | string  | Yes      | Path to redirect to. Example: `/new-page`         |
| `permanent`   | boolean | No       | `true` for 308, `false` for 307. Default: `true`. |

***

### `variables`

Global content variables replaced at build time using `{{variableName}}` syntax.

**Type:** object—key-value pairs where keys are variable names (alphanumeric and hyphens only) and values are replacement strings.

<Note>
  Variable substitution applies to MDX pages and snippets only. It does not apply to OpenAPI specification files (`.yaml`, `.yml`, `.json`) or other static assets.
</Note>

***

### `metadata`

Global page metadata settings.

**Type:** object

#### `metadata.timestamp`

Display a last-modified date on all pages. For deployments backed by GitHub or GitLab, the date reflects the last Git commit that touched a page's source file. It falls back to the most recent deployment timestamp if a Git commit date isn't available.

Set the `lastUpdatedDate` frontmatter field on a page to override the automatic date. See [Pages](/docs/organize/pages#last-modified-timestamp) for details.

**Type:** boolean
**Default:** `false`

***

### `errors`

Error page settings.

**Type:** object

#### `errors.404`

Settings for the 404 "Page not found" error page.

**Type:** object

##### `errors.404.redirect`

Whether to automatically redirect to the home page when a page is not found.

**Type:** boolean
**Default:** `true`

##### `errors.404.title`

Custom title for the 404 page.

**Type:** string

##### `errors.404.description`

Custom description for the 404 page. Supports MDX formatting including links, bold, italic, and custom components.

**Type:** string

***

### `api`

API documentation and playground settings.

**Type:** object

#### `api.openapi`

OpenAPI specification files.

**Type:** string | array of string | object with `source` (string) and `directory` (string)

#### `api.asyncapi`

AsyncAPI specification files.

**Type:** string | array of string | object with `source` (string) and `directory` (string)

#### `api.playground`

Interactive playground settings.

**Type:** object

##### `api.playground.display`

Playground display mode.

**Type:** `"interactive"` | `"simple"` | `"none"` | `"auth"`
**Default:** `"interactive"`

##### `api.playground.proxy`

Whether to route API requests through a proxy.

**Type:** boolean
**Default:** `true`

##### `api.playground.credentials`

Whether to include cookies and authentication headers for cross-origin requests when `proxy` is `false`. Has no effect when `proxy` is `true`.

**Type:** boolean
**Default:** `false`

#### `api.params`

API parameter display settings.

**Type:** object

##### `api.params.expanded`

Whether to expand all parameters by default.

**Type:** `"all"` | `"closed"`
**Default:** `"closed"`

##### `api.params.post`

OpenAPI spec field keys to surface as post pills next to every parameter name. For each key, Mintlify reads the value on the schema and renders it as a pill. Strings render verbatim, `true` renders the key name, numbers stringify, and arrays render one pill per element. Mintlify skips `false`, `null`, empty strings, and objects.

**Type:** array of string

#### `api.url`

Base URL display mode.

**Type:** `"full"`
**Default:** Only shown when multiple base URLs exist.

#### `api.examples`

Code example settings.

**Type:** object

##### `api.examples.languages`

Languages for autogenerated code snippets. See [supported languages](/docs/api-playground/overview#all-supported-languages).

**Type:** array of string

##### `api.examples.defaults`

Whether to include optional parameters in examples.

**Type:** `"required"` | `"all"`
**Default:** `"all"`

##### `api.examples.prefill`

Whether to prefill playground fields with spec example values.

**Type:** boolean
**Default:** `false`

##### `api.examples.autogenerate`

Whether to generate code samples from API specifications.

**Type:** boolean
**Default:** `true`

#### `api.mdx`

Settings for API pages built from MDX files.

**Type:** object

##### `api.mdx.auth`

Authentication configuration for MDX-based API requests.

**Type:** object

###### `api.mdx.auth.method`

Authentication method.

**Type:** `"bearer"` | `"basic"` | `"key"` | `"cobo"`

###### `api.mdx.auth.name`

Authentication parameter name.

**Type:** string

##### `api.mdx.server`

Base URL prepended to relative paths in page-level `api` frontmatter. Not used when frontmatter contains a full URL.

**Type:** string or array

***

### `markdown`

Settings for the Markdown that Mintlify serves to AI tools and agents. See [Markdown export](/docs/ai/markdown-export).

**Type:** object

#### `markdown.schema`

Whether to include the full OpenAPI or AsyncAPI specification in the Markdown export of API reference pages.

**Type:** boolean
**Default:** `true`

#### `markdown.instructions`

Custom agent instructions appended to the generated Markdown of every page, as well as your `llms.txt` and `llms-full.txt` files. Provide a single string or an array of strings. Mintlify joins array items with line breaks. See [Custom agent instructions](/docs/ai/markdown-export#custom-agent-instructions).

**Type:** string or array of strings

***

### `seo`

Search engine optimization settings.

**Type:** object

#### `seo.indexing`

Which pages search engines should index.

**Type:** `"navigable"` | `"all"`
**Default:** `"navigable"`

#### `seo.metatags`

Custom meta tags added to every page. Key-value pairs.

**Type:** object

#### `seo.organization`

Organization used as the publisher entity in structured data (JSON-LD) on every page. It accepts `id`, `name`, `legalName`, `url`, `logo`, and `sameAs`. See [SEO and search](/docs/organize/settings-seo#seo).

**Type:** object

***

### `search`

Search bar settings.

**Type:** object

#### `search.prompt`

Placeholder text in the search bar.

**Type:** string

***

### `integrations`

Third-party integrations.

**Type:** object

| Property                                | Type                            | Required field | Description                                                                   |
| --------------------------------------- | ------------------------------- | -------------- | ----------------------------------------------------------------------------- |
| `integrations.adobe.launchUrl`          | string (uri)                    | Yes            | Adobe Analytics launch URL.                                                   |
| `integrations.amplitude.apiKey`         | string                          | Yes            | Amplitude API key.                                                            |
| `integrations.clarity.projectId`        | string                          | Yes            | Microsoft Clarity project ID.                                                 |
| `integrations.clearbit.publicApiKey`    | string                          | Yes            | Clearbit public API key.                                                      |
| `integrations.fathom.siteId`            | string                          | Yes            | Fathom site ID.                                                               |
| `integrations.frontchat.snippetId`      | string (min 6)                  | Yes            | Front chat snippet ID.                                                        |
| `integrations.ga4.measurementId`        | string (must start with `G`)    | Yes            | Google Analytics 4 measurement ID.                                            |
| `integrations.gtm.tagId`                | string (must start with `G`)    | Yes            | Google Tag Manager container ID.                                              |
| `integrations.heap.appId`               | string                          | Yes            | Heap app ID.                                                                  |
| `integrations.hightouch.writeKey`       | string                          | Yes            | Hightouch write key.                                                          |
| `integrations.hightouch.apiHost`        | string                          | No             | Hightouch API host.                                                           |
| `integrations.hotjar.hjid`              | string                          | Yes            | Hotjar site ID.                                                               |
| `integrations.hotjar.hjsv`              | string                          | Yes            | Hotjar script version.                                                        |
| `integrations.intercom.appId`           | string (min 6)                  | Yes            | Intercom app ID.                                                              |
| `integrations.logrocket.appId`          | string                          | Yes            | LogRocket app ID.                                                             |
| `integrations.mixpanel.projectToken`    | string                          | Yes            | Mixpanel project token.                                                       |
| `integrations.pirsch.id`                | string                          | Yes            | Pirsch site ID.                                                               |
| `integrations.plausible.domain`         | string                          | Yes            | Plausible domain.                                                             |
| `integrations.plausible.server`         | string                          | No             | Plausible server (self-hosted only).                                          |
| `integrations.posthog.apiKey`           | string (must start with `phc_`) | Yes            | PostHog API key.                                                              |
| `integrations.posthog.apiHost`          | string (uri)                    | No             | PostHog API host (self-hosted only).                                          |
| `integrations.posthog.sessionRecording` | boolean                         | No             | Enable session recording. Default: `false`.                                   |
| `integrations.segment.key`              | string                          | Yes            | Segment write key.                                                            |
| `integrations.telemetry.enabled`        | boolean                         | No             | Enable Mintlify telemetry. When `false`, feedback features are also disabled. |
| `integrations.cookies.key`              | string                          | No             | Cookie key name.                                                              |
| `integrations.cookies.value`            | string                          | No             | Cookie value.                                                                 |


# SEO and search
Source: https://www.mintlify.com/docs/organize/settings-seo

Configure SEO settings in docs.json including site description, search engine indexing, meta tags, search bar placeholder, and page timestamps.

Use these settings in your `docs.json` file to control how search engines index your documentation and what metadata appears in search results. You can also control how the search bar behaves and whether pages display a last-modified timestamp.

## Settings

### `description`

**Type:** `string`

A description of your documentation site for SEO and AI indexing. It appears in search engine results. AI tools use it to understand your site's purpose.

```json docs.json theme={null}
"description": "Documentation for Example Co.'s API and developer platform."
```

***

### `seo`

**Type:** `object`

Search engine indexing and metadata settings.

<ResponseField name="seo.indexing" type="&#x22;navigable&#x22; | &#x22;all&#x22;">
  Specifies which pages search engines should index.

  * `navigable`: Index only pages included in your `docs.json` navigation. Defaults to this value.
  * `all`: Index every page in your project, including pages not in the navigation.
</ResponseField>

<ResponseField name="seo.metatags" type="object">
  Custom meta tags added to every page. Provide as key-value pairs where each key is a meta tag name and the value is its content.

  See [common meta tags reference](/docs/optimize/seo#common-meta-tags-reference) for available options.

  ```json theme={null}
  "metatags": {
    "og:site_name": "Example Co. Docs",
    "twitter:card": "summary_large_image"
  }
  ```
</ResponseField>

<ResponseField name="seo.organization" type="object">
  The organization used as the publisher entity in the [structured data](/docs/optimize/seo#structured-data) emitted on every page. All fields are optional. If you omit this object, Mintlify derives the organization from your site name, docs logo, and site URL.

  * `id`: Stable `@id` URL identifying your organization across pages, for example `https://example.com/#organization`. Defaults to `<site origin>/#organization`.
  * `name`: Organization name. Defaults to the site name.
  * `legalName`: Registered legal name.
  * `url`: Canonical organization homepage URL.
  * `logo`: Canonical logo URL used in structured data. Defaults to the docs logo.
  * `sameAs`: Array of URLs for official profiles, such as X, LinkedIn, or GitHub.

  ```json theme={null}
  "organization": {
    "id": "https://example.com/#organization",
    "legalName": "Example Co. Inc.",
    "url": "https://example.com",
    "logo": "https://example.com/images/logo.png",
    "sameAs": [
      "https://x.com/example",
      "https://github.com/example"
    ]
  }
  ```
</ResponseField>

```json docs.json theme={null}
"seo": {
  "indexing": "navigable",
  "metatags": {
    "og:site_name": "Example Co. Docs"
  }
}
```

***

### `search`

**Type:** `object`

Search bar display settings.

<ResponseField name="search.prompt" type="string">
  Placeholder text displayed in the search bar when it is empty.
</ResponseField>

```json docs.json theme={null}
"search": {
  "prompt": "Search the docs..."
}
```

***

### `metadata`

**Type:** `object`

Page-level metadata settings applied globally across all pages.

<ResponseField name="metadata.timestamp" type="boolean">
  Display a last-modified date on all pages. When enabled, each page shows the date its content was last modified. The default is `false`.

  You can override this setting for individual pages using the `timestamp` frontmatter field. See [Pages](/docs/organize/pages#last-modified-timestamp) for details.
</ResponseField>

```json docs.json theme={null}
"metadata": {
  "timestamp": true
}
```

## Example

```json docs.json theme={null}
{
  "description": "Documentation for Example Co.'s API and developer platform.",
  "seo": {
    "indexing": "navigable",
    "metatags": {
      "og:site_name": "Example Co. Docs",
      "twitter:card": "summary_large_image"
    }
  },
  "search": {
    "prompt": "Search the docs..."
  },
  "metadata": {
    "timestamp": true
  }
}
```


# Site structure
Source: https://www.mintlify.com/docs/organize/settings-structure

Configure navbar, navigation groups, footer links, banner, contextual menu, redirects, and other structural elements in your docs.json file.

Use these settings in your `docs.json` file to control your site's information architecture and user experience. Modify the navbar, footer, banners, navigation behavior, contextual menus, redirects, and global content variables.

## Settings

### `navigation` - <Badge>required</Badge>

**Type:** `object`

The navigation structure of your content. This is where you define your site's full page hierarchy using groups, tabs, dropdowns, anchors, and more.

See [Navigation](/docs/organize/navigation) for complete documentation on building your navigation structure.

<ResponseField name="navigation.global" type="object">
  Global navigation elements that appear across all pages and locales.

  <Expandable title="navigation.global">
    <ResponseField name="tabs" type="array of object">
      Top-level navigation tabs for organizing major sections. See [Tabs](/docs/organize/navigation#tabs).

      <Expandable title="tabs">
        <ResponseField name="tab" type="string">
          Display name of the tab. Minimum length: 1.
        </ResponseField>

        <ResponseField name="icon" type="string">
          The icon to display.

          Options:

          * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
          * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
          * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
          * URL to an externally hosted icon
          * Path to an icon file in your project
          * SVG code wrapped in curly braces

          For custom SVG icons:

          1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
          2. Paste your SVG code into the SVG input field.
          3. Copy the complete `<svg>...</svg>` element from the JSX output field.
          4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
          5. Adjust `height` and `width` as needed.
        </ResponseField>

        <ResponseField name="iconType" type="string">
          The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

          Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
        </ResponseField>

        <ResponseField name="hidden" type="boolean">
          Whether to hide this tab by default.
        </ResponseField>

        <ResponseField name="href" type="string (uri)">
          URL or path for the tab destination.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="anchors" type="array of object">
      Anchored links that appear prominently in the sidebar. See [Anchors](/docs/organize/navigation#anchors).

      <Expandable title="anchors">
        <ResponseField name="anchor" type="string">
          Display name of the anchor. Minimum length: 1.
        </ResponseField>

        <ResponseField name="icon" type="string">
          The icon to display.

          Options:

          * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
          * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
          * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
          * URL to an externally hosted icon
          * Path to an icon file in your project
          * SVG code wrapped in curly braces

          For custom SVG icons:

          1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
          2. Paste your SVG code into the SVG input field.
          3. Copy the complete `<svg>...</svg>` element from the JSX output field.
          4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
          5. Adjust `height` and `width` as needed.
        </ResponseField>

        <ResponseField name="iconType" type="string">
          The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

          Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
        </ResponseField>

        <ResponseField name="color" type="object">
          Custom colors for the anchor icon.

          <Expandable title="color">
            <ResponseField name="light" type="string">
              Anchor color for light mode. Must be a hex code beginning with `#`.
            </ResponseField>

            <ResponseField name="dark" type="string">
              Anchor color for dark mode. Must be a hex code beginning with `#`.
            </ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="hidden" type="boolean">
          Whether to hide this anchor by default.
        </ResponseField>

        <ResponseField name="href" type="string (uri)">
          URL or path for the anchor destination.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="dropdowns" type="array of object">
      Dropdown menus for organizing related content. See [Dropdowns](/docs/organize/navigation#dropdowns).

      <Expandable title="dropdowns">
        <ResponseField name="dropdown" type="string">
          Display name of the dropdown. Minimum length: 1.
        </ResponseField>

        <ResponseField name="icon" type="string">
          The icon to display.

          Options:

          * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
          * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
          * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
          * URL to an externally hosted icon
          * Path to an icon file in your project
          * SVG code wrapped in curly braces

          For custom SVG icons:

          1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
          2. Paste your SVG code into the SVG input field.
          3. Copy the complete `<svg>...</svg>` element from the JSX output field.
          4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
          5. Adjust `height` and `width` as needed.
        </ResponseField>

        <ResponseField name="iconType" type="string">
          The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

          Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
        </ResponseField>

        <ResponseField name="hidden" type="boolean">
          Whether to hide this dropdown by default.
        </ResponseField>

        <ResponseField name="href" type="string (uri)">
          URL or path for the dropdown destination.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="languages" type="array of object">
      Language switcher configuration for localized sites. See [Languages](/docs/organize/navigation#languages).

      <Expandable title="languages">
        <ResponseField name="language" type="&#x22;ar&#x22; | &#x22;ca&#x22; | &#x22;cn&#x22; | &#x22;cs&#x22; | &#x22;de&#x22; | &#x22;en&#x22; | &#x22;es&#x22; | &#x22;fi&#x22; | &#x22;fr&#x22; | &#x22;fr-CA&#x22; | &#x22;he&#x22; | &#x22;hi&#x22; | &#x22;hu&#x22; | &#x22;id&#x22; | &#x22;it&#x22; | &#x22;ja&#x22; | &#x22;ja-JP&#x22; | &#x22;jp&#x22; | &#x22;ko&#x22; | &#x22;lv&#x22; | &#x22;nl&#x22; | &#x22;no&#x22; | &#x22;pl&#x22; | &#x22;pt&#x22; | &#x22;pt-BR&#x22; | &#x22;ro&#x22; | &#x22;ru&#x22; | &#x22;sv&#x22; | &#x22;tr&#x22; | &#x22;uk&#x22; | &#x22;uz&#x22; | &#x22;vi&#x22; | &#x22;zh&#x22; | &#x22;zh-CN&#x22; | &#x22;zh-Hans&#x22; | &#x22;zh-Hant&#x22; | &#x22;zh-TW&#x22;">
          Language code in [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format.
        </ResponseField>

        <ResponseField name="default" type="boolean">
          Whether this is the default language.
        </ResponseField>

        <ResponseField name="hidden" type="boolean">
          Whether to hide this language option by default.
        </ResponseField>

        <ResponseField name="href" type="string (uri)">
          A valid path or external link to this language version of your documentation.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="versions" type="array of object">
      Version switcher configuration for multi-version sites. See [Versions](/docs/organize/navigation#versions).

      <Expandable title="versions">
        <ResponseField name="version" type="string">
          Display name of the version. Minimum length: 1.
        </ResponseField>

        <ResponseField name="default" type="boolean">
          Whether this is the default version.
        </ResponseField>

        <ResponseField name="hidden" type="boolean">
          Whether to hide this version by default.
        </ResponseField>

        <ResponseField name="href" type="string (uri)">
          URL or path to this version of your documentation.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="products" type="array of object">
      Product switcher for sites with multiple products. See [Products](/docs/organize/navigation#products).

      <Expandable title="products">
        <ResponseField name="product" type="string">
          Display name of the product.
        </ResponseField>

        <ResponseField name="description" type="string">
          Description of the product.
        </ResponseField>

        <ResponseField name="icon" type="string">
          The icon to display.

          Options:

          * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
          * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
          * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
          * URL to an externally hosted icon
          * Path to an icon file in your project
          * SVG code wrapped in curly braces

          For custom SVG icons:

          1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
          2. Paste your SVG code into the SVG input field.
          3. Copy the complete `<svg>...</svg>` element from the JSX output field.
          4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
          5. Adjust `height` and `width` as needed.
        </ResponseField>

        <ResponseField name="iconType" type="string">
          The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

          Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="navigation.languages" type="array of object">
  Language switcher for [multi-language](/docs/organize/navigation#languages) sites. Each entry can include language-specific `banner`, `footer`, and `navbar` configurations in addition to the navigation structure.

  <Expandable title="navigation.languages">
    <ResponseField name="language" type="&#x22;ar&#x22; | &#x22;ca&#x22; | &#x22;cn&#x22; | &#x22;cs&#x22; | &#x22;de&#x22; | &#x22;en&#x22; | &#x22;es&#x22; | &#x22;fi&#x22; | &#x22;fr&#x22; | &#x22;fr-CA&#x22; | &#x22;he&#x22; | &#x22;hi&#x22; | &#x22;hu&#x22; | &#x22;id&#x22; | &#x22;it&#x22; | &#x22;ja&#x22; | &#x22;ja-JP&#x22; | &#x22;jp&#x22; | &#x22;ko&#x22; | &#x22;lv&#x22; | &#x22;nl&#x22; | &#x22;no&#x22; | &#x22;pl&#x22; | &#x22;pt&#x22; | &#x22;pt-BR&#x22; | &#x22;ro&#x22; | &#x22;ru&#x22; | &#x22;sv&#x22; | &#x22;tr&#x22; | &#x22;uk&#x22; | &#x22;uz&#x22; | &#x22;vi&#x22; | &#x22;zh&#x22; | &#x22;zh-CN&#x22; | &#x22;zh-Hans&#x22; | &#x22;zh-Hant&#x22; | &#x22;zh-TW&#x22;">
      Language code in ISO 639-1 format.
    </ResponseField>

    <ResponseField name="default" type="boolean">
      Whether this is the default language.
    </ResponseField>

    <ResponseField name="banner" type="object">
      Language-specific banner configuration. Accepts the same options as the top-level [`banner`](#banner) field.
    </ResponseField>

    <ResponseField name="footer" type="object">
      Language-specific footer configuration. Accepts the same options as the top-level [`footer`](#footer) field.
    </ResponseField>

    <ResponseField name="navbar" type="object">
      Language-specific navbar configuration. Accepts the same options as the top-level [`navbar`](#navbar) field.
    </ResponseField>

    <ResponseField name="hidden" type="boolean">
      Whether to hide this language option by default.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="navigation.versions" type="array of object">
  Version switcher for sites with [multiple versions](/docs/organize/navigation#versions).

  <Expandable title="navigation.versions">
    <ResponseField name="default" type="boolean">
      Set to `true` to make this the default version. If omitted, the first version in the array is the default.
    </ResponseField>

    <ResponseField name="tag" type="string">
      Badge label displayed next to the version in the selector. Use to highlight versions such as `"Latest"`, `"Recommended"`, or `"Beta"`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="navigation.tabs" type="array of object">
  Top-level navigation [tabs](/docs/organize/navigation#tabs).
</ResponseField>

<ResponseField name="navigation.anchors" type="array of object">
  Sidebar [anchors](/docs/organize/navigation#anchors).
</ResponseField>

<ResponseField name="navigation.dropdowns" type="array of object">
  [Dropdowns](/docs/organize/navigation#dropdowns) for grouping related content.
</ResponseField>

<ResponseField name="navigation.products" type="array of object">
  Product switcher for sites with multiple [products](/docs/organize/navigation#products).
</ResponseField>

<ResponseField name="navigation.groups" type="array of object">
  [Groups](/docs/organize/navigation#groups) for organizing content into sections.
</ResponseField>

<ResponseField name="navigation.pages" type="array of string or object">
  Individual [pages](/docs/organize/navigation#pages) that make up your documentation.
</ResponseField>

<ResponseField name="navigation.directory" type="&#x22;none&#x22; | &#x22;accordion&#x22; | &#x22;card&#x22;">
  Directory layout for root pages in navigation groups. When set, groups with a `root` page automatically display a listing of their children below the page content. Values inherit recursively through the navigation tree. Descendants can override. See [Directory listings](/docs/organize/navigation#directory-listings).
</ResponseField>

***

### `navbar`

**Type:** `object`

Links and buttons displayed in the top navigation bar.

<ResponseField name="navbar.links" type="array of object">
  Links to display in the navbar.

  <Expandable title="navbar.links">
    <ResponseField name="type" type="&#x22;github&#x22; | &#x22;discord&#x22;">
      Optional link type. Omit for a standard text link. Set to `github` to link to a GitHub repository and show its star count. Set to `discord` to link to a Discord server and show its online user count.
    </ResponseField>

    <ResponseField name="label" type="string">
      Link text. Required when `type` is not set. Optional for `github` and `discord`. If omitted, Mintlify generates the label from API data.
    </ResponseField>

    <ResponseField name="href" type="string (uri)">
      Link destination. Must be a valid external URL. For `github`, must be a GitHub repository URL. For `discord`, must be a Discord invite URL.
    </ResponseField>

    <ResponseField name="icon" type="string">
      The icon to display.

      Options:

      * [Font Awesome](https://fontawesome.com/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `fontawesome` in your `docs.json`
      * [Lucide](https://lucide.dev/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `lucide` in your `docs.json`
      * [Tabler](https://tabler.io/icons) icon name, if you have the `icons.library` [property](/docs/organize/settings-appearance#param-icons) set to `tabler` in your `docs.json`
      * URL to an externally hosted icon
      * Path to an icon file in your project
      * SVG code wrapped in curly braces

      For custom SVG icons:

      1. Convert your SVG using the [SVGR converter](https://react-svgr.com/playground/).
      2. Paste your SVG code into the SVG input field.
      3. Copy the complete `<svg>...</svg>` element from the JSX output field.
      4. Wrap the JSX-compatible SVG code in curly braces: `icon={<svg ...> ... </svg>}`.
      5. Adjust `height` and `width` as needed.
    </ResponseField>

    <ResponseField name="iconType" type="string">
      The [Font Awesome](https://fontawesome.com/icons) icon style. Only used with Font Awesome icons.

      Options: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="navbar.primary" type="object">
  Primary call-to-action button in the navbar.

  <Expandable title="navbar.primary">
    <ResponseField name="type" type="&#x22;button&#x22; | &#x22;github&#x22; | &#x22;discord&#x22;">
      Button style. Choose `button` for a standard button, `github` for a GitHub repository link with star count, or `discord` for a Discord invite with online user count.
    </ResponseField>

    <ResponseField name="label" type="string">
      Button text. Required when `type` is `button`. Optional for `github` and `discord`.
    </ResponseField>

    <ResponseField name="href" type="string (uri)">
      Button destination. Must be an external URL. For `github`, must be a GitHub repository URL. For `discord`, must be a Discord invite URL.
    </ResponseField>
  </Expandable>
</ResponseField>

```json docs.json theme={null}
"navbar": {
  "links": [
    { "type": "github", "href": "https://github.com/your-org/your-repo" },
    { "label": "Community", "href": "https://example.com/community" }
  ],
  "primary": {
    "type": "button",
    "label": "Get started",
    "href": "https://example.com/signup"
  }
}
```

***

### `footer`

**Type:** `object`

Footer content and social media links.

<ResponseField name="footer.socials" type="object">
  Social media profiles to display in the footer. Each key is a platform name and each value is your profile URL.

  Valid keys: `x`, `website`, `facebook`, `youtube`, `discord`, `slack`, `github`, `linkedin`, `instagram`, `hacker-news`, `medium`, `telegram`, `twitter`, `x-twitter`, `earth-americas`, `bluesky`, `threads`, `reddit`, `podcast`

  ```json theme={null}
  "socials": {
    "x": "https://x.com/yourhandle",
    "github": "https://github.com/your-org"
  }
  ```
</ResponseField>

<ResponseField name="footer.links" type="array of object">
  Link columns displayed in the footer. Maximum 4 columns.

  <Expandable title="footer.links">
    <ResponseField name="header" type="string">
      Column header title. Minimum length: 1.
    </ResponseField>

    <ResponseField name="items" type="array of object">
      Links to display in the column.

      <Expandable title="items">
        <ResponseField name="label" type="string">
          Link text. Minimum length: 1.
        </ResponseField>

        <ResponseField name="href" type="string (uri)">
          Link destination URL.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

```json docs.json theme={null}
"footer": {
  "socials": {
    "x": "https://x.com/yourhandle",
    "github": "https://github.com/your-org"
  },
  "links": [
    {
      "header": "Company",
      "items": [
        { "label": "Blog", "href": "https://example.com/blog" },
        { "label": "Careers", "href": "https://example.com/careers" }
      ]
    }
  ]
}
```

***

### `banner`

**Type:** `object`

A site-wide banner displayed at the top of every page.

<ResponseField name="banner.content" type="string">
  The text content displayed in the banner. Supports basic MDX formatting including links, bold, and italic text. Custom components are not supported.

  ```json theme={null}
  "content": "We just launched something new. [Learn more](https://example.com)"
  ```
</ResponseField>

<ResponseField name="banner.dismissible" type="boolean">
  Whether to show a dismiss button so users can close the banner. Defaults to `false`.
</ResponseField>

```json docs.json theme={null}
"banner": {
  "content": "We just launched something new. [Learn more](https://example.com)",
  "dismissible": true
}
```

***

### `interaction`

**Type:** `object`

Controls user interaction behavior for navigation elements.

<ResponseField name="interaction.drilldown" type="boolean">
  Controls automatic navigation when selecting a navigation group. Set to `true` to automatically navigate to the first page when a group expands. Set to `false` to only expand or collapse the group without navigating. Leave unset to use the theme's default behavior.
</ResponseField>

***

### `contextual`

**Type:** `object`

The contextual menu gives users quick access to AI tools and page actions. It appears in the page header or table of contents sidebar.

<Note>
  The contextual menu is only available on preview and production deployments.
</Note>

<ResponseField name="contextual.options" type="array">
  Actions available in the contextual menu. The first option in the array appears as the default action.

  Built-in options:

  * `"add-mcp"`—Add your MCP server to the user's configuration
  * `"aistudio"`—Send the current page to Google AI Studio
  * `"assistant"`—Open the AI assistant with the current page as context
  * `"copy"`—Copy the current page as Markdown to the clipboard
  * `"chatgpt"`—Send the current page to ChatGPT
  * `"claude"`—Send the current page to Claude
  * `"cursor"`—Install your hosted MCP server in Cursor
  * `"devin"`—Send the current page to Devin
  * `"devin-mcp"`—Install your hosted MCP server in Devin
  * `"download-pdf"`—Download the current page as a PDF
  * `"download-spec"`—Download the deployment's OpenAPI specs (single file, or zipped if multiple)
  * `"grok"`—Send the current page to Grok
  * `"mcp"`—Copy your MCP server URL to the clipboard
  * `"perplexity"`—Send the current page to Perplexity
  * `"view"`—View the current page as Markdown in a new tab
  * `"vscode"`—Install your hosted MCP server in VS Code
  * `"devin-desktop"`—Open Devin Desktop with the current page as context

  Define custom options as objects:

  <Expandable title="Custom option">
    <ResponseField name="title" type="string">
      Display title for the custom option.
    </ResponseField>

    <ResponseField name="description" type="string">
      Description text for the custom option.
    </ResponseField>

    <ResponseField name="icon" type="string">
      Icon for the custom option. Supports icon library names, URLs, paths, or SVG code.
    </ResponseField>

    <ResponseField name="href" type="string or object">
      Link destination. Can be a URL string or an object with `base` and optional `query` parameters.

      Available placeholder values:

      * `$page`—Current page content
      * `$path`—Current page path
      * `$mcp`—MCP server URL
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="contextual.display" type="&#x22;header&#x22; | &#x22;toc&#x22;">
  Where to display the contextual options. Choose `header` to show them in the top-of-page context menu, or `toc` to show them in the table of contents sidebar. Defaults to `header`.
</ResponseField>

```json docs.json theme={null}
"contextual": {
  "options": ["copy", "view", "chatgpt", "claude"],
  "display": "header"
}
```

***

### `redirects`

**Type:** `array of object`

Redirects for moved, renamed, or deleted pages. Use these to preserve links when you reorganize your content.

<ResponseField name="redirects[].source" type="string">
  The path to redirect from. Example: `/old-page`
</ResponseField>

<ResponseField name="redirects[].destination" type="string">
  The path to redirect to. Example: `/new-page`
</ResponseField>

<ResponseField name="redirects[].permanent" type="boolean">
  If `true`, issues a permanent redirect (308). If `false`, issues a temporary redirect (307). Defaults to `true`.
</ResponseField>

```json docs.json theme={null}
"redirects": [
  {
    "source": "/old-page",
    "destination": "/new-page"
  },
  {
    "source": "/temp-redirect",
    "destination": "/destination",
    "permanent": false
  }
]
```

***

### `errors`

**Type:** `object`

Custom error page settings.

<ResponseField name="errors.404" type="object">
  Settings for the 404 "Page not found" error page.

  <Expandable title="errors.404">
    <ResponseField name="redirect" type="boolean">
      Whether to automatically redirect to the home page when a page is not found. Defaults to `true`.
    </ResponseField>

    <ResponseField name="title" type="string">
      Custom title for the 404 page.
    </ResponseField>

    <ResponseField name="description" type="string">
      Custom description for the 404 page. Supports MDX formatting including links, bold, and italic text, and custom components.
    </ResponseField>
  </Expandable>
</ResponseField>

```json docs.json theme={null}
"errors": {
  "404": {
    "redirect": false,
    "title": "Page not found",
    "description": "The page you're looking for doesn't exist. [Go home](/)."
  }
}
```

***

### `variables`

**Type:** `object`

Global variables for use throughout your documentation. Mintlify replaces `{{variableName}}` placeholders with the defined values at build time.

<ResponseField name="variables.[variableName]" type="string">
  A key-value pair where the key is the variable name and the value is the replacement text.

  * Variable names can contain alphanumeric characters and hyphens.
  * You must define all variables referenced in your content or the build fails.
  * Mintlify sanitizes values to prevent XSS attacks.
</ResponseField>

```json docs.json theme={null}
"variables": {
  "version": "2.0.0",
  "api-url": "https://api.example.com"
}
```

In your content, reference variables with double curly braces:

```mdx theme={null}
The current version is {{version}}. Make requests to {{api-url}}.
```

***

### `metadata`

**Type:** `object`

Page-level metadata settings applied globally.

<ResponseField name="metadata.timestamp" type="boolean">
  Enable a last-modified date on all pages. When enabled, pages display the date the content was last modified. Defaults to `false`.

  You can override this setting on individual pages using the `timestamp` frontmatter field. See [Pages](/docs/organize/pages#last-modified-timestamp) for details.
</ResponseField>

```json docs.json theme={null}
"metadata": {
  "timestamp": true
}
```


# Quickstart
Source: https://www.mintlify.com/docs/quickstart

Get started with Mintlify by deploying your documentation site in minutes and making your first content change with the web editor or Git.

After you complete this guide, you'll have a live documentation site ready to customize and update.

<Visibility>
  <Tip>
    Using an AI agent?

    Copy the following prompt to have your agent set up your site for you. It directs your agent to create your account and deploy your site. It also adds the Mintlify [skill](/docs/ai/skillmd) and [Model Context Protocol (MCP) server](/docs/ai/model-context-protocol) for better results when you update your content.

    The prompt splits the quickstart into tasks your agent can complete and directs it to ask you for any information it needs while getting everything set up.
  </Tip>

  <Prompt description="Copy and paste to have your agent set up your Mintlify site.">
    Get my documentation live on a published Mintlify site. You are successfully done when you give me the live URL and confirm it loads. Tell me clearly whenever a step needs my input—do everything else yourself. If this prompt was pasted before (for example, after a restart), continue from where things left off instead of starting over. If you don't have terminal or command execution access, tell me to follow the manual steps at [mintlify.com/start](https://mintlify.com/start) instead. Everything below requires running commands and requires Node.js v20.17.0+ (LTS versions recommended).

    1. Ask for my existing content that will be used for my Mintlify site. This may be a local folder or a repo. Verify the source before building: echo back exactly what you're reading and list its top-level contents so I can confirm it's right. If you can't access something I named (private repos return 404, same as nonexistent), stop and ask. Never substitute a different source.
    2. Check whether `mint` is installed with `mint --version`. If it's missing, install it with `npm i -g mint` (or `pnpm add -g mint`). If it's already installed, run `mint update` instead of reinstalling.
    3. Run `mint status`. If it already shows an organization, skip to step 7.
    4. Needs me: If `mint status` shows I'm not logged in, ask me directly whether I already have a Mintlify account. Don't guess.
       * If I have one: run `mint login`. You need me for browser steps and to approve access.
       * If I don't: ask me for my first name, last name, company, and email if I haven't given them already—never invent these. Run `mint signup --firstName [firstName] --lastName [lastName] --company [company] --email [email]` as a background task since it blocks until I click a verification link that can take several minutes.
    5. Needs me: I'll check my email and click the verification link. That opens a browser tab that automatically finishes the rest of account creation/logging in. I must approve the CLI, then connect a GitHub repository or let Mintlify host one. Tell me clearly this step is mine, then wait for it before continuing.
    6. Run `mint status` again to confirm an organization and subdomain now exist. The subdomain isn't provisioned until I select or connect a repository during the step 5 browser flow — so if `mint status` shows my organization but no subdomain yet, that almost always means I haven't finished the repo step, not that anything is broken. Don't treat it as an error or poll blindly: wait until I confirm I've completed onboarding, then re-run `mint status`. Provisioning can still lag a few seconds after that, so retry a few times before concluding something is wrong.
    7. Needs me: ask for the URL of the repository connected to my Mintlify project — `mint status` doesn't expose it, so you can't look it up yourself. Clone it once I give it to you.
    8. Check what's in that repo. If I connected my own existing docs repo, my content is already there — don't overwrite it. If Mintlify created the repo, it contains starter template content — replace that with my actual docs content from step 1. Only use `mint new [directory]` if I want a different theme or template than what's in the repo — scaffold it locally, then use its output in place of the seeded content.
    9. Preview with `mint dev`, which generally starts on `http://localhost:3000` unless that port is in use. It blocks until stopped, so run it as a background task. Verify the preview loads, then stop it before continuing.
    10. Commit and push your changes. Mintlify deploys automatically on push.
    11. Needs me: If I want a custom domain, run `mint add-domain <domain>`. It prints the DNS records I need to add with my domain provider. Tell me the DNS records, since only I can configure them at my registrar. Make it clear that this is a step I must complete.
    12. Confirm my site is live: fetch `https://<subdomain>.mintlify.site` (find the subdomain via `mint status`) and confirm it loads. If I added a custom domain in step 11, also fetch that domain and confirm it loads before calling this step done—DNS propagation can lag, so retry a few times before treating a failed fetch as an error.
    13. Set yourself up to keep working here: install the [Mintlify skill](https://mintlify.com/docs/ai/skillmd.md) with `npx skills add https://mintlify.com/docs`, then register the [admin MCP server](https://mintlify.com/docs/ai/model-context-protocol.md) at `https://mcp.mintlify.com` for your specific tool. For example, `claude mcp add --transport http mintlify https://mcp.mintlify.com` for Claude Code or fetch [https://mintlify.com/docs/ai/mintlify-mcp.md](https://mintlify.com/docs/ai/mintlify-mcp.md) for instructions for Claude, Cursor, Codex, or ChatGPT. Do this step yourself—don't ask me to run these commands.
    14. Needs me: the first admin MCP tool call opens a browser window for OAuth login. Approve it there. Most tools don't load newly added MCP servers mid-session — if the Mintlify tools don't show up, tell me to restart you and we'll pick up from here.
    15. If any command fails in a way not covered above, stop and tell me the exact error rather than guessing or retrying blindly. If it looks like something's wrong on Mintlify's end rather than in what you're doing, check [https://status.mintlify.com](https://status.mintlify.com) or point me to [https://mintlify.com/docs/contact-support](https://mintlify.com/docs/contact-support).
  </Prompt>
</Visibility>

<Visibility>
  ## Set up Mintlify for the user

  If the user asks you to set up Mintlify, a documentation site, or a local Mintlify project, complete the following workflow yourself. Ask the user only for information or approvals you cannot supply. Do not send the user to the browser-first quickstart unless you cannot run terminal commands.

  1. Run `node --version` and confirm it reports Node.js v20.17.0 or newer, preferring an LTS release.
  2. Run `mint --version`. If the command is unavailable, install the CLI with `npm i -g mint` or `pnpm add -g mint`. If the command succeeds, run `mint update`.
  3. Run `mint status` before starting authentication. If it already shows an organization, keep the existing session and do not create another account.
  4. Run `mint login` if the user has an account. Otherwise, ask for their first name, last name, company, and email, then run:

     ```bash theme={null}
     mint signup \
       --firstName <first-name> \
       --lastName <last-name> \
       --company <company> \
       --email <email>
     ```

     `mint signup` waits for email verification, so keep it running as a background process when your environment supports background commands. Tell the user to click the verification link and approve the CLI in the browser. Never invent signup details.
  5. After the user finishes verification and onboarding, run `mint status` again. Confirm that it reports their email, organization, and subdomain. If the organization exists but no subdomain appears, ask the user to finish selecting or connecting a GitHub repository in the onboarding browser tab, then retry.
  6. If the user has an existing documentation repository, clone or open it. Preserve its content. For a new local project, scaffold into a new, empty directory with either `mint new <directory> --name <name> --theme <theme>` or `mint new <directory> --template <template-name>`. Ask which theme or template they want if they have not specified one. Do not use `--force` on a directory containing user files.
  7. Run `mint dev --no-open` from the directory containing `docs.json` as a background process. Confirm the local URL loads, report it to the user, and stop the process when it is no longer needed.
  8. Run `mint validate` and `mint broken-links`. Fix issues caused by your changes before continuing.
  9. If a Git repository backs the project and the user asked for deployment, commit and push the changes. A push to the production branch triggers a deployment. Do not overwrite an existing repository with starter content.
  10. Run `mint status` to get the configured subdomain, then verify that `https://<subdomain>.mintlify.site` loads before reporting that deployment is complete.

  Have the user complete browser actions only for email verification, OAuth approval, and connecting or authorizing GitHub. Keep ownership of the terminal workflow and resume after each user action. For command flags and troubleshooting, use the [CLI command reference](/docs/cli/commands).
</Visibility>

## Before you begin

Mintlify uses a docs-as-code approach to manage your documentation. Every page on your site has a corresponding file stored in your documentation <Tooltip>repository</Tooltip>.

When you connect your documentation repository to your project, you can work on your documentation locally or in the web editor and sync any changes to your remote repository.

## Deploy your documentation site

<Visibility>
  Go to [mintlify.com/start](https://mintlify.com/start) and complete the onboarding process. During onboarding, you'll connect your GitHub account, create or select a repository for your documentation, and install the GitHub App to enable automatic deployments.

  After onboarding, your documentation site deploys and is accessible at your `.mintlify.site` URL.

  <Accordion title="Optional: Skip connecting a Git provider during onboarding">
    If you want to get started quickly without connecting your own repository, you can skip the Git provider connection during onboarding. Mintlify creates a private repository in a private organization and automatically configures the GitHub App for you.

    This lets you use the web editor immediately. If you want to use your own repository later, go to [Git Settings](https://app.mintlify.com/settings/deployment/git-settings) in your dashboard to migrate your content using the Git setup wizard. See [Clone to your own repository](/docs/deploy/github#clone-to-your-own-repository) for details.
  </Accordion>
</Visibility>

<Visibility>
  Use the preceding CLI setup workflow. Initiate the corresponding `mint signup` or `mint login` command. Account verification and GitHub authorization open browser pages; have the user approve them. Continue the setup when they finish. Do not consider setup complete until `mint status` reports a subdomain and the deployed `.mintlify.site` URL loads.
</Visibility>

## View your deployed site

Your documentation site is now deployed at `https://<your-project-name>.mintlify.site`.

Find your exact URL on the **Overview** page of your [dashboard](https://app.mintlify.com/).

<Frame>
  <img alt="Overview page of the Mintlify dashboard." />

  <img alt="Overview page of the Mintlify dashboard." />
</Frame>

<Tip>
  Your site is ready to view immediately. Use this URL for testing and sharing with your team. Before sharing with your users, you may want to add a [custom domain](/docs/customize/custom-domain).
</Tip>

## Make your first change

<Tabs>
  <Tab title="CLI">
    <Steps>
      <Step title="Install the CLI">
        The CLI requires [Node.js](https://nodejs.org/en) v20.17.0 or higher. Use an LTS version for stability.

        <CodeGroup>
          ```bash npm theme={null}
          npm i -g mint
          ```

          ```bash pnpm theme={null}
          pnpm add -g mint
          ```
        </CodeGroup>

        See [Install the CLI](/docs/cli/install) for full details and troubleshooting.
      </Step>

      <Step title="Clone your repository">
        If you haven't already cloned your repository locally, clone it using Git:

        ```bash theme={null}
        git clone <your-repository-url>
        ```

        If your repository is in Mintlify's private organization, see [Clone to your own repository](/docs/deploy/github#clone-to-your-own-repository) to move it to your account first.
      </Step>

      <Step title="Edit a page">
        Open `index.mdx` in your preferred editor and update the description in the frontmatter:

        ```mdx theme={null}
        ---
        title: "Introduction"
        description: "Your custom description here"
        ---
        ```
      </Step>

      <Step title="Preview locally">
        Run the following command from your documentation directory:

        ```bash theme={null}
        mint dev
        ```

        View your preview at `http://localhost:3000`.
      </Step>

      <Step title="Push your changes">
        Commit and push your changes to trigger a deployment:

        ```bash theme={null}
        git add .
        git commit -m "Update description"
        git push
        ```

        Mintlify automatically deploys your changes. View your deployment status on the [Overview](https://app.mintlify.com/) page of your dashboard.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Web editor">
    <Steps>
      <Step title="Open the web editor">
        Navigate to the [web editor](https://app.mintlify.com/editor) in your dashboard.
      </Step>

      <Step title="Edit a page">
        Open the **Introduction** page and update the description.

        <Frame>
          <img alt="Introduction page open in the web editor with the description edited to say Hello world!." />

          <img alt="Introduction page open in the web editor with the description edited to say Hello world!." />
        </Frame>
      </Step>

      <Step title="Publish">
        Click **Publish** in the top-right of the web editor toolbar.
      </Step>

      <Step title="View live">
        On the [Overview](https://app.mintlify.com/) page of your dashboard, you can see your site's deployment status. When it finishes deploying, refresh your documentation site to see your changes live.
      </Step>
    </Steps>
  </Tab>
</Tabs>

## Next steps

<Card title="Use the web editor" icon="mouse-pointer-2" href="/editor/index">
  Edit documentation in your browser and preview how your pages look when published.
</Card>

<Card title="Explore CLI commands" icon="terminal" href="/cli/index">
  Find broken links, check accessibility, validate OpenAPI specs, and more.
</Card>

<Card title="Add a custom domain" icon="globe" href="/customize/custom-domain">
  Use your own domain for your documentation site.
</Card>


# Customize agent behavior
Source: https://www.mintlify.com/docs/agent/customize

Customize agent behavior with an `AGENTS.md` configuration file to control how the agent handles documentation tasks and follows your conventions.

Create a `.mintlify/AGENTS.md` file at the root of your documentation project to customize the agent's behavior (`Agents.md` is also an accepted filename).

<Warning>
  Place your `AGENTS.md` file inside the `.mintlify/` directory, not at the root of your project. If you store the file at the root of your project, visitors can access your custom instructions at the `/agents.md` path. Mintlify does not serve the `.mintlify/` directory publicly, so visitors cannot access your `AGENTS.md` file there.

  If you must store your `AGENTS.md` file at the root of your project or any other directory, add it to your [`.mintignore`](/docs/organize/mintignore) file to exclude it from your documentation site.
</Warning>

Add any instructions that you want the agent to follow. The agent appends these instructions to its system prompt, so the instructions apply to all tasks whether you use the agent in your dashboard, on Slack, or via the API.

<Note>
  The agent only reads `AGENTS.md`. It does not read other agent instruction files that may exist in your repository, such as `CLAUDE.md`, `.cursorrules`, `.github/copilot-instructions.md`, or `GEMINI.md`, even if your `AGENTS.md` references them.

  If you use other tools that rely on their own instruction files, consolidate the instructions you want the Mintlify agent to follow into `.mintlify/AGENTS.md`. You can keep your other files for those tools, but duplicate any shared guidance into `AGENTS.md` so the agent picks it up.
</Note>

## What to include in AGENTS.md

Consider adding instructions for:

* **Style preferences**: Voice, tone, formatting, and terminology specific to your documentation.
* **Code standards**: Programming languages, frameworks, and coding conventions to use in examples.
* **Content requirements**: What sections or information to include for different types of pages.
* **Project context**: Specific details about your product, architecture, or user base that inform documentation decisions.

## Example AGENTS.md file

```markdown .mintlify/AGENTS.md theme={null}
# Documentation agent instructions

## Code examples
- Use TypeScript for all code examples. Our users are primarily TypeScript developers.
- Always include error handling in API call examples.
- Show both success and error response examples for all endpoints.
- Include import statements at the top of code examples.

## API documentation standards
- Every endpoint must document: authentication requirements, rate limits, and common error codes.
- Use real-world parameter values in examples (not foo/bar placeholders).
- Include a complete request/response cycle for each endpoint.

## Style and formatting
- Write for developers with 2-5 years of experience. Don't oversimplify, but explain non-obvious concepts.
- Use active voice and second person ("you").
- Date format: ISO 8601 (YYYY-MM-DD).
- When referencing UI elements, use bold: **Settings** button.

## What to include
- Add prerequisite sections to guides when users need API keys, environment setup, or dependencies.
- Include "Next steps" sections linking to related documentation.
- Add troubleshooting sections for common issues we see in support tickets.
```


# Write effective prompts
Source: https://www.mintlify.com/docs/agent/effective-prompts

Write clear, specific prompts to get better results from the Mintlify agent, with examples of effective instructions and tips for common patterns.

Think of the agent as a helpful assistant that needs your guidance to complete tasks. Give it clear instructions and context. More focused tasks are easier to complete, so break down complex projects into smaller steps.

## Make prompts specific and outcome-focused

Generic prompts like `@mintlify Improve the onboarding page` apply general best practices, but may not improve content in the specific way that you were picturing.

Try prompts based on outcomes you want your users to achieve or problems that they encounter.

* `@mintlify A lot of users have trouble installing the CLI. Review the onboarding page and update the docs so that users can easily install the CLI`
* `@mintlify Developers keep getting 401 errors when following our authentication guide. Review the auth docs and add clearer examples showing how to properly format the API key`

## Use broad prompts for maintenance tasks

Use broad prompts for general content maintenance like fixing typos, updating redirects, or renaming a feature throughout your docs.

* `@mintlify Find and fix all typos in the docs`
* `@mintlify change all unordered lists to use * instead of -`

## Specify a domain name for multi-site organizations

If you have multiple documentation sites, include the `subdomain` parameter in your message to specify which documentation set the agent should work on.

To find your domain name, look at your dashboard URL for the documentation set you want to update. The domain name is the last part after your organization name. For example, if your dashboard URL is `https://app.mintlify.com/org-name/domain-name`, your domain name is `domain-name`.

Use the format `@mintlify subdomain=<your-domain-name> <your-prompt>` to prompt the agent to work on a specific documentation set.

* `@mintlify subdomain=public-docs Add a new section to the quickstart about inviting collaborators based on this PR`: Prompts the agent to update the quickstart only on the `public-docs` site.
* `@mintlify subdomain=customer-docs Update the auth docs for the new authentication method`: Prompts the agent to update the auth docs only on the `customer-docs` site.


# What is the agent?
Source: https://www.mintlify.com/docs/agent/index

Learn how the Mintlify agent researches, plans, and writes documentation, then opens pull requests with proposed changes for your team to review.

<Info>
  The agent requires a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=agent).
</Info>

The agent is an AI tool that creates pull requests with proposed changes to your documentation based on your prompts. When you send a request, the agent:

* **Researches**: Searches and reads your existing documentation, any connected repositories, relevant context, and the web.
* **Plans**: Creates a structured task list for complex documentation work.
* **Writes**: Generates or updates content following writing standards and best practices.
* **Validates**: Runs Mintlify CLI checks to ensure documentation builds correctly.
* **Publishes changes**: Opens a pull request with proposed changes for review, or commits directly to your deployment branch, depending on your [review process setting](#choose-how-the-agent-publishes-changes).

## What you can do with the agent

Use the agent to:

* Write new content based on your prompts, pull requests, Slack threads, or file attachments.
* Update existing documentation for new features or API changes.
* Process and include images, diagrams, and other files from Slack attachments.
* Search and revise code examples and API references across your docs.
* Reference source code from any repository that has the Mintlify GitHub App installed.
* Automate documentation maintenance with automations.
* Answer questions about your docs and technical writing topics.
* Address code review feedback to maintain documentation quality.
* Capture knowledge from Slack conversations and pull requests before it gets lost.
* Navigate and coordinate changes across multiple files and directories efficiently.

## Connect your GitHub account

By default, the agent opens pull requests attributed to the Mintlify bot. To attribute pull requests to you, connect your GitHub account on the [My profile](https://app.mintlify.com/settings/account) page of the dashboard.

## Choose how the agent publishes changes

By default, the agent opens a pull request for every change so your team can review it before it ships. If Mintlify hosts your deployment, the agent commits changes directly to your deployment branch so changes publish immediately.

For deployments connected to your own Git provider, click **Configure Slack** on the [Automations](https://app.mintlify.com/products/automations) page of your dashboard, then set **Review process** in Slack settings:

* **Create a pull request**: The agent commits to a new branch and opens a pull request against your deploy branch. Use this option when you want a human to review changes before they publish.
* **Push to main**: The agent commits directly to your deploy branch, and changes publish as soon as the agent finishes. Use this option when you trust the agent to publish without review, for example on a staging deployment.

<Note>
  If your deploy branch has branch protection rules that block direct pushes, the agent opens a pull request even if you set **Review process** to **Push to main**.
</Note>

## Connect repositories as context

The agent can only access repositories that you connect through the Mintlify GitHub App. Configure which repositories the agent can access in the [GitHub App settings](https://github.com/apps/mintlify/installations/new). For GitLab, use [Git Settings](https://app.mintlify.com/settings/deployment/git-settings).

## Use a static IP for Git requests

<Info>
  Static agent egress requires an [Enterprise plan](https://mintlify.com/pricing?ref=static-agent-egress).
</Info>

If your Git provider restricts access with an IP allowlist, Mintlify can route Git requests from agent sandboxes through a static IP address.

Contact Mintlify about the deployment that you want to enable static agent egress for. Once enabled, the static address applies to Git operations from the agent and automations, including cloning, fetching, and pushing connected repositories.

<Note>
  Static agent egress applies only to Git requests from agent sandboxes. Other outbound requests do not use this static IP address.
</Note>

## Use AI tools alongside the agent

The agent works asynchronously through pull requests, but you can also use AI coding tools like Cursor or Claude Code locally for fast, iterative edits. Install the Mintlify [skill](/docs/ai/skillmd) and connect the [Model Context Protocol (MCP) server](/docs/ai/model-context-protocol) so your editor has the same context the agent uses.

To let an external agent edit your content directly through MCP tool calls, connect it to the [Mintlify MCP server](/docs/ai/mintlify-mcp).

<Prompt description="Install the Mintlify skill and MCP servers for AI coding tools.">
  Install the Mintlify skill for context on project structure, components, and documentation best practices:

  npx skills add [https://mintlify.com/docs](https://mintlify.com/docs)

  Add the Mintlify Docs MCP server for documentation search:

  [https://mintlify.com/docs/mcp](https://mintlify.com/docs/mcp)

  Add the Mintlify MCP server for dashboard access and content management:

  [https://mcp.mintlify.com](https://mcp.mintlify.com)
</Prompt>

## Next steps

<Card title="Connect Slack" icon="slack" href="/agent/slack">
  Add the agent to your Slack workspace.
</Card>

<Card title="Customize behavior" icon="wrench" href="/agent/customize">
  Configure the agent with an `AGENTS.md` file.
</Card>

<Card title="Write effective prompts" icon="pen" href="/agent/effective-prompts">
  Get better results with focused prompts.
</Card>

<Card title="Automate with automations" icon="refresh-cw" href="/automations/index">
  Automate recurring tasks and documentation maintenance with automations.
</Card>


# Add the agent to Slack
Source: https://www.mintlify.com/docs/agent/slack

Install the Mintlify agent in Slack to ask questions about your product, create content updates from team conversations, and capture knowledge in pull requests.

<Note>
  If your Slack Workspace Owner requires admin approval to install apps, ask them to approve the Mintlify app before you connect it.
</Note>

Use the agent in Slack to update your content, ask questions, and capture team knowledge. Mention the agent in a channel to use it collaboratively, or send it a direct message to use it privately.

<Tip>
  The Slack app and third-party integrations work together. Install the Slack app to talk with the agent and give the agent and automation runs access to permitted Slack content. Then connect [integrations](/docs/automations/integrations) so the agent can also use context from apps like Notion, Jira, Linear, or Google Drive.
</Tip>

## Connect your Slack workspace

<Note>
  Each Slack workspace can connect to only one Mintlify organization at a time. If you try to install the agent into a workspace that is already connected to a different organization, the installation fails with a "wrong organization" error. Uninstall the app from the other organization first, or use a different Slack workspace.

  You can install the Slack agent even if you don't have a Mintlify-hosted deployment. The agent still works for question answering and conversations. Features that open pull requests require a connected repository.
</Note>

1. Navigate to the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.
2. Click **Connect Slack**.
3. Follow the Slack prompts to install the `mintlify` app in your workspace and grant the requested permissions.
4. Confirm the connection in your Mintlify dashboard to your Slack workspace.
5. Test that the agent is working and responds when you:
   * Send a direct message to the agent.
   * Mention the agent with `@mintlify` in a channel.

<Warning>
  On Slack Enterprise Grid, you must install the app to the specific workspace where you want to use the agent. If you skip this step, the agent appears available at the organization level but does not respond in your workspace.

  To add the app to a workspace, open your organization's app management page (a URL like `https://app.slack.com/manage/<your-org-id>/integrations/installed`). Find the `mintlify` app and install it to your workspace.
</Warning>

### Disconnect the agent

To remove the agent from your Slack workspace:

1. Navigate to the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.
2. Click **Configure Slack**.
3. Click **Disconnect** to revoke the connection between Mintlify and your workspace.
4. In Slack, navigate to **Manage apps**.
5. Click **Remove** on the Mintlify app.

When you disconnect the Slack app, the agent stops responding to mentions and direct messages, and automations that post to Slack stop delivering notifications.

### Reconnect or reinstall the agent

To reauthorize the agent, reinstall the app from your Mintlify dashboard. Reauthorize when you need to grant new permissions after a Slack scope update or when you need to recover from a revoked token.

When you reinstall the agent into a workspace that is already connected to your organization, Mintlify refreshes the stored bot token in place. Your existing channels and threads remain intact.

<Tip>
  If your organization has multiple deployments, the agent asks you to select which deployment to work with the first time you send a request.

  Your preferred deployment is personal to your Slack account and does not affect
  other team members. You can switch to a different deployment at any time during a
  conversation by clicking the **Switch deployment** button on the agent's status
  message in the thread. The agent retains your conversation history so you can
  continue where you left off with the new deployment.
</Tip>

## Use the agent in Slack

Once connected, you can:

* Send direct messages to the agent to use it privately.
* Mention `@mintlify` in a channel to use it publicly and collaboratively.
* Attach files and images directly to your messages for the agent to process and include in your docs.
* Continue conversations in threads to iterate on changes or ask follow-up questions. The agent reuses files, images, and emoji reactions from earlier in the thread as context for follow-up requests, so you don't have to reupload them.
* Share pull request links with the agent to update related documentation.

## Ask questions about your docs

Ask the agent questions about your product or documentation and receive answers in the thread.

* **New question**: Send a direct message to the agent or mention `@mintlify` in a channel with your question.
* **Existing thread**: Reply in the thread and mention `@mintlify` with a follow-up question.

Example questions:

* "Which pages mention the API rate limit?"
* "How do I set up authentication?"
* "How is our navigation structured?"

## Use connected integrations

<Info>
  Integrations require an [Enterprise plan](https://mintlify.com/pricing?ref=automations).
</Info>

The Slack agent can use connected third-party apps as read-only tools while answering questions or updating your documentation.

* **Shared integrations** are available to everyone in your organization.
* **Personal integrations** use the account connected by the teammate who is chatting with the agent. For example, a Google Drive search uses that teammate's Drive connection.

You do not have to select integrations for each Slack conversation. Ask the agent to use a connected app naturally in your request, such as:

* "Compare this Linear issue with the launch plan in the connected Google Drive."
* "Update the migration guide based on the latest Jira issue."
* "What does our Notion launch brief say about availability?"

Prompt the agent to connect any integrations you want to use. Complete the authorization link it returns, then send another message in the same thread so the agent can confirm the connection.

See [Integrations](/docs/automations/integrations) for supported apps, connection scopes, and permissions.

## Update documentation

Use the agent to update your documentation with a new request or in an existing thread.

* **New request**: Send a direct message to the agent or mention `@mintlify` in a channel with instructions on what to update.
* **Existing thread**: Reply in the thread and mention `@mintlify` with instructions on what to update.
* **With attachments**: Upload images, diagrams, PDFs, SVGs, code files, or other documents with your message. The agent automatically processes and includes them in your documentation. In a thread, the agent has access to images and files shared in earlier messages, so you can reference them in follow-up requests without reuploading.

The agent reads the context of the request or thread and updates your connected repository. Depending on your [review process setting](/docs/agent/index#choose-how-the-agent-publishes-changes), the agent either opens a pull request or commits directly to your deployment branch.

## Continue an automation run

When an [automation](/docs/automations) posts a [Slack notification](/docs/automations/manage#slack-notifications) about a pull request it opened, reply in that thread and mention `@mintlify` to continue the work. The agent checks out the automation's branch and pushes your requested changes as follow-up commits to the same pull request, rather than opening a new one.

You can also share a link to an automation's pull request directly with the agent to continue it from a new thread.

## Manage automations

Ask the agent to create, configure, or run [automations](/docs/automations). The agent can perform the same actions as you on the [Automations](https://app.mintlify.com/products/automations) page of your dashboard.

Example prompts:

* "Create an automation that drafts a changelog entry every time we merge to main."
* "Set up an automation that updates the docs whenever a Jira issue closes."
* "Turn off the weekly changelog automation."
* "Run the automation that reviews assistant conversations right now."

You can also ask the agent about automation activity, such as recent runs, failures, or credit use.

* "How can I make my automations more credit efficient?"
* "Why did the last run of the code change automation fail?"

## Reference other repositories

The agent can read source code from any repository connected through the [GitHub App](/docs/deploy/github) or [GitLab integration](/docs/deploy/gitlab), even if it isn't your documentation repository. This lets the agent build deeper context to guide documentation updates.

When you mention another repository in your request, the agent clones it on demand and inspects the relevant files before drafting changes.

Example prompts:

* "Update the authentication guide based on the changes in `acme/api-server/src/auth.ts`."
* "Document the new endpoints added in `acme/backend#1234`."
* "What repositories do you have access to?"

The agent treats cloned repositories as read-only. It uses them for context, but only writes changes to your documentation repository.

## Track progress in real time

When the agent is making changes to your documentation, it provides live feedback in the Slack thread.

* **Status updates**: A live-updating message shows what the agent is doing, such as how many files it has searched, read, and edited.
* **Task progress**: When the agent breaks your request into multiple tasks, it displays a checklist so you can track progress on each one.
* **Questions**: If the agent needs more information, it presents options for you to select from or reply in the thread with a custom answer.
* **Interruptions**: If you send a follow-up message while the agent is still working, it stops the current task and starts on the new one.
* **Completion**: When the agent finishes, it posts a summary with a link to the pull request or commit and a link to open the changes in the web editor.

## Roles and permissions

The agent's capabilities in Slack match users' [roles](/docs/dashboard/roles).

* **Admins and editors**: Can ask questions and make documentation changes. The agent has access to file editing and pull request tools.
* **Viewers**: Can ask questions only. The agent runs in read-only mode for Mintlify tools.

To change a teammate's permissions, update their role on the [Members](https://app.mintlify.com/settings/organization/members) page of your dashboard.

## Best practices

* **Be specific**: Tell the agent exactly what you want to know or what you want changed and where.
* **Add context**: If a thread doesn't contain all the necessary information, include additional details in your message to the agent.
* **Review carefully**: Always review pull requests that the agent creates before merging them.


# Mintlify agent use cases and examples
Source: https://www.mintlify.com/docs/agent/use-cases

Explore real-world examples of using the Mintlify agent to automate documentation updates, capture knowledge, and maintain accurate docs.

The agent assists with many different documentation tasks. These examples show some of the ways you can integrate the agent into your documentation process. Try an approach that fits how your team currently works and adapt it to your specific needs.

## Iterate on a prompt in a Slack thread

Prompt the agent, then continue to mention it with `@mintlify` in the same thread to refine and iterate on the pull request that it creates.

For example: `@mintlify Our quickstart page needs a new section on inviting collaborators`. Then `@mintlify The new section should be called "Inviting collaborators"`. Followed by any other iterations.

## Start with the agent, finish manually

Prompt the agent to begin a project, then check out the branch it creates and finish the task in your local environment or the web editor. The agent can help you get started, then you can take over to complete the task.

For example: `@mintlify Update the quickstart page to include information about inviting collaborators` and then checkout the branch to make any additional changes using your preferred method.

## Update docs when merging feature changes

When you merge a feature pull request, share the PR link with the agent to update relevant docs.

For example: `@mintlify This PR adds a new authentication method. Update the docs to include the new auth flow: [PR link]`.

## Generate release notes from a pull request

Prompt the agent with a specific pull request to generate release notes or changelog updates based on the commit history.

For example: `@mintlify Generate release notes for this PR: [PR link]`.

## Address pull request review feedback

Share a pull request link with the agent to address reviewer comments and code review feedback on documentation pull requests.

For example: `@mintlify Address the review comments on this PR: [PR link]`.

## Generate code examples

Prompt the agent to generate code examples for features throughout your docs or on specific pages.

For example: `@mintlify Generate a code example to make the authentication method easier to understand`.

## Add images or files to your docs

Attach files or images directly to your Slack message when prompting the agent. The agent processes the attachment and includes it in the documentation. Supported attachments include images, PDFs, SVGs, and other documents.

For example: `@mintlify Add this diagram to the architecture overview page` with the image attached to the message.

## Review existing content

Prompt the agent to review existing content for technical accuracy, style, grammar, or other issues.

For example: `@mintlify Review the API rate limiting section. We changed limits last month`.

## Respond to user feedback

Prompt the agent with feedback from your users to make focused updates to your docs.

For example: `@mintlify Users are getting confused by step 3 in the setup guide. What might be making it unclear?`.

## Automate with automations

Create automations to automate recurring tasks and reactive maintenance tasks like writing changelogs or updating content when you add new features to your product.

See [Automations overview](/docs/automations/index) for more information.

## Automate with the API

Integrate the agent into your existing automation tools to automatically update documentation when code changes occur, trigger content reviews, or sync documentation updates across multiple repositories.

Use the agent endpoints to [create jobs](/docs/api/agent/v2/create-agent-job), [get job status](/docs/api/agent/v2/get-agent-job), and [send messages](/docs/api/agent/v2/send-message).

When creating jobs via the API, you can control whether pull requests open in draft mode using the `asDraft` parameter (defaults to `false`). Set `asDraft: true` to create draft pull requests, or keep the default to create non-draft pull requests ready for immediate review and merging in automated workflows.


# llms.txt
Source: https://www.mintlify.com/docs/ai/llmstxt

Automatically generate llms.txt and llms-full.txt files so AI tools like ChatGPT and Claude can index and understand your documentation.

The [llms.txt file](https://llmstxt.org) is an industry standard that helps large language models (LLMs) index content more efficiently, similar to how a sitemap helps search engines. AI tools can use this file to understand your documentation structure and find content relevant to user queries.

Mintlify automatically hosts an `llms.txt` file at the root of your project that lists all available pages in your documentation. This file is always up to date and requires zero maintenance. You can optionally add a custom `llms.txt` file to the root of your project.

<Note>
  Authentication affects `llms.txt` and `llms-full.txt` differently depending on your site configuration:

  * **Fully authenticated sites**: Both files require authentication. AI tools that cannot authenticate cannot access them.
  * **Partially authenticated sites**: Both files are publicly accessible, but only list public pages and exclude pages restricted to user groups.

  For more information on how authentication affects AI features, see [Feature availability](/docs/deploy/authentication-setup#feature-availability).
</Note>

View your `llms.txt` by appending `/llms.txt` to your documentation site's URL. Mintlify also hosts the file at `/.well-known/llms.txt` for compatibility with tools that follow the `.well-known` convention.

<PreviewButton href="https://mintlify.com/docs/llms.txt">Open the llms.txt for this site.</PreviewButton>

Mintlify adds HTTP headers to every page response so AI tools can discover your `llms.txt` files without prior knowledge of their location:

* `Link: </llms.txt>; rel="llms-txt", </llms-full.txt>; rel="llms-full-txt"`: Follows the standard HTTP `Link` header format for resource discovery.
* `X-Llms-Txt: /llms.txt`: A convenience header for tools that check for `llms.txt` support.

## Structure of the llms.txt file

An `llms.txt` file is a plain Markdown file that contains:

* **Site title** as an H1 heading.
* **Site description** as a blockquote summary below the title, sourced from the `description` field in your `docs.json` configuration.
* **Custom agent instructions** as an `Agent Instructions` block after the description, if you set [`markdown.instructions`](/docs/ai/markdown-export#custom-agent-instructions) in your `docs.json`.
* **Structured content sections** with links and a description of each page in your documentation.
* **API specification links** to your OpenAPI and AsyncAPI specs, if your documentation includes them.

The `llms.txt` file lists your pages alphabetically in the order they appear in your repository, starting from the root directory. Page links in the `llms.txt` file include a `.md` extension so AI tools can fetch the Markdown version of each page directly.

Each page's description comes from the `description` field in its frontmatter. Mintlify truncates descriptions at 300 characters and at the first line break. For API reference pages, the description also includes the specification information from the `openapi` or `api` frontmatter field. Pages without a `description` field appear in the `llms.txt` file without a description.

This structured approach allows LLMs to efficiently process your documentation at a high level and locate relevant content for user queries, improving the accuracy and speed of AI-assisted documentation searches.

<Note>
  Automatically generated `llms.txt` files cannot exceed 100,000 characters. If your documentation exceeds this limit, Mintlify truncates the file and appends a note listing the number of omitted pages. To list every page without truncation, add a [custom `llms.txt` file](#custom-files) at the root of your project.
</Note>

```mdx Example llms.txt theme={null}
# Site title

> A brief description of the documentation site.

## Docs

- [API](https://example.com/docs/api.md): Endpoint list and usage
- [Install](https://example.com/docs/install.md): Setup steps
- [Getting started](https://example.com/docs/start.md): Intro guide

## OpenAPI Specs

- [openapi](https://example.com/docs/openapi.json)

## AsyncAPI Specs

- [asyncapi](https://example.com/docs/asyncapi.yaml)
```

## llms-full.txt

The `llms-full.txt` file combines your entire documentation site into a single file as context for AI tools and LLM indexing.

Mintlify automatically hosts an `llms-full.txt` file at the root of your project. View your `llms-full.txt` by appending `/llms-full.txt` to your documentation site's URL. Mintlify also hosts the file at `/.well-known/llms-full.txt` for compatibility with tools that follow the `.well-known` convention.

<PreviewButton href="https://mintlify.com/docs/llms-full.txt">Open the llms-full.txt for this site.</PreviewButton>

## Custom files

To add a custom `llms.txt` or `llms-full.txt` file, create an `llms.txt` or `llms-full.txt` file at the root of your project. Adding a custom file overrides the automatically generated file of the same name. If you delete a custom file, Mintlify restores the automatically generated file.

Your custom `llms.txt` or `llms-full.txt` file must have a site title as an H1 heading. Other content is optional. See [Format](https://llmstxt.org/#format) in the `llms.txt` specification for more information on optional sections and best practices.


# Markdown export
Source: https://www.mintlify.com/docs/ai/markdown-export

Export clean Markdown versions of your documentation pages for AI tools, LLM integrations, and automated content processing workflows.

Markdown provides structured text that AI tools can process more efficiently than HTML, which results in better response accuracy, faster processing times, and lower token usage.

Mintlify automatically generates Markdown versions of pages optimized for AI tools and external integrations.

## .md URL extension

Add `.md` to any page's URL to view a Markdown version.

<PreviewButton href="https://mintlify.com/docs/ai/markdown-export.md">Open this page as Markdown</PreviewButton>

## Accept header

Send a request with `Accept: text/markdown` or `Accept: text/plain` to any page URL to receive the Markdown version instead of HTML. This is useful for AI tools and integrations that programmatically fetch documentation content.

```bash theme={null}
curl -L -H "Accept: text/markdown" https://mintlify.com/docs/ai/markdown-export
```

## Audience-specific content

Use the [visibility](/docs/components/visibility) component to customize content for human and AI audiences.

Content wrapped in `<Visibility for="humans">` appears on the web page, but not in Markdown output. Content wrapped in `<Visibility for="agents">` appears in Markdown output, but not on the web page.

```mdx theme={null}
<Visibility for="humans">
  Click the **Get started** button in the top-right corner to create your account.
</Visibility>

<Visibility for="agents">
  To create an account, call `POST /v1/accounts` with a valid email address.
</Visibility>
```

## API reference pages

By default, Markdown exports of API reference pages include the full OpenAPI or AsyncAPI specification so AI tools have complete context about each endpoint.

If you prefer to omit the spec from Markdown output, set `markdown.schema` to `false` in your `docs.json`:

```json theme={null}
"markdown": {
  "schema": false
}
```

## Custom agent instructions

To append your own guidance to the Markdown that Mintlify serves to AI agents, set `markdown.instructions` in your `docs.json`. Use it for site-wide directions like citing an API version, preferring a specific SDK, or following your terminology.

Provide a single string:

```json Example agent instructions string theme={null}
"markdown": {
  "instructions": "Always cite the API version. Prefer the TypeScript SDK in examples."
}
```

Or an array of strings, which Mintlify joins with line breaks:

```json Example agent instructions array theme={null}
"markdown": {
  "instructions": [
    "Always cite the API version.",
    "Prefer the TypeScript SDK in examples."
  ]
}
```

Mintlify renders your instructions as an `Agent Instructions` block in the Markdown output:

```md Example rendered agent instructions theme={null}
> ## Agent Instructions
> Always cite the API version.
> Prefer the TypeScript SDK in examples.
```

The block appears in:

* The Markdown export of every page, including API reference pages.
* Your [`llms.txt`](/docs/ai/llmstxt) file, after the site title and description.
* Your `llms-full.txt` file.

These instructions apply to every page. To tailor content for a single page or audience, use the [visibility](/docs/components/visibility) component instead.

## Authentication

Markdown export respects the same authentication rules as the HTML version of each page.

| Authentication mode    | Behavior                                                                                                                                        |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| No authentication      | All `.md` URLs are publicly accessible.                                                                                                         |
| Partial authentication | `.md` URLs for public pages are publicly accessible. `.md` URLs for protected pages require authentication and respect user group restrictions. |
| Full authentication    | All `.md` URLs require authentication and respect user group restrictions.                                                                      |

## Keyboard shortcut

Press <kbd>Command</kbd> + <kbd>C</kbd> (<kbd>Ctrl</kbd> + <kbd>C</kbd> on Windows) to copy a page as Markdown to your clipboard.


# Admin Model Context Protocol (MCP) server
Source: https://www.mintlify.com/docs/ai/mintlify-mcp

Give AI tools like Claude, ChatGPT, and Cursor write access to your Mintlify content and dashboard so they can edit pages, update settings, and open PRs.

## About the admin MCP

The admin MCP server gives AI tools write access to your Mintlify content and settings. Use it to update content and access your dashboard. With the admin MCP, you can use your preferred AI tools to edit pages, restructure navigation, update `docs.json`, open pull requests, change settings, create workflows, and more.

Connect an MCP client such as Claude, Claude Code, ChatGPT, or Cursor to the admin MCP server. Use it to collaborate on your Mintlify content and settings with the same tools you use to write code. All changes happen on a branch and require a pull request to merge. If your organization has multiple deployments, a single admin MCP connection can access and switch between all of them.

<Note>
  The admin MCP server allows AI tools to access your Mintlify dashboard. Treat it as a tool with write access. Connect it only from trusted AI tools and review every pull request before merging.
</Note>

The admin MCP is a hosted Mintlify service at `https://mcp.mintlify.com`. Every client connects to the same endpoint and authenticates with your Mintlify account.

### How the admin MCP differs from other Mintlify MCP servers

|              | Admin MCP                                                        | Search MCP                                     | Index MCP                                               |
| :----------- | :--------------------------------------------------------------- | :--------------------------------------------- | :------------------------------------------------------ |
| **Audience** | Your team                                                        | Your end users                                 | All developers and agents                               |
| **Access**   | Read, edit, restructure, save, create workflows, manage settings | Read and search one site's published pages     | Read and search all Mintlify sites                      |
| **Endpoint** | `https://mcp.mintlify.com`                                       | `/mcp` on your site domain                     | `https://index.mintlify.com`                            |
| **Output**   | Content edits, navigation changes, pull requests, workflow runs  | Search results and page content from your site | Search results and page content from all Mintlify sites |

See the [Mintlify Index MCP reference](/docs/search-index/mcp) for its tool inputs and rate limits.

## Prerequisites

Before connecting the admin MCP, confirm the following:

* **Mintlify account**: You need a Mintlify account with access to the project you want to edit. The OAuth session inherits your dashboard permissions, so admin-only actions (such as `update_config` on protected settings) require an admin role on the project.
* **Git provider access**: The GitHub, GitLab, or Bitbucket connection for the project must have write access to the deploy branch's repository. `save` opens PRs through the same integration used for normal deploys.
* **MCP client**: An MCP-capable AI tool such as Claude, Claude Code, ChatGPT, Cursor, or Codex.

## Connect to the admin MCP

You must have an interactive OAuth login against your Mintlify account to connect to the admin MCP. AI tools exchange that login for a session token scoped to one or more deployments, depending on how you grant access. A connection scoped to specific deployments can only check out those deployments. An organization-wide connection can check out any deployment in your organization.

<Tabs>
  <Tab title="Claude">
    <Steps>
      <Step title="Add the admin MCP as a custom connector">
        1. Navigate to the [Connectors](https://claude.ai/settings/connectors) page in the Claude settings.
        2. Click **Add custom connector**.
        3. Add the connector:
           * Name: Admin MCP
           * URL: `https://mcp.mintlify.com`
        4. Click **Add** and complete the OAuth login.
      </Step>

      <Step title="Use the MCP in a chat">
        Click the attachments button (the plus icon), then select your admin MCP server. Claude can now call the Mintlify admin MCP tools while answering your prompt.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Claude Code">
    Add the admin MCP server with the Claude Code CLI:

    ```bash theme={null}
    claude mcp add --transport http mintlify https://mcp.mintlify.com
    ```

    On first use, Claude Code opens a browser window to complete the OAuth login. After authenticating, Claude Code reuses the session for subsequent calls.
  </Tab>

  <Tab title="ChatGPT">
    Install the official Mintlify connector from the [ChatGPT app directory](https://chatgpt.com/apps/mintlify-mcp/asdk_app_6a4d5a687f0881918be3cb8b4b93773d) and complete the OAuth login when prompted. Once installed, ChatGPT can call the Mintlify admin MCP tools during a chat.
  </Tab>

  <Tab title="Cursor">
    1. Open the command palette with <kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> on Windows).
    2. Search for **Open MCP settings** and click **Add custom MCP**.
    3. In `mcp.json`, add the admin MCP:

    ```json theme={null}
    {
      "mcpServers": {
        "mintlify": {
          "url": "https://mcp.mintlify.com"
        }
      }
    }
    ```

    4. Reload Cursor and complete the OAuth login when prompted.
  </Tab>

  <Tab title="Codex">
    Add the admin MCP server to your Codex CLI config at `~/.codex/config.toml`:

    ```toml theme={null}
    [mcp_servers.mintlify]
    url = "https://mcp.mintlify.com"
    ```

    On first use, Codex opens a browser window to complete the OAuth login. After authenticating, Codex reuses the session for subsequent calls.

    See the [Codex MCP documentation](https://developers.openai.com/codex/mcp) for more details.
  </Tab>
</Tabs>

## How a session works

Every admin MCP session binds to a single Git branch. The flow is:

<Steps>
  <Step title="Discover deployments (optional)">
    If your connection has access to more than one deployment, call `list_deployments` to see which `subdomain` values you can check out. Skip this step if your connection covers only a single deployment.
  </Step>

  <Step title="Check out a branch">
    The first required call is `checkout {subdomain}`. It creates a fresh `mintlify-mcp/<slug>-<sha>` branch from that deployment's deploy branch (or attaches to an existing branch you name) and returns an `editorUrl` you can open to follow along in the dashboard editor.

    Call `list_branches` before `checkout` if you need to discover or filter existing branches in a deployment's repository.
  </Step>

  <Step title="Read, search, and edit">
    The AI uses tools like `search`, `read`, `list_nodes`, `edit_page`, `write_page`, `create_node`, and `update_config` to make changes. All edits buffer on the session branch in real time—nothing touches your deploy branch yet.
  </Step>

  <Step title="Review the diff">
    Call `diff` at any time to see exactly what changed since `main`. Open the `editorUrl` in your dashboard to see the same changes rendered.
  </Step>

  <Step title="Save">
    Call `save` to flush the branch to Git. `mode: "auto"` (default) opens a pull request. If the deployment's agent review setting is push-to-main and the deploy branch isn't protected, Mintlify merges the pull request immediately (the response includes `merged: true`). Use `mode: "pr"` to always open a pull request and leave it open for review. Use `mode: "commit"` to push directly to an existing PR branch without opening a new PR.
  </Step>

  <Step title="Discard if needed">
    Call `discard_session` to drop all in-session changes and release the branch.
  </Step>
</Steps>

<Tip>
  If your connection has access to multiple deployments, each checked-out deployment keeps its own session and branch in memory at the same time.

  Calling `checkout` again with a different `subdomain` or branch switches which session is active. It doesn't discard the others. To abandon an in-progress draft instead of switching away from it, call `discard_session`.
</Tip>

## What the admin MCP can do

### Content

* **`read`**: Fetch the full MDX of any page on the session branch.
* **`search`**: Find lines matching a substring or regular expression across every page.
* **`edit_page`**: Apply a targeted edit to a page.
* **`write_page`**: Overwrite a page's full MDX content.

### Navigation

* **`list_nodes`**: Walk the navigation tree with optional filters. Filter by `parentId` (use `recursive: true` to include all descendants), one or more node types, or any division scope: `language`, `version`, `tab`, `dropdown`, `anchor`, `product`, or `item`. Results paginate through an opaque `cursor`.
* **`create_node`**: Add a new page, group, tab, anchor, version, language, product, or dropdown.
* **`update_node`**: Update a node's properties in place (rename a group, change an icon, set a default version).
* **`move_node`**: Move a node, including renaming a page's path.
* **`delete_node`**: Remove a node from the navigation.

### Configuration

* **`update_config`**: Modify `docs.json` (theme, navigation roots, integrations, SEO settings).

### Session

* **`list_deployments`**: List the deployments your connection can access, returning each `{subdomain, name}`. Call this to discover which `subdomain` to pass to `checkout`.
* **`checkout`**: Bind a session to a branch for a given deployment `subdomain`, or switch which deployment's session is active.
* **`list_branches`**: List Git branches available for a deployment's project, with optional `query` filtering. Returns the branch names, total count, and the deploy branch. Call this before `checkout` to attach to an existing branch by name.
* **`get_session_state`**: Inspect the current branch, edited files, and pending nav diff.
* **`diff`**: List all changes between the session and `main`.
* **`save`**: Open a pull request or commit to the session branch. If your deployment allows the agent to push to main and you have no branch protection rules, auto-merges the PR.
* **`discard_session`**: Drop the session and its in-flight changes.

## Example prompts

After you connect the admin MCP, you can drive it with natural-language prompts. For example:

* *"Check out a branch called `add-billing-faq` and create a new page under the FAQ group titled 'Billing'. Draft answers for the five questions in this Linear issue."*
* *"Find every page that mentions the deprecated `legacy_token` field and update the example to use `api_key` instead. Save as a PR titled 'docs: replace legacy\_token references'."*
* *"Reorganize the API reference: move the webhooks pages into a new group called 'Webhooks' and update the icons to match the rest of the section."*

## Best practices

<AccordionGroup>
  <Accordion title="Open the editor URL">
    Every `checkout` returns an `editorUrl`. Open it in a separate tab so you can watch the AI's changes render live in the dashboard editor while you prompt.
  </Accordion>

  <Accordion title="Review every PR">
    The admin MCP is powerful enough to rewrite hundreds of pages in a single session. Before merging, read the PR diff and skim the rendered preview. Don't rubber-stamp large changes.
  </Accordion>

  <Accordion title="Use slugs for branch names">
    Pass a `slug` to `checkout` (for example, `add-quickstart`) so the auto-generated branch is human-readable. Without it, the branch name derives from the session token and is hard to recognize in your repository.
  </Accordion>

  <Accordion title="Keep sessions focused">
    Keep each session focused on one change. Smaller sessions produce pull requests that are easier to review and preserve agents' context windows. Use `discard_session` and `checkout` again to pivot to unrelated work.
  </Accordion>
</AccordionGroup>

<Note>
  Sessions hold an in-memory branch on the Mintlify side. If you abandon a session without saving or discarding it, the branch persists until your next checkout overwrites it. Avoid leaving stale `mintlify-mcp/*` branches in your repository. Clean them up periodically.
</Note>

## Disconnect or revoke access

Disconnect the admin MCP when you no longer want an AI tool to edit your project, or when you want to force a fresh OAuth login.

* **Revoke the OAuth grant**: In your Mintlify dashboard, navigate to **Settings → Security & access → Connected apps** and revoke the entry for the AI tool you connected. Revoking invalidates any active session tokens immediately, so in-flight tool calls fail and the tool must complete a new OAuth login on the next call.
* **Remove the connector in the client**:
  * Claude: **Settings → Connectors**, then remove the admin MCP entry.
  * Claude Code: `claude mcp remove mintlify`.
  * ChatGPT: **Settings → Connectors**, then remove the Mintlify entry.
  * Cursor: delete the `mintlify` entry from `mcp.json` and reload.
  * Codex: delete the `[mcp_servers.mintlify]` block from `~/.codex/config.toml`.

Revoking the OAuth grant does not affect pull requests the MCP has already opened. Close or revert those PRs in your Git provider if you want to undo pending changes.


# Search Model Context Protocol (MCP) server
Source: https://www.mintlify.com/docs/ai/model-context-protocol

Connect AI tools like Claude, Cursor, and ChatGPT to your hosted search MCP server so they can search and retrieve content from your site.

## About MCP servers

The Model Context Protocol (MCP) is an open protocol that creates standardized connections between AI applications and external services, like documentation. Mintlify generates a search MCP server for your site, preparing your content for the broader AI ecosystem. Any MCP client like Claude, Cursor, Goose, or ChatGPT can connect to your content.

Your search MCP server exposes tools for AI applications to search and retrieve your content. Your users must connect your search MCP server to their tools.

<Tip>
  To let trusted agents edit your content, use the [admin MCP server](/docs/ai/mintlify-mcp). To give coding agents one retrieval source across all Mintlify sites, use [Mintlify Index](/docs/search-index).
</Tip>

### How MCP servers work

When an AI application connects to your search MCP server, it can search your content and retrieve full pages as Markdown in response to a user's prompt. This avoids relying on information from training data or generic web searches. Your search MCP server provides access to all indexed content on your Mintlify site.

* AI applications can proactively search your content while generating a response even if not explicitly asked to search for an answer.
* AI applications determine when to use the available tools based on the context of the conversation and the relevance of your content.
* Each tool call happens during the generation process, so the AI application uses up-to-date information from your site to generate its response.

<Tip>
  Some AI tools like Claude support both MCP and skills. MCP gives access to your content, while skills instruct agents how to use that content effectively. They're complementary and connecting your MCP server gives agents access to both.
</Tip>

### MCP tools

Your search MCP server provides three tools that agents can use:

* **Search**: Searches across your site to find relevant content, returning snippets with titles and links. Use this to discover information or find pages matching a query.
* **Query docs filesystem**: Reads and navigates your site's virtual filesystem using shell-style commands. Use this to browse and retrieve content, or extract specific sections—including batch reads across multiple pages in a single call.
* **Submit feedback**: Reports a documentation issue back to your team when an agent finds a page that is incorrect, outdated, confusing, or incomplete. The agent supplies the page path and a description of the problem, which Mintlify records as unhelpful feedback in your analytics dashboard.

Agents determine when to use each tool based on the context of the conversation. For example, an agent might first search your site to find relevant pages, then use the query docs filesystem tool to read the full content of the most relevant results. If it discovers a problem with the page along the way, it can submit feedback.

### MCP resources

Your search MCP server also exposes your [skill.md files](/docs/ai/skillmd) as MCP resources. Agents connected to your search MCP server can discover and access your skill files without installing them separately.

`Skill.md` resources appear in the search MCP server's resource list and contain the capability descriptions Mintlify generates or that you define in your [custom skill files](/docs/ai/skillmd#custom-skill-files).

If your documentation uses [authentication](/docs/deploy/authentication-setup), skills with a `groups` field are only exposed to authenticated end users whose groups match. See [Restrict skills to user groups](/docs/ai/skillmd#restrict-skills-to-user-groups).

### Search parameters

The MCP search tool supports optional parameters that AI applications use to control and refine search results.

* **`version`**: Filter results to a specific site version. For example, `'v0.7'`. Only available when your site has multiple versions. Only returns content tagged with the specified version or content available across all versions.
* **`language`**: Filter results to a specific language code. For example, `'en'`, `'zh'`, or `'es'`. Only available when your site has multiple languages. Only returns content in the specified language or content available across all languages.

AI applications determine when to apply these parameters based on the context of the user's query. For example, if a user asks about a specific API version, the AI application may automatically apply the appropriate filter to provide more relevant results.

### Search MCP compared to web search

AI tools can search the web, but the search MCP provides distinct advantages.

* **Direct source access**: Web search depends on what search engines have indexed, which may be stale or incomplete. The search MCP searches your current indexed content directly.
* **Integrated workflow**: MCP allows the AI to search during response generation rather than performing a separate web search.
* **No search noise**: SEO and ranking algorithms influence web search results. MCP goes straight to your content.

## Access your search MCP server

Mintlify generates a search MCP server for your site and hosts it at the `/mcp` path of your site URL. For example, Mintlify's search MCP server is available at `https://mintlify.com/docs/mcp`.

* For public content, your search MCP server is available to anyone. It searches all indexed public pages.
* For content with partial authentication, where some pages are public and others require login, you must enable your search MCP server before users can access it. Unauthenticated users can search public content. Users who authenticate can search all content they have permission to access based on their [user groups](/docs/deploy/authentication-setup).
* For content where all pages require authentication, you must enable your search MCP server before it is available to users. Users must authenticate before connecting to your search MCP server. Your search MCP server searches only the content each user has access to based on their [user groups](/docs/deploy/authentication-setup).

If your site uses authentication, configure your hosted search MCP server from **Settings → Security & access → MCP** in your dashboard. The authenticated search MCP server is available at the `/authed/mcp` path of your site URL.

<Note>
  The **MCP** settings page only appears when you enable [authentication](/docs/deploy/authentication-setup) for your site. If your site doesn't require authentication, your search MCP server is still accessible at the `/mcp` path of your site URL.
</Note>

Mintlify reserves the `/mcp` and `/authed/mcp` paths for search MCP servers. You cannot use them for other navigation elements.

### Discovery endpoint

Mintlify hosts a discovery document at `/.well-known/mcp` for agents and tools to locate your search MCP server without prior configuration.

`GET /.well-known/mcp` returns a JSON document describing your search MCP server:

```json theme={null}
{
  "version": "1.0.0",
  "transport": "http",
  "url": "https://your-docs.com/mcp",
  "servers": [
    {
      "name": "public",
      "url": "https://your-docs.com/mcp",
      "transport": "http",
      "authentication": "none"
    },
    {
      "name": "authenticated",
      "url": "https://your-docs.com/authed/mcp",
      "transport": "http",
      "authentication": "oauth2"
    }
  ]
}
```

| Field                      | Description                                                                                                                          |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `version`                  | The MCP server version.                                                                                                              |
| `transport`                | The transport protocol. Always `http`.                                                                                               |
| `url`                      | The default public MCP server URL.                                                                                                   |
| `servers`                  | Available MCP servers. Always includes a `public` entry. When your site uses authentication, also includes an `authenticated` entry. |
| `servers[].name`           | Identifier for the server entry.                                                                                                     |
| `servers[].authentication` | Authentication method for the server entry.                                                                                          |

For agent-readiness, the same discovery document is also available at `/.well-known/mcp.json`. Mintlify also serves an MCP server card at `/.well-known/mcp/server-card.json` and a list of server cards at `/.well-known/mcp/server-cards.json`. Mintlify serves all discovery endpoints automatically. They require no configuration.

#### Server card endpoints

`GET /.well-known/mcp/server-card.json` returns a single server card describing your MCP server. `GET /.well-known/mcp/server-cards.json` returns a `servers` array with one card per available endpoint. The array always includes a public server card and includes an authenticated server card when your site uses authentication.

Each server card includes the standard discovery fields and a `tools` array that describes the MCP tools the server advertises. Use this to pre-populate tool metadata in MCP clients without making an `initialize` call to the server.

```json theme={null}
{
  "name": "your-docs-search",
  "version": "1.0.0",
  "url": "https://your-docs.com/mcp",
  "transport": "http",
  "description": "Search and retrieve your documentation",
  "capabilities": {
    "tools": true,
    "resources": true
  },
  "authentication": "none",
  "tools": [
    {
      "name": "search_your_docs",
      "title": "Search documentation",
      "description": "Search across your documentation site.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": { "type": "string", "description": "Search query" }
        },
        "required": ["query"]
      },
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    }
  ]
}
```

| Field                 | Description                                                                                                                                          |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tools[].name`        | Tool name advertised over MCP. Tool names are site-specific, so use the value returned by the discovery endpoint rather than hardcoding it.          |
| `tools[].title`       | Optional human-readable title for the tool.                                                                                                          |
| `tools[].description` | Human-readable description of what the tool does.                                                                                                    |
| `tools[].inputSchema` | JSON Schema for the tool's input parameters.                                                                                                         |
| `tools[].annotations` | Optional [MCP tool annotations](https://modelcontextprotocol.io/specification/2025-06-18/server/tools#tool-annotations) that describe tool behavior. |

The built-in search and query docs filesystem tools stay read-only and non-destructive, with the following annotations:

* `readOnlyHint: true`—the tool does not modify any state.
* `destructiveHint: false`—the tool has no destructive side effects.
* `idempotentHint: true`—repeated calls with the same arguments return equivalent results.
* `openWorldHint: false`—the tool operates against your indexed documentation rather than the open web.

MCP clients can use these annotations to surface tool safety information to users or to allow read-only tools to run without explicit approval.

### Enable authenticated MCP

If your site requires authentication, your search MCP server requires users to authenticate before connecting. When a user adds your MCP server URL to their AI tool, they must log in with their existing credentials. After authentication, a redirect sends them back to their tool. The MCP server returns only the content each user has permission to access based on their [user groups](/docs/deploy/authentication-setup).

If your site has partial authentication with both public and protected pages, you have two search MCP server endpoints:

* `/mcp`: Does not require authentication. Returns only public content. Share this with users who need access to public content.
* `/authed/mcp`: Always requires authentication. Returns content scoped to each user's permissions based on their [user groups](/docs/deploy/authentication-setup). Share this with users who need access to protected content.

The `/authed/mcp` endpoint uses its own OAuth flow at `/authed/mcp/oauth/*`. Redirect domains configured for your MCP server apply to both `/mcp` and `/authed/mcp`.

Popular MCP clients such as Claude, ChatGPT, Cursor, and Devin are always allowed to complete authentication with your MCP server. You do not need to add these clients to any allowlist.

To let other web-based tools connect, add their redirect domains in your dashboard. A redirect domain is the hostname that an AI tool uses after a user completes authentication. Your users' AI tools cannot complete authentication unless their redirect domain is on this list or the tool is one of the always-allowed clients.

Mintlify enables your hosted MCP server automatically when your site has [authentication](/docs/deploy/authentication-setup) configured.

<Steps>
  <Step title="Open the hosted MCP settings">
    In your dashboard, go to **Settings → Security & access → MCP**.
  </Step>

  <Step title="Add custom redirect domains">
    Under **Allowed OAuth redirect URIs**, add the redirect domains for any additional AI tools you want to grant your users access to. You only need to add domains for clients that aren't already on the always-allowed list.

    By default, redirect domains use `https://`. To allow a custom protocol scheme, include the full protocol in the domain entry. For example, a native app callback like `myapp://callback`. Mintlify always blocks dangerous protocols such as `javascript:`, `data:`, and `file:`.

    Loopback addresses (`localhost`, `127.0.0.1`) are always trusted and do not need to be added.
  </Step>
</Steps>

### Client credentials

Client credentials let you connect to your authenticated MCP server programmatically without a browser-based login. Use client credentials for server-side integrations, CI/CD pipelines, automated workflows, and any environment where a user cannot complete an interactive OAuth flow.

Client credentials authenticate against the `/authed/mcp` endpoint and return all content from public pages and authenticated pages that aren't restricted to specific groups.

<Note>
  MCP client credentials are separate from [Mintlify API keys](/docs/api/introduction). The admin and assistant API keys authenticate requests to the Mintlify REST API. They cannot authenticate to your MCP server. To call your MCP server programmatically, create a client credential from **Settings → Security & access → MCP** in your dashboard. Then exchange it for an access token.
</Note>

<Steps>
  <Step title="Create a client credential">
    1. In your dashboard, go to **Settings → Security & access → MCP**.
    2. In the **Client credentials** section, click **Generate**.
    3. Enter a label for the credential to identify its purpose, then confirm.
    4. Copy the **client ID** and **client secret** from the **Secret generated** dialog. The client secret is only shown once. You cannot retrieve it later.
  </Step>

  <Step title="Exchange credentials for an access token">
    Send a POST request to your MCP server's token endpoint with your client ID and secret. Your token endpoint is at the `/authed/mcp/oauth/token` path of your site's URL.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://your-docs.com/authed/mcp/oauth/token \
        -H 'Content-Type: application/x-www-form-urlencoded' \
        -d 'grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET'
      ```

      ```bash cURL (Basic Auth) theme={null}
      curl -X POST https://your-docs.com/authed/mcp/oauth/token \
        -H 'Content-Type: application/x-www-form-urlencoded' \
        -H 'Authorization: Basic BASE64_CLIENT_ID_COLON_SECRET' \
        -d 'grant_type=client_credentials'
      ```
    </CodeGroup>

    The response includes an access token and a refresh token:

    ```json theme={null}
    {
      "access_token": "eyJhbGciOi...",
      "token_type": "Bearer",
      "expires_in": 1209600,
      "refresh_token": "eyJhbGciOi...",
      "scope": "mcp:search"
    }
    ```

    Access tokens expire after the number of seconds specified in `expires_in`. Use the `refresh_token` to obtain a new access token when the current one expires.
  </Step>

  <Step title="Connect to the MCP server">
    Use the access token as a bearer token when connecting to the `/authed/mcp` endpoint.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://your-docs.com/authed/mcp \
        -H 'Authorization: Bearer ACCESS_TOKEN' \
        -H 'Content-Type: application/json' \
        -H 'Accept: application/json, text/event-stream' \
        -d '{
          "jsonrpc": "2.0",
          "id": 1,
          "method": "initialize",
          "params": {
            "protocolVersion": "2025-03-26",
            "capabilities": {},
            "clientInfo": {"name": "my-integration", "version": "1.0.0"}
          }
        }'
      ```

      ```bash Claude Code theme={null}
      claude mcp add --transport http \
        my-docs https://your-docs.com/authed/mcp \
        --header "Authorization: Bearer ACCESS_TOKEN"
      ```
    </CodeGroup>
  </Step>
</Steps>

#### Managing client credentials

You can manage your client credentials from **Settings → Security & access → MCP** in your dashboard.

* **Delete a credential** to permanently revoke access. This cannot be undone.
* **Rotate a credential** by creating a new credential, updating any integrations that use the old one to the new client ID and secret, then deleting the old credential. Each credential has a unique secret, so creating a new one does not affect existing credentials until you delete them.

<Warning>
  Treat client secrets like passwords. Do not commit them to source control or expose them in client-side code. Use environment variables or a secrets manager to store them.
</Warning>

### Rate limits

To protect availability, Mintlify applies rate limits to MCP servers.

| Scope                                                 | Limit                    | Description                                                                                      |
| :---------------------------------------------------- | :----------------------- | :----------------------------------------------------------------------------------------------- |
| Per user (IP address)                                 | 5,000 requests per hour  | Limits how frequently a single user can query your MCP server configuration.                     |
| Search per site (domain)                              | 10,000 requests per hour | Limits total search tool calls across all users of your MCP server.                              |
| Query docs filesystem per site (domain)               | 10,000 requests per hour | Limits total query docs filesystem tool calls across all users of your MCP server.               |
| Authenticated search per site (domain)                | 5,000 requests per hour  | Limits total authenticated search tool calls across all users of your MCP server.                |
| Authenticated query docs filesystem per site (domain) | 5,000 requests per hour  | Limits total authenticated query docs filesystem tool calls across all users of your MCP server. |

If you exceed a limit, the MCP server returns an HTTP `429 Too Many Requests` response. MCP clients should back off and retry after a short delay. Limits reset on a rolling hourly window, so most callers recover automatically within an hour.

If your site consistently hits these limits, contact [support@mintlify.com](mailto:support@mintlify.com) to request higher limits.

## Content filtering and indexing

Your MCP server searches content that Mintlify indexes from your project repository. File processing and search indexing control what content is available through your MCP server.

For sites that require authentication, your MCP server indexes [public pages](/docs/deploy/authentication-setup#make-pages-public) and any pages an authenticated user has permission to access based on their [user groups](/docs/deploy/authentication-setup#restrict-pages-to-specific-user-groups).

For sites with partial authentication, unauthenticated users can search public pages. Authenticated users can search public pages and any pages they have permission to access based on their user groups.

### File processing with `.mintignore`

If files match [.mintignore](/docs/organize/mintignore) patterns, Mintlify does not process or index them. These files are not available through your MCP server.

### Search indexing with `docs.json`

By default, Mintlify only indexes pages included in your `docs.json` navigation for search through your MCP server.

Mintlify excludes [hidden pages](/docs/organize/hidden-pages) (pages not in your navigation) from the search index unless you choose to index all pages. To include hidden pages in your MCP server's search results, add the `seo.indexing` property to your `docs.json`.

```json theme={null}
"seo": {
    "indexing": "all"
}
```

To exclude a specific page from search indexing, add `noindex: true` to its frontmatter.

```mdx theme={null}
---
title: "Hidden page"
description: "This page is not in the navigation and is not available through search."
noindex: true
---
```

## Use your MCP server

Your users must connect your MCP server to their preferred AI tools.

1. Make your MCP server URL publicly available.
2. Your users copy your MCP server URL and add it to their tools.
3. Your users access your content through their tools.

These are some of the ways you can help your users connect to your MCP server:

<Tabs>
  <Tab title="Contextual menu">
    Add options in the [contextual menu](/docs/ai/contextual-menu) for your users to connect to your MCP server from any page on your site.

    | Option                       | Identifier | Description                                                 |
    | :--------------------------- | :--------- | :---------------------------------------------------------- |
    | **Copy MCP server URL**      | `mcp`      | Copies your MCP server URL to the user's clipboard.         |
    | **Copy MCP install command** | `add-mcp`  | Copies the `npx add-mcp` command to install the MCP server. |
    | **Connect to Cursor**        | `cursor`   | Installs your MCP server in Cursor.                         |
    | **Connect to VS Code**       | `vscode`   | Installs your MCP server in VS Code.                        |
  </Tab>

  <Tab title="Claude">
    <Steps>
      <Step title="Get your MCP server URL">
        Your MCP server URL is the `/mcp` path of your site URL. For example, `https://your-docs.com/mcp`. If your site requires authentication, use the `/authed/mcp` path instead.
      </Step>

      <Step title="Publish your MCP server URL for your users">
        Create a guide for your users that includes your MCP server URL and the steps to connect it to Claude.

        1. Navigate to the [Connectors](https://claude.ai/settings/connectors) page in the Claude settings.
        2. Click **Add custom connector**.
        3. Add your MCP server name and URL.
        4. Click **Add**.
        5. When using Claude, click the attachments button (the plus icon).
        6. Select your MCP server.
      </Step>
    </Steps>

    See the [Model Context Protocol documentation](https://modelcontextprotocol.io/docs/tutorials/use-remote-mcp-server#connecting-to-a-remote-mcp-server) for more details.
  </Tab>

  <Tab title="Claude Code">
    <Steps>
      <Step title="Get your MCP server URL">
        Your MCP server URL is the `/mcp` path of your site URL. For example, `https://your-docs.com/mcp`. If your site requires authentication, use the `/authed/mcp` path instead.
      </Step>

      <Step title="Publish your MCP server URL for your users">
        Create a guide for your users that includes your MCP server URL and the command to connect it to Claude Code.

        ```bash theme={null}
        claude mcp add --transport http <name> <url>
        ```
      </Step>
    </Steps>

    See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/mcp#installing-mcp-servers) for more details.
  </Tab>

  <Tab title="Codex">
    <Steps>
      <Step title="Get your MCP server URL">
        Your MCP server URL is the `/mcp` path of your site URL. For example, `https://your-docs.com/mcp`. If your site requires authentication, use the `/authed/mcp` path instead.
      </Step>

      <Step title="Publish your MCP server URL for your users">
        Create a guide for your users that includes your MCP server URL and the steps to connect it to Codex CLI.

        In `~/.codex/config.toml`, add:

        ```toml theme={null}
        [mcp_servers.<your-mcp-server-name>]
        url = "<your-mcp-server-url>"
        ```
      </Step>
    </Steps>

    See the [Codex MCP documentation](https://developers.openai.com/codex/mcp) for more details.
  </Tab>

  <Tab title="Cursor">
    <Steps>
      <Step title="Get your MCP server URL">
        Your MCP server URL is the `/mcp` path of your site URL. For example, `https://your-docs.com/mcp`. If your site requires authentication, use the `/authed/mcp` path instead.
      </Step>

      <Step title="Publish your MCP server URL for your users">
        Create a guide for your users that includes your MCP server URL and the steps to connect it to Cursor.

        1. Use <kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> on Windows) to open the command palette.
        2. Search for `Open MCP settings`.
        3. Click **Add custom MCP**. This opens the `mcp.json` file.
        4. In `mcp.json`, configure your server:

        ```json theme={null}
        {
          "mcpServers": {
            "<your-mcp-server-name>": {
              "url": "<your-mcp-server-url>"
            }
          }
        }
        ```
      </Step>
    </Steps>

    See the [Cursor documentation](https://docs.cursor.com/en/context/mcp#installing-mcp-servers) for more details.
  </Tab>

  <Tab title="VS Code">
    <Steps>
      <Step title="Get your MCP server URL">
        Your MCP server URL is the `/mcp` path of your site URL. For example, `https://your-docs.com/mcp`. If your site requires authentication, use the `/authed/mcp` path instead.
      </Step>

      <Step title="Publish your MCP server URL for your users">
        Create a guide for your users that includes your MCP server URL and the steps to connect it to VS Code.

        1. Create a `.vscode/mcp.json` file.
        2. In `mcp.json`, configure your server:

        ```json theme={null}
        {
          "servers": {
            "<your-mcp-server-name>": {
              "type": "http",
              "url": "<your-mcp-server-url>"
            }
          }
        }
        ```
      </Step>
    </Steps>

    See the [VS Code documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more details.
  </Tab>
</Tabs>

### Example: Connect to the Mintlify MCP server

Connect to the Mintlify MCP server to search this documentation site within your preferred AI tool. This gives you more accurate answers about how to use Mintlify in your local environment and demonstrates how you can help your users connect to your MCP server.

<Tabs>
  <Tab title="Contextual menu">
    At the top of this page, click the contextual menu, then click **Connect to Cursor** or **Connect to VS Code** to connect the Mintlify MCP server to the IDE of your choice.
  </Tab>

  <Tab title="Claude">
    To use the Mintlify MCP server with Claude:

    <Steps>
      <Step title="Add the Mintlify MCP server to Claude">
        1. Navigate to the [Connectors](https://claude.ai/settings/connectors) page in the Claude settings.
        2. Click **Add custom connector**.
        3. Add the Mintlify MCP server:

        * Name: `Mintlify`
        * URL: `https://mintlify.com/docs/mcp`

        4. Click **Add**.
      </Step>

      <Step title="Access the MCP server in your chat">
        1. When using Claude, click the attachments button (the plus icon).
        2. Select the Mintlify MCP server.
        3. Ask Claude a question about Mintlify.
      </Step>
    </Steps>

    See the [Model Context Protocol documentation](https://modelcontextprotocol.io/docs/tutorials/use-remote-mcp-server#connecting-to-a-remote-mcp-server) for more details.
  </Tab>

  <Tab title="Claude Code">
    To use the Mintlify MCP server with Claude Code, run the following command:

    ```bash theme={null}
    claude mcp add --transport http Mintlify https://mintlify.com/docs/mcp
    ```

    Test the connection by running:

    ```bash theme={null}
    claude mcp list
    ```

    See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/mcp#installing-mcp-servers) for more details.
  </Tab>

  <Tab title="Codex">
    To connect the Mintlify MCP server to Codex CLI, add it to your config file at `~/.codex/config.toml`:

    ```toml theme={null}
    [mcp_servers.mintlify]
    url = "https://mintlify.com/docs/mcp"
    ```

    Test the connection by starting a Codex session and asking:

    ```text theme={null}
    What tools do you have available?
    ```

    Codex should list the Mintlify MCP server as an available tool.

    See the [Codex MCP documentation](https://developers.openai.com/codex/mcp) for more details.
  </Tab>

  <Tab title="Cursor">
    <PreviewButton href="cursor://anysphere.cursor-deeplink/mcp/install?name=mintlify&config=eyJ1cmwiOiJodHRwczovL21pbnRsaWZ5LmNvbS9kb2NzL21jcCJ9">Install in Cursor</PreviewButton>

    To connect the Mintlify MCP server to Cursor, click the **Install in Cursor** button. Or to manually connect the MCP server, follow these steps:

    <Steps>
      <Step title="Open MCP settings">
        1. Use <kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> on Windows) to open the command palette.
        2. Search for `Open MCP settings`.
        3. Click **Add custom MCP**. This opens the `mcp.json` file.
      </Step>

      <Step title="Configure the Mintlify MCP server">
        In `mcp.json`, add:

        ```json theme={null}
        {
          "mcpServers": {
            "Mintlify": {
              "url": "https://mintlify.com/docs/mcp"
            }
          }
        }
        ```
      </Step>

      <Step title="Test the connection">
        In Cursor's chat, ask "What tools do you have available?" Cursor should show the Mintlify MCP server as an available tool.
      </Step>
    </Steps>

    See [Installing MCP servers](https://docs.cursor.com/en/context/mcp#installing-mcp-servers) in the Cursor documentation for more details.
  </Tab>

  <Tab title="VS Code">
    <PreviewButton href="https://vscode.dev/redirect/mcp/install?name=mintlify&config=%7B%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fmintlify.com%2Fdocs%2Fmcp%22%7D">Install in VS Code</PreviewButton>

    To connect the Mintlify MCP server to VS Code, click the **Install in VS Code** button. Or to manually connect the MCP server, create a `.vscode/mcp.json` file and add:

    ```json theme={null}
    {
      "servers": {
        "Mintlify": {
          "type": "http",
          "url": "https://mintlify.com/docs/mcp"
        }
      }
    }
    ```

    See the [VS Code documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more details.
  </Tab>
</Tabs>

### Use multiple MCP servers

Users can connect multiple MCP servers to their AI tools. Connected MCP servers do not add content to the conversation until the AI calls a search tool. The AI decides when to search based on query relevance, so it doesn't search every connected server for every question.

When the AI searches, each query returns multiple results and adds them to the conversation. Searching several servers for one question can make the conversation much longer and leave less room for the AI's response.

Best practices for using multiple MCP servers:

* Connect only the MCP servers relevant to your current work.
* Be specific in your prompts so the AI searches the most relevant server.
* Disconnect servers you're not actively using to reduce potential context usage.


# skill.md
Source: https://www.mintlify.com/docs/ai/skillmd

Make your documentation agent-ready with automatically generated skill.md files that describe your product's capabilities for AI agents.

Mintlify hosts a `skill.md` file at the root of your project that describes what AI agents can do with your product.

The [skill.md specification](https://agentskills.io/specification) is a structured, machine-readable format that makes product capabilities, required inputs, and constraints explicit. Agents can then use those products more reliably.

Mintlify automatically generates a `skill.md` file for your project by analyzing your documentation with an agentic loop. This file stays up to date as you make updates to your documentation and requires no maintenance. You can optionally add a custom `skill.md` file to the root of your project that overrides the automatically generated one.

<Note>Generating or updating a `skill.md` file can take up to 24 hours.</Note>

View your `skill.md` by appending `/skill.md` to your documentation site's URL. Mintlify only generates `skill.md` files for documentation sites that are public.

<PreviewButton href="https://mintlify.com/docs/skill.md">
  Open the skill.md for this site.
</PreviewButton>

<Tip>
  Both `llms.txt` and `skill.md` files help agents work with your documentation, but they serve different purposes.

  * `llms.txt` is a directory. It lists all your documentation pages with descriptions so agents know where to find information.
  * `skill.md` is a capability summary. It tells agents what they can accomplish with your product, what inputs they need, and what constraints apply.
</Tip>

## Use `skill.md` files with agents

<Note>
  If you use a [reverse proxy](/docs/deploy/reverse-proxy), configure it to forward `/skill.md`, `/.well-known/skills/*`, and `/.well-known/agent-skills/*` paths to your Mintlify subdomain. See the [routing configuration](/docs/deploy/reverse-proxy#routing-configuration) for the destination paths and caching policies.
</Note>

When users connect to your Model Context Protocol (MCP) server, their agents can discover and use your `skill.md` files as [MCP resources](/docs/ai/model-context-protocol#mcp-resources) without installing the skills separately.

To add your skills to an agent's context manually, use the [skills CLI](https://www.npmjs.com/package/skills).

```bash theme={null}
npx skills add https://your-docs-domain.com
```

This adds your product's capabilities to the agent's context so it can take actions on behalf of users.

<Prompt description="Install a product's skill.md files into your agent.">
  Install the `skill.md` files from a Mintlify-hosted documentation site into my agent context so you know what this product can do.

  1. Ask me for the documentation site URL if I haven't provided one, then run `npx skills add <url>` with that URL.
  2. Print the list of skills that were installed, including each skill's name and description.
  3. Summarize the key capabilities in one paragraph so I know what you can now help me accomplish with this product.
  4. If any skill declares required inputs or constraints in its frontmatter, call them out before I ask you to use it.
</Prompt>

<Tip>
  Teach your users how to use `skill.md` files with agents so that they have better results using your product with their AI tools.
</Tip>

## Structure of `skill.md`

Mintlify generates a `skill.md` file following the [agentskills.io specification](https://agentskills.io/specification). The generated file includes:

* **Metadata**: Project name, description, and version.
* **Capabilities**: What agents can accomplish with your product.
* **Skills**: Specific actions organized by category.
* **Workflows**: Step-by-step procedures for common tasks.
* **Integration**: Supported tools and services.
* **Context**: Background on your product's architecture.

## Custom skill files

Add custom skill files to override the automatically generated `skill.md`. Mintlify supports hosting a single skill file and a directory for multiple skills. If you delete all custom skill files, Mintlify generates a new `skill.md` file.

### Single skill file

Add a `skill.md` file to the root of your project to override the automatically generated file.

### Multiple skill files

Add multiple skill files to the `.mintlify/skills/` directory in your project. Each skill must be in its own subdirectory with a `SKILL.md` file:

```
.mintlify/
  skills/
    payments/
      SKILL.md
    analytics/
      SKILL.md
```

When you have multiple skills, the `/skill.md` endpoint redirects to the `/.well-known/skills/index.json` discovery endpoint, which lists all available skills. The discovery endpoints make each skill individually accessible.

<Note>
  You can use both approaches together with a root `skill.md` file and `.mintlify/skills/` directory. The discovery index includes all skills.
</Note>

### Use symlinks to avoid duplication

If your skill files live elsewhere in your repository (for example, in a `plugins/` or `skills/` directory), you can symlink `.mintlify/skills` to that location instead of duplicating files:

```bash theme={null}
# Skills live in a top-level skills/ directory
ln -s ../skills .mintlify/skills
```

```
project/
  skills/
    payments/
      SKILL.md
    analytics/
      SKILL.md
  .mintlify/
    skills -> ../skills
  docs.json
```

Mintlify resolves symlinks during deployment, so it discovers and serves the skill files as if they were directly inside `.mintlify/skills/`. This works with both directory symlinks and individual skill symlinks.

### Frontmatter fields

Custom `skill.md` files must start with YAML frontmatter.

| Field           | Type   | Description                                                                                                                      |
| --------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------- |
| `name`          | string | The name of your skill.                                                                                                          |
| `description`   | string | A brief description of what your skill does.                                                                                     |
| `license`       | string | The license for your skill (for example, `MIT` or `Apache-2.0`).                                                                 |
| `compatibility` | string | Requirements or compatibility notes (for example, runtime dependencies).                                                         |
| `metadata`      | object | Additional metadata as string key-value pairs (for example, `author` or `version`).                                              |
| `allowed-tools` | string | Space-delimited list of pre-approved tools the skill may use (experimental).                                                     |
| `groups`        | array  | Restrict the skill to specific authenticated user groups. See [Restrict skills to user groups](#restrict-skills-to-user-groups). |

```md Example frontmatter theme={null}
---
name: mintlify
description: Build and maintain documentation sites with Mintlify. Use when creating docs pages, configuring navigation, adding components, or setting up API references.
license: MIT
compatibility: Requires Node.js for CLI. Works with any Git-based workflow.
metadata:
  author: mintlify
  version: "1.0"
---
```

### Restrict skills to user groups

If your documentation uses [authentication](/docs/deploy/authentication-setup), you can restrict a skill to specific user groups by adding a `groups` array to its frontmatter. Group filtering works the same way as [page visibility](/docs/create/personalization#page-visibility): the skill is only exposed to authenticated users who belong to at least one of the listed groups.

```md SKILL.md theme={null}
---
name: admin-tools
description: Internal operations for administrators.
groups: ["admin"]
---
```

Group-gated skills are:

* Hidden from the public [skills discovery endpoints](#skills-discovery-endpoints) and the public `/skill.md` file.
* Exposed as [MCP resources](/docs/ai/model-context-protocol#mcp-resources) only to authenticated end users whose groups match. Users who don't match, and machine-to-machine clients without an end user, only see ungrouped skills.

Skills without a `groups` field remain visible to everyone.

## Skills discovery endpoints

Mintlify hosts skills directories at `/.well-known/skills/` and `/.well-known/agent-skills/` that agents can use to discover and fetch your skill files programmatically.

### Agent-skills discovery (recommended)

The `/.well-known/agent-skills/` endpoint follows the [agent-skills 0.2.0 discovery spec](https://schemas.agentskills.io/discovery/0.2.0/schema.json) and includes content integrity verification.

`GET /.well-known/agent-skills/index.json` returns a JSON manifest listing all available skills:

```json theme={null}
{
  "$schema": "https://schemas.agentskills.io/discovery/0.2.0/schema.json",
  "skills": [
    {
      "name": "my-product",
      "type": "skill-md",
      "description": "A brief description of what your skill does.",
      "url": "/.well-known/agent-skills/my-product/SKILL.md",
      "digest": "sha256:a1b2c3..."
    }
  ]
}
```

| Field         | Description                                                                         |
| ------------- | ----------------------------------------------------------------------------------- |
| `$schema`     | Schema URL for the agent-skills 0.2.0 discovery spec.                               |
| `name`        | A URL-safe slug derived from the `name` in your `skill.md` frontmatter.             |
| `type`        | The skill format. Always `skill-md`.                                                |
| `description` | A brief description from your `skill.md` frontmatter, truncated to 1024 characters. |
| `url`         | The path to fetch the full skill file.                                              |
| `digest`      | A `sha256` hash of the skill file content for integrity verification.               |

`GET /.well-known/agent-skills/{name}/SKILL.md` returns the `skill.md` file for a specific skill identified by its slugified name from the index.

### Skills index

The `/.well-known/skills/` endpoint is the original discovery format.

`GET /.well-known/skills/index.json` returns a JSON manifest listing all available skills:

```json theme={null}
{
  "skills": [
    {
      "name": "my-product",
      "description": "A brief description of what your skill does.",
      "files": ["SKILL.md"]
    }
  ]
}
```

The `name` field is a URL-safe slug derived from the `name` in your `skill.md` frontmatter.

### Individual skill files

`GET /.well-known/skills/{name}/skill.md` returns the `skill.md` file for a specific skill identified by its slugified name from the index.

## Agent card

Mintlify hosts an [Agent-to-Agent (A2A)](https://a2aproject.github.io/A2A/latest/) agent card at `/.well-known/agent-card.json`. The agent card is a standardized JSON document that helps A2A-compatible agents discover your documentation site and available skills in a single request.

`GET /.well-known/agent-card.json` returns a JSON document following the [A2A agent card 0.3 schema](https://a2aproject.github.io/A2A/latest/specification/#agent-card). Each entry in the `skills` array corresponds to a skill from your skills discovery endpoints.

A2A-compatible agents fetch `/.well-known/agent-card.json` to discover your site by name and description, follow `documentationUrl` to retrieve human-readable content, and iterate over `skills` to fetch each `skill.md` file. The card also advertises a `supportedInterfaces` array so agents can negotiate transport before making a request.

| Field                 | Description                                                                                             |
| --------------------- | ------------------------------------------------------------------------------------------------------- |
| `protocolVersion`     | A2A protocol version. Always `0.3`.                                                                     |
| `preferredTransport`  | Default transport for clients that do not negotiate. Always `HTTP+JSON`.                                |
| `supportedInterfaces` | Array of `{ url, protocolBinding, protocolVersion }` entries describing how agents can reach your site. |
| `provider`            | `{ url, organization }` identifying the documentation site. `organization` is the site title.           |
| `defaultInputModes`   | Media types the agent accepts as input. Always `["text/plain"]`.                                        |
| `defaultOutputModes`  | Media types the agent produces. Always `["text/plain"]`.                                                |
| `capabilities`        | Feature flags. Currently `{ streaming: false, pushNotifications: false }`.                              |
| `skills`              | The skills exposed at `/.well-known/agent-skills/`.                                                     |

URLs in the card (`url`, `documentationUrl`, `provider.url`, and each skill URL) use your configured custom domain, so the published card always advertises the canonical domain instead of the `*.mintlify.site` subdomain.

<Note>
  If you use a [reverse proxy](/docs/deploy/reverse-proxy), configure it to forward `/.well-known/agent-card.json` to your Mintlify subdomain.
</Note>

The agent card complements [MCP](/docs/ai/model-context-protocol) by providing a lightweight discovery layer that does not require establishing a session.


# Add SDK examples
Source: https://www.mintlify.com/docs/api-playground/adding-sdk-examples

Add SDK code samples to your API documentation with autogenerated examples from Speakeasy and Stainless across multiple languages.

If your users interact with your API through an SDK rather than direct network requests, add SDK code samples with the `x-codeSamples` extension. Mintlify displays these samples on your OpenAPI pages.

Add this property to any request method. It has the following schema.

<ParamField type="string">
  The language of the code sample.
</ParamField>

<ParamField type="string">
  The label for the sample. This is useful when providing multiple examples for a single endpoint.
</ParamField>

<ParamField type="string">
  The source code of the sample.
</ParamField>

The following example shows code samples for a plant tracking app that has both a Bash CLI tool and a JavaScript SDK.

```yaml theme={null}
paths:
  /plants:
    get:
      # ...
      x-codeSamples:
        - lang: bash
          label: List all unwatered plants
          source: |
            planter list -u
        - lang: javascript
          label: List all unwatered plants
          source: |
            const planter = require('planter');
            planter.list({ unwatered: true });
        - lang: bash
          label: List all potted plants
          source: |
            planter list -p
        - lang: javascript
          label: List all potted plants
          source: |
            const planter = require('planter');
            planter.list({ potted: true });
```


# AsyncAPI setup
Source: https://www.mintlify.com/docs/api-playground/asyncapi-setup

Set up real-time WebSocket documentation using AsyncAPI specification files to generate interactive channel and message reference pages.

## Demo

See the [WebSocket playground](/docs/api-playground/websocket-playground) for an example of the AsyncAPI playground.

## Add an AsyncAPI specification file

To create pages for your WebSocket channels, you must have a valid AsyncAPI schema document in JSON or YAML format. The document must follow the [AsyncAPI specification 3.0](https://www.asyncapi.com/docs/reference/specification/v3.0.0).

<Tip>
  Use the [AsyncAPI Studio](https://studio.asyncapi.com/) to validate your AsyncAPI schema.
</Tip>

```json {3} theme={null}
/your-project
  |- docs.json
  |- asyncapi.json
```

## Auto-populate WebSocket pages

To automatically generate pages for all channels in your AsyncAPI schema, add an `asyncapi` property to any navigation element. The property accepts a path to an AsyncAPI schema document in your documentation repo or a URL to a hosted AsyncAPI document. It also accepts an array of links to AsyncAPI schema documents.

### Examples with tabs

<CodeGroup>
  ```json Local file theme={null}
  "navigation": {
    "tabs": [
      {
          "tab": "API Reference",
          "asyncapi": "/path/to/asyncapi.json"
      }
    ]
  }

  ```

  ```json Remote URL theme={null}
  "navigation": {
    "tabs": [
      {
          "tab": "API Reference",
          "asyncapi": "https://github.com/asyncapi/spec/blob/master/examples/simple-asyncapi.yml"
      }
    ]
  }
  ```

  ```json Multiple files theme={null}
  "navigation": {
    "tabs": [
      {
        "tab": "API Reference",
        "asyncapi": [
          "/path/to/events.json",
          "/path/to/webhooks.json"
        ]
      }
    ]
  }
  ```
</CodeGroup>

<Note>
  When you specify multiple AsyncAPI files, each file generates its own set of channel pages.
</Note>

### Examples with groups

```json theme={null}
"navigation": {
  "tabs": [
    {
      "tab": "AsyncAPI",
      "groups": [
        {
          "group": "Websockets",
          "asyncapi": {
            "source": "/path/to/asyncapi.json",
            "directory": "websockets"
          }
        }
      ]
    }
  ]
}
```

<Note>
  The `directory` field is optional. If not specified, Mintlify adds the files to the **api-reference** folder of the docs repository.
</Note>

### Examples with nested groups

The `asyncapi` property supports nested groups. Mintlify generates the channel pages and adds them to the nested group, alongside any existing pages.

Use nested groups to organize WebSocket channels as a subsection of a broader API group. You can also combine multiple AsyncAPI specifications under a shared parent group.

```json theme={null}
"navigation": {
  "tabs": [
    {
      "tab": "API Reference",
      "groups": [
        {
          "group": "Voice API",
          "pages": [
            "voice/overview",
            {
              "group": "Voice API Commands",
              "asyncapi": "/path/to/voice-asyncapi.json"
            }
          ]
        }
      ]
    }
  ]
}
```

## Schema rendering

Array schemas and combinatorial schemas (`oneOf`, `anyOf`, `allOf`) expand to show their child attributes inline in the generated channel pages. Readers can open the expandable section for an array item schema. They can also select a tab for each `oneOf`/`anyOf` option to see all nested fields.

## Channel page

To control channel order or reference only specific channels, create an MDX file with the `asyncapi` property in the frontmatter.

```mdx theme={null}
---
title: "Websocket Channel"
asyncapi: "/path/to/asyncapi.json channelName"
---
```


# Complex data types
Source: https://www.mintlify.com/docs/api-playground/complex-data-types

Describe APIs with flexible schemas using oneOf, anyOf, and allOf keywords for optional properties, polymorphism, and multiple data formats.

When your API accepts multiple data formats, has conditional fields, or uses inheritance patterns, OpenAPI's schema composition keywords help you document these flexible structures. Using `oneOf`, `anyOf`, and `allOf`, you can describe APIs that handle different input types or combine multiple schemas into comprehensive data models.

## `oneOf`, `anyOf`, `allOf` keywords

For complex data types, OpenAPI provides keywords for combining schemas:

* `allOf`: Combines multiple schemas (like merging objects or extending a base schema). Functions like an `and` operator.
* `anyOf`: Accepts data matching any of the provided schemas. Functions like an `or` operator.
* `oneOf`: Accepts data matching exactly one of the provided schemas. Functions like an `exclusive-or` operator.

<Warning>Mintlify treats `oneOf` and `anyOf` identically since the practical difference rarely affects using the API.</Warning>

For detailed specifications of these keywords see the [OpenAPI documentation](https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/).

<Info>The `not` keyword is currently unsupported.</Info>

### Combining schemas with `allOf`

When you use `allOf`, Mintlify performs some preprocessing on your OpenAPI document to display complex combinations in a readable way. For example, when you combine two object schemas with `allOf`, Mintlify combines the properties of both into a single object. This becomes especially useful when you use OpenAPI's reusable [components](https://swagger.io/docs/specification/components/).

```yaml theme={null}
org_with_users:
  allOf:
    - $ref: '#/components/schemas/Org'
    - type: object
      properties:
        users:
          type: array
          description: An array containing all users in the organization
# ...
components:
  schemas:
    Org:
      type: object
      properties:
        id:
          type: string
          description: The ID of the organization
```

<ParamField type="object">
  <Expandable>
    <ParamField type="string">
      The ID of the organization
    </ParamField>

    <ParamField type="object[]">
      An array containing all users in the organization
    </ParamField>
  </Expandable>
</ParamField>

### `any` and `undefined` types

Fields typed as `any` or `undefined` render the same way as `oneOf` schemas with a picker that lets users select a concrete shape before sending a request. This allows the API playground to present a meaningful input even when the schema doesn't constrain the value to a single type.

### Providing options with `oneOf` and `anyOf`

When you use `oneOf` or `anyOf`, the options display in a tabbed container. Specify a `title` field in each subschema to give your options names. For example, here's how you might display two different types of delivery addresses:

```yaml theme={null}
delivery_address:
  oneOf:
    - title: StreetAddress
      type: object
      properties:
        address_line_1:
          type: string
          description: The street address of the recipient
        # ...
    - title: POBox
      type: object
      properties:
        box_number:
          type: string
          description: The number of the PO Box
        # ...
```

<ParamField type="object">
  <div>
    <Tabs>
      <Tab title="StreetAddress">
        <ParamField type="string">
          The street address of the residence
        </ParamField>
      </Tab>

      <Tab title="POBox">
        <ParamField type="string">
          The number of the PO Box
        </ParamField>
      </Tab>
    </Tabs>
  </div>
</ParamField>


# GraphQL setup
Source: https://www.mintlify.com/docs/api-playground/graphql-setup

Generate reference pages for your GraphQL API from a schema definition file, with linked types and example queries, mutations, and responses.

## Add a GraphQL schema

To create pages for your GraphQL API, you need a valid GraphQL schema in SDL (Schema Definition Language) format. Store the schema in your documentation repository or host it at an HTTPS URL that Mintlify can fetch.

```graphql schema.graphql theme={null}
"An object with a stable identifier."
interface Node {
  id: ID!
}

type Organization implements Node {
  id: ID!
  name: String!
}

type Query {
  organization(id: ID!): Organization
}
```

## Auto-populate GraphQL pages

To automatically generate pages for every query, mutation, and type in your schema, add a `graphql` property to a tab in your `docs.json`. Mintlify parses the schema and creates a page for each operation and named type.

<CodeGroup>
  ```json Local file theme={null}
  "navigation": {
    "tabs": [
      {
        "tab": "GraphQL API",
        "graphql": "schema.graphql"
      }
    ]
  }
  ```

  ```json Remote URL theme={null}
  "navigation": {
    "tabs": [
      {
        "tab": "GraphQL API",
        "graphql": "https://example.com/schema.graphql"
      }
    ]
  }
  ```

  ```json Custom directory theme={null}
  "navigation": {
    "tabs": [
      {
        "tab": "GraphQL API",
        "graphql": {
          "source": "schema.graphql",
          "directory": "api/graphql"
        }
      }
    ]
  }
  ```
</CodeGroup>

The `graphql` property accepts either a string (a local path or HTTPS URL) or an object with the following fields.

<Note>
  You must declare `graphql` on a [tab](/docs/organize/navigation#tabs). A tab with `graphql` may include `groups`, but no other navigation structures, such as `pages`, `versions`, or `languages`. It also cannot include an `openapi` or `asyncapi` property.
</Note>

<ParamField type="string">
  A local path to an SDL file in your documentation repository or an HTTPS URL to a hosted SDL file. Does not accept HTTP URLs.
</ParamField>

<ParamField type="string">
  The directory to store generated pages. Defaults to `graphql-reference`.
</ParamField>

## Generated pages

Mintlify organizes generated pages into three sections under the tab you configured:

* **Queries**: One page per field on your `Query` root type.
* **Mutations**: One page per field on your `Mutation` root type.
* **Types**: One page per named object, input, enum, interface, union, or scalar type.

Each operation page shows the field description, arguments, return type, and links to any referenced types. Query and mutation pages also include a generated example operation, the required variables, and a sample JSON response.

Type pages render the schema definition read-only, with linked field types so readers can navigate the graph.

## Deprecations

Fields and arguments that you mark with `@deprecated` in your schema display as deprecated on the generated pages. If you provide a deprecation reason, it appears next to the field.

## Update your documentation

Mintlify regenerates GraphQL reference pages when you run `mint dev` or when you push changes to your documentation repository. If your schema is hosted at an HTTPS URL, updates to the schema regenerate on the next build.


# Manage page visibility
Source: https://www.mintlify.com/docs/api-playground/managing-page-visibility

Control which API endpoints appear in your documentation navigation by hiding, filtering, or organizing autogenerated OpenAPI pages.

You can control which OpenAPI operations get published as documentation pages and their visibility in navigation. This is useful for internal-only endpoints, deprecated operations, beta features, or endpoints that should be accessible via direct URL but not discoverable through site navigation.

If your pages are autogenerated from an OpenAPI document, manage page visibility with the `x-hidden` and `x-excluded` extensions.

## `x-hidden`

The `x-hidden` extension creates a page for an endpoint, but hides it from navigation. The page is only accessible by navigating directly to its URL.

Common use cases for `x-hidden` are:

* Endpoints you want to document, but not promote.
* Pages that you link to from other content.
* Endpoints for specific users.

## `x-excluded`

The `x-excluded` extension completely excludes an endpoint from your documentation.

Common use cases for `x-excluded` are:

* Internal-only endpoints.
* Deprecated endpoints that you don't want to document.
* Beta features that are not ready for public documentation.

## Implementation

Add the `x-hidden` or `x-excluded` extension under the HTTP method in your OpenAPI specification.

Here are examples of how to use each property in an OpenAPI schema document for an endpoint and a webhook path.

```json Endpoint example {11, 19} theme={null}
"paths": {
  "/plants": {
    "get": {
      "description": "Returns all plants from the store",
      "parameters": { /*...*/ },
      "responses": { /*...*/ }
    }
  },
  "/hidden_plants": {
    "get": {
      "x-hidden": true,
      "description": "Returns all somewhat secret plants from the store",
      "parameters": { /*...*/ },
      "responses": { /*...*/ }
    }
  },
  "/secret_plants": {
    "get": {
      "x-excluded": true,
      "description": "Returns all top secret plants from the store (do not publish this endpoint!)",
      "parameters": { /*...*/ },
      "responses": { /*...*/ }
    }
  }
},
```

```json Webhook example {9, 15} theme={null}
"webhooks": {
  "/plants_hook": {
    "post": {
      "description": "Webhook for information about a new plant added to the store",
    }
  },
  "/hidden_plants_hook": {
    "post": {
      "x-hidden": true,
      "description": "Webhook for somewhat secret information about a new plant added to the store"
    }
  },
  "/secret_plants_hook": {
    "post": {
      "x-excluded": true,
      "description": "Webhook for top secret information about a new plant added to the store (do not publish this endpoint!)"
    }
  }
}
```


# Create manual API pages
Source: https://www.mintlify.com/docs/api-playground/mdx-setup

Create API reference pages manually with MDX files when you need full control over layout for small APIs, prototypes, or custom docs.

You can manually define API endpoints in individual MDX pages. This approach is useful for small APIs or prototyping.

## Setup

<Steps>
  <Step title="Configure your API settings">
    In your `docs.json` file, define your base URL and authentication method.

    ```json Example docs.json theme={null}
    "api": {
      "mdx": {
        "server": "https://api.acme.com/",
        "auth": {
          "method": "key",
          "name": "x-api-key"
        }
      }
    }
    ```

    If you want to hide the API playground, set the `display` field to `none`. You don't need to include an authentication method if you hide the playground.

    ```json theme={null}
    "api": {
      "playground": {
        "display": "none"
      }
    }
    ```

    Find a full list of API configurations in [Settings](/docs/organize/settings-api).
  </Step>

  <Step title="Create your endpoint pages">
    Create an MDX file for each endpoint. Define the `title` and `api` in the frontmatter:

    ```mdx theme={null}
    ---
    title: 'Create new user'
    api: 'POST /v1/users'
    ---
    ```

    The `api` frontmatter field accepts either a full URL or a relative path:

    * **Full URL** like `POST https://api.acme.com/v1/users`. The `server` field in `docs.json` is ignored for that endpoint.
    * **Relative path** like `POST /v1/users`. Requires a `server` field in `docs.json`. The server URL is prepended to the path.

    Specify path parameters by wrapping them in `{}`:

    ```bash theme={null}
    https://api.example.com/v1/endpoint/{userId}
    ```

    To override the global playground display mode for a specific page, add `playground` to the frontmatter:

    ```mdx theme={null}
    ---
    title: 'Create new user'
    api: 'POST https://api.mintlify.com/user'
    playground: 'none'
    ---
    ```

    Options:

    * `playground: 'interactive'` - Display the interactive playground (default)
    * `playground: 'simple'` - Display a copyable endpoint with no playground
    * `playground: 'none'` - Hide the playground entirely
  </Step>

  <Step title="Add parameters and responses">
    Use [parameter and response fields](/docs/components/fields) to document your endpoint's parameters and return values. To show request and response code samples in the right sidebar, wrap them in [`<RequestExample>` and `<ResponseExample>`](/docs/components/examples) components.

    ```mdx theme={null}
    <ParamField path="userId" type="string" required>
      Unique identifier for the user
    </ParamField>

    <ParamField body="email" type="string" required>
      User's email address
    </ParamField>

    <ResponseField name="id" type="string" required>
      Unique identifier for the newly created user
    </ResponseField>

    <ResponseField name="email" type="string" required>
      User's email address
    </ResponseField>
    ```
  </Step>

  <Step title="Add your endpoints to your docs">
    Add your endpoint pages to the navigation by updating the `pages` field in your `docs.json`:

    ```json docs.json theme={null}
    "navigation": {
      "tabs": [
        {
          "tab": "API Reference",
          "groups": [
            {
              "group": "Users",
              "pages": [
                "api-reference/users/create-user",
                "api-reference/users/get-user",
                "api-reference/users/update-user"
              ]
            },
            {
              "group": "Orders",
              "pages": [
                "api-reference/orders/create-order",
                "api-reference/orders/list-orders"
              ]
            }
          ]
        }
      ]
    }
    ```

    Each page path corresponds to an MDX file in your docs repository. For example, `api-reference/users/create-user.mdx`. Learn more about structuring your docs in [Navigation](/docs/organize/navigation).

    ### Using OpenAPI endpoints in navigation

    If you have an OpenAPI specification, you can reference endpoints directly in your navigation without creating individual MDX files. Reference specific endpoints by including the OpenAPI file path and the endpoint:

    ```json docs.json theme={null}
    "navigation": {
      "pages": [
        "introduction",
        "/path/to/users-openapi.json POST /users",
        "/path/to/orders-openapi.json GET /orders"
      ]
    }
    ```

    You can also set a default OpenAPI spec for a navigation group and reference endpoints by method and path:

    ```json docs.json theme={null}
    {
      "group": "API reference",
      "openapi": "/path/to/openapi-v1.json",
      "pages": [
        "overview",
        "authentication",
        "GET /users",
        "POST /users",
        {
          "group": "Orders",
          "openapi": "/path/to/openapi-v2.json",
          "pages": [
            "GET /orders",
            "POST /orders"
          ]
        }
      ]
    }
    ```

    For more details on OpenAPI integration, see [OpenAPI setup](/docs/api-playground/openapi-setup).
  </Step>
</Steps>

## Enable authentication

You can set authentication globally in `docs.json`. To override it on an individual page, use the `authMethod` field in frontmatter. A page-specific method overrides the global setting.

### Bearer token

<CodeGroup>
  ```json docs.json theme={null}
  "api": {
    "mdx": {
      "auth": {
        "method": "bearer"
      }
    }
  }
  ```

  ```mdx Page Metadata theme={null}
  ---
  title: "Your page title"
  authMethod: "bearer"
  ---
  ```
</CodeGroup>

### Basic authentication

<CodeGroup>
  ```json docs.json theme={null}
  "api": {
    "mdx": {
      "auth": {
        "method": "basic"
      }
    }
  }
  ```

  ```mdx Page Metadata theme={null}
  ---
  title: "Your page title"
  authMethod: "basic"
  ---
  ```
</CodeGroup>

### API key

<CodeGroup>
  ```json docs.json theme={null}
  "api": {
    "mdx": {
      "auth": {
        "method": "key",
        "name": "x-api-key"
      }
    }
  }
  ```

  ```mdx Page Metadata theme={null}
  ---
  title: "Your page title"
  authMethod: "key"
  ---
  ```
</CodeGroup>

### None

To disable authentication on a specific page, set `authMethod` to `none`:

```mdx Page Metadata theme={null}
---
title: "Your page title"
authMethod: "none"
---
```


# Multiple responses
Source: https://www.mintlify.com/docs/api-playground/multiple-responses

Document multiple response variations for API endpoints, including success and error cases, with status codes and example payloads.

If your API returns different responses based on input parameters, user context, or other conditions of the request, you can document multiple response examples with the `examples` property.

Add this property to any response. It has the following schema.

```yaml theme={null}
responses:
  "200":
    description: Successful response
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/YourResponseSchema"
        examples:
          us:
            summary: Response for United States
            value:
              countryCode: "US"
              currencyCode: "USD"
              taxRate: 0.0825
          gb:
            summary: Response for United Kingdom
            value:
              countryCode: "GB"
              currencyCode: "GBP"
              taxRate: 0.20
```

The playground also handles non-JSON response types differently based on their content type.

## Audio response examples

For endpoints that return audio files, set the response content type to `audio/*` and provide a URL to an audio file as the example value. The playground renders an interactive audio player instead of a code snippet.

```yaml theme={null}
responses:
  "200":
    description: Audio file generated successfully
    content:
      audio/mpeg:
        schema:
          type: string
          format: binary
        examples:
          sample:
            summary: Sample audio output
            value: "https://example.com/sample-audio.mp3"
```


# OpenAPI setup
Source: https://www.mintlify.com/docs/api-playground/openapi-setup

Generate interactive API documentation from OpenAPI specification files with automatic endpoint pages, request builders, and navigation.

OpenAPI is a specification for describing APIs. Mintlify supports OpenAPI 3.0 and 3.1 documents to generate interactive API documentation and keep it up to date.

## Add an OpenAPI specification file

To document your endpoints with OpenAPI, you need one or more valid OpenAPI specifications in either JSON or YAML format that follow the [OpenAPI specification 3.0 or 3.1](https://swagger.io/specification/).

Add OpenAPI specifications to your documentation repository or host them online where you can access the specifications by URL. Mintlify serves specifications stored in your repository as [downloadable files](/docs/create/files) at their path on your docs domain. For example, `https://your-domain/docs/openapi.json`.

Reference any number of OpenAPI specifications in the navigation element of your `docs.json` to create pages for your API endpoints. Each specification file generates its own set of endpoints.

<CodeGroup>
  ```json Single specification theme={null}
  "navigation": {
    "tabs": [
      {
        "tab": "API Reference",
        "openapi": "openapi.json"
      }
    ]
  }
  ```

  ```json Multiple specifications theme={null}
  "navigation": {
    "tabs": [
      {
        "tab": "API Reference",
        "openapi": [
          "openapi/v1.json",
          "openapi/v2.json"
        ]
      }
    ]
  }
  ```
</CodeGroup>

<Note>
  Mintlify supports `$ref` for **internal references only** within a single OpenAPI document. Mintlify does not support external references.
</Note>

### Describe your API

Use the following resources to learn about and construct your OpenAPI specification.

* [Swagger's OpenAPI Guide](https://swagger.io/docs/specification/v3_0/basic-structure/) to learn the OpenAPI syntax.
* [The OpenAPI specification Markdown sources](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/) to reference details of the latest OpenAPI specification.
* [Swagger Editor](https://editor.swagger.io/) to edit, validate, and debug your OpenAPI document.
* [The Mint CLI](https://www.npmjs.com/package/mint) to validate your OpenAPI document with the command: `mint validate`.

<Note>
  Swagger's OpenAPI Guide is for OpenAPI v3.0, but nearly all of the information is applicable to v3.1. For more information on the differences between v3.0 and v3.1, see [Migrating from OpenAPI 3.0 to 3.1.0](https://www.openapis.org/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0) in the OpenAPI blog.
</Note>

### Specify the base URL for your API

To enable the API playground, add a `servers` field to your OpenAPI specification with your API's base URL.

```json theme={null}
{
  "servers": [
    {
      "url": "https://api.example.com/v1"
    }
  ]
}
```

In an OpenAPI specification, paths like `/users/{id}` or `/` identify different API endpoints. The base URL defines where clients append these paths. For more information on how to configure the `servers` field, see [API Server and Base Path](https://swagger.io/docs/specification/api-host-and-base-path/) in the OpenAPI documentation.

The API playground uses these server URLs to determine where to send requests. If you specify multiple servers, a dropdown allows users to toggle between servers. If you do not specify a server, the API playground uses simple mode since it cannot send requests without a base URL.

If your API has endpoints that exist at different URLs, you can [override the `servers` field](https://swagger.io/docs/specification/v3_0/api-host-and-base-path/#overriding-servers) for a given path or operation.

### Configure file uploads

For OpenAPI 3.1 specifications, define a file upload as a string schema with a binary `contentMediaType`. The API playground recognizes the field as a file input and sends it as part of a `multipart/form-data` request.

Use this configuration when an endpoint accepts a file inside a multipart request. You can also use `contentEncoding` to describe how the file content encodes. A `contentEncoding` value without a binary `contentMediaType` remains a text field. For base64-encoded files, set `contentEncoding` to `base64` or `base64url`. The API playground treats either value as a base64 file. For other values or no value, the API playground uses binary file handling.

```json theme={null}
{
  "paths": {
    "/imports": {
      "post": {
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "contentMediaType": "application/octet-stream"
                  }
                },
                "required": ["file"]
              }
            }
          }
        }
      }
    }
  }
}
```

You can use binary media types such as `application/octet-stream`, images, audio, video, PDFs, and archives. The API playground does not treat structured media types such as `application/json` as file uploads. The older `format: "binary"` and `format: "base64"` values remain supported.

### Specify authentication

To enable authentication in your API documentation and playground, configure the `securitySchemes` and `security` fields in your OpenAPI specification. The API descriptions and API playground add authentication fields based on the security configurations in your OpenAPI specification.

<Steps>
  <Step title="Define your authentication method.">
    Add a `securitySchemes` field to define how users authenticate.

    This example shows a configuration for bearer authentication.

    ```json theme={null}
    {
      "components": {
        "securitySchemes": {
          "bearerAuth": {
            "type": "http",
            "scheme": "bearer"
          }
        }
      }
    }
    ```
  </Step>

  <Step title="Apply authentication to your endpoints.">
    Add a `security` field to require authentication.

    ```json theme={null}
    {
      "security": [
        {
          "bearerAuth": []
        }
      ]
    }
    ```
  </Step>
</Steps>

Common authentication types include:

* [API Keys](https://swagger.io/docs/specification/authentication/api-keys/): For header, query, or cookie-based keys.
* [Bearer](https://swagger.io/docs/specification/authentication/bearer-authentication/): For JWT or OAuth tokens.
* [Basic](https://swagger.io/docs/specification/authentication/basic-authentication/): For username and password.

If different endpoints within your API require different authentication methods, you can [override the `security` field](https://swagger.io/docs/specification/authentication/#:~:text=you%20can%20apply%20them%20to%20the%20whole%20API%20or%20individual%20operations%20by%20adding%20the%20security%20section%20on%20the%20root%20level%20or%20operation%20level%2C%20respectively.) for a given operation.

For more information on defining and applying authentication, see [Authentication](https://swagger.io/docs/specification/authentication/) in the OpenAPI documentation.

#### Set default values for security schemes

Use the `x-default` extension on a security scheme to pre-fill the authentication field in the API playground. This is useful for providing placeholder values or test credentials that help users get started quickly.

```json {6} theme={null}
{
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "x-default": "your-api-key-here"
      }
    }
  }
}
```

The `x-default` extension supports `apiKey` and `http` bearer security scheme types. The value appears as the default input in the playground's authentication fields. Prefill for security schemes is unconditional and does not require any additional configuration.

Use `x-default` on other schema properties in your OpenAPI specification to set a default value in the API playground without affecting the `default` field in the schema definition. Unlike security schemes, prefill for non-security-scheme properties only takes effect when you set [`api.examples.prefill`](/docs/organize/settings-api) to `true` in your [`docs.json`](/docs/api-playground/overview#example-configuration).

## Let visitors download your spec

Opt into a "Download API spec" entry in the [page context menu](/docs/organize/settings-structure#contextual) by adding `"download-spec"` to `contextual.options` in your `docs.json`:

```json theme={null}
"contextual": {
  "options": ["copy", "download-spec", "chatgpt", "claude"]
}
```

When enabled, clicking the option downloads your OpenAPI spec directly. Deployments with multiple specs receive them bundled as `api-specs.zip`. On deployments behind `auth` or `userAuth`, only authenticated readers can download the spec.

<Warning>
  The downloaded OpenAPI spec is unfiltered and does not respect [authentication groups](/docs/deploy/authentication-setup). Any authenticated reader who can open the contextual menu receives the full spec, including endpoints and schemas that would otherwise be hidden from their group. Do not enable `download-spec` on an authenticated site if your OpenAPI spec contains endpoints or fields you consider sensitive.
</Warning>

## Customize your endpoint pages

Customize your endpoint pages by adding the `x-mint` extension to your OpenAPI specification. The `x-mint` extension gives you additional control over how your API documentation generates and displays.

### Metadata

Override the default metadata for generated API pages by adding `x-mint: metadata` to any operation. You can use any metadata field that would be valid in MDX frontmatter except for `openapi`.

```json {7-14} theme={null}
{
  "paths": {
    "/users": {
      "get": {
        "summary": "Get users",
        "description": "Retrieve a list of users",
        "x-mint": {
          "metadata": {
            "title": "List all users",
            "sidebarTitle": "List users",
            "description": "Fetch paginated user data with filtering options",
            "og:title": "Display a list of users"
          }
        },
        "parameters": [
          {
            // Parameter configuration
          }
        ]
      }
    }
  }
}
```

You can also control playground display per endpoint using the `playground` and `groups` metadata fields:

```json {7-11} theme={null}
{
  "paths": {
    "/admin/users": {
      "post": {
        "summary": "Create admin user",
        "x-mint": {
          "metadata": {
            "playground": "auth",
            "groups": ["admin"],
            "public": true
          }
        }
      }
    }
  }
}
```

This configuration makes the page publicly visible while restricting the interactive playground to authenticated users in the `admin` group.

### Content

Add content before the auto-generated API documentation using `x-mint: content`. The `x-mint: content` extension supports all Mintlify MDX components and formatting.

```json {6-8} theme={null}
{
  "paths": {
    "/users": {
      "post": {
        "summary": "Create user",
        "x-mint": {
          "content": "## Prerequisites\n\nThis endpoint requires admin privileges and has rate limiting.\n\n<Note>User emails must be unique across the system.</Note>"
        },
        "parameters": [
          {
            // Parameter configuration
          }
        ]
      }
    }
  }
}
```

### href

Set the URL of the autogenerated endpoint page using `x-mint: href`. When `x-mint: href` is present, the generated API page uses the specified URL instead of the default autogenerated URL.

```json {6-8, 14-16} theme={null}
{
  "paths": {
    "/legacy-endpoint": {
      "get": {
        "summary": "Legacy endpoint",
        "x-mint": {
          "href": "/deprecated-endpoints/legacy-endpoint"
        }
      }
    },
    "/documented-elsewhere": {
      "post": {
        "summary": "Special endpoint",
        "x-mint": {
          "href": "/guides/special-endpoint-guide"
        }
      }
    }
  }
}
```

### Parameter pills

Annotate parameters in the API reference and playground with custom pill labels using `x-mint.pre` and `x-mint.post` on any schema. Pills defined with `x-mint.pre` render before the parameter name, and pills defined with `x-mint.post` render after it, alongside Mintlify's built-in pills like `required`, `read-only`, and `write-only`.

Both fields accept an array of strings. Each string becomes its own pill.

```json {7-10} theme={null}
{
  "components": {
    "schemas": {
      "User": {
        "properties": {
          "email": {
            "type": "string",
            "x-mint": {
              "pre": ["PII"],
              "post": ["indexed", "unique"]
            }
          }
        }
      }
    }
  }
}
```

To surface arbitrary OpenAPI spec fields as pills across every parameter without editing each schema, configure [`api.params.post`](/docs/organize/settings-api#api-params) in your `docs.json`. List the field keys you want to display, and Mintlify reads each value from the schema and renders matching pills automatically.

```json theme={null}
{
  "api": {
    "params": {
      "post": ["nullable", "x-internal"]
    }
  }
}
```

With this configuration, a property like `{ "type": "string", "nullable": true, "x-internal": "admin" }` renders `nullable` and `admin` pills next to its name. Post pills appear in this order: built-in pills (`read-only`, `write-only`), then `api.params.post` config-driven pills, then per-property `x-mint.post` pills.

### Group display names

Set a custom display name for a tag's navigation group using the `x-group` extension on a tag object. By default, Mintlify uses the tag `name` as both the navigation group label and the URL path segment. The `x-group` extension overrides the group label while keeping the tag name for the URL.

This is useful when you want a human-readable group name that differs from the tag used in your API paths.

```json {4-9} theme={null}
{
  "tags": [
    {
      "name": "user-management",
      "description": "Endpoints for managing users",
      "x-group": "User Management"
    }
  ],
  "paths": {
    "/users": {
      "get": {
        "tags": ["user-management"],
        "summary": "List users"
      }
    }
  }
}
```

In this example, the navigation group displays as "User Management" but the generated page URL still uses the `user-management` tag name as its path segment.

## Auto-populate API pages

Add an `openapi` field to any navigation element in your `docs.json` to automatically generate pages for OpenAPI endpoints. You can control where these pages appear in your navigation structure, as dedicated API sections or with other pages.

The `openapi` field accepts either a path in your docs repo or a URL to a hosted OpenAPI document. Hosted specs must be reachable from the public internet.

<Tip>
  When you use a URL for your OpenAPI spec, changes to the spec don't trigger a Git push, so your docs won't redeploy automatically. To keep your docs in sync, call the [Trigger deployment](/docs/api/update/trigger) API endpoint in the same CI action that generates or updates your spec. This way your docs update automatically without needing to manually trigger a deployment from the dashboard.
</Tip>

Generated endpoint pages have these default metadata values:

* `title`: The operation's `summary` field, if present. If there is no `summary`, Mintlify generates the title from the HTTP method and endpoint.
* `description`: The operation's `description` field, if present.
* `version`: The `version` value from the parent anchor or tab, if present.
* `deprecated`: The operation's `deprecated` field. If `true`, a deprecated label appears next to the endpoint title in the side navigation and on the endpoint page.

<Tip>
  To exclude specific endpoints from your auto-generated API pages, add the [x-hidden](/docs/api-playground/managing-page-visibility#x-hidden) property to the operation in your OpenAPI spec.
</Tip>

There are two approaches for adding endpoint pages into your documentation:

1. **Dedicated API sections**: Reference OpenAPI specs in navigation elements for dedicated API sections.
2. **Selective endpoints**: Reference specific endpoints in your navigation alongside other pages.

### Dedicated API sections

Generate dedicated API sections by adding an `openapi` field to a navigation element and no other pages. All endpoints in the specification appear in the generated section.

```json {5} theme={null}
"navigation": {
  "tabs": [
    {
        "tab": "API Reference",
        "openapi": "https://petstore3.swagger.io/api/v3/openapi.json"
    }
  ]
}
```

To organize multiple OpenAPI specifications in separate sections of your documentation, assign each specification to a different group in your navigation hierarchy. Each group can reference its own OpenAPI specification.

```json {8-11, 15-18} theme={null}
"navigation": {
  "tabs": [
    {
      "tab": "API Reference",
      "groups": [
        {
          "group": "Users API",
          "openapi": {
            "source": "/path/to/users-openapi.json",
            "directory": "users-api-reference"
          }
        },
        {
          "group": "Admin API",
          "openapi": {
            "source": "/path/to/admin-openapi.json",
            "directory": "admin-api-reference"
          }
        }
      ]
    }
  ]
}
```

<Note>
  The `directory` field is optional and specifies where Mintlify stores generated API pages in your docs repo. If not specified, defaults to the `api-reference` directory of your repo.
</Note>

### Selective endpoints

When you want more control over where endpoints appear in your documentation, you can reference specific endpoints in your navigation. This approach lets you generate pages for API endpoints alongside other content. You can also use this approach to mix endpoints from different OpenAPI specifications.

#### Set a default OpenAPI spec

Configure a default OpenAPI specification for a navigation element. Then reference specific endpoints in the `pages` field.

```json {12, 15-16} theme={null}
"navigation": {
  "tabs": [
    {
      "tab": "Getting started",
      "pages": [
        "quickstart",
        "installation"
      ]
    },
    {
      "tab": "API reference",
      "openapi": "/path/to/openapi.json",
      "pages": [
        "api-overview",
        "GET /users",
        "POST /users",
        "guides/authentication"
      ]
    }
  ]
}
```

Any page entry matching the format `METHOD /path` generates an API page for that endpoint using the default OpenAPI specification.

#### OpenAPI spec inheritance

Child navigation elements inherit their parent's OpenAPI specification unless they define their own.

```json {3, 7-8, 11, 13-14} theme={null}
{
  "group": "API reference",
  "openapi": "/path/to/openapi-v1.json",
  "pages": [
    "overview",
    "authentication",
    "GET /users",
    "POST /users",
    {
      "group": "Orders",
      "openapi": "/path/to/openapi-v2.json",
      "pages": [
        "GET /orders",
        "POST /orders"
      ]
    }
  ]
}
```

#### Individual endpoints

Reference specific endpoints without setting a default OpenAPI specification by including the file path. You can reference endpoints from multiple OpenAPI specifications in the same documentation section.

```json {5-6} theme={null}
"navigation": {
  "pages": [
    "introduction",
    "user-guides",
    "/path/to/users-openapi.json POST /users",
    "/path/to/orders-openapi.json GET /orders"
  ]
}
```

This approach is useful when you need individual endpoints from different specifications, only want to include select endpoints, or want to include endpoints alongside other types of documentation.

## Create MDX pages from your OpenAPI specification

For more granular control over individual endpoint pages, create MDX pages from your OpenAPI specification. This lets you customize page metadata, content, and reorder or exclude pages in your navigation while still using the auto-generated parameters and responses.

There are two ways to document your OpenAPI specification with individual MDX pages:

* Document endpoints with the `openapi` field in the frontmatter.
* Document data models with the `openapi-schema` field in the frontmatter.

### Document endpoints

Create a page for each endpoint and specify which OpenAPI operation to display using the `openapi` field in the frontmatter.

<CodeGroup>
  ```mdx Example theme={null}
  ---
  title: "Get users"
  description: "Returns all plants from the system that the user has access to"
  openapi: "/path/to/openapi-1.json GET /users"
  deprecated: true
  version: "1.0"
  ---
  ```

  ```mdx Format theme={null}
  ---
  title: "title of the page"
  description: "description of the page"
  openapi: openapi-file-path method path
  deprecated: boolean (not required)
  version: "version-string" (not required)
  ---
  ```
</CodeGroup>

The method and path must exactly match your OpenAPI spec. If you have multiple OpenAPI specifications, include the path to the correct specification in your reference. You can also reference external OpenAPI URLs in `docs.json`.

<Warning>
  **Always specify the OpenAPI file path when you have multiple OpenAPI specifications in your repository.**

  Mintlify uploads every OpenAPI specification in your docs repository, even if it isn't referenced in `docs.json`. When an MDX page uses `openapi: "METHOD /path"` without a file path, Mintlify searches every uploaded specification for a matching operation. If more than one spec contains the same method and path, the first match wins based on alphabetical filename order, which may not be the spec you expect.

  To avoid ambiguity, do one of the following:

  * Include the spec file path in the frontmatter: `openapi: "path/to/correct-openapi.json POST /v1/endpoint"`.
  * Use [automatic page generation](#auto-populate-api-pages) by referencing the OpenAPI file in `docs.json`, which always maps endpoints to the correct spec.
  * Remove the conflicting path from the other specification.
  * Delete OpenAPI files that are no longer needed from your repository.
</Warning>

#### Autogenerate endpoint pages

To autogenerate MDX files from your OpenAPI specification, use the Mintlify [scraper](https://www.npmjs.com/package/@mintlify/scraping).

```bash theme={null}
npx @mintlify/scraping@latest openapi-file <path-to-openapi-file> -o <folder-name>
```

<Tip>
  Add the `-o` flag to specify a folder to populate the files into. If a folder is not specified, the files populate in the working directory.
</Tip>

### Document data models

Create a page for each data structure defined in your OpenAPI specification's `components.schemas` using the `openapi-schema` field in the frontmatter.

<CodeGroup>
  ```mdx Example theme={null}
  ---
  openapi-schema: OrderItem
  ---
  ```

  ```mdx Format theme={null}
  ---
  openapi-schema: "openapi-file-path schema-key"
  ---
  ```
</CodeGroup>

If you have schemas with the same name in multiple files, specify the OpenAPI file:

<CodeGroup>
  ```mdx Example theme={null}
  ---
  openapi-schema: en-schema.json OrderItem
  ---
  ```

  ```mdx Format theme={null}
  ---
  openapi-schema: "path-to-schema-file schema-key"
  ---
  ```
</CodeGroup>

## Webhooks

Webhooks are HTTP callbacks that your API sends to notify external systems when events occur. OpenAPI 3.1+ documents support webhooks.

Add a `webhooks` field to your OpenAPI document alongside the `paths` field.

For more information on defining webhooks, see [Webhooks](https://spec.openapis.org/oas/v3.1.0#oasWebhooks) in the OpenAPI documentation.

To create an MDX page for a webhook (OpenAPI 3.1+), use `webhook` instead of an HTTP method:

```mdx theme={null}
---
title: "Order updated webhook"
description: "Triggered when an order is updated"
openapi: "openapi.json webhook orderUpdated"
---
```

The webhook name must exactly match the key in your OpenAPI spec's `webhooks` field.

## Callbacks

Callbacks describe out-of-band requests that your API sends to a URL provided by the caller, such as event notifications tied to a specific operation. When an OpenAPI operation defines `callbacks`, Mintlify renders them on the endpoint page in a collapsible section between the request body and response sections. Each callback shows its HTTP method, expression, and reuses the same body and response components as the parent operation.

For more information on defining callbacks, see [Callbacks](https://spec.openapis.org/oas/v3.1.0#callback-object) in the OpenAPI documentation.

Define callbacks on the operation in your OpenAPI spec:

```yaml theme={null}
paths:
  /subscribe:
    post:
      summary: Subscribe to events
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                callbackUrl:
                  type: string
                  format: uri
      responses:
        "201":
          description: Subscription created
      callbacks:
        orderUpdated:
          "{$request.body#/callbackUrl}":
            post:
              requestBody:
                required: true
                content:
                  application/json:
                    schema:
                      type: object
                      properties:
                        orderId:
                          type: string
                        status:
                          type: string
              responses:
                "200":
                  description: Callback received
```


# API playground overview
Source: https://www.mintlify.com/docs/api-playground/overview

Let developers test API endpoints directly in your documentation with an interactive playground that sends real requests and shows responses.

The API playground is an interactive environment where you can test and explore your API endpoints. You can craft API requests, submit them, and view responses without leaving your documentation.

See [Trigger an update](/docs/api/update/trigger) for an example of the API playground in action.

<Frame>
  <img alt="API playground for the trigger an update endpoint." />

  <img alt="API playground for the trigger an update endpoint." />
</Frame>

The playground generates interactive pages for your endpoints based on your OpenAPI specification or AsyncAPI schema. If you modify your API, the playground automatically updates the relevant pages.

Generate your API playground from an OpenAPI specification for the best results. You can also manually create API reference pages after defining a base URL and authentication method in your `docs.json`.

## Get started

<Steps>
  <Step title="Add your OpenAPI specification file.">
    <Tip>
      Validate your OpenAPI specification file using the [Swagger Editor](https://editor.swagger.io/) or [Mint CLI](https://www.npmjs.com/package/mint) command `mint validate`.
    </Tip>

    ```bash {3} theme={null}
    /your-project
      |- docs.json
      |- openapi.json
    ```
  </Step>

  <Step title="Generate endpoint pages.">
    Update your `docs.json` to reference your OpenAPI specification.

    **To automatically generate pages for all endpoints in your OpenAPI specification**, add an `openapi` property to any navigation element.

    This example generates a page for each endpoint specified in `openapi.json` and organizes the pages in the "API reference" group.

    ```json Generate all endpoint pages theme={null}
    "navigation": {
      "groups": [
        {
          "group": "API reference",
          "openapi": "openapi.json"
        }
      ]
    }
    ```

    **To generate pages for only specific endpoints**, list the endpoints in the `pages` property of the navigation element.

    This example generates pages for only the `GET /users` and `POST /users` endpoints. To generate other endpoint pages, add additional endpoints to the `pages` array.

    ```json Generate specific endpoint pages theme={null}
    "navigation": {
      "groups": [
          {
            "group": "API reference",
            "openapi": "openapi.json",
            "pages": [
              "GET /users",
              "POST /users"
            ]
          }
      ]
    }
    ```
  </Step>
</Steps>

## Customize your playground

Customize your API playground by defining the following properties in your `docs.json`.

<ResponseField name="playground" type="object">
  Configurations for the API playground.

  <Expandable title="playground">
    <ResponseField name="display" type="&#x22;interactive&#x22; | &#x22;simple&#x22; | &#x22;none&#x22; | &#x22;auth&#x22;">
      The display mode of the API playground.

      * `"interactive"`: Display the interactive playground.
      * `"simple"`: Display a copyable endpoint with no playground.
      * `"none"`: Display nothing.
      * `"auth"`: Display the interactive playground only to authenticated users. Unauthenticated users or users not in the required groups see no playground.

      Defaults to `interactive`.
    </ResponseField>

    <ResponseField name="proxy" type="boolean">
      Whether to pass API requests through Mintlify's proxy server. Defaults to `true`.

      When `true`, playground requests are routed through Mintlify's servers. When `false`, the playground sends requests directly from the browser to your API. Set to `false` when your API accepts direct browser requests and you don't need Mintlify to proxy the traffic. This is useful when your API requires specific headers that can't be forwarded through the proxy. It is also useful when you need the request to originate directly from the user's browser for authentication purposes.
    </ResponseField>

    <ResponseField name="credentials" type="boolean">
      Whether to include cookies, authorization headers, and TLS client certificates for cross-origin requests when `proxy` is `false`. Defaults to `false`.

      When `true` and `proxy` is `false`, the playground sends requests with browser-managed credentials included. For example, when your API uses cookie-based authentication or HTTP session tokens.

      This option has no effect when `proxy` is `true`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="url" type="&#x22;full&#x22;">
  The display mode for base URLs in endpoint headers. When set to `full`, the full base URL displays for every endpoint page. By default, only the relative endpoint path displays.
</ResponseField>

<ResponseField name="examples" type="object">
  Configurations for the autogenerated API examples.

  <Expandable title="examples">
    <ResponseField name="languages" type="array of string">
      Example languages for the autogenerated API snippets.

      Languages display in the order specified.

      <Accordion title="All supported languages">
        | Display name | Key          | Aliases                   |
        | ------------ | ------------ | ------------------------- |
        | cURL         | `bash`       | `curl`, `sh`, `shell`     |
        | Python       | `python`     | `py`                      |
        | JavaScript   | `javascript` | `js`                      |
        | Node.js      | `node`       | `nodejs`, `node.js`       |
        | PHP          | `php`        |                           |
        | Go           | `go`         | `golang`                  |
        | Java         | `java`       |                           |
        | Ruby         | `ruby`       | `rb`                      |
        | PowerShell   | `powershell` |                           |
        | Swift        | `swift`      |                           |
        | C#           | `csharp`     | `c#`                      |
        | .NET         | `dotnet`     | `.net`, `.NET`, `dot-net` |
        | TypeScript   | `typescript` | `ts`                      |
        | C            | `c`          |                           |
        | C++          | `c++`        | `cpp`                     |
        | Kotlin       | `kotlin`     | `kt`                      |
        | Rust         | `rust`       | `rs`                      |
        | Dart         | `dart`       | `flutter`                 |
      </Accordion>
    </ResponseField>

    <ResponseField name="defaults" type="&#x22;required&#x22; | &#x22;all&#x22;">
      Whether to show optional parameters in API examples. Defaults to `all`.
    </ResponseField>

    <ResponseField name="prefill" type="boolean">
      Whether to prefill the API playground with data from schema examples. When enabled, the playground automatically populates request fields with example values from your OpenAPI specification. Defaults to `false`.
    </ResponseField>

    <ResponseField name="autogenerate" type="boolean">
      Whether to generate code samples for endpoints from API specifications. Defaults to `true`. When set to `false`, only manually written code samples (from `x-codeSamples` in OpenAPI specifications or `<RequestExample>` components in MDX) appear in the API playground.
    </ResponseField>
  </Expandable>
</ResponseField>

### Example configuration

This example configures the API playground to be interactive with example code snippets for cURL, Python, and JavaScript. It only shows required parameters in the code snippets, and the playground prefills the request body with example values.

```json theme={null}
{
 "api": {
   "playground": {
     "display": "interactive"
   },
   "examples": {
     "languages": ["curl", "python", "javascript"],
     "defaults": "required",
     "prefill": true
   }
 }
}
```

### Auth-based playground display

Use the `auth` display mode to show the interactive playground only to authenticated users. This is useful when you want to let users view your API documentation publicly while restricting playground access to logged-in users.

When `display` is set to `auth`:

* Authenticated users see the interactive playground.
* Unauthenticated users see no playground (equivalent to `none`).

You can also combine `auth` with the `groups` property in page frontmatter to restrict playground access to specific user groups.

```mdx Page with group-restricted playground theme={null}
---
title: "Create user"
openapi: POST /users
playground: auth
groups: ["admin", "developer"]
public: true
---
```

In this example:

* The page is publicly visible (anyone can view the documentation).
* Only authenticated users in the `admin` or `developer` groups see the interactive playground.
* Users not in those groups see no playground.

If the page has no `groups` property, all authenticated users see the interactive playground.

<Note>
  The `auth` display mode requires your documentation to have [authentication](/docs/deploy/authentication-setup) configured.
</Note>

### Custom endpoint pages

When you need more control over your API documentation, use the `x-mint` extension in your OpenAPI specification or create individual MDX pages for your endpoints.

Both options allow you to:

* Customize page metadata
* Add additional content like examples
* Control playground behavior per page

Use the `x-mint` extension so that all of your API documentation generates automatically from your OpenAPI specification and stays maintained in one file.

Use individual MDX pages for small APIs or when you want to experiment with changes on a per-page basis.

## Response rendering

The playground automatically renders responses based on the `Content-Type` header returned by your API.

* **Images**: Rendered inline (`image/*`).
* **Audio**: Rendered with a built-in audio player (`audio/*`).
* **Video**: Rendered with a built-in video player (`video/*`). Any response with a `video/*` content type, such as `video/mp4` or `video/webm`, displays as a playable video directly in the playground.
* **All other responses**: Displayed in a code block.

## Parameter anchor links

Every parameter in the API playground has a clickable anchor link. Hover over a parameter name to reveal the link icon, then click to copy a direct URL to that parameter.

Use parameter anchor links to:

* Share links to specific parameters in support conversations or documentation
* Navigate directly to a parameter from another page or external resource
* Bookmark frequently referenced parameters

The URL format is `your-docs-url/endpoint-path#parameter-name`. For nested parameters, the anchor includes the parent path.

## Further reading

* [OpenAPI setup](/docs/api-playground/openapi-setup) for more information on creating your OpenAPI document.
* [x-mint extension](/docs/api-playground/openapi-setup#customize-your-endpoint-pages) for more information on customizing your endpoint pages.
* [MDX setup](/docs/api-playground/mdx-setup) for more information on manually creating individual API reference pages.
* [AsyncAPI setup](/docs/api-playground/asyncapi-setup) for more information on creating your AsyncAPI schema to generate WebSocket reference pages.


# Generate SDK reference pages from doc-tool output
Source: https://www.mintlify.com/docs/api-playground/sdk-reference-setup

Publish SDK reference documentation in Mintlify from TypeDoc, DocFX, Javadoc, Sphinx, or phpDocumentor artifacts using the sdk navigation property.

Use the `sdk` navigation property to generate reference pages for your SDK libraries from the documentation tools you already run. Mintlify reads each tool's build artifact. It creates a page for every class, interface, module, and function. It also includes navigation groups, cross-page links, and search indexing.

## Supported formats

| `format`  | Tool                                                                             | Artifact                                                  |
| --------- | -------------------------------------------------------------------------------- | --------------------------------------------------------- |
| `typedoc` | [TypeDoc](https://typedoc.org) (TypeScript/JavaScript)                           | JSON export file                                          |
| `docfx`   | [DocFX](https://dotnet.github.io/docfx/) (.NET)                                  | `docfx metadata` output directory (ManagedReference YAML) |
| `javadoc` | [Javadoc](https://docs.oracle.com/en/java/javase/17/javadoc/javadoc.html) (Java) | Standard doclet HTML directory                            |
| `sphinx`  | [Sphinx](https://www.sphinx-doc.org) (Python)                                    | JSON builder output directory                             |
| `phpdoc`  | [phpDocumentor](https://phpdoc.org) (PHP)                                        | `structure.xml` file                                      |

## Generate an artifact

Run your documentation tool with a machine-readable output format. If you already publish generated docs from CI, this is usually a one-flag change to the same command.

<CodeGroup>
  ```bash TypeDoc theme={null}
  npx typedoc --json typedoc.json src/index.ts
  ```

  ```bash DocFX theme={null}
  docfx metadata docfx.json
  ```

  ```bash Javadoc theme={null}
  javadoc -d javadoc-output -sourcepath src/main/java -subpackages com.example
  # Or download the published javadoc jar from Maven Central
  ```

  ```bash Sphinx theme={null}
  python -m sphinx -b json docs/source artifacts/json
  ```

  ```bash phpDocumentor theme={null}
  phpdoc -d src -t artifacts --template=xml
  ```
</CodeGroup>

## Auto-populate SDK pages

Add an `sdk` property to a tab or group in your `docs.json`. Mintlify parses the artifact. It creates navigation groups and pages for the library.

```json theme={null}
"navigation": {
  "tabs": [
    {
      "tab": "SDK Reference",
      "sdk": {
        "format": "typedoc",
        "source": "sdk-artifacts/typedoc.json",
        "directory": "sdk/typescript"
      }
    }
  ]
}
```

Add `sdk` to a [group](/docs/organize/navigation#groups) to generate pages inside one section of a tab instead of an entire tab. Groups and pages inherit the `sdk` settings of the parent tab or group. If a nested group sets its own `sdk`, Mintlify uses those settings instead of the inherited ones.

```json theme={null}
{
  "group": "TypeScript SDK",
  "sdk": {
    "format": "typedoc",
    "source": "sdk-artifacts/typedoc.json",
    "directory": "sdk/typescript"
  },
  "pages": ["sdk/typescript/overview"]
}
```

A group with `sdk` can also list `pages` that you write yourself. Your pages appear first, followed by the generated reference groups.

<Note>
  You can declare `sdk` on a [tab](/docs/organize/navigation#tabs) or a [group](/docs/organize/navigation#groups).

  * A tab with `sdk` can include `groups`, but no other navigation structures, such as `pages`, `versions`, or `languages`. It also cannot include an `openapi`, `asyncapi`, or `graphql` property.
  * A group with `sdk` can include `pages` and nested groups, but cannot include a `graphql` property.
</Note>

<ParamField type="string">
  The documentation tool that produced the artifact: `typedoc`, `docfx`, `javadoc`, `sphinx`, or `phpdoc`.
</ParamField>

<ParamField type="string">
  Relative path to the artifact file or directory in your docs repository, or an HTTPS URL. The `source` field does not accept HTTP URLs.
</ParamField>

<ParamField type="string">
  The URL path prefix for generated pages. Defaults to `sdk-reference`.
</ParamField>

Add multiple tabs or groups to document multiple libraries. For example, use two groups in the same tab for the stable and beta versions of an SDK. Use a unique `directory` for each library to avoid route collisions.

<Tip>
  Add your artifact directory to [`.mintignore`](/docs/organize/mintignore) so Mintlify treats artifacts as build inputs rather than publishing them as static assets.
</Tip>

## Generated pages

Mintlify adds the generated navigation groups after any `groups` on the tab. If you add `sdk` to a group, the generated groups appear after that group's `pages`. The groups vary by format and may represent modules, packages, namespaces, or symbol types.

Each generated page documents a class, interface, function, type, or other symbol from the artifact and links to related generated pages. If a converter produces pages that do not belong to a group, Mintlify collects them under a `Reference` group.

## Customize a page for a single symbol

Use the `sdk` frontmatter on an MDX page to target one symbol from the artifact. Mintlify renders any body content you write, then appends the generated reference for that symbol below it. Use this when you want to add examples, migration notes, or context above a specific class, interface, or method.

Add the page to your `docs.json` navigation like any other page. Mintlify only builds SDK content for pages that appear in your navigation.

Once a tab or group with `sdk` contains a page with `sdk` frontmatter, Mintlify stops auto-populating that tab or group and shows only the pages you wrote. Move the page out of the tab or group if you want the rest of the library to auto-populate.

Point `sdk` at a symbol:

```mdx theme={null}
---
title: "Client"
sdk: "class Client"
---

Create a `Client` to call the API.
```

The string form follows the pattern `[source] kind name`. If you leave out `source`, the page inherits it from the tab or group `sdk` config. The string form always inherits `format`, so it only works on pages under a tab or group with `sdk`. Everywhere else, set `sdk` to an object with the fields below. For methods and properties, include the parent name, such as `method Client.getUser`.

If you leave out `title` or `description`, Mintlify uses the title and description generated for the symbol.

<ParamField type="string">
  The symbol kind: `class`, `interface`, `enum`, `function`, `type`, `variable`, `method`, or `property`.
</ParamField>

<ParamField type="string">
  The symbol name as it appears in the artifact.
</ParamField>

<ParamField type="string">
  Required for `method` and `property` targets. The enclosing class, interface, or type.
</ParamField>

<ParamField type="string">
  Overrides the inherited `format`. Required when the page is not under a tab or group with `sdk`. Only available in the object form.
</ParamField>

<ParamField type="string">
  Overrides the inherited `source`. Required when the page is not under a tab or group with `sdk`.
</ParamField>

## Use remote sources

Set `source` to an HTTPS URL to fetch the artifact at build time instead of committing it to your docs repository.

Single-file formats (`typedoc`, `phpdoc`) accept a direct file URL. Directory formats (`docfx`, `javadoc`, `sphinx`) accept a zip archive. Javadoc jars published to Maven Central work without repackaging:

```json theme={null}
{
  "tab": "Java SDK",
  "sdk": {
    "format": "javadoc",
    "source": "https://repo1.maven.org/maven2/com/example/my-library/1.0.0/my-library-1.0.0-javadoc.jar",
    "directory": "sdk/java"
  }
}
```

Remote artifacts have a 50 MB download limit and a 200 MB extracted size limit.

## Keep references up to date

Regenerate the artifact whenever your SDK changes. A common pattern is a CI job in each SDK repository that runs the documentation tool on release. The job either commits the artifact to your docs repository or uploads it to a stable URL that `source` points to.

## Repository setup

Store your SDK code and documentation in the same repository or separate repositories. Pick the pattern that matches your setup. Both options support the same capabilities.

### SDK and documentation in the same repository

Generate your SDK artifact in the same repository as your documentation and point `source` at its relative path. An existing workflow that produces the artifact on push or release can commit it back to the repository. The next documentation site deployment publishes the update.

```txt theme={null}
docs-repo/
  docs.json
  content/
  sdk-artifacts/
    typedoc.json
```

### SDK in a separate repository

When the SDK is in its own repository, you have two options.

1. **Commit the artifact to your documentation repository.** In the SDK repository, run a CI job at release time. The job generates the artifact and opens a pull request or pushes a commit with the updated file to your documentation repository. Merge the change into your deployment branch to trigger a site deployment. Point `source` at the committed path, as in the single-repository setup.

2. **Host the artifact and fetch it at build time.** Upload the artifact to a stable HTTPS URL. For example, an S3 bucket, GitHub Releases asset, or Maven Central for Javadoc jars. Set `source` to the URL. Trigger a documentation site deployment to fetch the new artifact whenever you update it. Call the [Trigger deployment](/docs/api/update/trigger) endpoint from your SDK release pipeline after you publish the artifact.

<Tip>
  If your release cadence is low or you want the documentation repository to be the source of truth, commit the artifact to your documentation repository. If your releases are frequent, artifacts are large, or you already publish them (for example, Javadoc jars on Maven Central), host the artifact and fetch it at build time.
</Tip>


# Troubleshooting
Source: https://www.mintlify.com/docs/api-playground/troubleshooting

Troubleshoot common issues with API playground configuration, including OpenAPI validation errors, missing endpoints, and auth problems.

If your API pages aren't displaying correctly, check these common configuration issues.

<AccordionGroup>
  <Accordion title="All of my OpenAPI pages are completely blank">
    This usually means that Mintlify cannot find your OpenAPI document or that the document is invalid.

    Run `mint dev` locally to reveal some of these issues.

    To verify your OpenAPI document passes validation:

    1. Visit [this validator](https://editor.swagger.io/).
    2. Switch to the **Validate text** tab.
    3. Paste in your OpenAPI document.
    4. Click **Validate it!**

    If the text box that appears below has a green border, your document has passed validation.
    Mintlify uses this exact validation package to validate OpenAPI documents. If your document passes
    validation here, the problem likely lies elsewhere.

    Additionally, Mintlify does not support OpenAPI 2.0. If your document uses this version of the specification,
    you could encounter this issue. You can convert your document at [editor.swagger.io](https://editor.swagger.io/) (under Edit > Convert to OpenAPI 3):

    <Frame>
      <img alt="Screenshot of the Swagger Editor with the Edit menu expanded and the &#x22;Convert to OpenAPI 3&#x22; menu item highlighted." />
    </Frame>
  </Accordion>

  <Accordion title="One of my OpenAPI pages is completely blank">
    A misspelled `openapi` field in the page metadata usually causes this issue. Make sure
    the HTTP method and path match the HTTP method and path in the OpenAPI document.

    <Note>
      Mintlify automatically resolves trailing slash differences between your `openapi` reference
      and the OpenAPI specification. For example, `GET /users/{id}/` matches a specification path of `/users/{id}`.
    </Note>

    Here's an example of how things might go wrong:

    ```mdx get-user.mdx theme={null}
    ---
    openapi: "GET /user/{id}"
    ---
    ```

    ```yaml openapi.yaml theme={null}
    paths:
      "/users/{id}":
        get: ...
    ```

    The path in the `openapi` field says `/user/{id}` (singular). The path in the OpenAPI document is
    `/users/{id}` (plural).

    Another common issue is a misspelled filename. If you specify a particular OpenAPI document
    in the `openapi` field, ensure the filename is correct. For example, if you have two OpenAPI
    documents, `openapi/v1.json` and `openapi/v2.json`, your metadata might look like this:

    ```mdx api-reference/v1/users/get-user.mdx theme={null}
    ---
    openapi: "v1 GET /users/{id}"
    ---
    ```
  </Accordion>

  <Accordion title="My build fails with &#x22;Failed to fetch OpenAPI file for anchor or tab&#x22;">
    This error means Mintlify could not download the OpenAPI document at the URL in your `docs.json` `openapi` field during the build. Common causes include:

    * The host is unreachable or resolves only from a private network.
    * The URL requires authentication (a token, session cookie, or IP allowlist).
    * The certificate is invalid or the domain has a DNS issue.
    * The origin returned a transient 5xx or timed out.
    * The spec was being republished at the moment the build ran, so the URL served a partial or empty response.

    Builds fetch the URL from the public internet without credentials, so confirm that the document downloads with `curl` from a machine outside your network. To fix the error, switch to one of these patterns:

    * **Commit the spec into your docs repo.** This is the recommended pattern when the source URL is behind auth. Point the `openapi` field at the repo-relative path (for example, `"openapi": "openapi.json"`) and update the file in the same commit that changes your API.
    * **Serve the spec from a stable public HTTPS URL.** Host it on a CDN or object storage bucket that does not require auth, has a valid TLS certificate, and returns the full document on every request.

    For a full diagnostic walkthrough, including intermittent failures caused by CI publishing the spec after triggering the build, see [Build fails with "Failed to fetch OpenAPI file for anchor or tab"](/docs/help-center/openapi-url-fetch-fails-during-build).
  </Accordion>

  <Accordion title="Requests from the API Playground don't work">
    If you use a custom domain, your reverse proxy might cause this issue. By default, the API
    Playground starts requests with a `POST` request to the `/_mintlify/api/request` path on the docs
    site. If your reverse proxy allows only `GET` requests, all of these requests fail. Configure your
    reverse proxy to allow `POST` requests to the `/_mintlify/api/request` path.

    Alternatively, if your reverse proxy prevents you from accepting `POST` requests, configure Mintlify
    to send requests directly to your backend with the `api.playground.proxy` setting in the `docs.json`.
    See the [settings documentation](/docs/organize/settings-api) for details. When you use this configuration,
    requests come directly from users' browsers rather than through your proxy. Configure Cross-Origin
    Resource Sharing (CORS) on your server.
  </Accordion>

  <Accordion title="OpenAPI navigation entries are not generating pages">
    If you are using an OpenAPI navigation configuration, but the pages aren't generating, check these common issues:

    1. **Missing default OpenAPI spec**: Ensure you have an `openapi` field set for the navigation element:

    ```json {5} theme={null}
    "navigation": {
      "groups": [
        {
          "group": "API reference",
          "openapi": "/path/to/openapi.json",
          "pages": [
            "GET /users",
            "POST /users"
          ]
        }
      ]
    }
    ```

    2. **OpenAPI spec inheritance**: If using nested navigation, ensure child groups inherit the correct OpenAPI spec or specify their own.

    3. **Validation issues**: Use `mint validate` to verify your OpenAPI document is valid.
  </Accordion>

  <Accordion title="Some OpenAPI operations appear in navigation but others don't">
    1. **Hidden operations**: Operations marked with `x-hidden: true` in your OpenAPI spec won't appear in auto-generated navigation.
    2. **Invalid operations**: Operations with validation errors in the OpenAPI spec may be skipped. Check your OpenAPI document for syntax errors.
    3. **Manual vs automatic inclusion**: If you reference any endpoints from an OpenAPI spec, only the explicitly referenced operations appear in navigation. No other pages are automatically added. This includes operations that are referenced in child navigation elements.
  </Accordion>

  <Accordion title="The Authorization field description is generic or unhelpful">
    Mintlify auto-generates a description for the `Authorization` field in the API playground based on the security scheme type. Add a `description` to the security scheme in your OpenAPI specification to override the generated text.

    ```json {7} theme={null}
    {
      "components": {
        "securitySchemes": {
          "bearerAuth": {
            "type": "http",
            "scheme": "bearer",
            "description": "Your API key from the [dashboard](https://example.com/dashboard). Send it as `Bearer <key>`."
          }
        }
      }
    }
    ```

    The `description` supports Markdown and replaces the auto-generated text on every endpoint that uses the security scheme.
  </Accordion>

  <Accordion title="Mixed navigation (OpenAPI and MDX pages) not working correctly">
    When combining OpenAPI operations with regular documentation pages in navigation:

    1. **File conflicts**: Mintlify does not support both an `MDX` file and a navigation entry for the same operation. For example, if you have `get-users.mdx`, do not also include `"GET /users"` in your navigation. If a file must share a name with an operation, use the `x-mint` extension for the endpoint so its href points to a different location.
    2. **Path resolution**: Mintlify treats navigation entries that don't match OpenAPI operations as file paths. Ensure your `MDX` files exist at the expected locations.
    3. **Case sensitivity**: OpenAPI operation matching is case-sensitive. Ensure HTTP methods are uppercase in navigation entries.
  </Accordion>
</AccordionGroup>


# Detect AI-sounding prose
Source: https://www.mintlify.com/docs/api/admin/deslop

admin-openapi.json POST /v1/deslop/{projectId}
Analyzes a page for AI-generated prose and returns flagged passages with suggested rewrites. Consumes one AI credit per checked page. Skips pages under 50 words. Limited to 30 requests per minute per client IP address.

This endpoint analyzes a documentation page for AI-generated prose and returns flagged passages with suggested human rewrites.

Authenticate with an [admin API key](/docs/api/introduction#admin-api-key).

## Credits

* Consumes 1 AI credit per checked page.
* The endpoint skips pages under 50 words and does not charge for them. The response returns `skipped: "too_short"` with `creditsCharged: 0`.
* If detection is temporarily unavailable, the endpoint returns `503` and doesn't consume a credit.
* The endpoint accepts up to 30 requests per minute per client IP address.

## Response

Checked pages return a verdict (`predictionShort`), AI and human fractions, and a `windows` array of flagged passages. Each window includes a line range and can include one to three suggested rewrites.

## Usage

```bash theme={null}
curl -X POST https://api.mintlify.com/v1/deslop/{projectId} \
  -H "Authorization: Bearer mint_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "path": "guides/quickstart.mdx",
    "content": "# Quickstart\n\nWelcome to our comprehensive documentation..."
  }'
```


# Create agent job
Source: https://www.mintlify.com/docs/api/agent/v2/create-agent-job

admin-openapi.json POST /v2/agent/{projectId}/job
Creates a new agent job that runs in the background. The job processes the prompt asynchronously — poll the get job endpoint to track progress. If the agent edits files successfully, a pull request is automatically created.

Authenticate with an admin API key.

This endpoint creates a background agent job. The job runs asynchronously. Use the [get agent job](/docs/api/agent/v2/get-agent-job) endpoint to poll for status updates.

If the agent edits files successfully, Mintlify creates a pull request and populates the `prLink` field in the job response.

## Rate limits

* 100 uses per Mintlify project per hour

## Usage

```bash theme={null}
curl -X POST https://api.mintlify.com/v2/agent/{projectId}/job \
  -H "Authorization: Bearer mint_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Add a quickstart guide for the Python SDK"}'
```


# Get agent job
Source: https://www.mintlify.com/docs/api/agent/v2/get-agent-job

admin-openapi.json GET /v2/agent/{projectId}/job/{id}
Retrieves the current status and details of an agent job. Poll this endpoint to track job progress.

Authenticate with an admin API key.

Poll this endpoint to track the progress of an agent job. The `status` field transitions through `active` → `completed` or `failed`.

After the agent creates a pull request, the `prLink` field contains the link.


# Send follow-up message
Source: https://www.mintlify.com/docs/api/agent/v2/send-message

admin-openapi.json POST /v2/agent/{projectId}/job/{id}/message
Sends a follow-up message to an existing agent job. The message is processed asynchronously — poll the get job endpoint to track progress.

Authenticate with an admin API key.

Send a follow-up instruction to an existing agent job. The agent processes the message asynchronously. Poll the [get agent job](/docs/api/agent/v2/get-agent-job) endpoint to track progress.

## Rate limits

* 100 uses per Mintlify project per hour

## Usage

```bash theme={null}
curl -X POST https://api.mintlify.com/v2/agent/{projectId}/job/{id}/message \
  -H "Authorization: Bearer mint_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Also add error handling examples to the quickstart guide"}'
```


# Get assistant caller stats
Source: https://www.mintlify.com/docs/api/analytics/assistant-caller-stats

analytics.openapi.json GET /v1/analytics/{projectId}/assistant/caller-stats
Returns a breakdown of assistant query counts by caller type (web, API, and other) for the specified date range.

Authenticate with an admin API key.

## Usage

Use this endpoint to see how the system distributes assistant queries across different caller types. The response breaks down total queries into:

* `web`: Queries from the documentation site
* `api`: Queries from direct API calls
* `other`: Queries from other sources (for example, integrations, SDKs)
* **total**: Sum of all query types

## Filtering

Filter by date range using `dateFrom` and `dateTo` parameters.

## Rate limits

This endpoint allows 100 requests per organization per hour. All analytics endpoints share this limit.


# Get assistant conversations
Source: https://www.mintlify.com/docs/api/analytics/assistant-conversations

analytics.openapi.json GET /v1/analytics/{projectId}/assistant
Returns paginated AI assistant conversation history

Authenticate with an admin API key.

## Usage

Use this endpoint to export AI assistant conversation history from your documentation. Each conversation includes the user query, assistant response, sources cited, resolution status, and query category.

Paginate through results using the `cursor` parameter returned in the response. Continue fetching while `hasMore` is `true`.

## Filtering

Filter conversations by date range using `dateFrom` and `dateTo` parameters.

## Conversation data

Each row represents one user turn in a conversation. A conversation with multiple back-and-forth messages produces multiple rows that share a `conversationId`.

Each row includes:

* **query**: The user's question.
* **response**: The assistant's answer. For clarifying-question turns, this is the follow-up question the assistant asked the user.
* **responseType**: Either `answer` or `clarifying_question`. `clarifying_question` means the assistant asked the user a follow-up question instead of answering. Defaults to `answer` when not present.
* **sources**: Pages referenced in the response, with title and URL.
* **resolutionStatus**: Whether the assistant successfully answered this turn. Either `answered` or `unanswered`. Computed per row, so a single conversation can contain both statuses. Use this field to track and analyze documentation gaps surfaced by user questions the assistant could not resolve.
* **timestamp**: When the user sent the message that started this turn. Rows in the same conversation have different timestamps.
* **queryCategory**: Classification of the query type, if available.
* **pageUrl**: Full URL of the documentation page where the conversation started, or `null` if no page path is available. Use this field to attribute conversations to a specific page.

## Rate limits

This endpoint allows 100 requests per organization per hour. All analytics endpoints share this limit.


# Get assistant conversation thread
Source: https://www.mintlify.com/docs/api/analytics/assistant-thread

analytics.openapi.json GET /v1/analytics/{projectId}/assistant/threads/{threadId}
Returns the full message transcript for a single assistant conversation thread. The thread ID is available from the assistant conversations endpoint, or as the `threadId` query parameter appended to assistant link-mode deflection support URLs.

Authenticate with an admin API key.

## Usage

Use this endpoint to fetch the full message transcript of a single assistant conversation as JSON. The response includes the ordered list of user and assistant messages, each with an ID, role, content, and timestamp.

Common uses:

* Attach the conversation transcript to a support ticket when a user reaches out from the assistant.
* Reconstruct a specific conversation for review, quality assurance, or offline analysis.

## Getting a thread ID

You can obtain a `threadId` from either of the following sources:

* The `id` field of any row returned by [Get assistant conversations](/docs/api/analytics/assistant-conversations).
* The `threadId` query parameter that Mintlify appends to the support URL when the assistant deflects to your support platform using [link deflection](/docs/assistant/configure#deflect-to-a-support-link).

## Rate limits

This endpoint allows 100 requests per organization per hour. All analytics endpoints share this limit.


# Get feedback
Source: https://www.mintlify.com/docs/api/analytics/feedback

analytics.openapi.json GET /v1/analytics/{projectId}/feedback
Returns paginated user feedback with optional filtering

Authenticate with an admin API key.

## Usage

Use this endpoint to export user feedback collected from your documentation. Feedback includes contextual feedback from page ratings, code snippet feedback, and agent feedback.

Paginate through results using the `cursor` parameter returned in the response. Continue fetching while `hasMore` is `true`.

## Filtering

Filter feedback by:

* **Date range**: Use `dateFrom` and `dateTo` to limit results to a specific time period
* **Source**: Filter by `code_snippet`, `contextual`, or `agent` feedback types
* **Status**: Filter by status values like `pending`, `in_progress`, `resolved`, or `dismissed`

## Response types

The response contains different feedback types based on the source:

* **Contextual feedback**: Includes `helpful` boolean and optional `contact` email
* **Code snippet feedback**: Includes `code`, `filename`, and `lang` fields
* **Agent feedback**: Includes a `comment` with the agent's feedback text and the `path` of the page it relates to

## Rate limits

This endpoint allows 100 requests per organization per hour. All analytics endpoints share this limit.


# Get feedback by page
Source: https://www.mintlify.com/docs/api/analytics/feedback-by-page

analytics.openapi.json GET /v1/analytics/{projectId}/feedback/by-page
Returns feedback counts aggregated by documentation page path (thumbs up/down for contextual feedback, code snippet count, and total per page)

Authenticate with an admin API key.

## Usage

Use this endpoint to export user feedback aggregated by documentation page path. Each entry shows the total feedback count for a page, broken down by type.

## Filtering

Filter feedback by:

* **Date range**: Use `dateFrom` and `dateTo` to limit results to a specific time period
* **Source**: Filter by `code_snippet`, `contextual`, or `agent` feedback types
* **Status**: Filter by status values like `pending`, `in_progress`, `resolved`, or `dismissed`

## Rate limits

This endpoint allows 100 requests per organization per hour. All analytics endpoints share this limit.


# Get search queries
Source: https://www.mintlify.com/docs/api/analytics/searches

analytics.openapi.json GET /v1/analytics/{projectId}/searches
Returns paginated documentation search terms for the date range, ordered by hit count descending. Each row includes click-through rate, the most-clicked result path for that query (if any), and the last time the term was searched. `totalSearches` is the total number of search query events in the same date range (sum of all hits, not distinct queries).

Authenticate with an admin API key.

## Usage

Use this endpoint to export documentation search analytics. Results are ordered by hit count descending, showing which terms your users search for most.

Paginate through results using the `nextCursor` parameter returned in the response. Continue fetching while `nextCursor` is not null.

## Filtering

Filter search data by date range using `dateFrom` and `dateTo` parameters.

## Rate limits

This endpoint allows 100 requests per organization per hour. All analytics endpoints share this limit.


# Get page views
Source: https://www.mintlify.com/docs/api/analytics/views

analytics.openapi.json GET /v1/analytics/{projectId}/views
Returns per-path and site-wide content view event counts, split by human and AI traffic.

Authenticate with an admin API key.

## Usage

Use this endpoint to export page view analytics. Results include both site-wide totals and per-page breakdowns, split by human and AI traffic.

Paginate through results using offset-based pagination. Increment `offset` by `limit` while `hasMore` is true.

## Filtering

Filter view data by date range using `dateFrom` and `dateTo` parameters.

## Rate limits

This endpoint allows 100 requests per organization per hour. All analytics endpoints share this limit.


# Create assistant message
Source: https://www.mintlify.com/docs/api/assistant/create-assistant-message-v2

discovery-openapi.json POST /v2/assistant/{domain}/message
Generates a response message from the assistant for the specified domain. Compatible with AI SDK v5+.

Authenticate with an assistant API key.

<Info>
  The assistant message v2 endpoint is compatible with **AI SDK v5+**. If you
  use AI SDK v4, use the [assistant message v1
  endpoint](/docs/api/assistant/create-assistant-message) instead.
</Info>

## Integration with `useChat`

The `useChat` hook from Vercel's AI SDK is the recommended way to integrate the assistant API into your application.

<Steps>
  <Step title="Install AI SDK">
    ```bash theme={null}
    npm i ai@^6 @ai-sdk/react
    ```
  </Step>

  <Step title="Use the hook">
    ```tsx theme={null}
    import { useState } from "react";
    import { useChat } from "@ai-sdk/react";
    import { DefaultChatTransport } from "ai";

    function MyComponent({ domain }) {
      const [input, setInput] = useState("");

      const { messages, sendMessage } = useChat({
        transport: new DefaultChatTransport({
          api: `https://api.mintlify.com/discovery/v2/assistant/${domain}/message`,
          headers: {
            Authorization: `Bearer ${process.env.PUBLIC_MINTLIFY_ASSISTANT_KEY}`,
          },
          body: {
            fp: "anonymous",
            retrievalPageSize: 5,
            context: [
              {
                type: "code",
                value: 'const example = "code snippet";',
                elementId: "code-block-1",
              },
            ],
          },
        }),
      });

      return (
        <div>
          {messages.map((message) => (
            <div key={message.id}>
              {message.role === "user" ? "User: " : "Assistant: "}
              {message.parts
                .filter((part) => part.type === "text")
                .map((part) => part.text)
                .join("")}
            </div>
          ))}
          <form
            onSubmit={(e) => {
              e.preventDefault();
              if (input.trim()) {
                sendMessage({ text: input });
                setInput("");
              }
            }}
          >
            <input value={input} onChange={(e) => setInput(e.target.value)} />
            <button type="submit">Send</button>
          </form>
        </div>
      );
    }
    ```

    **Required configuration:**

    * `transport` - Use `DefaultChatTransport` to configure the API connection.
    * `body.fp` - Fingerprint identifier (use `'anonymous'` or a unique user identifier).
    * `body.retrievalPageSize` - Number of search results to use (recommended: 5).

    **Optional configuration:**

    * `body.context` - Array of contextual information to provide to the assistant. Each context object contains:
      * `type` - Either `'code'` or `'textSelection'`.
      * `value` - The code snippet or selected text content.
      * `path` (optional) - Path to the source file or page.
      * `elementId` (optional) - Identifier for the UI element containing the context.
    * `body.currentPath` - The path of the page the user is currently viewing. When provided, the assistant uses this context to provide more relevant answers. Maximum length: 200 characters.
  </Step>
</Steps>

See [useChat](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat) and [Transport](https://ai-sdk.dev/docs/ai-sdk-ui/transport) in the AI SDK documentation for more details.

## Rate limits

The assistant API has the following limits:

* 10,000 requests per Mintlify organization per hour
* 10,000 requests per IP per day


# Get page content
Source: https://www.mintlify.com/docs/api/assistant/get-page-content

discovery-openapi.json POST /v1/page/{domain}
Retrieve the full text content of a specific documentation page by its path. Use this after a search to fetch the complete content of a matching page.

Authenticate with an assistant API key. Page content requests do not consume credits.

## Rate limits

* 10,000 requests per Mintlify organization per hour


# Search documentation
Source: https://www.mintlify.com/docs/api/assistant/search

discovery-openapi.json POST /v1/search/{domain}
Perform semantic and keyword searches across your documentation with configurable filtering and pagination.

Authenticate with an assistant API key. Search requests do not consume credits.

## Rate limits

* 10,000 requests per Mintlify organization per hour


# Trigger automation
Source: https://www.mintlify.com/docs/api/automations/trigger

openapi.json POST /workflow/{projectId}/{workflowSchemaId}/trigger
Trigger a scheduled automation to run immediately, instead of waiting for its next scheduled time. Useful for running automations from CI/CD pipelines, like a GitHub Action that runs on every merge to your default branch. Only scheduled (custom schedule) automations can be triggered. The run picks up changes since the last completed run, identical to a regular scheduled run.

Authenticate with an admin API key.

Use this endpoint to trigger a scheduled automation on demand, instead of waiting for its next scheduled run. The automation behaves identically to a regular scheduled run: it picks up everything that has changed since the last completed run.

This endpoint only supports automations configured with a **Custom schedule** trigger. Requests for automations with other triggers, like **Code change** or **Content update**, return a `400` error.

## Use cases

* **CI/CD pipelines**: Run the **Update from code changes** automation on every merge to `main`, so docs update at your release cadence rather than on a fixed schedule.
* **Release events**: Run the **Draft changelog** automation when you cut a release tag, so the changelog drafts at the same time the release ships.
* **Custom tooling**: Trigger automations from internal tools, Slack commands, or scheduled jobs you already run.

## Find the automation ID

Copy the automation ID from the automation's settings panel on the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.

## Example

Trigger an automation from a GitHub Action whenever code merges to `main`:

```yaml .github/workflows/trigger-docs.yml theme={null}
on:
  push:
    branches: [main]

jobs:
  trigger:
    runs-on: ubuntu-latest
    steps:
      - run: |
          curl -fsS -X POST \
            "https://api.mintlify.com/v1/workflow/$PROJECT_ID/$WORKFLOW_ID/trigger" \
            -H "Authorization: Bearer ${{ secrets.MINTLIFY_API_KEY }}"
        env:
          PROJECT_ID: ${{ vars.MINTLIFY_PROJECT_ID }}
          WORKFLOW_ID: ${{ vars.MINTLIFY_WORKFLOW_ID }}
```

## Rate limits

This endpoint shares a rate limit with [Trigger update](/docs/api/update/trigger): up to 10 requests per 10 seconds per organization. Triggered runs consume credits at the same rate as scheduled runs.


# Mintlify REST API introduction
Source: https://www.mintlify.com/docs/api/introduction

Use the Mintlify REST API to trigger deployments, embed an AI assistant, export analytics data, and manage documentation programmatically.

<Info>
  The platform REST API requires a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=api).

  The [Mintlify Index REST API](/docs/api/search-index/introduction) uses a separate API key and base URL.
</Info>

The Mintlify REST (Representational State Transfer) API enables you to programmatically interact with your documentation, trigger updates, embed AI-powered chat experiences, and export analytics data.

## Endpoints

* [Trigger update](/docs/api/update/trigger): Trigger an update of your site when desired.
* [Get update status](/docs/api/update/status): Get the status of an update and other details about your docs.
* [Trigger preview deployment](/docs/api/preview/trigger): Create or update a preview deployment for a specific branch.
* [Trigger automation](/docs/api/automations/trigger): Run a scheduled automation on demand.
* [Detect AI-sounding prose](/docs/api/admin/deslop): Analyze a page for AI-generated prose and get suggested human rewrites.
* [Create agent job](/docs/api/agent/v2/create-agent-job): Create an agent job to automatically edit your documentation.
* [Get agent job](/docs/api/agent/v2/get-agent-job): Retrieve the details and status of a specific agent job.
* [Send follow-up message](/docs/api/agent/v2/send-message): Send a follow-up message to an existing agent job.
* [Create assistant message](/docs/api/assistant/create-assistant-message-v2): Embed the assistant, trained on your docs, into any application of your choosing.
* [Search documentation](/docs/api/assistant/search): Search through your documentation.
* [Get page content](/docs/api/assistant/get-page-content): Retrieve the full text content of a documentation page.
* [Get user feedback](/docs/api/analytics/feedback): Export user feedback from your documentation.
* [Get feedback by page](/docs/api/analytics/feedback-by-page): Export feedback counts aggregated by page.
* [Get assistant conversations](/docs/api/analytics/assistant-conversations): Export AI assistant conversation history.
* [Get assistant caller stats](/docs/api/analytics/assistant-caller-stats): Retrieve a breakdown of assistant query counts by caller type.
* [Get search queries](/docs/api/analytics/searches): Export documentation search terms and analytics.
* [Get page views](/docs/api/analytics/views): Export per-page and site-wide content view counts.
* [Get unique visitors](/docs/api/analytics/visitors): Export per-page and site-wide unique visitor counts.

### Common use cases

* **Automated deployments**: Trigger site updates at set intervals or when events occur with [Trigger update](/docs/api/update/trigger) and [Get update status](/docs/api/update/status).
* **Continuous integration and continuous delivery (CI/CD)**: Update documentation as part of your deployment pipeline when code changes with [Trigger update](/docs/api/update/trigger).
* **Preview deployments**: Create or update preview deployments programmatically in your CI/CD pipeline with [Trigger preview deployment](/docs/api/preview/trigger).
* **On-demand automations**: Run scheduled automations from your CI/CD pipeline or release tooling with [Trigger automation](/docs/api/automations/trigger).
* **Assistant integrations**: Embed the AI assistant into your product, support portal, or internal tools with [Create assistant message](/docs/api/assistant/create-assistant-message-v2).
* **Documentation retrieval**: Find and retrieve documentation for custom search experiences with [Search documentation](/docs/api/assistant/search) and [Get page content](/docs/api/assistant/get-page-content).
* **Automated editing**: Use agent jobs to programmatically update documentation at scale with [Create agent job](/docs/api/agent/v2/create-agent-job), [Get agent job](/docs/api/agent/v2/get-agent-job), and [Send follow-up message](/docs/api/agent/v2/send-message).
* **Analytics export**: Export feedback, assistant conversations, search analytics, page views, and visitor data for external analysis with [Get user feedback](/docs/api/analytics/feedback), [Get feedback by page](/docs/api/analytics/feedback-by-page), [Get assistant conversations](/docs/api/analytics/assistant-conversations), [Get assistant caller stats](/docs/api/analytics/assistant-caller-stats), [Get search queries](/docs/api/analytics/searches), [Get page views](/docs/api/analytics/views), and [Get unique visitors](/docs/api/analytics/visitors).

## Authentication

Generate API keys on the [API keys page](https://app.mintlify.com/settings/organization/api-keys) in your dashboard. Admin and Index API keys belong to an organization. You can use the same keys across multiple deployments within the same organization. Assistant API keys belong to the deployment where you create them.

You can create up to 10 API keys per hour per organization.

When you create a key, you can set it to expire in 7, 30, 60, or 90 days, or select **No expiration**. New keys default to 90 days. The API keys page shows an **Expires in …** badge for keys that expire within 7 days and an **Expired** badge for keys that have already expired. Expired keys stop working, so rotate or replace them before the expiration date.

Mintlify uses three types of API keys, each scoped to a different set of endpoints:

| Key type          | Prefix      | Use for                                                                          |
| ----------------- | ----------- | -------------------------------------------------------------------------------- |
| Admin API key     | `mint_`     | Updates, agent jobs, and analytics exports. Server-side only.                    |
| Assistant API key | `mint_dsc_` | Assistant messages, documentation search, and page content. Proxy in production. |
| Index API key     | `mint_us_`  | Index search, context assembly, and content retrieval. Server-side only.         |

### Admin API key

Use the admin API key for deployment, triggering the agent, and analytics endpoints.

* [Trigger update](/docs/api/update/trigger)
* [Get update status](/docs/api/update/status)
* [Trigger preview deployment](/docs/api/preview/trigger)
* [Trigger automation](/docs/api/automations/trigger)
* [Detect AI-sounding prose](/docs/api/admin/deslop)
* [Create agent job](/docs/api/agent/v2/create-agent-job)
* [Get agent job](/docs/api/agent/v2/get-agent-job)
* [Send follow-up message](/docs/api/agent/v2/send-message)
* [Get user feedback](/docs/api/analytics/feedback)
* [Get feedback by page](/docs/api/analytics/feedback-by-page)
* [Get assistant conversations](/docs/api/analytics/assistant-conversations)
* [Get assistant caller stats](/docs/api/analytics/assistant-caller-stats)
* [Get search queries](/docs/api/analytics/searches)
* [Get page views](/docs/api/analytics/views)
* [Get unique visitors](/docs/api/analytics/visitors)

Admin API keys begin with the `mint_` prefix.

The admin API key is a server-side secret. Do not expose it in client-side code.

### Assistant API key

<Warning>
  Do not directly embed the assistant API key in client-side code. Any visitor who extracts the key can call the assistant message endpoint on your behalf, consuming credits and potentially triggering overage charges.

  For production deployments, proxy requests that use an assistant API key through your own backend and store the key as a server-side environment variable. Routing requests through a proxy also lets you add rate limiting, authentication, and bot protection to prevent abuse.
</Warning>

Use the assistant API key to authenticate requests to the assistant, search, and page content endpoints.

* [Create assistant message](/docs/api/assistant/create-assistant-message-v2)
* [Search documentation](/docs/api/assistant/search)
* [Get page content](/docs/api/assistant/get-page-content)

Assistant API keys begin with the `mint_dsc_` prefix.

<Note>
  Search documentation and page content requests do not consume credits. Assistant message requests use credits and can incur overages.
</Note>

### Index API key

Use an Index API key to authenticate requests to the [Mintlify Index](/docs/search-index) REST API. Index API keys begin with the `mint_us_` prefix.

The Index API key is a server-side secret. Do not expose it in client-side code.

### Restrict keys by IP address

Optionally restrict an API key to a list of allowed IP addresses or Classless Inter-Domain Routing (CIDR) ranges. When a key has an allowlist, requests from any other IP address return a `403` response. Admin, assistant, and Index API keys support allowlists.

Set the allowlist when you create a key on the [API keys page](https://app.mintlify.com/settings/organization/api-keys) in your dashboard. You set the allowlist for the lifetime of the key when you create it. To change the allowlist, you must create a new key. If you don't set an allowlist, the key accepts requests from any IP address.

Allowlist entries support:

* IPv4 and IPv6 addresses, for example `203.0.113.5` or `2001:db8::1`.
* CIDR ranges, for example `198.51.100.0/24` or `2001:db8::/48`.

You cannot use catch-all entries like `0.0.0.0/0` and `::/0`.

Use IP allowlists when a stable set of egress IPs call your API key. For example, a CI/CD runner, a static network address translation (NAT) gateway, or your backend server. Avoid allowlists for keys used from developer laptops or other environments with changing IPs.

### Restrict admin keys by scope

Optionally restrict an admin API key to `read` or `write` scopes. Scopes apply only to admin API keys.

Set scopes when you create a key on the [API keys page](https://app.mintlify.com/settings/organization/api-keys) in your dashboard. You set the scopes for the lifetime of the key when you create it. To change the scopes, you must create a new key. If you don't set any scopes, the key can call every admin endpoint.

Mintlify derives the required scope from the HTTP method of the request.

| HTTP method   | Required scope |
| ------------- | -------------- |
| `GET`, `HEAD` | `read`         |
| All others    | `write`        |

A key with `write` also satisfies `read`, so `["read", "write"]` and `["write"]` both allow every endpoint. Requests that require a scope the key does not have return a `403` response.

The scope only accepts `read` and `write`. Any other value returns a `400` response at key creation.

### Set an expiration date

Optionally set an expiration date on any API key at creation. After the expiration timestamp passes, requests using the key return a `401` response. All API keys support expiration.

Set the expiration on the [API keys page](https://app.mintlify.com/settings/organization/api-keys) in your dashboard. You set the expiration for the lifetime of the key. To change it, you must create a new key. If you don't set an expiration, the key never expires.

The expiration must be a future ISO 8601 timestamp. Past or invalid timestamps return a `400` response at key creation. The expiration returns as `expiresAt` when you list keys, or `null` for keys with no expiration.

Use expirations for short-lived credentials, such as CI/CD tokens, external contractors, or one-off scripts. Rotate long-lived keys by creating a replacement, updating your integrations, and deleting the old key.


# Trigger preview deployment
Source: https://www.mintlify.com/docs/api/preview/trigger

openapi.json POST /project/preview/{projectId}
Create or update a preview deployment for a specific branch. If a preview already exists for the branch, it triggers a redeployment. Returns a status ID to track progress and the preview URL.

Authenticate with an admin API key.

Use this endpoint to programmatically create or update a preview deployment for a Git branch. If a preview already exists for the specified branch, the endpoint triggers a redeployment instead of creating a duplicate.

The response includes a `statusId` that you can pass to [Get deployment status](/docs/api/update/status) to track the deployment progress.

## Use cases

* **CI/CD pipelines**: Automatically create preview deployments when users open or update pull requests.
* **Scheduled previews**: Build previews from long-running feature branches on a schedule.
* **Custom tooling**: Integrate preview creation into internal workflows or Slack bots.

## Rate limits

This endpoint allows up to 5 requests per minute per organization.


# Get result contents
Source: https://www.mintlify.com/docs/api/search-index/contents

index-openapi.json POST /v1/contents
Retrieves content for Mintlify result IDs or result URLs returned by the search endpoint. A request can include up to 20 items across both fields.



# Build implementation context
Source: https://www.mintlify.com/docs/api/search-index/context

index-openapi.json POST /v1/context
Searches Mintlify Index and returns source-cited content assembled within a token budget. Use this endpoint when an application or agent needs ready-to-use context in one request.



# Mintlify Index REST API
Source: https://www.mintlify.com/docs/api/search-index/introduction

Use the Mintlify Index REST API to search documentation and the web, assemble source-cited context, and retrieve page contents for applications and agents.

Use the Mintlify Index Representational State Transfer (REST) API to retrieve technical knowledge for applications and agents. The API supports three retrieval patterns:

* [`context`](/docs/api/search-index/context) assembles source-cited content within a token budget.
* [`search`](/docs/api/search-index/search) returns ranked documentation and web results.
* [`contents`](/docs/api/search-index/contents) retrieves content for selected Mintlify result IDs or result URLs.

<Info>
  The REST API requires an API key for your organization. The public [Index Model Context Protocol (MCP) server](/docs/search-index/mcp) does not require an API key.
</Info>

## Base URL

Send REST API requests to:

```text theme={null}
https://leaves.mintlify.com/api/universal-search/v1
```

Append an endpoint path to this base URL, for example `/context`, `/search`, or `/contents`.

## Authentication

Authenticate each request with an Index API key in the `Authorization` header:

```http theme={null}
Authorization: Bearer mint_us_...
```

Index API keys begin with `mint_us_`.

<Steps>
  <Step title="Create an Index API key">
    Open the [API keys page](https://app.mintlify.com/settings/organization/api-keys) in your dashboard and create an Index API key.

    If this key type is unavailable, your organization does not have access to the Index REST API.
  </Step>

  <Step title="Store the key securely">
    Save the key in a server-side environment variable. Mintlify only displays the complete key when you first create it. Store it securely.

    ```bash theme={null}
    export MINTLIFY_INDEX_API_KEY="mint_us_..."
    ```

    <Warning>
      Do not expose an Index API key in client-side code or commit it to version control.
    </Warning>
  </Step>

  <Step title="Build context">
    Send your first request to the `context` endpoint:

    ```bash theme={null}
    curl -X POST "https://leaves.mintlify.com/api/universal-search/v1/context" \
      -H "Authorization: Bearer $MINTLIFY_INDEX_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "query": "How should I configure caching in Next.js 16?",
        "product": "Next.js",
        "format": "txt",
        "tokenBudget": 3000
      }'
    ```

    A successful response includes assembled context with source URLs, the number of results used, and the output token count.
  </Step>
</Steps>

## Rate limits

REST API limits apply per Mintlify organization. All API keys in an organization share the same limit:

| Window     |          Limit |
| ---------- | -------------: |
| Per second |    10 requests |
| Per day    | 1,000 requests |

Requests exceeding either limit return `429 Too Many Requests`. Use exponential backoff before retrying.

## Errors

| Status | Meaning                                                                                     |
| ------ | ------------------------------------------------------------------------------------------- |
| `400`  | The request body is invalid.                                                                |
| `401`  | The API key is missing or invalid, or the organization does not have Index REST API access. |
| `403`  | The request IP is not allowed by the API key.                                               |
| `429`  | The organization exceeded a rate limit.                                                     |
| `500`  | Index could not complete the request.                                                       |


# Search technical knowledge
Source: https://www.mintlify.com/docs/api/search-index/search

index-openapi.json POST /v1/search
Returns ranked results from publisher-maintained documentation or the web. Use Mintlify result IDs or any result URL with the contents endpoint when you need more content.



# Get deployment status
Source: https://www.mintlify.com/docs/api/update/status

openapi.json GET /project/update-status/{statusId}
Get the status of an update from the status ID

Authenticate with an admin API key.



# Trigger deployment
Source: https://www.mintlify.com/docs/api/update/trigger

openapi.json POST /project/update/{projectId}
Queue a deployment update for your documentation project. Returns a status ID that can be used to track the update progress. The update is triggered from your configured deployment branch.

Authenticate with an admin API key.



# Configure the assistant
Source: https://www.mintlify.com/docs/assistant/configure

Configure the AI assistant in your Mintlify dashboard: toggle availability, customize responses, add starter questions, set bot protection, and manage billing.

Configure the assistant on the [Assistant](https://app.mintlify.com/products/assistant) page of your dashboard. Manage billing and usage on the [Usage](https://app.mintlify.com/settings/organization/usage) page.

## Enable or disable the assistant

Toggle the status to enable or disable the assistant for your documentation site.

<Frame>
  <img alt="The assistant status toggle in the dashboard." />

  <img alt="The assistant status toggle in the dashboard." />
</Frame>

## Set deflection emails

In the Response Handling section, enable the assistant to prompt users to contact your support and sales teams when it can't answer a question on its own.

Choose the **Email** deflection mode, then enter one or both of the following addresses:

* **Support**: For questions the assistant can't resolve from your documentation.
* **Sales**: For questions about pricing, plans, or purchasing.

When you enable deflection and the assistant detects a matching question, an in-chat contact form appears. The form asks for the user's first name, last name, company, company email, and a message. Mintlify emails the submission to the appropriate team, which can respond directly to the user's email.

The same contact form is available in the [assistant widget](/docs/assistant/widget) embedded on other sites. No extra widget configuration is required.

<Tip>
  If you prefer to route support questions to your existing support channels instead, disable the **Contact form** in the Response Handling section.

  When you disable the contact form, the assistant directs users to your support email address in plain text instead of showing the in-chat form. Sales questions still use the in-chat form when a sales email is configured.
</Tip>

## Deflect to a support link

Switch the deflection mode to **Link** to send users to your existing support platform (for example, a help center, ticket portal, or community forum) instead of collecting email through an in-chat form.

Enter the full URL of your support destination. The URL must use `http` or `https` and cannot include credentials.

When the assistant detects a support question, it shows the user a card linking to your support URL. Mintlify appends the assistant thread ID as a `threadId` query parameter so your support tool can attach the conversation transcript to the resulting ticket. Fetch the transcript with the [Get assistant conversation thread](/docs/api/analytics/assistant-thread) endpoint.

In link deflection mode, the assistant does not show the email contact form. Sales deflection is only available in email mode.

## Search domains

In the Response Handling section, configure domains that the assistant can use for web search to find additional context when answering questions.

* Domains must be publicly available.
* Domains that require JavaScript to load are not supported.

<Frame>
  <img alt="The assistant search domains panel enabled in the dashboard. The assistant is configured to search the mintlify.com/pricing domain." />

  <img alt="The assistant search domains panel enabled in the dashboard. The assistant is configured to search the mintlify.com/pricing domain." />
</Frame>

For more precise control over what the assistant can search, use filtering syntax.

* **Domain-level filtering**
  * `example.com`: Search only the `example.com` domain
  * `docs.example.com`: Search only the `docs.example.com` subdomain
  * `*.example.com`: Search all subdomains of `example.com`

- **Path-level filtering**
  * `docs.example.com/api`: Search all pages under the `/api` subpath

* **Multiple patterns**
  * Add multiple entries to target different sections of sites

## Add sample questions

Help your users begin conversations with the assistant by adding starter questions.

The assistant can generate page-specific questions based on the page a user is viewing, or you can add persistent questions that are available across pages.

You can add up to three starter questions. Click **Ask Assistant** for recommended questions based on your documentation.

<Frame>
  <img alt="The search suggestions panel in the dashboard with contextual starter questions enabled." />

  <img alt="The search suggestions panel in the dashboard with contextual starter questions enabled." />
</Frame>

## Bot protection

In the Bot Protection section, enable invisible captcha to protect your assistant from automated abuse. The bot protection is privacy-friendly and invisible to nearly all visitors.

To enable bot protection:

1. Go to the [Assistant settings](https://app.mintlify.com/products/assistant/settings) page in your dashboard.
2. In the **Bot Protection** section, toggle **Invisible Captcha** on.

Changes take up to 10 minutes to propagate.

<Note>
  If you use custom [Content Security Policy headers](/docs/deploy/csp-configuration), you must include `hcaptcha.com` and `*.hcaptcha.com` in your allowlist.
</Note>

## Manage billing

The assistant runs on credits. Each assistant message consumes credits, where a message is any user interaction with the assistant that receives a response. See [Credit pricing](/docs/credits) for more information.

### Change your credit tier

1. Go to the [Usage](https://app.mintlify.com/settings/organization/usage) page of your dashboard.
2. In the **Credit packages** section, select a tier from the dropdown menu.
3. Confirm the change to proceed to checkout.

### Allow overages

Your organization shares credits across deployments. By default, Mintlify disables overages. You can configure different overage limits for each deployment. If you disable overages for a deployment, the assistant becomes unavailable if you spend your organization's shared credit balance. The assistant remains unavailable until your credit balance resets.

To allow overages, enable them in the **Spending controls** section of the [Usage](https://app.mintlify.com/settings/organization/usage) page of your dashboard. If you enable overages, each credit spent beyond the shared balance incurs an overage charge.

### Set usage alerts

In the **Spending controls** section of your dashboard, set usage alerts to receive an email when your organization reaches a certain percentage of its shared credit balance.

### Higher credit volumes

For plans larger than 10,000 credits per month, [contact sales](mailto:sales@mintlify.com) to discuss custom credit packages.


# Customize assistant behavior
Source: https://www.mintlify.com/docs/assistant/customize

Customize the AI assistant by adding an Assistant.md file with system instructions that shape its tone, persona, focus areas, and response behavior.

Add a `.mintlify/Assistant.md` file at the root of your documentation project to give the assistant custom instructions that shape how it responds. The assistant also accepts `ASSISTANT.md` as a filename. It uses these instructions as system-level context for every response.

<Warning>
  Place your `Assistant.md` file inside the `.mintlify/` directory, not at the root of your project. If you store the file at the root of your project, visitors can access your custom instructions at the `/assistant.md` path. Mintlify does not serve the `.mintlify/` directory publicly, so visitors cannot access your `Assistant.md` file there.

  If you must store your `Assistant.md` file at the root of your project or any other directory, add it to your [`.mintignore`](/docs/organize/mintignore) file to exclude it from your documentation site.
</Warning>

Instructions in an `Assistant.md` file add to the assistant's system prompt. They do not replace or override the assistant's default instructions.

To remove the custom instructions, remove the `Assistant.md` file.

Use `Assistant.md` to:

* Adjust the assistant's persona and tone
* Provide product-specific context
* Define support escalation paths
* Specify terminology preferences
* Restrict or scope the assistant's focus areas
* Provide version-specific guidance

<Tip>
  Use assistant [skills](/docs/assistant/skills) for topic-specific guidance that the assistant loads only when a user asks a relevant question.
</Tip>

## Example `Assistant.md` file

```markdown .mintlify/Assistant.md theme={null}
You are a helpful assistant for Acme Corp's developer platform.

## Tone
- Be concise and direct. Getting to the point helps people more than being exhaustive.
- Use technical language appropriate for software developers. Most people asking you questions are familiar with Acme's products.

## Product context
- Acme SDK v3 is the current stable release. v2 is deprecated. If people ask about v2, remind them it's deprecated but answer their questions.
- Direct billing questions to support@acme.com.

## Terminology
- Use "workspace" instead of "project" or "organization".
- Use "access token" instead of "API key".
```


# Assistant
Source: https://www.mintlify.com/docs/assistant/index

Add an AI-powered chat assistant to your documentation site that answers user questions, cites sources, and generates code examples on demand.

<Info>
  The assistant is available on the [Pro plan and above](https://mintlify.com/pricing?ref=assistant). Every Pro plan contributes 10,000 credits per month to your organization's shared credit balance, used across the assistant, agent, and automations on every deployment. See [Manage billing](/docs/assistant/configure#manage-billing) for more information about credit tiers and options.
</Info>

## About the assistant

The assistant answers questions about your documentation through natural language queries. Users access the assistant on your documentation site, so they can find answers quickly and succeed with your product even if they don't know where to look.

The assistant uses tool calling, which lets it invoke tools to answer questions. When users ask questions, the assistant:

* **Searches and retrieves** relevant content from your documentation as Markdown to provide accurate answers.
* **Builds context** from the page a user is viewing when they ask questions.
* **Cites sources** and provides navigable links to take users directly to referenced pages.
* **Returns detailed API information** when answering questions about your API, including methods, parameters, request bodies, and response schemas from your OpenAPI specifications.
* **Generates copyable code examples** to help users implement solutions from your documentation.
* **Supports multiple modalities** by allowing users to add text, images, and other files as context.

### How indexing works

The assistant indexes your published documentation and API specifications to answer questions accurately. When you publish changes, the assistant immediately indexes new, updated, or deleted content. The assistant does not index draft branches or preview deployments.

By default, the assistant does not index hidden pages. To include hidden pages in the assistant's index, set `seo.indexing: "all"` in your `docs.json`. See [Hidden pages](/docs/organize/hidden-pages#search-seo-and-ai-indexing) for more information.

### How the assistant handles unknown questions

The assistant only answers questions based on information in your documentation. If it cannot find relevant information after searching, it responds that it doesn't have enough information to answer.

You can [set a deflection email](/docs/assistant/configure#set-deflection-email) so that the assistant provides your support email to users whose questions it cannot answer. This gives users a path forward, even if the documentation doesn't address their specific question.

## Assistant insights

Use assistant insights to understand how users interact with your documentation and identify improvement opportunities.

The [assistant page](https://app.mintlify.com/products/assistant) shows usage trends for the month to date. View more detailed insights in [assistant analytics](/docs/analytics/assistant).

## Make content AI ingestible

Structure your documentation to help the assistant provide accurate, relevant answers. Clear organization and comprehensive context benefit both human readers and AI understanding.

<Card title="Structure and organization">
  * Use semantic markup.
  * Write descriptive headings for sections.
  * Create a logical information hierarchy.
  * Use consistent formatting across your docs.
  * Include comprehensive metadata in the frontmatter at the top of each page.
  * Break up long blocks of text into shorter paragraphs.
</Card>

<Card title="Context">
  * Define specific terms and acronyms when first introduced.
  * Provide sufficient conceptual content about features and procedures.
  * Include examples and use cases.
  * Cross-reference related topics.
  * Add [hidden pages](/docs/organize/hidden-pages) with additional context that users don't need, but the assistant can reference.
</Card>

<Tip>
  Use the [`Visibility`](/docs/components/visibility) component to tailor content for human readers and AI tools on the same page. Wrap UI-oriented content in `<Visibility for="humans">` and API-oriented or agent-only context in `<Visibility for="agents">`. This helps the assistant and other AI tools see the most relevant information without cluttering your published pages.
</Tip>


# Add assistant skills
Source: https://www.mintlify.com/docs/assistant/skills

Tune the assistant's responses with topic-specific Markdown guides that the assistant loads on demand to answer specific questions with your team's guidance.

Skills are Markdown files that direct the assistant's responses on specific topics. The assistant has access to any skills you add to your project in the `.mintlify/assistant/skills/` directory. It loads a skill only when a user's question matches it, so you can provide curated answers for specific topics without adding context to every response.

Use skills to:

* Provide specific answers for topics where search results alone are unreliable.
* Encode playbooks, troubleshooting flows, or migration guides that aren't structured as documentation pages.
* Guide users through multi-step or nuanced procedures.

## Add a skill

Add a `skill.md` file inside a directory named for the skill under `.mintlify/assistant/skills/`:

```text Example directory structure theme={null}
.mintlify/
└── assistant/
    └── skills/
        ├── migrate-to-v3/
        │   └── skill.md
        └── debug-webhooks/
            └── skill.md
```

Each `skill.md` file needs YAML frontmatter with a `name` and `description`, followed by the skill instructions:

```markdown .mintlify/assistant/skills/migrate-to-v3/skill.md example skill file theme={null}
---
name: Migrate to SDK v3
description: Step-by-step guide for upgrading from SDK v2 to v3, including breaking changes, code mods, and rollout checklist.
---

# Migrating to SDK v3

Follow these steps to upgrade an existing v2 integration to v3.

## 1. Update dependencies

...
```

The assistant uses the `name` and `description` to decide when to load a skill, so write descriptions that state when the skill applies. Keep the instructions concise. The assistant truncates skill content at approximately 6,000 tokens.

<Note>
  After you add or change a `skill.md` file, redeploy your site to make the skill available to the assistant.
</Note>

## How the assistant uses skills

The assistant lists every available skill by name, slug, and description in its system prompt. When a user's question matches a skill description, the assistant loads the skill and treats it as high-priority guidance that takes precedence over general search results.

The assistant can load up to three skills per response.

On follow-up messages, the assistant removes previously loaded skill content from the conversation history to preserve the context window. It reloads a skill if it needs it again.

Skills work alongside [custom assistant instructions](/docs/assistant/customize) in `.mintlify/Assistant.md`. Use `Assistant.md` for tone, persona, and rules that apply to every response. Use skills for topic-specific guidance that the assistant should load only when relevant.

## Write effective skills

* Give each skill a distinct `description`. Overlapping descriptions make it harder for the assistant to load the right skill.
* Use a unique, URL-safe slug for each directory name. Slugs must contain only lowercase letters, numbers, and hyphens. You cannot publish skills with duplicate slugs.
* Structure skills with clear headings and numbered steps.
* Keep skills self-contained. The assistant loads one skill at a time, so a skill should not depend on another skill.
* Use prose and code samples. Do not use screenshots.

## Disable skills

Skills are on by default when at least one `skill.md` file is present. To remove all skills, delete the `.mintlify/assistant/skills/` directory and redeploy your site. To turn off the skills feature for your deployment, contact [support](mailto:support@mintlify.com).


# Use the assistant
Source: https://www.mintlify.com/docs/assistant/use

Open the assistant with keyboard shortcuts, highlighted text, code blocks, file attachments, or URL parameters. Test assistant behavior in local preview.

You have multiple ways to start a conversation with the assistant. Each method opens a chat panel on the right side of your docs. You can ask any question and the assistant searches your documentation for an answer. If the assistant cannot retrieve relevant information, it responds that it cannot answer the question.

## Use the assistant in local preview

The assistant is available in your local preview when you log in with the CLI. This lets you test assistant behavior, custom instructions in `Assistant.md`, and responses while developing documentation locally.

1. If you haven't already, install the CLI with `npm i -g mint`.
2. Run `mint login` to authenticate.
3. Run `mint dev` to start the local preview.

The assistant in local preview uses the same indexed content as your deployed documentation site.

## UI placement

The assistant appears in two locations: as a button next to the search bar and as a bar at the bottom of the page.

<Columns>
  <Frame>
    <img alt="Search bar and assistant button in light mode." />

    <img alt="Search bar and assistant button in dark mode." />
  </Frame>

  <Frame>
    <img alt="Assistant bar in light mode." />

    <img alt="Assistant bar in dark mode." />
  </Frame>
</Columns>

## Keyboard shortcut

Open the assistant chat panel with the keyboard shortcut <kbd>Command</kbd> + <kbd>I</kbd> on macOS and <kbd>Ctrl</kbd> + <kbd>I</kbd> on Windows.

## URL parameters

Open the assistant from any page on your documentation site by adding the `?assistant` query parameter to the URL. Use this to deep-link to the assistant from external content like emails, support replies, in-app banners, or onboarding flows.

* `?assistant`: Open the assistant chat panel without sending a message.
* `?assistant=<message>`: Open the assistant chat panel and submit `<message>` as the user's first message. URL-encode the value so spaces and special characters survive the request.

```text Examples theme={null}
https://yourdocs.mintlify.site/quickstart?assistant
https://yourdocs.mintlify.site/quickstart?assistant=How%20do%20I%20get%20started%3F
```

## Highlight text

Highlight text on a page and click the **Add to assistant** button to open the assistant chat panel and add the highlighted text as context. You can add multiple text snippets or code blocks to the assistant's context.

<Frame>
  <img alt="The Add to assistant button above highlighted text in light mode." />

  <img alt="The Add to assistant button above highlighted text in dark mode." />
</Frame>

## Code blocks

Click the **Ask Assistant** button in a code block to open the assistant chat panel and add the code block as context. You can add multiple code blocks or text snippets to the assistant's context.

<Frame>
  <img alt="The Ask Assistant button in a code block in light mode." />

  <img alt="The Ask Assistant button in a code block in dark mode." />
</Frame>

## File attachments

Attach files to assistant messages to provide additional context.

Supported file types:

* **Images**: JPEG, PNG, GIF, WebP, SVG
* **Documents**: PDF
* **Code and text files**: JavaScript (`.js`, `.jsx`, `.mjs`, `.cjs`), TypeScript (`.ts`, `.tsx`), Python, HTML, CSS, Markdown, MDX, JSON, YAML, XML, SQL, CSV, plain text, shell scripts (`.sh`, `.bash`, `.env`), GraphQL, TOML, Go, Rust, Ruby, Java, Kotlin, Swift, C (`.c`, `.h`), C++ (`.cpp`, `.hpp`), C#, PHP, Lua, R, Scala

Limits:

* Maximum file size: 5 MB per attachment
* Maximum attachments per message: 10

<Frame>
  <img alt="An image added as context in the assistant chat panel." />

  <img alt="An image added as context in the assistant chat panel." />
</Frame>

## Troubleshooting

<Accordion title="Assistant chat bar not visible">
  If the assistant UI is not visible in some browsers, you may need to submit a false positive report to [EasyList](https://easylist.to). Browsers that use the EasyList Cookies List, such as Brave and Comet, sometimes block the assistant or other UI elements. The EasyList Cookies List includes a domain-specific rule that hides fixed elements on certain domains to block cookie banners. This rule inadvertently affects legitimate UI components.

  Report the incorrect block to [EasyList](https://github.com/easylist/easylist) and request removal of the rule. This resolves the issue for all users once the filter list updates.
</Accordion>

<Accordion title="Assistant blocked on a corporate network, VPN, or firewall">
  If the assistant loads on personal networks but fails on a work network, VPN, or other restricted network, the block occurs at the network level. Corporate proxies, VPNs, and firewalls sometimes block the outbound requests the assistant needs to make. The chat panel cannot connect even though the rest of the site loads normally.

  **For readers:** Ask your IT team to allow outbound HTTPS requests to the following hostnames from your network. If you can, try the assistant from a personal network to confirm the issue is network-specific.

  * `leaves.mintlify.com`: Assistant API
  * `*.mintlify.dev`: Assistant streaming and supporting services
  * `*.mintlify.com`: Dashboard, API, and analytics
  * `hcaptcha.com` and `*.hcaptcha.com`: CAPTCHA verification for the assistant

  **For site owners:** If a reader reports that the assistant does not load on their corporate network or VPN, treat it as an outbound network block. It is not a problem with your documentation. Point them to the preceding hostnames and suggest that they share the list with their IT team. This allowlist applies to the visitor's device or network. You cannot configure it from your site. If you self-host behind a reverse proxy that overwrites the default CSP, see [CSP configuration](/docs/deploy/csp-configuration) for the domains to allow.
</Accordion>


# Embed the AI assistant widget
Source: https://www.mintlify.com/docs/assistant/widget

Install and configure the Mintlify widget to embed an AI assistant trained on your content into any website, web app, or dashboard.

The [assistant](/docs/assistant) answers questions on your Mintlify site. To embed the same capability on another site or web app, use the widget. The widget gives your users access to AI chat trained on your content, wherever they use your product. Embed it in your dashboard, marketing site, support portal, or elsewhere.

Add the widget to any website or web application with a hosted script. The widget owns its trigger and renders inside a closed Shadow DOM, an isolated document tree that prevents your application styles from affecting the widget.

The only required browser option is the public widget ID. Manage the enabled state, allowed origins, attachments, bot protection, and [deflection contact form](/docs/assistant/configure#set-deflection-emails) in your dashboard. Set embed-specific starter questions and a support email in the browser configuration.

## Prerequisites

* A [Pro or Enterprise plan](https://mintlify.com/pricing?ref=assistant). The widget uses the same credits as the assistant.

## Enable the widget

1. Navigate to your deployment's [Widget](https://app.mintlify.com/settings/deployment/widget) page.
2. Enable the widget.
3. Add allowed origins where you embed the widget.
4. Copy the widget ID.

## Install and configure

Use the playground to configure the presentation, visual options, and observer hooks for your widget. The installation code block updates as you change each option.

<Info>
  Replace `YOUR_WIDGET_ID` in the generated code with the widget ID from the [Widget](https://app.mintlify.com/settings/deployment/widget) page of your dashboard.
</Info>

After you add the generated code to your site, reload the page. Confirm the trigger appears, then click it and send a test question to verify the connection.

<AssistantWidgetPlayground>
  <Warning>
    Module scripts defer and run in document order. Keep the hosted loader before the initialization block when you install the widget with HTML, or the widget fails to mount.
  </Warning>

  ## Open on initialization

  Set `defaultOpen` to `true` to open the widget immediately after its first mount:

  ```js theme={null}
  await window.MintlifyAssistant.init({
    id: "YOUR_WIDGET_ID",
    defaultOpen: true,
  });
  ```

  `defaultOpen` defaults to `false` and only applies to the first initialization. Calling `init()` again with the same widget ID and API endpoint does not reopen a widget that a visitor closed. Use `open()` and `close()` to control it after initialization.

  ## Use a custom trigger

  Await `init()` before calling other methods. Keep the built-in trigger or open the configured presentation from any button in your application.

  ```js theme={null}
  await window.MintlifyAssistant.init({
    id: "YOUR_WIDGET_ID",
    supportEmail: "hi@mintlify.com",
    starterQuestions: [
      "How do I get started with Mintlify?",
      "How do I customize my docs?",
      "How do I deploy my docs?",
    ],
  });

  document.querySelector("#help-button").addEventListener("click", () => {
    void window.MintlifyAssistant.open({
      source: "help-button",
      focus: true,
    });
  });
  ```

  To open the widget and immediately send a question, call `ask()`:

  ```js theme={null}
  await window.MintlifyAssistant.ask("How do I authenticate?", {
    source: "authentication-guide",
    open: true,
    focus: true,
  });
  ```

  Event metadata and requests include the `source` value, which lets you distinguish built-in interactions from your custom entry points.

  ## Update a mounted widget

  Use `update()` to change appearance, labels, support email, starter questions, or hooks without clearing the current conversation. Only the supplied fields change.

  ```js theme={null}
  await window.MintlifyAssistant.update({
    appearance: {
      theme: "dark",
      accent: "#7c3aed",
    },
    labels: {
      title: "Docs copilot",
      trigger: "Ask docs",
    },
    supportEmail: "support@example.com",
    starterQuestions: [
      "How do I get started?",
      "How do I manage my account?",
    ],
  });
  ```

  Pass `null` to restore a field or group to its default, remove the support email, or restore an empty starter-question list:

  ```js theme={null}
  await window.MintlifyAssistant.update({
    appearance: {
      accent: null,
    },
    supportEmail: null,
    starterQuestions: null,
    hooks: null,
  });
  ```

  Changing `identity` starts a new conversation. Changing the widget ID or API endpoint requires calling `destroy()` before a new `init()`.

  You can supply `supportEmail` and `starterQuestions` during initialization and change them later with `update()`. These values apply to the current embed and do not inherit from your Mintlify dashboard.

  ## Scope retrieval by language or version

  Use `filter` to restrict what the assistant retrieves when you organize your content by language or [versions](/docs/organize/navigation#versions). Omit a field to search across every value for it.

  ```js theme={null}
  await window.MintlifyAssistant.init({
    id: "YOUR_WIDGET_ID",
    filter: {
      language: "en",
      version: "v2",
    },
  });
  ```

  `language` must be a [supported language code](/docs/organize/settings-reference#navigation-global-languages), such as `en`, `es`, `fr`, or `zh-Hans`. `version` matches the version name configured in your dashboard.

  Change filters at runtime with `update()` when the visitor switches language or version in your application:

  ```js theme={null}
  await window.MintlifyAssistant.update({
    filter: {
      language: "fr",
      version: null,
    },
  });
  ```

  Pass `null` on a field to clear that filter, or `filter: null` to clear both.

  ## Configuration reference

  ### `AssistantConfig`

  Pass this object to `init()`.

  | Option             | Type                                          | Description                                                           |
  | ------------------ | --------------------------------------------- | --------------------------------------------------------------------- |
  | `id`               | string                                        | Public widget ID from the Mintlify dashboard.                         |
  | `endpoint`         | string                                        | Overrides the hosted widget API endpoint.                             |
  | `identity`         | string                                        | Signed end-user identity token. Omit for anonymous visitors.          |
  | `nonce`            | string                                        | CSP nonce copied to resources created by the widget.                  |
  | `defaultOpen`      | boolean                                       | Opens the widget on its first initialization. The default is `false`. |
  | `appearance`       | [`AssistantAppearance`](#assistantappearance) | Visual and presentation overrides.                                    |
  | `labels`           | [`AssistantLabels`](#assistantlabels)         | Customer-facing text overrides.                                       |
  | `supportEmail`     | string                                        | Sets the support address shown in the widget toolbar for this embed.  |
  | `starterQuestions` | string\[]                                     | Sets up to three empty-state prompts for this embed.                  |
  | `filter`           | [`AssistantFilter`](#assistantfilter)         | Restricts retrieval to a docs language and version.                   |
  | `hooks`            | [`AssistantHooks`](#assistanthooks)           | Event and error observers.                                            |

  ### `AssistantAppearance`

  | Option                     | Values                                                         | Description                                                                                             |
  | -------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
  | `variant`                  | `widget`, `modal`, `panel`                                     | Controls whether the assistant opens as an anchored popover, centered dialog, or responsive side panel. |
  | `theme`                    | `light`, `dark`, `system`                                      | Sets the widget color scheme. The default is `system`.                                                  |
  | `accent`                   | CSS color                                                      | Sets the color of primary controls.                                                                     |
  | `radius`                   | CSS border radius                                              | Sets the panel radius, such as `18px`.                                                                  |
  | `font`                     | CSS font family                                                | Uses a font already loaded by your application. The default is Inter, which the widget bundles.         |
  | `side`                     | `top`, `bottom`, `left`, `right`, `inline-start`, `inline-end` | Positions the built-in trigger on a screen edge.                                                        |
  | `align`                    | `start`, `center`, `end`                                       | Aligns the trigger along its selected edge.                                                             |
  | `dismissOnInteractOutside` | boolean                                                        | Controls whether pointer or focus interactions outside close the assistant.                             |
  | `logo`                     | URL or `{ light, dark }`                                       | Replaces the default Mintlify mark.                                                                     |
  | `zIndex`                   | number                                                         | Changes the stacking order of the widget host.                                                          |

  The widget does not support arbitrary CSS or neutral-palette overrides. The closed Shadow DOM protects both your application and the widget from cross-site style regressions.

  ### `AssistantFilter`

  | Option     | Type             | Description                                                                                                                                               |
  | ---------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `language` | string or `null` | Restricts retrieval to a [supported language code](/docs/organize/settings-reference#navigation-global-languages), such as `en`. Omit to search all languages. |
  | `version`  | string or `null` | Restricts retrieval to a docs version, such as `v2`. Omit to search all versions.                                                                         |

  ### `AssistantLabels`

  | Option        | Values                     | Description                                                                 |
  | ------------- | -------------------------- | --------------------------------------------------------------------------- |
  | `title`       | string or `null`           | Sets the panel header. The default is `Assistant`.                          |
  | `trigger`     | string or `null`           | Sets the compact widget and panel trigger text.                             |
  | `placeholder` | string or `null`           | Sets the composer and modal trigger placeholder.                            |
  | `disclaimer`  | string, `false`, or `null` | Sets the empty-state disclaimer. Pass `false` to hide it.                   |
  | `suggestions` | string or `null`           | Sets the heading preceding starter questions. The default is `Suggestions`. |

  ### `AssistantHooks`

  ```js theme={null}
  hooks: {
    event(event) {
      console.log(event.type, event.actor, event.source);
    },
    error(error) {
      console.error(error.code, error.retryable, error.status);
    },
  }
  ```

  The `event` hook receives lifecycle and interaction metadata for `init`, `open`, `close`, `ask`, `update`, `reset`, `navigate`, and `destroy`. Events do not include question text, identity, session, or CAPTCHA tokens.

  The `error` hook receives a stable `code`, a `retryable` boolean, and an optional HTTP `status`. Exceptions thrown by either hook do not interrupt the widget.

  ### `AssistantOpenOptions`

  Pass this optional object to `open()`.

  | Option   | Type    | Description                                                   |
  | -------- | ------- | ------------------------------------------------------------- |
  | `source` | string  | Customer-defined attribution included in events and requests. |
  | `focus`  | boolean | Focuses the composer after opening. The default is `true`.    |

  ### `AssistantAskOptions`

  Pass this optional object after the question string in `ask()`.

  | Option   | Type    | Description                                                   |
  | -------- | ------- | ------------------------------------------------------------- |
  | `source` | string  | Customer-defined attribution included in events and requests. |
  | `open`   | boolean | Opens the panel before sending. The default is `true`.        |
  | `focus`  | boolean | Focuses the composer when opening. The default is `true`.     |

  ### `AssistantUpdate`

  Pass this object to `update()`. Every field is optional, and `null` restores its default.

  | Option             | Type                                                    | Description                                                        |
  | ------------------ | ------------------------------------------------------- | ------------------------------------------------------------------ |
  | `identity`         | string or `null`                                        | Changes the signed identity and starts a new conversation.         |
  | `appearance`       | [`AssistantAppearance`](#assistantappearance) or `null` | Deep-patches appearance settings.                                  |
  | `labels`           | [`AssistantLabels`](#assistantlabels) or `null`         | Deep-patches customer-facing text.                                 |
  | `supportEmail`     | string or `null`                                        | Changes the support address. Pass `null` to remove it.             |
  | `starterQuestions` | string\[] or `null`                                     | Changes up to three prompts. Pass `null` to restore an empty list. |
  | `filter`           | [`AssistantFilter`](#assistantfilter) or `null`         | Deep-patches retrieval filters. Pass `null` to clear all filters.  |
  | `hooks`            | [`AssistantHooks`](#assistanthooks) or `null`           | Deep-patches event and error observers.                            |

  ## Browser API

  | Method                   | Parameter types                                       | Description                                                                        |
  | ------------------------ | ----------------------------------------------------- | ---------------------------------------------------------------------------------- |
  | `init(config)`           | [`AssistantConfig`](#assistantconfig)                 | Loads and mounts the widget. This is the readiness promise for every other method. |
  | `open(options)`          | [`AssistantOpenOptions`](#assistantopenoptions)       | Opens the configured presentation.                                                 |
  | `close()`                | None                                                  | Closes the widget.                                                                 |
  | `ask(question, options)` | string, [`AssistantAskOptions`](#assistantaskoptions) | Opens the widget if requested and sends a question.                                |
  | `update(config)`         | [`AssistantUpdate`](#assistantupdate)                 | Deep-patches mutable identity, appearance, copy, and observer settings.            |
  | `reset()`                | None                                                  | Starts a fresh conversation.                                                       |
  | `destroy()`              | None                                                  | Removes the widget and releases its browser resources.                             |

  Conversation snapshots remain private to the widget. Each method resolves to `void`.

  ## Content Security Policy

  If your site uses a Content Security Policy, allow the origins required by your enabled widget features:

  | Directive                                    | Source                              | Required for                          |
  | -------------------------------------------- | ----------------------------------- | ------------------------------------- |
  | `script-src`                                 | `https://widget.mintlify.com`       | Widget loader and runtime             |
  | `connect-src`                                | `https://widget.mintlify.com`       | Widget version manifest               |
  | `connect-src`                                | `https://api.mintlify.com`          | Configuration, messages, and feedback |
  | `connect-src`                                | `https://ph.mintlify.com`           | Internal widget analytics             |
  | `font-src`                                   | `https://widget.mintlify.com`       | Optional bundled Inter font           |
  | `script-src`, `connect-src`, and `frame-src` | `https://challenges.cloudflare.com` | Turnstile bot protection              |
  | `script-src`                                 | `https://js.hcaptcha.com`           | hCaptcha bot protection               |
  | `connect-src` and `frame-src`                | `https://*.hcaptcha.com`            | hCaptcha bot protection               |

  A strict `script-src` policy must still authorize both the loader and initialization script. A strict `style-src` policy must authorize the nonce you pass to `init()`, which the widget copies to its injected style sheet. Passing `nonce` to `init()` propagates it only to resources the widget creates after initialization.
</AssistantWidgetPlayground>


# Create a custom automation
Source: https://www.mintlify.com/docs/automations/create

Create a Mintlify automation that runs on a schedule, repository push, or integration event. Add context repositories and a custom agent prompt.

A custom automation runs the agent on a schedule, on repository pushes, or on connected integration events using instructions that you write. Use a custom automation when you need to automate a task that isn't covered by a [predefined automation](/docs/automations/reference).

For an overview of triggers, update modes, and configuration options shared across all automations, see [Automations](/docs/automations).

## Prerequisites

* A Mintlify project connected to a GitHub or GitLab repository
* For GitHub: the [Mintlify GitHub App](/docs/deploy/github) installed on every repository you plan to use in the automation
* For GitLab: a connected GitLab account (see [GitLab setup](#gitlab-setup) below)

## Create a custom automation

<Note>
  The agent runs in an isolated sandbox with restricted internet access. It cannot install additional packages or tools at runtime. Prompts that reference unavailable tools may produce unexpected results or fail.
</Note>

1. Open the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.
2. Click **Create a custom automation**.
3. Configure the automation name, trigger, instructions, context repositories, integrations, and update mode. For details on each field, see [Configurations](/docs/automations/manage#configurations).
4. Click **Create automation**.

<Tip>
  You can also ask the [agent in Slack](/docs/agent/slack#manage-automations) to create an automation for you by describing what you want the automation to do.
</Tip>

## Write effective instructions

Effective automation instructions focus on a single task and define a clear, verifiable outcome. Automations can vary because agents may produce different results for the same instructions, but well-formatted instructions produce more consistent results.

* **Describe the outcome.** Tell the agent what a successful run should look like.
* **Write a procedure.** Give the agent a step-by-step guide to follow.
* **Keep scope narrow.** Split complex tasks across multiple automations rather than combining them into one prompt.

For more examples and patterns, see [Use automations](/docs/guides/use-automations).

<Tip>
  Review the output of your custom automations to confirm they work as expected. Update your instructions to improve the results.
</Tip>

## GitLab setup

To use GitLab repositories in an automation, connect each project through the [GitLab OAuth](https://app.mintlify.com/settings/organization/gitlab-oauth) settings page. Connect every repository the automation touches—your documentation repository and any trigger or context repositories. You must have at least the Maintainer role on each project.

<Note>
  Automations require a paid GitLab tier. The agent uses short-lived project access tokens for repository access, which GitLab's Free plan does not support.
</Note>

## Edit a custom automation

1. Open the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.
2. Click the <Icon icon="settings" /> settings button beside an automation.
3. Update any of the fields described in [Configurations](/docs/automations/manage#configurations).
4. Click **Save**.

## Delete a custom automation

Deleting an automation is permanent and removes its configuration and run history.

1. Open the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.
2. Click the <Icon icon="settings" /> settings button beside an automation.
3. Click **Delete**.


# Automations overview
Source: https://www.mintlify.com/docs/automations/index

Automate content maintenance with Mintlify automations by running the agent on a schedule, on repository pushes, or on connected integration events.

<Info>
  Automations require a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=automations).
</Info>

Automations run the agent automatically on a schedule, in response to pushes to a repository, or when an event occurs in a connected integration. Each automation defines a prompt for the agent and a trigger for when to run it. Automations support both GitHub and GitLab repositories with the same triggers, predefined automations, and update modes. Throughout this guide, "pull request" also refers to GitLab merge requests unless noted otherwise.

When an automation runs, the agent reads your project content and any connected repositories, then follows the prompt to make updates.

<Tip>
  Use automations that run on a schedule for recurring tasks, like publishing changelogs or improving content based on users' conversations with the [assistant](/docs/assistant).

  Use automations that trigger on content or code changes for reactive maintenance, like translations or updating content when source code changes.
</Tip>

## Trigger types

Automations support four trigger types.

* **Content update**: Runs when content changes push to your Mintlify project repository, including pull request merges and direct pushes.
* **Code change**: Runs when a pull request merges in a connected source code repository.
* **Custom schedule**: Runs on a recurring schedule. Automations queue within 10 minutes of the scheduled time.
* **Integration**: Runs when a selected event occurs in a connected shared integration. Requires an [Enterprise plan](https://mintlify.com/pricing?ref=automations).

Each automation has exactly one trigger. You cannot combine trigger types in a single automation.

## Pull request grouping

Automations group related changes into a single pull request instead of opening a separate one for every change. When a later run produces more changes that belong with an open pull request, the agent appends them to that pull request rather than opening a duplicate. Grouping behavior depends on the automation. See [Predefined automations](/docs/automations/reference) for each automation's behavior.

<Note>
  Draft changelog, Fill gaps from assistant conversations, Improve docs from user feedback, Update from support feedback, and custom automations do not group or append. Each run opens its own pull request with the changes from that run. Update from support feedback can open up to three pull requests per run, one for each distinct theme it identifies.
</Note>

## Reviewing automation pull requests

When an automation opens or updates a pull request, Mintlify adds context directly to it so you can review without leaving GitHub or GitLab.

* **PR title** includes the name of the automation that generated it, so you can identify automation PRs at a glance when scanning an open PR list.
* **PR description** summarizes what changed and why. Each time a run appends new changes to an existing PR, the description updates to show a running timeline of what each run contributed.
* **PR comments** for any runs that append changes, explaining the changes and which source code pull requests the agent used as context.
* **Reviewers** assigned based on who authored the source code changes that triggered the update. Applies to automations that use source code repositories as context on GitHub. GitLab does not support automatic reviewer assignment, so assign reviewers manually on merge requests.

## Usage limits

Automation runs count toward your credit usage. The credits a single run consumes depend on the size of the task: how much content the agent reads, how many files it changes, and how long the run takes. Larger context repositories and broader prompts use more credits than narrowly scoped ones.

See your credit usage, set overages, and manage your credit package on the [Usage](https://app.mintlify.com/settings/organization/usage) page of your dashboard.

Each automation can run up to 500 times per day. Runs that fail do not count toward this limit.

## Next steps

<CardGroup>
  <Card title="Predefined automations" icon="list" href="/automations/reference">
    Reference for all predefined automations: triggers, update modes, and required configuration.
  </Card>

  <Card title="Manage automations" icon="toggle-right" href="/automations/manage">
    Turn on predefined automations and configure triggers, update mode, and context.
  </Card>

  <Card title="Create a custom automation" icon="plus" href="/automations/create">
    Build an automation with your own trigger, instructions, and context repositories.
  </Card>

  <Card title="Learn best practices" icon="book-open" href="/guides/use-automations">
    Choose the right trigger, write effective instructions, and review results.
  </Card>
</CardGroup>


# Integrations for the agent and automations
Source: https://www.mintlify.com/docs/automations/integrations

Connect third-party apps so the Mintlify agent can use live context in Slack, during automation runs, or as a trigger for custom automations.

Integrations connect the Mintlify agent to other tools your team uses. The agent can use connected apps while responding in Slack or running an automation. Events from some shared integrations can also start a custom automation.

| Integration use        | What it does                                                                                                      |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **Slack agent**        | Uses shared integrations and the personal integrations of the teammate who is chatting with the agent as context. |
| **Automation tool**    | Gives an automation read-only context from the shared integrations selected in its **Tools** setting.             |
| **Automation trigger** | Starts a custom automation when a selected event occurs in a supported shared integration.                        |

<Note>
  The [Mintlify Slack app](/docs/agent/slack) is separate from the integrations on this page. Installing the Slack app adds the agent to your workspace and gives the agent and automation runs access to Slack content that the app can read. You do not connect Slack from the **Integrations** settings page or select it in an automation's **Tools** field.
</Note>

## Connection scope

Integrations have one of two connection scopes.

* **Shared integrations** connect once for your organization. The Slack agent can use them, and you can add them as tools to supported automations. Shared integrations that provide events can also trigger custom automations.
* **Personal integrations** connect separately for each teammate. The Slack agent uses the personal account of the teammate who is chatting with it. Automations cannot use personal integrations as tools or triggers.

For example, if two teammates connect separate Google Drive accounts, each sees results from their own Drive when asking the agent a question in Slack.

There is no limit to how many teammates can connect their own accounts. In a Slack thread with multiple participants, the agent uses the personal integrations of each message's sender.

## Connect an integration

Admins and editors can connect shared integrations on behalf of the organization. Each teammate connects their own personal integrations.

### From the dashboard

1. Go to the [Integrations](https://app.mintlify.com/settings/organization/integrations) page in your dashboard settings.
2. Find the integration you want to connect.
3. Click **Connect**.
4. Follow the authorization prompts.

You can also connect an integration while configuring an automation. Select an unconnected app in the automation's **Tools** field, then complete the authorization flow.

### From the Slack agent

Prompt the agent to connect an app, such as "Connect Google Drive." The agent returns an authorization link in the Slack thread. Complete the authorization, then send another message in the same thread so the agent can confirm and use the connection.

## Supported integrations

The dashboard shows the integrations currently available to your organization.

| Integration              | Scope    | Available as an automation trigger |
| ------------------------ | -------- | ---------------------------------- |
| Confluence               | Shared   | Yes                                |
| Contentful               | Shared   | No                                 |
| Excel                    | Personal | No                                 |
| Figma                    | Shared   | No                                 |
| Gmail                    | Personal | No                                 |
| Google Drive             | Personal | No                                 |
| HubSpot                  | Shared   | No                                 |
| Intercom                 | Shared   | No                                 |
| Jira                     | Shared   | Yes                                |
| LaunchDarkly             | Shared   | No                                 |
| Linear                   | Shared   | Yes                                |
| Notion                   | Shared   | Yes                                |
| OneDrive                 | Personal | No                                 |
| OneNote                  | Personal | No                                 |
| Outlook                  | Personal | No                                 |
| Plain                    | Shared   | No                                 |
| PostHog                  | Shared   | No                                 |
| Pylon                    | Shared   | No                                 |
| Salesforce               | Shared   | No                                 |
| Salesforce Service Cloud | Shared   | No                                 |
| Stripe                   | Shared   | Yes                                |
| Zendesk                  | Shared   | Yes                                |

## Use integrations with the Slack agent

After you install the [Mintlify Slack app](/docs/agent/slack), the agent can use integrations while answering questions or updating your documentation. You do not have to select integrations for each Slack conversation.

The agent can use:

* Shared integrations connected to your organization.
* Personal integrations connected by the teammate who sent the request.
* Slack channels and threads that the installed Mintlify app has permission to read.

For example, ask the agent to compare a Linear issue with a Google Drive product brief or answer a question using a Notion page. You can also ask it to update documentation using context from a Jira issue.

The agent only accesses integration data when it is relevant to the request.

## Use integrations as automation tools

Automation tools give the agent additional context after an automation starts. You can select only shared integrations.

1. Open the automation's settings.
2. In **Tools**, select the integrations that the automation can use.
3. Connect any selected integration that is not already connected.
4. Save the automation.

If an integration is an automation trigger, it is always a tool for that automation. This lets the agent retrieve additional details after it receives the event that started the run.

## Trigger an automation from an integration

Custom automations can run when an event occurs in a supported shared integration.

1. Create or open a custom automation.
2. For **Trigger**, select **Integration**.
3. Select or connect a shared integration.
4. Select the **Trigger event**.
5. Complete any additional event fields that appear.
6. Save and turn on the automation.

The supported events depend on the integration:

| Integration | Events                                                               |
| ----------- | -------------------------------------------------------------------- |
| Confluence  | Page created; content added to a space                               |
| Jira        | Issue created; issue updated; project created                        |
| Linear      | Issue created; issue updated; project created; project update posted |
| Notion      | Page created; page content updated                                   |
| Stripe      | Product created                                                      |
| Zendesk     | Ticket created                                                       |

When the event occurs, Mintlify starts the automation and includes the event payload as context for the agent. Duplicate deliveries of the same event do not start duplicate runs.

## Permissions and access

The agent has read-only access through third-party integration tools. It can search and retrieve content, but it cannot use these tools to create, edit, or delete data in the connected app.

The agent inherits the access of the account that authorized the connection:

* For a shared integration, it can read content available to the connected workspace account.
* For a personal integration, it can read content available to the teammate who connected it.
* For Slack, it can read public and private channels that include the Mintlify app.

Authorization providers may group permissions differently. Review the authorization screen for the exact permissions requested before connecting an app. To narrow access, restrict the authorizing account's permissions or only grant the Mintlify app access to specific resources.

If your organization restricts which apps users can authorize, ask the relevant administrator, such as your Google Workspace or Atlassian administrator, to approve the Mintlify app.

## Disconnect an integration

1. Go to the [Integrations](https://app.mintlify.com/settings/organization/integrations) page in your dashboard settings.
2. Find the connected integration and click **Configure**.
3. Click **Disable integration**.

Disconnecting a shared integration removes it for everyone in your organization. Automations can no longer use it as a tool, and custom automations configured to use it as a trigger stop receiving new events.

Disconnecting a personal integration only removes your connection. Other teammates keep their personal connections.

## Troubleshoot a connection

If an integration stops working:

1. Confirm that the authorizing account can still access the relevant content.
2. Open the integration's **Configure** dialog and disable it.
3. Connect the integration again and complete the authorization flow.
4. If the connection is for the Slack agent, send another message in the original Slack thread.

If an administrator blocks authorization, ask your app or workspace administrator to approve Mintlify. The authorization screen shows the app identity and permissions that require approval.


# Manage automations
Source: https://www.mintlify.com/docs/automations/manage

Enable, disable, trigger, and delete automations from your dashboard. Configure repository, schedule, and integration triggers; context repos; and automerge.

## Prerequisites

* A Mintlify project connected to a GitHub or GitLab repository
* For GitHub: the [Mintlify GitHub App](/docs/deploy/github) installed on every repository you plan to use in the automation
* For GitLab: a connected GitLab account (see [GitLab setup](#gitlab-setup) below)

<Tip>
  You can also create, list, and delete automations from the terminal with [`mint workflow`](/docs/cli/commands#mint-workflow). The CLI is useful for scripting and CI. The dashboard is the easiest way to configure and monitor automation runs.
</Tip>

## Enable an automation

1. Open the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.
2. Click the toggle beside an automation to enable it.

   <Frame>
     <img alt="The automations dashboard." />

     <img alt="The automations dashboard." />
   </Frame>

   If the automation can run with default settings, it activates immediately. Otherwise, the settings panel opens so you can fill in any required configurations.

   <Frame>
     <img alt="The configuration options for an automation." />

     <img alt="The configuration options for an automation." />
   </Frame>
3. If the settings panel opens, fill in the required fields.
4. Click **Turn on automation**.

To change settings for an active automation, click the <Icon icon="settings" /> settings button beside it. Use the toggle in the modal header to enable or disable the automation without leaving the settings view.

## Configurations

### Trigger

Each automation has a default trigger that controls when it runs. To change the trigger, select a different option in the settings panel.

* **Content update**: Runs whenever you push content to your project repository, including pull request merges and direct pushes.
* **Code change**: Runs when a pull request merges in a connected source code repository. You must specify at least one source repository.
* **Custom schedule**: Runs on a recurring schedule you define. Automations queue within 10 minutes of the scheduled time.
* **Integration**: Runs when a selected event occurs in a connected shared integration. Available for custom automations. Select the integration and event, then complete any additional event fields that appear.

### Update mode

Each automation has a default mode for how it makes updates: either directly merging changes into your content repository, or opening a pull request for review.

To require a review before the automation updates your content, select **Require review** in the settings panel.

<Note>
  For GitHub repositories, automatic updates require the Mintlify GitHub App to have bypass permissions on every ruleset targeting your deploy branch, including organization-level and repository-level rulesets. See [Configure automerge](/docs/guides/configure-automerge) for setup instructions.

  For GitLab repositories, automerge uses the GitLab OAuth connection and requires at least the Maintainer role on each project.
</Note>

### Context repositories

For custom automations and some predefined automations, you can add context repositories—additional source code repositories the agent reads when the automation runs. This is useful when your automation prompt references code, APIs, or other content that lives outside your project repository.

You can add up to 10 context repositories per automation. For each GitHub repository, install the Mintlify GitHub App. Add repositories on the [GitHub App settings](https://app.mintlify.com/settings/organization/github-app) page.

### Integrations

For custom automations and supported predefined automations, enable connected [integrations](/docs/automations/integrations). The agent pulls context from shared tools like Notion, Jira, or Linear when the automation runs.

To enable integrations for an automation, open its settings and select the integrations you want to use in **Tools**.

If you select **Integration** as the trigger for a custom automation, the triggering integration is always a tool for that automation. See [Integrations](/docs/automations/integrations) for connection scopes, supported events, and permissions.

### Slack notifications

Send Slack messages to one or more channels when automations run.

To enable Slack notifications:

1. Install the [Mintlify Slack app](/docs/agent/slack) in your workspace.
2. Click **Configure Slack** on the [Automations](https://app.mintlify.com/products/automations) page of your dashboard.
3. Select one or more channels to send notifications to.
4. Click **Save changes**.

Once enabled, Mintlify posts to the selected channels when:

* An automation opens a pull request for review.
* An automation pull request has been waiting for review for three days.
* An automation merges a pull request, or fails to complete.

### Instructions

Add optional instructions that append to the automation's base prompt on every run. Use these to adjust the style, tone, or other project-specific behaviors without changing the core automation logic.

### Target languages

When you enable the **Translate content** automation, select one or more languages to keep in sync with your source content.

* Mintlify reads the [languages](/docs/organize/navigation#languages) defined in your `docs.json` to identify your default language and preselects any already configured target languages.
* You must select at least one target language to save the automation.
* You cannot select the source language as a target.

You can add target languages at any time by opening the automation's settings and editing the **Translate to** field.

## GitLab setup

To use GitLab repositories in an automation, connect each project through the [GitLab OAuth](https://app.mintlify.com/settings/organization/gitlab-oauth) settings page. Connect every repository the automation touches—your documentation repository and any trigger or context repositories. You must have at least the Maintainer role on each project.

<Note>
  Automations require a paid GitLab tier. The agent uses short-lived project access tokens for repository access, which GitLab's Free plan does not support.
</Note>

## Disable an automation

1. Open the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.
2. Click the toggle beside an automation to disable it.

When you re-enable a scheduled automation or change its schedule, Mintlify recalculates the next run time from the current time. Disabled automations do not retain a pending run time.

## Run an automation manually

You can trigger any enabled automation on demand without waiting for its next scheduled or event-based run.

1. Open the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.
2. Click the <Icon icon="play" /> run button beside the automation you want to start.

Manual runs use the automation's current configuration, count toward your credit usage, and appear in the run history alongside scheduled runs.

## Trigger a scheduled automation via API

For automations with a **Custom schedule** trigger, you can start a run from your own tooling instead of waiting for the next scheduled time. Use the [Trigger automation](/docs/api/automations/trigger) endpoint to fire a run from a CI/CD pipeline, release script, or any service that can make an authenticated HTTP request.

API-triggered runs behave exactly like scheduled runs: they pick up everything that has changed since the last completed run, count toward credit usage, and appear in the run history.

## View run history

Each automation keeps a log of past runs, including the status and a summary of changes made.

1. Open the [Automations](https://app.mintlify.com/products/automations?tab=runs) page in your dashboard.
2. Use the dropdown menus to filter by specific automations or status.

Each run shows one of the following statuses:

* **Review needed**: The agent finished the run, but the changes must be reviewed and merged by someone on your team.
* **Running**: The agent is actively working on the automation job.
* **Accepted**: The agent finished the run and the changes merged into your repository.
* **Closed**: The agent finished the run, but someone rejected the changes.
* **Failed**: The agent could not complete the run. Failed runs do not count toward your daily run limit.
* **No action needed**: The agent finished the run but did not find anything to update.

Click an individual run to see its prompt, the files it read or changed, and any pull request it opened.

## Continue a run in the editor

After an automation completes and creates changes on a branch, you can open those changes directly in the editor to review, refine, or publish them.

1. Open the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.
2. Click **View changes** beside the workflow run you want to continue working on in the editor.

The editor opens to the automation's branch with the agent panel already open. The agent panel shows each page the automation changed. Click any page to view changes made by the automation.

The editor agent has full context on what the automation did, including the automation's prompt, a summary of the changes, and which pages the automation modified. Ask the agent to refine or extend the work without re-explaining the background.


# Predefined automations
Source: https://www.mintlify.com/docs/automations/reference

Reference for all predefined Mintlify automations, including default trigger, update mode, context repository support, and required configurations.

Mintlify includes predefined automations for the most common documentation maintenance tasks. Each automation has a base prompt and a default configuration. You can customize the trigger, update mode, and instructions from the [Automations](https://app.mintlify.com/products/automations) page in your dashboard.

## At a glance

| Automation                             | Default trigger                | Default update mode | Context repos | Required configuration                                   |
| -------------------------------------- | ------------------------------ | ------------------- | ------------- | -------------------------------------------------------- |
| Update from code changes               | Custom schedule (twice weekly) | Pull request        | Supported     | At least one source code repository                      |
| Draft changelog                        | Custom schedule                | Pull request        | Supported     | None                                                     |
| Fill gaps from assistant conversations | Custom schedule                | Pull request        | Not supported | None                                                     |
| Improve docs from user feedback        | Custom schedule                | Pull request        | Not supported | Feedback collection enabled                              |
| Update from support feedback           | Custom schedule                | Pull request        | Supported     | Intercom, Plain, Pylon, or Zendesk integration connected |
| Translate content                      | Content update                 | Direct merge        | Not supported | At least one target language                             |
| Fix broken links                       | Content update                 | Pull request        | Not supported | None                                                     |
| Fix SEO issues                         | Content update                 | Pull request        | Not supported | None                                                     |
| Fix grammar & typos                    | Content update                 | Pull request        | Not supported | None                                                     |
| Enforce your style guide               | Content update                 | Pull request        | Not supported | None                                                     |

You can change all defaults from the automation's settings panel. See [Configurations](/docs/automations/manage#configurations) for the available options.

## Self-updating content automations

Self-updating content automations make updates based on context that you define so your content remains accurate and up to date.

### Update from code changes

Monitors your source code repositories and opens pull requests to update content for changes that affect users. You can run this automation on a schedule, which generally uses fewer credits, or on every source code pull request. By default, this automation runs twice weekly (Tuesday and Thursday).

When you run the automation on a schedule, the agent reads all merged source code pull requests since the last time the automation ran. It groups related changes that require content updates into a pull request in your Mintlify project repository. If there are any unmerged pull requests from previous runs, the agent adds relevant changes to existing pull requests. The agent cites where the changes come from in your source code repositories.

When you run the automation on every source code pull request, the agent opens a content update pull request whenever you merge a code change that requires content updates. Use the push-based variant when you want content updates to appear as soon as code ships, rather than batched on a schedule.

You can enable [integrations](/docs/automations/integrations) for this automation to give the agent additional context from tools like Slack or Linear when determining what to update.

### Draft changelog

Creates a changelog entry on a recurring schedule. Add source code repositories as context so the agent has more detail about how your product changed. Without context repositories, the agent works from your content updates to write a changelog entry.

<div />

### Fill gaps from assistant conversations

Reviews question trends from your [assistant](/docs/assistant/index) to identify gaps in your content, then opens a pull request to address them. The more assistant conversations your users have, the more signal the agent has to work with. Run this automation on a recurring schedule to keep content aligned with what users want to know about your product.

<div />

### Improve docs from user feedback

Reviews page [feedback](/docs/optimize/feedback)—thumbs ratings and written comments—and updates content where users have reported problems. The agent focuses on pages with recurring negative signals rather than one-off feedback, so results improve as feedback accumulates.

You must enable feedback collection on the [Add-ons](https://app.mintlify.com/products/addons) page before you can use this automation.

### Update from support feedback

Reviews resolved support conversations from [Intercom](/docs/automations/integrations), [Plain](/docs/automations/integrations), [Pylon](/docs/automations/integrations), or [Zendesk](/docs/automations/integrations) to identify recurring gaps in your content, then opens a pull request to address them. The agent focuses on themes across multiple conversations rather than one-off questions, so results improve as your support volume grows.

Select a single support platform when you configure the automation. Connect it from the settings panel if it isn't already connected for your organization. Add source code repositories as context to help the agent tie support themes back to the product areas they describe.

Each scheduled run groups related findings into up to three themes, and opens a separate pull request for each. Every run lists the resolved support conversations it reviewed and links back to the source platform, so you can trace every content suggestion to the underlying customer feedback.

This automation is available on plans with custom integrations. Contact your account team if you don't see it in the dashboard.

## Maintenance automations

Maintenance automations automate routine tasks to improve the quality and consistency of your content. You can run them on a content update trigger or on a recurring schedule.

Running on a content update trigger maintains your content with minimal lag. Running on a schedule is generally more credit-efficient because the agent batches work across multiple changes in a single run. The tradeoff is a delay between when content changes and when the automation acts on it.

As content changes, each maintenance automation appends new fixes to a single open pull request. This keeps routine maintenance in one pull request to review instead of many.

Self-updating content automations create pull requests, and any enabled maintenance automations run on those pull requests. If a maintenance automation identifies required changes, the agent combines the work into a single pull request. For example, if you enable the **Translate content** automation, the agent adds translations to any pull requests opened by the **Update from code changes** automation.

### Translate content

Translates updated content into your selected target languages whenever changes push to your project repository. You must specify at least one target language. Mintlify reads the [languages](/docs/organize/navigation#languages) defined in your `docs.json` and preselects any already configured target languages.

To disable translations for a language, remove all files in that language's directory. You cannot disable translations for a language that still has published content.

### Fix broken links

Finds and fixes broken internal and external links whenever content changes push to your project repository. Useful to run after major content reorganizations or when external services you reference change their URLs.

<div />

### Fix SEO issues

Checks and fixes titles, meta descriptions, headings, and canonical tags whenever content changes. Add instructions to align the agent's suggestions with your SEO strategy or target keywords.

### Fix grammar & typos

Finds and fixes typos, spelling mistakes, and grammar errors whenever content changes. Add instructions to specify exceptions for technical terms, product names, or intentional stylistic choices that the agent should not change.

<div />

### Enforce your style guide

Keeps voice, tone, and writing rules consistent whenever content changes. Add instructions to define the specific rules you want enforced or link to your style guide. The more precise your instructions, the more consistent the results.


# Credit pricing
Source: https://www.mintlify.com/docs/credits

Understand how your organization's credit balance works, what consumes credits, and how we bill credit add-ons, overages, and rollovers.

Mintlify's AI features run on credits. Your organization has one monthly credit balance, shared by every deployment and everyone on your team. Manage it on the [Usage](https://app.mintlify.com/settings/organization/usage) page in your dashboard.

## Your shared balance

Your balance comes from three places:

* **Your plans.** Every Pro plan in your organization contributes 10,000 credits per month. An organization with two Pro deployments starts each month with 20,000 credits.
* **Add-ons.** Buy an add-on when you need more than your plans include. An add-on is one purchase for the organization rather than one per deployment, and any deployment can spend it.
* **Rollover.** Unused credits carry into the next month and join the same balance.

Every deployment and every team member spends from that shared balance. The [Usage](https://app.mintlify.com/settings/organization/usage) page shows the organization-wide balance, with per-deployment usage broken out below it.

Two things stay with the individual deployment: its plan, and its overage setting, which decides whether that deployment keeps running after the shared balance runs out.

<Note>
  Credits were previously tracked per deployment. They now pool at the organization level.
</Note>

## What uses credits

Three products draw from your balance: the assistant, the agent, and automations.

| Feature            | Average credits per interaction |
| :----------------- | :------------------------------ |
| Assistant response | 23                              |
| Editor agent run   | 115                             |
| Slack agent run    | 110                             |

Automations consume credits each time they run, whether you run them on a schedule, on a trigger, or manually.

| Automation                          | Average credits per run |
| :---------------------------------- | :---------------------- |
| Update from code changes            | 180                     |
| Update from assistant conversations | 212                     |
| Broken link detection               | 285                     |
| Changelog                           | 223                     |
| SEO audit                           | 422                     |
| Translations                        | 913                     |
| Typo check                          | 330                     |
| Writing style                       | 235                     |

These numbers are averages. A single run costs more or less depending on the task size. The cost depends on how much content the agent reads, how many files it changes, and how long the run takes.

## Plan availability

Credits are available on the Pro and Enterprise plans.

The Starter plan does not include AI features, and you cannot purchase credits on it. To use the assistant, agent, or automations, upgrade to Pro or Enterprise.

<Note>
  Customers on legacy credit plans keep their existing credit packs and pricing. The add-ons below apply to the Pro plan.
</Note>

## Credit add-ons

Each add-on adds credits to your organization's monthly balance on top of what your plans include.

| Extra credits per month | Monthly cost |
| :---------------------- | :----------- |
| 15,000                  | \$145        |
| 40,000                  | \$370        |
| 90,000                  | \$800        |

A single Pro deployment with the 40,000-credit add-on has 50,000 credits per month. Larger add-ons cost less per credit. The 90,000-credit add-on costs about 8% less per credit than the 15,000-credit one. All three add-ons cost less per credit than the \$0.01 overage rate.

Add or change an add-on in the **Credit packages** section of the [Usage](https://app.mintlify.com/settings/organization/usage) page. Changes take effect immediately, and we prorate the charges to your current billing cycle.

The 90,000-credit add-on is the largest you can buy yourself. For more than that, [contact sales](https://www.mintlify.com/contact/sales) to discuss a custom credit package, available on Enterprise plans only.

For the most current pricing, see the [pricing page](https://mintlify.com/pricing).

## Spending controls

### Overages

Overages let a deployment keep running after your organization exhausts its monthly credits, at \$0.01 per additional credit. They are off by default. Enable them in the **Spending controls** section of the [Usage](https://app.mintlify.com/settings/organization/usage) page.

You configure overages per deployment, so when the shared balance runs out, each deployment's own setting decides what happens to it. A deployment with overages off loses its credit-powered features until the balance resets.

Every add-on costs less per credit than the \$0.01 overage rate. Use overages to absorb an occasional busy month. If your organization exceeds its balance consistently, buy an add-on or move to a larger one instead.

### Usage alerts

Set usage alerts in the **Spending controls** section of the [Usage](https://app.mintlify.com/settings/organization/usage) page to receive an email when your organization reaches a given percentage of its balance. Alerts cover the organization as a whole rather than a single deployment.

### Rollovers

Up to 50% of unused credits carry forward to the next month, so the most your organization can have available in any month is 1.5 times its monthly balance. Rollovers reset when you change add-ons.

## Estimating your usage

Use the averages in [What uses credits](#what-uses-credits) to estimate what your organization needs each month.

A site that handles 500 assistant responses per month uses roughly 11,500 credits (500 × 23). Adding a weekly broken link detection automation adds about 1,140 credits per month (4 × 285).

Estimates get you to a starting point. After a month of real usage, check the [Usage](https://app.mintlify.com/settings/organization/usage) page and adjust your add-on.

## Export usage activity

Export your usage activity log to CSV for deeper analysis, reporting, or record-keeping.

1. Navigate to the [Usage](https://app.mintlify.com/settings/organization/usage) page in your dashboard.
2. Optionally, adjust the date range in the toolbar to change the period the export covers.
3. In the **Activity log** section, click **Export to CSV**.
4. Mintlify emails you a download link when the export is ready. The link expires after 72 hours.

The exported CSV includes the date, product, and credits consumed for each event in the selected range.

## Reduce credit usage

### Run automations on a schedule

SEO audits, writing style checks, and broken link detection don't need to run on every code change. A daily or weekly schedule lowers credit consumption because the agent batches work across multiple changes in a single run. The tradeoff is a delay between when content changes and when the automation acts on it.

### Find what's consuming your credits

The [Usage](https://app.mintlify.com/settings/organization/usage) page breaks usage down by feature category. If one automation costs more than you expect, review its trigger frequency and any custom instructions that widen its scope.


# Audit logs
Source: https://www.mintlify.com/docs/dashboard/audit-logs

Review, export, and stream audit logs to Amazon S3 or Datadog to track deployments, configuration changes, and permission updates in your organization.

<Info>
  Audit logs are available on [Enterprise plans](https://mintlify.com/pricing?ref=audit-logs).
</Info>

Use audit logs to monitor and track actions performed by members of your organization. Audit logs provide a record of activities for security, compliance, and troubleshooting purposes.

* **Monitor security**: Track authentication attempts and permission changes.
* **Ensure compliance**: Maintain records of all organizational activities.
* **Troubleshoot issues**: Investigate failed actions and their causes.
* **Track changes**: Review who made specific changes and when.

## View audit logs

Only organization admins can view and export audit logs.

Navigate to the [Audit log](https://app.mintlify.com/settings/organization/audit-logs) page of your dashboard to view audit logs. Mintlify retains audit log entries for two years. Export logs to CSV to keep records for longer.

Click any log entry to expand it and view detailed information, including:

| Field     | Description                                            |
| --------- | ------------------------------------------------------ |
| Timestamp | Date and time when the action occurred                 |
| Actor     | The email address of the user who performed the action |
| Action    | What action the user performed                         |
| Category  | Type of resource affected                              |
| Outcome   | Whether the action succeeded or failed                 |
| Metadata  | Additional context about the action                    |

### Filter logs

Filter audit logs to find specific activities.

**Date range**: Select a preset date range to view logs over a specific period.

**Category**: Filter logs by the type of action.

| Category           | Description                                                                                                           |
| ------------------ | --------------------------------------------------------------------------------------------------------------------- |
| Organization       | Organization settings updates and deletion requests.                                                                  |
| Member             | Team member invitations, removals, role changes, and credential revocations.                                          |
| Deployment         | Deployment configuration changes including custom domains, authentication, Git sources, and MCP client credentials.   |
| Preview deployment | Preview deployment creation, updates, and authentication changes.                                                     |
| API key            | API key and discovery API key creation and deletion.                                                                  |
| Assistant          | Assistant setting updates like deflection email, web search sites, and starter questions.                             |
| PDF export         | PDF export generation and deletion.                                                                                   |
| Integration        | GitHub and Slack installations and removals.                                                                          |
| Billing            | Subscription updates, add-on purchases, and invoice views.                                                            |
| Quota              | Overage policy and alert configuration changes.                                                                       |
| User               | Individual user notification settings.                                                                                |
| Automations        | Automation configurations and repository management.                                                                  |
| Audit log          | Audit log views and exports.                                                                                          |
| Auth               | Login attempts, logouts, session creations, and break-glass logins.                                                   |
| SSO                | SSO connection changes, sign-in policy updates, break-glass access updates, and verified domain changes.              |
| SCIM               | Automated user provisioning, updates, and deprovisioning from your identity provider, and group role mapping changes. |

## Stream audit logs

Stream audit logs to Amazon S3 or Datadog in near real time. Use streaming to send audit events to your existing security monitoring and long-term retention systems without repeatedly exporting CSV files.

Organization admins can add multiple destinations and select which categories to send. By default, all categories stream, and the category selection applies to every configured destination.

### Add a destination

1. Navigate to the [Audit log](https://app.mintlify.com/settings/organization/audit-logs) page of your dashboard.

2. In the **Audit log streaming** section, click **Configure**.

3. Click **Add destination** and select **Amazon S3** or **Datadog**.

4. Enter an optional label to identify the destination, then provide the required connection details:

   | Destination | Required details                                         | Optional details |
   | ----------- | -------------------------------------------------------- | ---------------- |
   | Amazon S3   | Bucket, AWS region, access key ID, and secret access key | Key prefix       |
   | Datadog     | Datadog site and API key                                 | None             |

5. Click **Add destination**.

<AccordionGroup>
  <Accordion title="Prepare Amazon S3 credentials">
    Create an IAM user (or role with programmatic access credentials) whose policy allows writing to the target bucket. At minimum, grant `s3:PutObject` on the bucket and key prefix that you plan to use. For example:

    ```json theme={null}
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["s3:PutObject"],
          "Resource": "arn:aws:s3:::your-bucket-name/audit-logs/*"
        }
      ]
    }
    ```

    Use the access key ID and secret access key from that IAM user when adding the destination. The key prefix is optional, and Mintlify prepends it to every object it writes.
  </Accordion>

  <Accordion title="Prepare Datadog credentials">
    Create a Datadog API key from **Organization Settings > API Keys** in your Datadog account. Do not use an application key.

    Set the Datadog site to match the region where you host your Datadog account, for example `datadoghq.com` (US1), `us3.datadoghq.com`, `us5.datadoghq.com`, `datadoghq.eu` (EU1), `ap1.datadoghq.com`, or `ddog-gov.com`. Using the wrong site rejects the events.
  </Accordion>
</AccordionGroup>

To stop streaming to a destination, open the streaming configuration and click the <Icon icon="trash-2" /> remove icon next to the destination.

### Select streamed categories

1. Navigate to the [Audit log](https://app.mintlify.com/settings/organization/audit-logs) page of your dashboard.
2. In the **Audit log streaming** section, click **Configure**.
3. Under **Streamed categories**, select the categories that you want to send. Clear a category to exclude its events from the stream.
4. Click **Save changes**.

## Export audit logs

Export audit logs to CSV for analysis, compliance reporting, or long-term archival.

1. Navigate to the [Audit log](https://app.mintlify.com/settings/organization/audit-logs) page of your dashboard.
2. Optionally, apply filters to narrow down the logs you want to export.
3. Click **Export CSV**.
4. Mintlify sends you an email with a download link when the export is ready.


# Dashboard access policies
Source: https://www.mintlify.com/docs/dashboard/network-access

Restrict Mintlify dashboard access to trusted IP addresses and control how long dashboard sessions stay valid with idle timeouts and maximum session lifetimes.

<Info>
  Dashboard access policies require an [Enterprise plan](https://mintlify.com/pricing?ref=network-access).
</Info>

Control how organization members access the Mintlify dashboard. You can restrict access to trusted IP addresses and set how long dashboard sessions stay valid. Manage both policies on the **Policies** tab of the [Identity & access](https://app.mintlify.com/settings/organization/access) page in your dashboard.

## IP allowlist

Use an IP allowlist to restrict dashboard and editor access to trusted IP addresses and Classless Inter-Domain Routing (CIDR) ranges. When you enable the allowlist, organization members can only sign in and use the dashboard and web editor from an allowed IP address.

The IP allowlist applies to your Mintlify dashboard and editor, including SSO and break-glass sign-ins. It does not affect your published documentation site. API requests use separate IP controls.

If a member tries to sign in or use the dashboard from a blocked IP address, Mintlify rejects the request. It shows a message explaining that the address is not on the allowlist. Members can contact an admin to have their address added.

You can allow access two ways:

* **Individual IP address**: Allow a single address, such as `203.0.113.7` or `2001:db8::1`.
* **CIDR range**: Allow a block of addresses, such as `10.0.0.0/8` or `2001:db8::/48`. Use CIDR notation to grant access to an entire office or VPN network without listing each address individually.

Both IPv4 and IPv6 addresses are supported.

### Configure the IP allowlist

<Warning>
  Add your current IP address to the allowlist before enabling it. If your address is not on the list, you can lock yourself out of the dashboard. The **Policies** tab displays your current IP address to help you avoid this.
</Warning>

1. In your Mintlify dashboard, navigate to the [Identity & access](https://app.mintlify.com/settings/organization/access) page.
2. On the **Policies** tab, under **Allowed IP addresses**, enter an individual IP address (for example, `203.0.113.7`) or a CIDR range (for example, `10.0.0.0/8`).
3. Click **Add**.
4. Repeat for each address or range you want to allow.
5. Enable the allowlist to begin enforcing it.

## Session lifetimes

Control how long dashboard sessions stay valid before members must sign in again. You can set two independent limits:

* **Maximum session lifetime**: Members must sign in again once a session reaches this age, regardless of activity. When off, sessions have no maximum age.
* **Idle session timeout**: Members are signed out after this period of inactivity. When off, sessions time out after 14 days of inactivity.

Both limits accept values from 5 minutes to 14 days.

### Configure session lifetimes

1. In your Mintlify dashboard, navigate to the [Identity & access](https://app.mintlify.com/settings/organization/access) page.
2. On the **Policies** tab, under **Session lifetimes**, toggle on **Maximum session lifetime** or **Idle session timeout**.
3. Set a duration for each limit that you enable.
4. Click **Save**.

Lowering the maximum session lifetime applies to active sessions immediately. Any session older than the new limit ends the next time it makes a request. Changes to the idle session timeout take effect as active sessions refresh.


# Roles
Source: https://www.mintlify.com/docs/dashboard/roles

Assign admin, editor, or viewer roles to team members to control access levels, editing permissions, and deployment capabilities in Mintlify.

<Info>
  Role-based access control (RBAC) is available on [Enterprise plans](https://mintlify.com/pricing?ref=rbac).
</Info>

Mintlify provides three dashboard access levels: viewer, editor, and admin.

|                                               | Viewer | Editor | Admin |
| --------------------------------------------- | :----: | :----: | :---: |
| View content in the editor                    |    ✅   |    ✅   |   ✅   |
| View dashboard and analytics                  |    ✅   |    ✅   |   ✅   |
| Ask the [Slack agent](/docs/agent/slack) questions |    ✅   |    ✅   |   ✅   |
| Make changes with the Slack agent             |    ❌   |    ✅   |   ✅   |
| Edit content in the web editor                |    ❌   |    ✅   |   ✅   |
| Publish changes                               |    ❌   |    ✅   |   ✅   |
| Create, rename, and delete pages              |    ❌   |    ✅   |   ✅   |
| Reorder navigation                            |    ❌   |    ✅   |   ✅   |
| Upload media                                  |    ❌   |    ✅   |   ✅   |
| Trigger deployments                           |    ❌   |    ✅   |   ✅   |
| Create and delete API keys                    |    ❌   |    ✅   |   ✅   |
| Configure integrations                        |    ❌   |    ✅   |   ✅   |
| Configure assistant                           |    ❌   |    ✅   |   ✅   |
| Configure add-ons                             |    ❌   |    ✅   |   ✅   |
| Invite editors and viewers                    |    ❌   |    ✅   |   ✅   |
| Update user roles                             |    ❌   |    ❌   |   ✅   |
| Invite admins                                 |    ❌   |    ❌   |   ✅   |
| Delete users                                  |    ❌   |    ❌   |   ✅   |
| Manage billing                                |    ❌   |    ❌   |   ✅   |
| Manage SSO                                    |    ❌   |    ❌   |   ✅   |
| Update custom domain                          |    ❌   |    ❌   |   ✅   |
| Update Git source                             |    ❌   |    ❌   |   ✅   |
| Delete organization                           |    ❌   |    ❌   |   ✅   |

<Tip>
  Limit admin access to only the people who need to perform admin tasks.
</Tip>

## Repository contributors and deployments

Anyone with access to your documentation repository can contribute by pushing changes. However, their changes do not deploy until an editor or admin manually triggers a deployment from your dashboard.

## Add members to your organization

By default, the person who creates your Mintlify organization has admin access. Add additional members in the [Members](https://app.mintlify.com/settings/organization/members) page of your dashboard.

You can invite any number of members to your organization.

## Change a member's role

Admins can change the role assigned to any member.

1. Navigate to the [Members](https://app.mintlify.com/settings/organization/members) page of your dashboard.
2. In the member's row, select a new role from the role dropdown.
3. Confirm the change.

The new role takes effect the next time the member loads the dashboard.

## Remove a member

Admins can remove a member from the organization entirely, which deletes their access and any keys they created.

1. Navigate to the [Members](https://app.mintlify.com/settings/organization/members) page of your dashboard.
2. In the member's row, click the <Icon icon="trash" /> **Remove** button.
3. Confirm the removal.

Removing a member deletes the member from your organization. Revoking a member's credentials signs them out and clears their keys, but keeps their membership.

## Revoke a member's credentials

Admins can sign a member out of the dashboard and revoke their keys and tokens without removing them from the organization. Use credential revocation when offboarding someone or responding to a compromised account.

1. Navigate to the [Members](https://app.mintlify.com/settings/organization/members) page of your dashboard.
2. In the member's row, click the <Icon icon="shield-off" /> **Revoke credentials** button.
3. Select which credentials to revoke.
4. Click **Revoke**.

You can revoke any combination of the following credentials:

| Credential         | What revoking it does                                       |
| ------------------ | ----------------------------------------------------------- |
| Sessions           | Signs the member out of the dashboard.                      |
| CLI tokens         | Signs the member out of the [CLI](/docs/cli/install).            |
| API keys           | Deletes the API keys that the member created.               |
| Discovery API keys | Deletes the discovery API keys that the member created.     |
| M2M clients        | Revokes the member's machine-to-machine client credentials. |
| Connected apps     | Disconnects the apps the member authorized through OAuth.   |

Revoking credentials cannot be undone. The member can sign in again and create new keys and tokens unless you also remove them from the organization or block their sign-in method. You cannot revoke your own credentials.


# SCIM user provisioning
Source: https://www.mintlify.com/docs/dashboard/scim

Automatically provision, deprovision, and map users to roles for Mintlify dashboard members from Okta or another SCIM 2.0 identity provider.

<Info>
  SCIM requires an [Enterprise plan](https://mintlify.com/pricing?ref=scim).
</Info>

SCIM (System for Cross-domain Identity Management) lets admins provision and deprovision Mintlify organization members directly from your identity provider.

SCIM manages who has access to your organization. To control how users sign in, set up [SSO](/docs/dashboard/sso).

## Supported identity providers

Mintlify's SCIM endpoint works with any SCIM 2.0-compliant identity provider that authenticates with a bearer token. Step-by-step instructions below cover Okta. For other providers, [contact us](mailto:support@mintlify.com) for setup guidance.

## Enable SCIM

<Steps>
  <Step title="Open SCIM settings">
    In your Mintlify dashboard, navigate to the [SCIM](https://app.mintlify.com/settings/organization/scim) tab of the "Identity & access" page.
  </Step>

  <Step title="Turn on SCIM">
    Click **Configure SCIM**. Mintlify generates a **SCIM base URL** and a **bearer token**.

    <Warning>
      Securely store the bearer token. Mintlify shows it only once and cannot display it again.
    </Warning>
  </Step>

  <Step title="Add the credentials to your identity provider">
    Enter the SCIM base URL and bearer token into your identity provider's SCIM app configuration. See [Configure your identity provider](#configure-your-identity-provider) for provider-specific steps.
  </Step>
</Steps>

## Configure your identity provider

### Okta

<Steps>
  <Step title="Add a SCIM app in Okta">
    In Okta, under **Applications**, click **Browse App Catalog** and search for **SCIM 2.0 Test App (Header Auth)**. This is Okta's standard integration for any SCIM 2.0 API that authenticates with a bearer token.
  </Step>

  <Step title="Add your Mintlify credentials">
    Under the app's **Provisioning** settings, enter the Mintlify SCIM base URL and bearer token. Format the token as `Bearer <token>`.
  </Step>

  <Step title="Enable provisioning actions">
    Under **Provisioning to app**, enable the create, update, and deactivate options you want Okta to manage. Leave **Sync password** off, since Mintlify doesn't use Okta-managed passwords.
  </Step>

  <Step title="Create and push groups">
    In Okta, use your existing groups or create new ones for each set of users you want to provision, then push those groups to the SCIM app under **Push groups**.

    <Warning>
      Group names are case-sensitive. The name you map in Mintlify must match the Okta group name exactly.
    </Warning>
  </Step>

  <Step title="Assign users">
    Assign the relevant groups or individual users to the app under **Assignments**.
  </Step>

  <Step title="Map groups to roles">
    In the Mintlify dashboard, map each pushed group name to a dashboard role. See [Map groups to roles](#map-groups-to-roles).
  </Step>
</Steps>

## Map groups to roles

Assign [roles](/docs/dashboard/roles) to users based on their identity provider group membership.

1. In the Mintlify dashboard, navigate to the [SCIM](https://app.mintlify.com/settings/organization/scim) tab of the "Identity & access" page.
2. In the "Group-to-role mappings" section, click **Add mapping**.
3. Enter the identity provider group name and select a role.

When a user belongs to multiple mapped groups, Mintlify assigns the highest-privilege role among them.

You can edit or remove a mapping at any time. This mapping is one-directional and only controls which Mintlify role a group receives. For example, suppose you map your identity provider's `developers` group to the editor role and later change that mapping to viewer. New members of `developers` become viewers in Mintlify, but the existing `developers` group itself is unchanged in your identity provider.

## Rotate the bearer token

Rotate the bearer token if it's exposed or as part of routine credential hygiene.

1. Navigate to the [SCIM](https://app.mintlify.com/settings/organization/scim) tab of the "Identity & access" page.
2. Click **Rotate token**.
3. Copy the new token and update your identity provider's SCIM configuration.

<Warning>
  Rotating the token immediately invalidates the previous token. Provisioning stops working until you update your identity provider with the new token.
</Warning>

## Disable SCIM

1. Navigate to the [SCIM](https://app.mintlify.com/settings/organization/scim) tab of the "Identity & access" page.
2. Toggle SCIM off.

Disabling SCIM stops new provisioning and deprovisioning events from your identity provider. Existing dashboard members keep their current access until removed manually or through another method.


# Security contact
Source: https://www.mintlify.com/docs/dashboard/security-contact

Configure a security contact email address for your organization to receive vulnerability reports, security alerts, and compliance updates.

<Info>
  Security contact is available on [Enterprise plans](https://mintlify.com/pricing?ref=security-contact).
</Info>

List a security contact in your dashboard to receive security-related communications about your organization.

## Configure a security contact

To add, update, or remove a security contact, navigate to the [Security contact](https://app.mintlify.com/settings/organization/security-contact) page of your dashboard.


# Session security
Source: https://www.mintlify.com/docs/dashboard/session-security

Configure dashboard session timeouts, maximum session lifetime, and an IP allowlist to enforce stricter authentication and network access policies.

<Info>
  Session security settings are available on [Enterprise plans](https://mintlify.com/pricing?ref=session-security).
</Info>

As an enterprise admin, you can require dashboard users to reauthenticate on a schedule. Choose a schedule that fits your organization's security policies. Two independent controls determine when a dashboard session ends:

* **Idle session timeout**: How long a session can remain inactive before the user is signed out.
* **Maximum session lifetime**: The absolute lifetime of a session, regardless of activity. When exceeded, the user is signed out and must reauthenticate.

Each setting has its own enable toggle. If a setting is disabled, Mintlify's default applies. Both settings accept values between **5 minutes and 14 days** (20,160 minutes).

## Configure session lifetimes

To review or change session lifetimes, go to the **Policies** tab of the [Identity & access](https://app.mintlify.com/settings/organization/access?tab=policies) page in your dashboard.

For each setting, use the toggle to enable or disable it. Enter a value, select a unit (minutes, hours, days, or weeks for maximum lifetime; minutes, hours, or days for idle timeout), and click **Save**. Disabling a setting and saving clears it so Mintlify's default takes over.

### Idle session timeout

The idle session timeout controls how long a session can remain inactive before it expires. Any dashboard request from the user resets the idle timer.

Use a shorter idle timeout to reduce the risk of unattended sessions being used by someone other than the signed-in user, for example on shared or unlocked devices.

### Maximum session lifetime

The maximum session lifetime is the absolute cap on how long a single sign-in can last. It is measured from the moment the user signed in. Activity does not extend it. When the maximum lifetime is reached, the user is signed out even if they are actively using the dashboard.

Use a maximum lifetime to guarantee that users reauthenticate on a regular cadence, which can help you meet compliance requirements or revalidate access after identity provider changes.

## How the settings interact

The two settings apply independently. A user's session ends at whichever limit is reached first:

* If the user is inactive for longer than the **idle session timeout**, the session ends.
* If the **maximum session lifetime** elapses since sign-in, the session ends even if the user is active.

For example, set the idle timeout to 1 hour and the maximum lifetime to 8 hours. An actively working user is signed out after 8 hours. An idle user is signed out after 1 hour.

## Restrict dashboard access by IP

Use the IP allowlist to restrict dashboard access to a set of trusted networks. When the allowlist has one or more entries, only requests from those IPs or ranges can sign in to or use the dashboard. An empty allowlist leaves the dashboard accessible from any IP address.

<Warning>
  If your current IP address is not on the allowlist, you can lock yourself out of the dashboard. Confirm your IP is included before saving.
</Warning>

To configure the allowlist, go to the **Policies** tab of the [Identity & access](https://app.mintlify.com/settings/organization/access?tab=policies) page in your dashboard.

* **Add an entry**: Enter an IPv4 or IPv6 address, or a CIDR range (for example, `203.0.113.7` or `10.0.0.0/8`), then click **Add**. Adding the first entry enables the allowlist.
* **Remove an entry**: Click the **×** on any entry. Removing the last entry disables the allowlist.
* **Check your IP**: Your current IP address is shown below the entry list so you can confirm it is covered before saving changes.

The status badge next to **IP allowlist** shows **Active** when at least one entry is present and **Disabled** when the list is empty.

## Audit logging

Your organization's [audit logs](/docs/dashboard/audit-logs) record changes to session security settings under the `org` category. Look for these actions to review who updated the settings and when:

* `org.session_security_session_duration_updated`
* `org.session_security_session_duration_deleted`
* `org.session_security_max_session_lifetime_updated`
* `org.session_security_max_session_lifetime_deleted`
* `org.session_security_ip_allowlist_updated`


# Single sign-on (SSO)
Source: https://www.mintlify.com/docs/dashboard/sso

Set up single sign-on with SAML or OIDC identity providers like Okta, Azure AD, and Google Workspace for secure team authentication.

<Info>
  SSO is available on [Enterprise plans](https://mintlify.com/pricing?ref=sso).
</Info>

Enterprise admins can configure Security Assertion Markup Language (SAML) SSO for Okta or Microsoft Entra directly from the Mintlify dashboard. To set up SSO for other providers, such as Google Workspace or Okta OpenID Connect (OIDC), [contact us](mailto:support@mintlify.com).

## Configure SSO

### Okta

<Steps>
  <Step title="Configure Okta SSO in your Mintlify dashboard">
    1. In your Mintlify dashboard, navigate to the [Identity & access](https://app.mintlify.com/settings/organization/sso) page.
    2. Click **Configure**.
    3. Select **Okta SAML**.
    4. Copy the **Single sign on URL** and **Audience URI**.
  </Step>

  <Step title="Create a SAML app in Okta">
    1. In Okta, under **Applications**, create a new app integration using SAML 2.0.

    2. Enter the following from Mintlify:
       * **Single sign on URL**: the URL you copied from your Mintlify dashboard
       * **Audience URI**: the URI you copied from your Mintlify dashboard
       * **Name ID Format**: `EmailAddress`

    3. Add these attribute statements:

       | Name        | Name format | Value            |
       | ----------- | ----------- | ---------------- |
       | `firstName` | Basic       | `user.firstName` |
       | `lastName`  | Basic       | `user.lastName`  |
  </Step>

  <Step title="Copy the Okta metadata URL">
    In Okta, go to the **Sign On** tab of your application and copy the metadata URL.
  </Step>

  <Step title="Save in Mintlify">
    Back in the Mintlify dashboard, paste the metadata URL and click **Save changes**.
  </Step>
</Steps>

### Microsoft Entra

<Steps>
  <Step title="Configure Microsoft Entra SSO in your Mintlify dashboard">
    1. In your Mintlify dashboard, navigate to the [Identity & access](https://app.mintlify.com/settings/organization/sso) page.
    2. Click **Configure**.
    3. Select **Microsoft Entra ID SAML**.
    4. Copy the **Single sign on URL** and **Audience URI**.
  </Step>

  <Step title="Create an enterprise application in Microsoft Entra">
    1. In Microsoft Entra, navigate to **Enterprise applications**.
    2. Click **New application**.
    3. Click **Create your own application**.
    4. Select "Integrate any other application you don't find in the gallery (Non-gallery)."
  </Step>

  <Step title="Configure SAML in Microsoft Entra">
    1. In Microsoft Entra, navigate to **Single Sign-On**.
    2. Click **SAML**.
    3. Under **Basic SAML Configuration**, enter the following:
       * **Identifier (Entity ID)**: the Audience URI from Mintlify
       * **Reply URL (Assertion Consumer Service URL)**: the Single sign on URL from Mintlify

    Leave the other values blank and click **Save**.
  </Step>

  <Step title="Configure Attributes & Claims in Microsoft Entra">
    1. In Microsoft Entra, navigate to **Attributes & Claims**.
    2. Select **Unique User Identifier (Name ID)** under "Required Claim."
    3. Change the Source attribute to `user.primaryauthoritativeemail`.
    4. Under **Additional claims**, create the following:
       | Name        | Value            |
       | ----------- | ---------------- |
       | `firstName` | `user.givenname` |
       | `lastName`  | `user.surname`   |
  </Step>

  <Step title="Copy the Microsoft Entra metadata URL">
    Under **SAML Certificates**, copy the **App Federation Metadata URL**.
  </Step>

  <Step title="Save in Mintlify">
    Back in the Mintlify dashboard, paste the metadata URL and click **Save changes**.
  </Step>

  <Step title="Assign users">
    In Microsoft Entra, navigate to **Users and groups**. Assign the users who should have access to your Mintlify dashboard.
  </Step>
</Steps>

## JIT provisioning

When you enable JIT (just-in-time) provisioning, Mintlify automatically adds users who sign in through your identity provider to your organization.

<Note>
  JIT provisioning only works when users start the login from their identity provider (IdP). Users must sign in from your identity provider (Okta dashboard or Microsoft Entra portal) rather than starting from the Mintlify login page.
</Note>

To enable JIT provisioning, you must have SSO enabled. In your dashboard, navigate to the [Identity & access](https://app.mintlify.com/settings/organization/sso) page. Set up SSO, then enable JIT provisioning.

## Verified domains

Verify ownership of your email domains so Mintlify can scope SSO and member provisioning to people with matching email addresses. When someone signs in with an email address on a verified domain, Mintlify automatically routes them to your identity provider. This automatic routing works whether or not you require SSO, as long as your organization has an active SSO connection.

You can add up to five verified domains per organization.

1. Navigate to the [Identity & access](https://app.mintlify.com/settings/organization/sso) page in your dashboard.
2. On the **SSO** tab, in the **Verified domains** section, enter the domain (for example, `example.com`) and click **Add**.
3. Mintlify generates a verification token. In your DNS provider, create a TXT record with the name `_mintlify-verification.example.com` and the token as the value. Some DNS providers append the domain automatically. If yours does, enter just `_mintlify-verification` as the record name.
4. Return to the dashboard and click **Verify**. The status changes from **Pending** to **Verified** once the record propagates.

To remove a domain, click the <Icon icon="trash" /> delete button beside it.

## Require SSO

To require everyone in your organization to sign in through your identity provider, turn on **Require SSO**. When **Require SSO** is on, Mintlify rejects password, magic link, and Google OAuth sign-ins.

1. Navigate to the [Identity & access](https://app.mintlify.com/settings/organization/sso) page in your dashboard.
2. Confirm that SSO works end-to-end. In a private browser window, sign in to your Mintlify dashboard from your identity provider's app catalog (IdP-initiated). Then sign in from the [Mintlify login page](https://app.mintlify.com/login) using an email on a verified domain (service provider (SP)-initiated). Both flows should redirect through your identity provider and land you in the dashboard.
3. On the **SSO** tab, in the **Sign-in policy** section, turn on **Require SSO**.

<Warning>
  You can only require SSO after configuring an SSO connection. Requiring SSO does not check whether members can still sign in, so add break-glass access for at least one admin before turning it on.
</Warning>

To stop requiring SSO, toggle the setting off. Other sign-in methods become available again immediately.

## Break-glass access

Designate members who can bypass SSO and sign in with a password or magic link. Use break-glass access to recover access if your identity provider has an outage. It also helps if a misconfiguration locks members out.

1. Navigate to the [Identity & access](https://app.mintlify.com/settings/organization/sso) page in your dashboard.
2. On the **SSO** tab, in the **Break-glass access** section, enter the email address of a member who should retain non-SSO access and click **Add**.

Each break-glass email must belong to an existing member of your organization. Break-glass access only takes effect while Require SSO is on.

<Tip>
  Add break-glass access for admin accounts that are not tied to your primary identity provider. Store the credentials in a secure password manager, and review the list whenever team membership changes.
</Tip>

## Map RBAC roles with SAML groups

Assign [roles](/docs/dashboard/roles) to users based on their identity provider group membership. When a user signs in through SSO, Mintlify reads the `groups` attribute from the SAML assertion. It maps those groups to dashboard roles.

### Configure group attribute statements

Add a `groups` attribute statement to your SAML identity provider configuration. The attribute must use the `unspecified` name format.

The resulting SAML assertion should include an `AttributeStatement`.

```xml Example SAML assertion theme={null}
<saml2:AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
    <saml2:Attribute Name="groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
        <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
                              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                              xsi:type="xs:string">Everyone</saml2:AttributeValue>
        <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
                              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                              xsi:type="xs:string">Engineering</saml2:AttributeValue>
        <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
                              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                              xsi:type="xs:string">Admins</saml2:AttributeValue>
    </saml2:Attribute>
</saml2:AttributeStatement>
```

**Key requirements:**

* The attribute name must be `groups` (case-sensitive)
* The name format must be `urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified`
* Each group the user belongs to should be a separate `AttributeValue` element

<Tabs>
  <Tab title="Okta">
    In your Okta SAML app configuration, add a group attribute statement:

    | Name     | Name format | Filter          | Value |
    | -------- | ----------- | --------------- | ----- |
    | `groups` | Unspecified | `Matches regex` | `.*`  |

    Adjust the filter to match the specific groups you want to send to Mintlify.
  </Tab>

  <Tab title="Microsoft Entra">
    In your Microsoft Entra enterprise application:

    1. Navigate to **Single Sign-On** > **Attributes & Claims**.
    2. Click **Add a group claim**.
    3. Select which groups to include (all groups or specific ones).
    4. Under **Advanced options**, check **Customize the name of the group claim** and set the name to `groups`.
  </Tab>
</Tabs>

Once configured, Mintlify maps the group names from the SAML assertion to roles in your organization. To set up or modify group-to-role mappings, contact your Mintlify account representative.

## Change or remove SSO provider

1. Navigate to the [Identity & access](https://app.mintlify.com/settings/organization/sso) page in your dashboard.
2. Click **Configure**.
3. Select your preferred SSO provider or no SSO.

If you remove SSO, users must authenticate with a password, magic link, or Google OAuth instead.

## Other providers

For providers other than Microsoft Entra or Okta SAML, [contact us](mailto:support@mintlify.com) to configure SSO.

### Google Workspace with SAML

<Steps>
  <Step title="Create an application">
    1. In Google Workspace, navigate to **Web and mobile apps**.
    2. Click **Add custom SAML app** in the **Add app** dropdown.

    <Frame>
      <img alt="Screenshot of the Google Workspace SAML application creation page with the &#x22;Add custom SAML app&#x22; menu item highlighted" />
    </Frame>
  </Step>

  <Step title="Send us your IdP information">
    Copy the provided SSO URL, Entity ID, and x509 certificate and send it to the Mintlify team.

    <Frame>
      <img alt="Screenshot of the Google Workspace SAML application page with the SSO URL, Entity ID, and x509 certificate highlighted. The specific values for each of these appear blurred." />
    </Frame>
  </Step>

  <Step title="Configure integration">
    On the Service provider details page, enter the following:

    * ACS URL (provided by Mintlify)
    * Entity ID (provided by Mintlify)
    * Name ID format: `EMAIL`
    * Name ID: `Basic Information > Primary email`

    <Frame>
      <img alt="Screenshot of the Service provider details page with the ACS URL and Entity ID input fields highlighted." />
    </Frame>

    On the next page, enter the following attribute statements:

    | Google Directory Attribute | App Attribute |
    | -------------------------- | ------------- |
    | `First name`               | `firstName`   |
    | `Last name`                | `lastName`    |

    After you complete this step and assign users to the application, tell our team. We'll enable SSO for your account.
  </Step>
</Steps>

### Okta (OIDC)

<Steps>
  <Step title="Create an application">
    In Okta, under **Applications**, create a new app integration using OIDC. Select the **Web Application** type.
  </Step>

  <Step title="Configure integration">
    Select the authorization code grant type and enter the Redirect URI provided by Mintlify.
  </Step>

  <Step title="Send us your IdP information">
    Navigate to the **General** tab and locate the client ID and client secret. Securely provide these to us along with your Okta instance URL (for example, `<your-tenant-name>.okta.com`). You can send these details via a service like 1Password or SendSafely.
  </Step>
</Steps>


# Authentication setup
Source: https://www.mintlify.com/docs/deploy/authentication-setup

Set up user authentication to control access to pages and API references using password, OAuth, JWT, or Mintlify-managed private access.

<Info>
  Private authentication for your Mintlify organization is available on all plans.

  Password authentication requires a [Pro or Enterprise plan](https://mintlify.com/pricing?ref=authentication).

  OAuth and JWT authentication require an [Enterprise plan](https://mintlify.com/pricing?ref=authentication).
</Info>

Authentication requires users to log in before accessing your content.

You can configure full authentication for all pages or partial authentication where some pages are public and others require authentication.

Authentication is only available for sites hosted on a custom domain or Mintlify subdomain. For example, `docs.example.com` or `example.mintlify.site`. Authentication is **not supported** for sites with a [custom subpath](/docs/deploy/docs-subpath). For example, `example.com/docs`.

To identify visitors while keeping pages public, use [personalization](/docs/create/personalization). Personalization supports custom subpaths and can prefill API playground inputs without requiring visitors to authenticate before viewing a page.

## Choose an authentication method

Use this comparison to pick the method that fits your use case. See [Feature availability](#feature-availability) for how each method interacts with other Mintlify features.

| Method                 | Best for                                                      | Plan              | Group-based access | API playground prefill | Personalization |
| :--------------------- | :------------------------------------------------------------ | :---------------- | :----------------: | :--------------------: | :-------------: |
| Password               | Simple shared access with no per-user tracking                | Pro or Enterprise |         No         |           No           |        No       |
| Private authentication | Internal site for members of your Mintlify organization       | All plans         |         No         |           No           |        No       |
| OAuth 2.0              | Existing identity provider or SSO with per-user sessions      | Enterprise        |         Yes        |           Yes          |       Yes       |
| JWT                    | Custom auth backend or embedded content behind your own login | Enterprise        |         Yes        |           Yes          |       Yes       |

## Configure authentication

<Tabs>
  <Tab title="Password">
    <Info>
      Password authentication provides access control only and does **not** support user-specific features like group-based access control or API playground prefilling.
    </Info>

    ### Password prerequisites

    * Your security requirements allow sharing passwords among users.

    ### Password setup

    <Steps>
      <Step title="Create a password.">
        1. In your dashboard, go to [Authentication](https://app.mintlify.com/products/authentication).
        2. In the **Authentication method** section, set site visibility to **Private**.
        3. Click **Password**.
        4. Enter a secure password.
        5. Click **Save changes**.

        After you save, your site redeploys. When it finishes deploying, anyone who visits your site must enter the password to access your content.
      </Step>

      <Step title="Distribute access.">
        Securely share the password and documentation URL with authorized users.
      </Step>
    </Steps>

    ### Password example

    You host your documentation at `docs.foo.com` and you need basic access control without tracking individual users. You want to prevent public access while keeping setup simple.

    **Create a strong password** in your dashboard. **Share credentials** with authorized users.
  </Tab>

  <Tab title="Private authentication">
    ### Private authentication prerequisites

    * Everyone who needs to access your site must be a member of your Mintlify organization.

    ### Private authentication setup

    <Steps>
      <Step title="Enable private authentication.">
        1. In your dashboard, go to [Authentication](https://app.mintlify.com/products/authentication).
        2. In the **Authentication method** section, set site visibility to **Private**.
        3. Click **Authenticated**.
        4. Click **Save changes**.

        After you save, your site redeploys. When it finishes deploying, anyone who visits your site must log in to your Mintlify organization to access your content.
      </Step>

      <Step title="Add authorized users.">
        1. In your dashboard, go to [Members](https://app.mintlify.com/settings/organization/members).
        2. Add each person who should have access to your documentation.
        3. Assign appropriate roles based on their editing permissions.
      </Step>
    </Steps>

    ### Private example

    You host your documentation at `docs.foo.com` and your entire team has access to your dashboard. You want to restrict access to team members only.

    **Enable private authentication** in your dashboard settings.

    **Verify team access** by checking that all team members are active in your organization.
  </Tab>

  <Tab title="OAuth 2.0">
    ### OAuth 2.0 prerequisites

    * An OAuth or OIDC server that supports the Authorization Code Flow.
    * Ability to create an API endpoint accessible by OAuth access tokens (optional, to enable group-based access control).

    ### OAuth 2.0 setup

    <Steps>
      <Step title="Configure your OAuth settings.">
        1. In your dashboard, go to [Authentication](https://app.mintlify.com/products/authentication).
        2. In the **Authentication method** section, set site visibility to **Private**.
        3. Click **Custom**.
        4. Click **OAuth**.
        5. Configure these fields:

        * **Authorization URL**: Your OAuth endpoint.
        * **Client ID**: Your OAuth 2.0 client identifier.
        * **Client Secret**: Your OAuth 2.0 client secret.
        * **Scopes** (optional): Permissions to request. Copy the **entire** scope string (for example, for a scope like `provider.users.docs`, copy the complete `provider.users.docs`). Use multiple scopes if you need different access levels.
        * **Additional authorization parameters** (optional): Additional query parameters to add to the initial authorization request.
        * **Token URL**: Your OAuth token exchange endpoint.
        * **Info API URL** (optional): Endpoint on your server that Mintlify calls to retrieve user info. Use this field for group-based access control. If omitted, the OAuth flow only verifies identity.
        * **Logout URL** (optional): The native logout URL for your OAuth provider. When users log out, Mintlify validates the logout redirect against this configured URL for security. The redirect only succeeds if it exactly matches the configured `logoutUrl`. If you do not configure a logout URL, users redirect to `/login`. Mintlify redirects users with a `GET` request and does not append query parameters. Include any parameters (for example, `returnTo`) directly in the URL.
        * **Redirect URL** (optional): The URL to redirect users to after authentication.

        6. Click **Save changes**.

        After you configure your OAuth settings, your site redeploys. When it finishes deploying, anyone who visits your site must log in to your OAuth provider to access your content.
      </Step>

      <Step title="Configure your OAuth server.">
        1. Copy the **Redirect URL** from your [authentication settings](https://app.mintlify.com/products/authentication).
        2. Add the redirect URL as an authorized redirect URL for your OAuth server.
      </Step>

      <Step title="Create your user info endpoint for group access (optional).">
        To enable group-based access control, create an API endpoint that:

        * Responds to `GET` requests.
        * Accepts an `Authorization: Bearer <access_token>` header for authentication.
        * Returns user data in the `User` format. See [User data format](#user-data-format) for more information.

        Mintlify calls this endpoint with the OAuth access token to retrieve user information. No additional query parameters are sent.

        Add this endpoint URL to the **Info API URL** field in your [authentication settings](https://app.mintlify.com/products/authentication).
      </Step>
    </Steps>

    ### Use groups from OAuth token claims

    If your identity provider includes group membership in the ID token or access token, you can use those claims instead of an Info API URL. This option is available for OAuth configurations that use a client secret.

    When configuring OAuth token claims for your deployment, use values such as:

    ```json theme={null}
    {
      "source": "id_token",
      "groupsClaim": "groups",
      "groupsDelimiter": ","
    }
    ```

    * `source`: Selects `id_token` or `access_token`. If you select `id_token`, include the `openid` scope in your OAuth scopes.
    * `groupsClaim`: Identifies the token claim that contains groups. Defaults to `groups`.
    * `groupsDelimiter`: An optional delimiter from 1 to 4 characters. Mintlify uses it only to split string claim values. If the delimiter can be part of a group name, omit `groupsDelimiter`.

    For example, with `"groups": "general,client"` and `groupsDelimiter` set to `","`, Mintlify uses `general` and `client` as separate groups.

    Mintlify trims whitespace around each group and ignores empty segments. Without `groupsDelimiter`, the complete string is a single group. Array claims are always one group per string item and are not split.

    ### OAuth 2.0 example

    You host your documentation at `docs.foo.com` and you have an existing OAuth server at `auth.foo.com` that supports the Authorization Code Flow.

    **Configure your OAuth server details** in your dashboard:

    * **Authorization URL**: `https://auth.foo.com/authorization`
    * **Client ID**: `ydybo4SD8PR73vzWWd6S0ObH`
    * **Scopes**: `['provider.users.docs']`
    * **Token URL**: `https://auth.foo.com/exchange`
    * **Info API URL**: `https://api.foo.com/docs/user-info`
    * **Logout URL**: `https://auth.foo.com/logout?returnTo=https%3A%2F%2Fdocs.foo.com`

    **Create a user info endpoint** at `api.foo.com/docs/user-info`, which requires an OAuth access token with the `provider.users.docs` scope, and returns:

    ```json theme={null}
    {
      "groups": ["engineering", "admin"],
      "expiresAt": 1893456000,
      "apiPlaygroundInputs": {
        "header": {
          "Authorization": "Bearer user_abc123"
        }
      }
    }
    ```

    <Note>
      Control session length with the `expiresAt` field in your user info response. This is a Unix timestamp (seconds since epoch) indicating when the session should expire. See [User data format](#user-data-format) for more details.
    </Note>

    **Configure your OAuth server to allow redirects** to your callback URL.
  </Tab>

  <Tab title="JWT">
    ### JWT prerequisites

    * An authentication system that can generate and sign JWTs.
    * A backend service that can create redirect URLs.

    ### JWT setup

    <Steps>
      <Step title="Generate a private key.">
        1. In your dashboard, go to [Authentication](https://app.mintlify.com/products/authentication).
        2. In the **Authentication method** section, set site visibility to **Private**.
        3. Click **Custom**.
        4. Click **JWT**.
        5. Enter the URL of your existing login flow.
        6. To offer more than one login flow, click **Add login URL** and enter a display name and URL for each option. You can configure up to 10 login URLs.
        7. Click **Save changes**.
        8. Click **Generate new key**.
        9. Store your key securely where your backend can access it.

        After you generate a private key, your site redeploys. When it finishes deploying, anyone who visits your site must log in to your JWT authentication system to access your content.
      </Step>

      <Step title="Integrate Mintlify authentication into your login flow.">
        Modify your existing login flow to include these steps after user authentication:

        * Create a JWT containing the authenticated user's info in the `User` format. See [User data format](#user-data-format) for more information.
        * Sign the JWT with your secret key, using the EdDSA algorithm.
        * Create a redirect URL back to the `/login/jwt-callback` path of your docs, including the JWT as the hash.
      </Step>
    </Steps>

    When JWT authentication has one login URL, unauthenticated visitors redirect to it automatically. With two or more named login URLs, visitors first see a selection page and then continue to the selected login flow. Mintlify forwards the validated `redirect` parameter so the visitor returns to the documentation page they originally requested.

    <Note>
      Multiple login URLs are available for full and partial JWT authentication. JWT [personalization](/docs/create/personalization) accepts one login URL because it identifies visitors without requiring a login before they can view public content.
    </Note>

    ### JWT example

    You host your documentation at `docs.foo.com` with an existing authentication system at `foo.com`. You want to extend your login flow to grant access to the docs while keeping your docs separate from your dashboard (or you don't have a dashboard).

    Create a login endpoint at `https://foo.com/docs-login` that extends your existing authentication.

    After verifying user credentials:

    * Generate a JWT with user data in Mintlify's format.
    * Sign the JWT and redirect to `https://docs.foo.com/login/jwt-callback#{SIGNED_JWT}`.

    <CodeGroup>
      ```ts TypeScript theme={null}
      import * as jose from 'jose';
      import { Request, Response } from 'express';

      const TWO_WEEKS_IN_MS = 1000 * 60 * 60 * 24 * 7 * 2;
      const DOCS_HOST = 'docs.example.com';

      const signingKey = await jose.importPKCS8(process.env.MINTLIFY_PRIVATE_KEY, 'EdDSA');

      export async function handleRequest(req: Request, res: Response) {
        const user = {
          host: DOCS_HOST, // Must match your docs URL
          expiresAt: Math.floor((Date.now() + TWO_WEEKS_IN_MS) / 1000), // 2 week session expiration
          groups: res.locals.user.groups,
          apiPlaygroundInputs: {
            header: {
              "Authorization": `Bearer ${res.locals.user.apiKey}`,
            },
          },
        };

        const jwt = await new jose.SignJWT(user)
          .setProtectedHeader({ alg: 'EdDSA' })
          .setExpirationTime('10 s') // 10 second JWT expiration
          .sign(signingKey);

        return res.redirect(`https://${DOCS_HOST}/login/jwt-callback#${jwt}`);
      }
      ```

      ```python Python theme={null}
      import jwt # pyjwt
      import os

      from datetime import datetime, timedelta
      from fastapi.responses import RedirectResponse

      private_key = os.getenv(MINTLIFY_JWT_PEM_SECRET_NAME, '')
      DOCS_HOST = 'docs.example.com'

      @router.get('/auth')
      async def return_mintlify_auth_status(current_user):
        jwt_token = jwt.encode(
          payload={
            'host': DOCS_HOST, # Must match your docs URL
            'exp': int((datetime.now() + timedelta(seconds=10)).timestamp()),    # 10 second JWT expiration
            'expiresAt': int((datetime.now() + timedelta(weeks=2)).timestamp()), # 2 week session expiration
            'groups': ['admin'] if current_user.is_admin else [],
            'apiPlaygroundInputs': {
              'header': {
                'Authorization': f'Bearer {current_user.api_key}',
              },
            },
          },
          key=private_key,
          algorithm='EdDSA'
        )

        return RedirectResponse(url=f'https://{DOCS_HOST}/login/jwt-callback#{jwt_token}', status_code=302)
      ```
    </CodeGroup>

    ### Redirect unauthenticated users

    When an unauthenticated user tries to access a protected page, the redirect to your login URL preserves the user's intended destination.

    1. User attempts to visit a protected page: `https://docs.foo.com/quickstart`.
    2. Redirect to your login URL with a redirect query parameter: `https://foo.com/docs-login?redirect=%2Fquickstart`.
    3. After authentication, redirect to `https://docs.foo.com/login/jwt-callback?redirect=%2Fquickstart#{SIGNED_JWT}`.
    4. User lands in their original destination.
  </Tab>
</Tabs>

## Make pages public

When using authentication, all pages require authentication to access by default. You can make specific pages viewable without authentication at the page or group level with the `public` property.

### Individual pages

To make a page public, add `public: true` to the page's frontmatter.

```mdx Public page example theme={null}
---
title: "Public page"
public: true
---
```

### Groups of pages

To make all pages in a group public, add `"public": true` beneath the group's name in the `navigation` object of your `docs.json`.

```json Public group example theme={null}
{
  "navigation": {
    "groups": [
      {
        "group": "Public group",
        "public": true,
        "icon": "play",
        "pages": [
          "quickstart",
          "installation",
          "settings"
        ]
      },
      {
        "group": "Private group",
        "icon": "pause",
        "pages": [
          "private-information",
          "secret-settings"
        ]
      }
    ]
  }
}
```

## Control access with groups

When you use OAuth or JWT authentication, you can restrict specific pages to certain user groups. This is useful when you want different users to see different content based on their role or attributes.

Manage groups through user data passed during authentication. See [User data format](#user-data-format) for details.

```json Example user info theme={null}
{
  "groups": ["admin", "beta-users"],
  "expiresAt": 1893456000
}
```

Specify which groups can access specific pages using the `groups` property in frontmatter.

```mdx Example page restricted to the admin group highlight={3} theme={null}
---
title: "Admin dashboard"
groups: ["admin"]
---
```

Users must belong to at least one of the listed groups to access the page. If a user tries to access a page without the required group, they'll receive a 404 error.

### How groups interact with public pages

* All pages require authentication by default.
* Pages with a `groups` property are only accessible to authenticated users in those groups.
* Pages without a `groups` property are accessible to all authenticated users.
* Pages with `public: true` and no `groups` property are accessible to everyone.

<CodeGroup>
  ```mdx Public page theme={null}
  ---
  title: "Public guide"
  public: true
  ---
  ```

  ```mdx Protected page theme={null}
  ---
  title: "API reference"
  ---
  ```

  ```mdx Protected page with groups theme={null}
  ---
  title: "Advanced configurations"
  groups: ["pro", "enterprise"]
  ---
  ```
</CodeGroup>

## User data format

When using OAuth or JWT authentication or standalone personalization, your system returns user data that controls session length, group membership, and [content personalization](/docs/create/personalization).

<CodeGroup>
  ```tsx Format theme={null}
  type User = {
    host?: string;
    expiresAt?: number;
    groups?: string[];
    content?: Record<string, any>;
    apiPlaygroundInputs?: {
      server?: Record<string, string>;
      header?: Record<string, unknown>;
      query?: Record<string, unknown>;
      cookie?: Record<string, unknown>;
      path?: Record<string, unknown>;
    };
  };
  ```

  ```json Example theme={null}
  {
    "host": "docs.example.com",
    "expiresAt": 1893456000,
    "groups": ["admin", "beta-users"],
    "content": {
      "firstName": "Jane",
      "company": "Acme Corp"
    },
    "apiPlaygroundInputs": {
      "header": {
        "Authorization": "Bearer user_abc123"
      },
      "server": {
        "baseUrl": "https://api.foo.com"
      }
    }
  }
  ```
</CodeGroup>

<ParamField type="string">
  **Required for JWT authentication.** The hostname of your documentation site. The string must exactly match the domain where you deploy your documentation. Mintlify validates that the JWT's host matches the requesting host to prevent token reuse across different sites.
</ParamField>

<ParamField type="number">
  Session expiration time in seconds since epoch. When the current time passes this value, Mintlify expires the stored user data. The visitor must authenticate again or repeat the identification flow to refresh it.

  <Warning>**For JWT:** This differs from the JWT's `exp` claim, which determines when a JWT is considered invalid. Set the JWT `exp` claim to a short duration (10 seconds or less) for security. Use `expiresAt` for the actual session length (hours to weeks).</Warning>
</ParamField>

<ParamField type="string[]">
  List of groups the user belongs to. With authentication, pages with matching `groups` in their frontmatter are accessible to this user. With standalone personalization, groups control page and content visibility but do not restrict access to a page's direct URL.

  **Example**: A user with `groups: ["admin", "engineering"]` matches content tagged with either the `admin` or `engineering` groups.
</ParamField>

<ParamField type="Record<string, any>">
  Custom data accessible in MDX pages via the `user` variable for [personalized content](/docs/create/personalization#dynamic-mdx-content).
</ParamField>

<ParamField type="object">
  Prefills API playground fields with user-specific values. When a user authenticates, these values populate the corresponding input fields in the API playground. Users can override prefilled values, and their overrides persist in local storage.

  Mintlify applies only values that match the current endpoint's security scheme.

  <Expandable title="properties">
    <ParamField type="Record<string, unknown>">
      Header values to prefill, keyed by header name.
    </ParamField>

    <ParamField type="Record<string, unknown>">
      Query parameter values to prefill, keyed by parameter name.
    </ParamField>

    <ParamField type="Record<string, unknown>">
      Cookie values to prefill, keyed by cookie name.
    </ParamField>

    <ParamField type="Record<string, string>">
      Server variable values to prefill, keyed by variable name.
    </ParamField>

    <ParamField type="Record<string, unknown>">
      Path parameter values to prefill, keyed by parameter name.
    </ParamField>
  </Expandable>
</ParamField>

## Feature availability

Some features behave differently or are unavailable when you enable authentication.

| Feature                                                  | Public       | Fully authenticated (all pages protected)                                                       | Partially authenticated (some public pages)                                                     |
| :------------------------------------------------------- | :----------- | :---------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------- |
| [llms.txt and llms-full.txt](/docs/ai/llmstxt)                | Full support | Available behind authentication, so AI tools may not be able to access the files                | Publicly accessible, reflecting public pages only                                               |
| [MCP server](/docs/ai/model-context-protocol)                 | Full support | Requires authentication to connect                                                              | Available without authentication for public pages and with authentication for protected pages   |
| [Markdown export](/docs/ai/markdown-export)                   | Full support | Full support, respects user groups                                                              | Full support, respects user groups                                                              |
| [PDF export](/docs/optimize/pdf-exports)                      | Full support | Full support, respects user groups. Authenticated pages export with images and assets included. | Full support, respects user groups. Authenticated pages export with images and assets included. |
| [Search](/docs/assistant/index)                               | Full support | Full support, respects user groups                                                              | Full support, respects user groups                                                              |
| [Assistant](/docs/assistant/index)                            | Full support | Full support, respects user groups                                                              | Full support, respects user groups                                                              |
| [skill.md](/docs/ai/skillmd)                                  | Full support | Not supported                                                                                   | Not supported                                                                                   |
| [Sitemap](/docs/optimize/seo#sitemaps-and-robotstxt-files)    | Full support | Available behind authentication, but excludes pages in groups                                   | Available behind authentication, but excludes pages in groups                                   |
| [robots.txt](/docs/optimize/seo#sitemaps-and-robotstxt-files) | Full support | Available behind authentication                                                                 | Available behind authentication                                                                 |
| [Live preview](/docs/editor/live-preview)                     | Full support | Supported for Mintlify authentication                                                           | Supported for Mintlify authentication                                                           |


# Custom developer portals
Source: https://www.mintlify.com/docs/deploy/custom-portal

Deploy a fully custom developer portal on top of self-hosted Mintlify, designed and built by Mintlify and delivered through versioned releases.

<Info>
  Custom portals require an [Enterprise plan](https://mintlify.com/pricing?ref=custom-portal) and a [self-hosted deployment](/docs/deploy/self-host). Reach out to your account team to scope one.
</Info>

For some platforms, documentation is one surface of a larger product. The product might be an API marketplace, a partner portal, or a developer experience with sign-in, credentials, and support built in. Mintlify supports those use cases by designing, building, and maintaining a custom presentation layer that replaces your existing portal front end. Your team authors content through the Mintlify editor or a Git-backed workflow.

The portal integrates with your existing APIs, gateway, and downstream systems, which remain owned and operated by your team.

## Features

| Feature                      | What ships                                                                                                                             | Backed by                                    |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
| Custom presentation layer    | A full front-end application in your design system, deployed inside your environment                                                   | Mintlify, alongside the self-hosted platform |
| Product and catalog pages    | Marketplace, product discovery, and documentation surfaces                                                                             | Content maintained on Mintlify               |
| Sign-in                      | Authenticated sessions across the portal                                                                                               | Your identity provider                       |
| Applications and credentials | Application registration and credential management                                                                                     | Your backend APIs                            |
| Subscriptions                | Product and plan subscriptions                                                                                                         | Your backend APIs                            |
| Profiles and notifications   | User profiles and notification centers                                                                                                 | Your backend APIs                            |
| Support                      | Support ticket creation and tracking                                                                                                   | Your backend APIs                            |
| Search                       | Login-aware search scoped to what the user can access                                                                                  | Mintlify platform                            |
| Personalized content         | Entitlement and group-based filtering applied server-side at render time, so users only see the products and pages they have access to | Mintlify platform and your identity provider |
| Ongoing releases             | Versioned releases with upgrade guides, the same operating model as any [self-hosted deployment](/docs/deploy/self-host#updates)            | Mintlify                                     |

## Authoring flow

The custom front end doesn't affect how content gets written. Maintain content with the editor or a local Git-based workflow. Every change flows through your repository's review process with a full audit trail, and publishing triggers builds that update the portal automatically. Content changes do not require a front-end deploy.

## Architecture

The custom presentation layer integrates with the self-hosted Mintlify platform for content, search, and personalization; your API gateway for applications, subscriptions, and support; and your identity provider for authentication.

```mermaid theme={null}
flowchart TD
  U[Users] --> CDN[CDN and WAF]
  CDN --> PORTAL[Custom presentation layer]
  PORTAL --> PLAT[Mintlify platform<br/>content, search, personalization]
  PORTAL --> GW[Your API gateway]
  GW --> BE[Your backend services<br/>applications, subscriptions, support]
  PORTAL --> IDP[Your identity provider]
  W[Writers] --> ED[Editor and Git workflow]
  ED --> PLAT
```

The custom presentation layer and Mintlify platform run inside your network boundary, using your cluster, data stores, and observability stack, with no third-party egress. Your downstream systems of record remain unchanged; the portal accesses them through your existing APIs.

## How the engagement runs

<Steps>
  <Step title="Scope and design">
    Your account team maps the portal surfaces, your design system, and the backend APIs the portal consumes, and agrees on an integration contract with your platform team.
  </Step>

  <Step title="Public surfaces first">
    The engagement typically implements your design system and public content surfaces first, so you can validate the experience against your existing portal before cutover.
  </Step>

  <Step title="Authenticated surfaces">
    Sign-in, credential management, subscriptions, and other logged-in experiences follow, integrated with your identity provider and backend APIs.
  </Step>

  <Step title="Search, personalization, and AI">
    Login-aware search and server-side personalization complete the core experience. Optional AI features remain disabled until your security or AI governance team approves them.
  </Step>
</Steps>

Throughout, your team reviews releases in non-production environments and controls every cutover.

## Next steps

<Columns>
  <Card title="Talk to your account team" icon="messages-square" href="https://www.mintlify.com/enterprise">
    Scope a custom portal engagement and plan your launch.
  </Card>

  <Card title="Self-host" icon="server" href="/deploy/self-host">
    The deployment foundation a custom portal runs on.
  </Card>
</Columns>


# Offline export
Source: https://www.mintlify.com/docs/deploy/export

Export your documentation site as a self-contained zip archive for offline viewing, internal distribution, or air-gapped environment hosting.

<Info>
  Offline exports require an [Enterprise plan](https://mintlify.com/pricing?ref=offline-export).
</Info>

Use `mint export` to package your entire documentation site into a self-contained zip archive. Recipients can unzip and view the docs in their browser without an internet connection, a Mintlify account, or any build tools—they only need [Node.js](https://nodejs.org) installed.

This is useful when you need to distribute documentation to users who can't access your live site, such as for on-premise customers, air-gapped environments, or internal compliance reviews.

## Prerequisites

* The [CLI](/docs/cli/install) installed and up to date
* [Node.js](https://nodejs.org) v20.17.0+ installed

## Export your site

Navigate to your documentation directory containing your `docs.json` file and run:

```bash theme={null}
mint export
```

The CLI builds your site, crawls every page defined in your navigation, and packages the output into a zip file in your current directory.

### Options

| Flag                | Description                                                                                                                                                                                            | Default      |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ |
| `--output <path>`   | Set the output zip file path.                                                                                                                                                                          | `export.zip` |
| `--groups <group>`  | Mock [user groups](/docs/deploy/authentication-setup#control-access-with-groups) for the export. Useful when your docs use group-based access control and you want the archive to include restricted pages. | —            |
| `--disable-openapi` | Skip OpenAPI file generation during the export. Use this if you have many OpenAPI specs and want faster builds.                                                                                        | —            |

For example, to export your site to a custom filename with a specific user group:

```bash theme={null}
mint export --output customer-docs.zip --groups enterprise
```

<Note>
  The export only includes pages listed in your navigation. [Hidden pages](/docs/organize/hidden-pages) are not included in the archive.
</Note>

### Security considerations

The exported archive is a static, unauthenticated bundle. Anyone with the zip file can view every page it contains.

* The `--groups` flag controls which group-restricted pages Mintlify includes in the archive at export time. It does not enforce authentication after export.
* Only share archives with recipients who are allowed to see the content they contain.
* Regenerate and redistribute the archive to publish new changes. Anyone running an older zip continues to see the older content.

## What's in the zip

The exported archive contains everything needed to view your docs offline:

| File                 | Purpose                                                  |
| -------------------- | -------------------------------------------------------- |
| HTML pages           | Pre-rendered version of every page in your navigation    |
| `_next/static/`      | Bundled CSS, JavaScript, and other static assets         |
| `serve.js`           | Zero-dependency Node.js HTTP server that serves the site |
| `Start Docs.command` | macOS launcher—double-click to open the docs             |
| `Start Docs.bat`     | Windows launcher—double-click to open the docs           |

## View the exported docs

Share the zip file with anyone who has Node.js installed. To view the docs:

<Tabs>
  <Tab title="Manual">
    1. Unzip the archive.
    2. Open a terminal in the unzipped directory.
    3. Run `node serve.js`.
    4. Open `http://localhost:3000` in your browser.
  </Tab>

  <Tab title="macOS">
    1. Unzip the archive.
    2. Double-click **Start Docs.command**.
    3. The docs open in your default browser at `http://localhost:3000`.

    <Note>
      macOS may block the file because it was downloaded from the internet. If you see a security warning, go to **System Settings > Privacy & Security** and click **Open Anyway**. See [Apple's guide to overriding security settings](https://support.apple.com/guide/mac-help/mh40617/mac) for details.
    </Note>
  </Tab>

  <Tab title="Windows">
    1. Unzip the archive.
    2. Double-click **Start Docs.bat**.
    3. The docs open in your default browser at `http://localhost:3000`.

    <Note>
      Windows may show a "Windows protected your PC" warning because the file was downloaded from the internet. Click **More info**, then click **Run anyway**.
    </Note>
  </Tab>
</Tabs>


# Self-hosted GitLab OAuth
Source: https://www.mintlify.com/docs/deploy/gitlab-self-hosted

Connect a self-hosted GitLab instance to Mintlify via OAuth so automations can clone repositories, push commits, and open merge requests on your behalf.

Mintlify supports OAuth-based authorization for self-hosted GitLab instances, in addition to gitlab.com. OAuth lets the Mintlify agent act as a GitLab user during automation runs: cloning repositories, pushing commits, opening merge requests, and registering project webhooks.

You must configure OAuth authorization for self-hosted GitLab instances to support [automations](/docs/automations).

Unlike gitlab.com, where Mintlify ships a single OAuth application that every customer authorizes against, each self-hosted instance must register its own OAuth application. Create the application on your GitLab instance, share its credentials with Mintlify, and then go through an OAuth authorization to connect a user.

<Note>
  This guide is only for the **OAuth** integration that powers automations. You must configure the deployment-side connection (used for content sync and previews) separately with a deploy token. See the [GitLab guide](/docs/deploy/gitlab) for instructions. The OAuth integration depends on the deployment-side connection.
</Note>

## Prerequisites

* Admin access to your self-hosted GitLab instance.
* Your GitLab instance must be reachable from `https://app.mintlify.com`. Instances behind a VPN or behind a firewall that blocks public ingress do not work.
* A Mintlify organization on the **Pro or Enterprise plan**.
* A Mintlify organization that has the self-hosted GitLab feature enabled. Contact support if you don't see the **Self-hosted GitLab** section in your [Git settings](https://app.mintlify.com/settings/deployment/git-settings) dashboard page.

## Set up the connection

<Steps>
  <Step title="Register an OAuth application on your GitLab instance">
    In your self-hosted GitLab, sign in as an admin and navigate to **Admin Area** > **Applications** > **Add new application**.

    Configure the application with these values:

    * **Name**: `Mintlify`
    * **Redirect URI**: `https://app.mintlify.com/api/gitlab-oauth/callback`
    * **Trusted**: leave **unchecked**. Trusting the application skips the consent screen for every user; leaving it unchecked surfaces a normal authorization prompt the first time each user connects.
    * **Confidential**: **checked**. Mintlify is a server-side client and keeps the secret confidential.
    * **Scopes**: select `api`, `read_repository`, and `write_repository`. The agent uses these to read project metadata, clone repositories, and push commits.

    Click **Save application**.

    <Tip>
      Editing an OAuth application on GitLab can rotate the client secret silently. If you make changes later, click **Renew secret** and update the new value in Mintlify.
    </Tip>
  </Step>

  <Step title="Copy the application credentials">
    After saving, GitLab displays the application's **Application ID** and **Secret**. Keep this page open—the secret is only shown once.
  </Step>

  <Step title="Register the instance in Mintlify">
    In your Mintlify dashboard, open **Settings** > **Git settings** and find the **Self-hosted GitLab** section under **GitLab OAuth**.

    Click **Connect Self-Hosted GitLab** and enter:

    * **GitLab instance URL**: the public URL of your GitLab instance, for example `https://gitlab.your-company.com`. Mintlify reaches your instance through this URL when exchanging tokens and calling the GitLab API.
    * **OAuth application client ID**: the **Application ID** from the previous step.
    * **OAuth application client secret**: the **Secret** from the previous step.

    Click **Save instance**. Mintlify encrypts the secret at rest and never returns it to the browser after saving.
  </Step>

  <Step title="Authorize">
    Click **Authorize self-hosted GitLab**. GitLab redirects you to your instance, prompts you to sign in if needed, and shows a consent screen listing the requested scopes.

    After you click **Authorize** on GitLab, GitLab redirects you back to Mintlify. Mintlify displays the new connection in the installations list with your instance hostname.
  </Step>

  <Step title="Choose projects">
    Expand the connection in the dashboard. Mintlify lists every group your authorizing user has Maintainer or higher access to, plus a **Personal projects** entry for projects in the user's personal namespace.

    Select the box next to each project that should participate in automations. Mintlify registers a webhook on the project, generates a secret token, and stores it encrypted. From then on, Mintlify receives push and merge-request events from your instance for that project.

    <Note>
      The connecting user must have **Maintainer** role on a project for Mintlify to mint short-lived project access tokens during automation runs. Without Maintainer, the agent can read but cannot push commits or open merge requests.
    </Note>
  </Step>
</Steps>

## Rotate credentials

If you need to change the registered application's client secret, remove the saved instance in Mintlify and add it again with the new values after renewing the secret on GitLab. You must revoke active OAuth connections first. Otherwise, Mintlify blocks the removal.

<Steps>
  <Step title="Revoke each connection">
    Click **Revoke** on every installation listed under the self-hosted instance. This removes the webhook on every connected project and revokes the OAuth token on GitLab.
  </Step>

  <Step title="Remove the instance">
    In the **Self-hosted GitLab** card, click **Remove instance**.
  </Step>

  <Step title="Re-add with new credentials">
    Follow the **Set up the connection** steps described earlier with the new client secret.
  </Step>
</Steps>

## Troubleshooting

### Authorization fails with `invalid_client`

GitLab rejected the token-exchange step because the client secret Mintlify sent doesn't match what's registered on the application. The most common cause is that a secret rotated on GitLab—by an explicit **Renew secret**, or silently when someone edited the application—and the value in Mintlify is stale.

Fix: rotate credentials following the [Rotate credentials](#rotate-credentials) steps with the current secret.

### Webhook registration failed: `Invalid url given`

GitLab refused to register the webhook because its outbound-request allowlist rejected the URL Mintlify sent (`https://app.mintlify.com/gitlab-oauth-webhook`). Self-hosted instances reject "local" URLs unless the admin explicitly allows them.

Fix: in your GitLab admin area, go to **Settings** > **Network** > **Outbound requests** and enable **Allow requests to the local network from webhooks and integrations**. If your network policy blocks `app.mintlify.com`, contact your network admin to allow outbound HTTPS to that host.

### No consent screen on authorize

If you don't see GitLab's consent dialog when authorizing, either:

* The application carries the **Trusted** flag on GitLab. Trusted applications skip consent for all users. Clear the **Trusted** checkbox in the application settings if you want users to see and confirm scopes.
* Your GitLab user has previously authorized the application with the same scopes. GitLab remembers prior grants and skips consent on subsequent authorizes. Revoke the application authorization in **User settings** > **Applications** > **Authorized applications** to see consent again.


# Adobe Analytics
Source: https://www.mintlify.com/docs/integrations/analytics/adobe

Integrate Adobe Analytics with your Mintlify documentation site using Adobe Experience Platform Launch tags for detailed usage tracking.

Add the following to your `docs.json` file to send analytics to Adobe Analytics.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "adobe": {
          "launchUrl": "required"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "adobe": {
          "launchUrl": "https://assets.adobedtm.com/launch-EN93497c30fdf0424eb678d5f4ffac66dc.min.js"
      }
  }
  ```
</CodeGroup>

## Get your Launch URL

1. Sign in to [Adobe Experience Platform Data Collection](https://experience.adobe.com/#/data-collection/).
2. Open your Launch property and go to the **Environments** tab.
3. Copy the script URL from your production environment.


# Amplitude
Source: https://www.mintlify.com/docs/integrations/analytics/amplitude

Integrate Amplitude analytics with your Mintlify documentation site to track user behavior, page views, and content engagement metrics.

Add the following to your `docs.json` file to send analytics to Amplitude.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "amplitude": {
          "apiKey": "required"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "amplitude": {
          "apiKey": "76bb138bf3fbf58186XXX00000"
      }
  }
  ```
</CodeGroup>


# Clarity
Source: https://www.mintlify.com/docs/integrations/analytics/clarity

Integrate Microsoft Clarity with your Mintlify documentation site to capture session recordings, heatmaps, and user interaction analytics.

Add the following to your `docs.json` file to send analytics to Microsoft Clarity.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "clarity": {
          "projectId": "required"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "clarity": {
          "projectId": "abc123xyz"
      }
  }
  ```
</CodeGroup>

## Get your project ID

1. Create a [Clarity account](https://clarity.microsoft.com/projects).
2. Click **Get tracking code.**
3. Copy your project ID from the tracking code.


# Clearbit
Source: https://www.mintlify.com/docs/integrations/analytics/clearbit

Integrate Clearbit with your Mintlify documentation to enrich visitor data, identify visiting companies, and track enterprise engagement.

Add the following to your `docs.json` file to send analytics to Clearbit.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "clearbit": {
          "publicApiKey": "required"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "clearbit": {
          "publicApiKey": "pk_1a1882"
      }
  }
  ```
</CodeGroup>


# Fathom
Source: https://www.mintlify.com/docs/integrations/analytics/fathom

Integrate Fathom Analytics with your Mintlify documentation for privacy-focused, GDPR-compliant visitor tracking with a simple site ID setup.

Add the following to your `docs.json` file to send analytics to Fathom.

You can get the `siteId` from your script settings.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "fathom": {
          "siteId": "required"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "fathom": {
          "siteId": "YSVMSDAY"
      }
  }
  ```
</CodeGroup>


# Google Analytics 4
Source: https://www.mintlify.com/docs/integrations/analytics/google-analytics

Integrate Google Analytics 4 with your Mintlify documentation to track visitor behavior, page views, and content engagement with your GA4 ID.

You need to generate a new <Tooltip>GA4</Tooltip> property to use with Mintlify. The data collected goes into the same project as your other Google Analytics data.

If you are using the old version of Google Analytics, Universal Analytics, you can still generate a <Tooltip>GA4</Tooltip> property. <Tooltip>GA4</Tooltip> data is slightly different from UA data but still gets collected in the same project.

## Connect GA4 to Mintlify

### Create a web stream

You need to create a web stream to get the Measurement ID to put into Mintlify.

Click the cog at the bottom left of the Google Analytics screen. Then click Data Streams.

<Frame>
  <img alt="Screenshot of the Data Streams page in the Google Analytics dashboard." />
</Frame>

Create a Web Stream and put the URL of your Mintlify docs site as the stream URL.

Your Measurement ID looks like `G-XXXXXXX` and appears under Stream Details immediately after you create the Web Stream.

### Put measurement ID in docs.json

Add your Measurement ID to your `docs.json` file like so:

```json docs.json theme={null}
"integrations": {
    "ga4": {
        "measurementId": "G-XXXXXXX"
    }
}
```

### Wait

Google Analytics takes two to three days to show your data.

You can use the [Google Analytics Debugger](https://chrome.google.com/webstore/detail/google-analytics-debugger/jnkmfdileelhofjcijamephohjechhna?hl=en) to check your analytics configuration. The extension logs to your browser's console every time GA4 makes a request.

<Note>
  Preview links have analytics turned off.
</Note>


# Google Tag Manager
Source: https://www.mintlify.com/docs/integrations/analytics/google-tag-manager

Integrate Google Tag Manager with your Mintlify documentation to manage analytics tags, conversion tracking, and marketing events centrally.

Add your tag ID to `docs.json` file and we'll inject the Google Tag Manager script to all your pages.

You are responsible for setting up cookie consent banners with Google Tag Manager if you need them.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "gtm": {
          "tagId": "required"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "gtm": {
          "tagId": "GTM-MGBL4PW"
      }
  }
  ```
</CodeGroup>


# Heap
Source: https://www.mintlify.com/docs/integrations/analytics/heap

Integrate Heap analytics with your Mintlify documentation site to automatically capture user interactions and events for behavioral analysis.

Add the following to your `docs.json` file to send analytics to Heap.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "heap": {
          "appId": "required"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "heap": {
          "appId": "1234567890"
      }
  }
  ```
</CodeGroup>

Replace `1234567890` with your Heap app ID. You can find this in your [Heap account settings](https://heapanalytics.com/app/settings).


# Hightouch
Source: https://www.mintlify.com/docs/integrations/analytics/hightouch

Integrate Hightouch with your Mintlify documentation to sync analytics data for audience activation, segmentation, and downstream tool routing.

Add the following to your `docs.json` file to send analytics to Hightouch.

<Info>
  Do not include `https://` for the `apiHost`.
</Info>

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "hightouch": {
          "writeKey": "required",
          "apiHost": "optional"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "hightouch": {
          "writeKey": "9132c81do371p76sr11da0075469b54f77649c9a067dp0303p56q0q64n072336",
          "apiHost": "us-east-1.hightouch-events.com" # optional, defaults to `us-east-1.hightouch-events.com`
      }
  }
  ```
</CodeGroup>


# Hotjar
Source: https://www.mintlify.com/docs/integrations/analytics/hotjar

Integrate Hotjar with your Mintlify documentation site to capture session recordings, heatmaps, and user feedback for experience insights.

Add the following to your `docs.json` file to send analytics to Hotjar.

```json Analytics options in docs.json theme={null}
"integrations": {
    "hotjar": {
        "hjid": "required",
        "hjsv": "required"
    }
}
```


# LogRocket
Source: https://www.mintlify.com/docs/integrations/analytics/logrocket

Integrate LogRocket with your Mintlify documentation to replay user sessions, monitor frontend errors, and debug interaction issues in detail.

Add the following to your `docs.json` file to send analytics to LogRocket.

```json Analytics options in docs.json theme={null}
"integrations": {
    "logrocket": {
        "apiKey": "required"
    }
}
```


# Mixpanel
Source: https://www.mintlify.com/docs/integrations/analytics/mixpanel

Integrate Mixpanel with your Mintlify documentation site to track product analytics, user behavior funnels, and content engagement events.

Add the following to your `docs.json` file to send analytics to Mixpanel.

```json Analytics options in docs.json theme={null}
"integrations": {
    "mixpanel": {
        "projectToken": "YOUR_MIXPANEL_PROJECT_TOKEN"
    }
}
```

Replace `YOUR_MIXPANEL_PROJECT_TOKEN` with your Mixpanel project token. You can find this in your [Mixpanel project settings](https://mixpanel.com/settings/project).

## Data residency

If your Mixpanel project uses EU or India data residency, set `region` so Mintlify sends events directly to the matching Mixpanel ingestion host. Omit `region` to use the default US host.

```json Mixpanel with EU data residency theme={null}
"integrations": {
    "mixpanel": {
        "projectToken": "YOUR_MIXPANEL_PROJECT_TOKEN",
        "region": "eu"
    }
}
```

Supported values:

* `us` (default): `api.mixpanel.com`
* `eu`: `api-eu.mixpanel.com`
* `in`: `api-in.mixpanel.com`

Set this to match your Mixpanel project's data residency region. If the host doesn't match your project's region, Mixpanel drops the events.

## Tracked events

Mintlify automatically tracks the following user interactions:

* Page views
* Search queries
* Feedback submissions
* Context menu interactions
* Navigation clicks

If you're not seeing events in Mixpanel, ensure your project token is correct and that no content security policies are blocking the Mixpanel script.


# Analytics integrations
Source: https://www.mintlify.com/docs/integrations/analytics/overview

Connect your Mintlify documentation to analytics platforms like Google Analytics, Mixpanel, PostHog, and more to track visitor engagement.

Track how users interact with your documentation by connecting to third-party analytics platforms. Mintlify sends engagement events to your configured analytics providers.

## How analytics integrations work

When you add analytics integrations to your documentation site, Mintlify tracks user interactions like page views, search queries, API playground requests, and feedback submissions. Mintlify then sends these events to your analytics providers. You can connect any number of supported analytics providers by adding your API keys to the `docs.json` file. Analytics events flow to your providers as soon as you add them to your configuration with no further configuration required.

## Supported platforms

<CardGroup>
  <Card
    title="Adobe Analytics"
    href="/integrations/analytics/adobe"
    icon={
  <svg
    className="h-6 w-6"
    width="16"
    height="16"
    viewBox="0 0 133 118"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <rect width="133" height="118" fill="#fff"/>
    <path fill="#FA0F00" d="m0,0v118L49,0m35,0 49,118V0M67,44l32,74H78L68,94H45" />
  </svg>
}
  />

  <Card
    title="Amplitude"
    href="/integrations/analytics/amplitude"
    icon={<svg className="h-6 w-6" width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.5988 8.04494C15.4989 7.91714 15.3924 7.84668 15.2646 7.84668C15.1728 7.85323 15.0876 7.88273 15.009 7.93188C14.0635 8.67087 12.7773 11.8055 11.7188 15.9412L12.6576 15.9477C14.5059 15.969 16.4165 15.9903 18.3008 16.0182C17.8027 14.1273 17.3341 12.5068 16.9015 11.1926C16.2674 9.28205 15.8414 8.42181 15.5988 8.04494Z" fill="#1E61F0"/>
<path d="M17.6964 0.078125C7.92405 0.078125 0 8.00217 0 17.7745C0 27.5468 7.92405 35.4709 17.6964 35.4709C27.4687 35.4709 35.3928 27.5468 35.3928 17.7745C35.3928 8.00217 27.4687 0.078125 17.6964 0.078125ZM30.7589 17.5615C30.7098 17.7598 30.5885 17.9531 30.4181 18.094C30.3968 18.1088 30.3755 18.1219 30.3542 18.1366L30.3329 18.1514L30.2903 18.1792L30.2543 18.2005C30.1199 18.271 29.9692 18.307 29.8135 18.307H21.4274C21.4913 18.584 21.5699 18.9035 21.6469 19.2459C22.109 21.2286 23.3248 26.5014 24.6242 26.5014H24.652H24.6668H24.6946C25.704 26.5014 26.2234 25.0382 27.3606 21.8316L27.3753 21.7955C27.5605 21.2843 27.7669 20.701 27.9865 20.0832L28.0439 19.9276C28.1291 19.7211 28.3634 19.6146 28.5698 19.6998C28.7189 19.7572 28.8254 19.9063 28.8254 20.0701C28.8254 20.1127 28.8189 20.1488 28.8107 20.1832L28.7615 20.3388C28.6403 20.7223 28.5207 21.2417 28.3699 21.8463C27.6948 24.6466 26.6707 28.8757 24.0556 28.8757H24.0343C22.3433 28.861 21.334 26.1606 20.8998 25.0022C20.0903 22.8409 19.4791 20.5453 18.8893 18.3152H11.1864L9.58718 23.439L9.56588 23.4177C9.32501 23.7946 8.82034 23.9076 8.44347 23.6668C8.20916 23.5176 8.0666 23.262 8.0666 22.9851V22.9573L8.16655 22.3739C8.38612 21.0598 8.65648 19.6867 8.9547 18.3087H5.68578L5.67104 18.2939C5.00251 18.194 4.54043 17.5697 4.64039 16.9012C4.71904 16.3817 5.1172 15.9705 5.62843 15.8771C5.75624 15.8623 5.88405 15.8558 6.01186 15.8623H6.16752C7.19817 15.8771 8.29272 15.8984 9.50034 15.9115C11.1995 9.00333 13.1674 5.49191 15.3565 5.48535C17.7013 5.48535 19.4431 10.8221 20.8359 16.0458L20.8424 16.0671C23.7 16.1245 26.756 16.2097 29.7185 16.4227L29.8463 16.4374C29.8954 16.4374 29.938 16.444 29.9888 16.4522H30.0036L30.0183 16.4588H30.0249C30.5312 16.5587 30.8654 17.0568 30.7589 17.5615Z" fill="#1E61F0"/>
</svg>}
  />

  <Card
    title="Clearbit"
    href="/integrations/analytics/clearbit"
    icon={
  <svg width="161" height="162" className="h-6 w-6" viewBox="0 0 161 162" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M117.9 161.5H43H39.9C27.3 161.3 22.2 159.8 17.2 157C11.7 154.1 7.5 149.8 4.5 144.3L3.9 143.1C1.5 138.2 0.1 132.7 0 119.9V43.1C0 28.1 1.6 22.7 4.5 17.2C7.4 11.7 11.7 7.4 17.2 4.5L18.4 3.90001C23.3 1.50001 28.7 0.1 41.5 0H117.9C132.8 0 138.2 1.6 143.7 4.5C149.2 7.4 153.4 11.7 156.4 17.2L157 18.4C159.4 23.3 160.8 28.8 160.9 41.6V121.5C160.7 134.2 159.2 139.2 156.5 144.3C153.6 149.8 149.3 154.1 143.8 157L142.6 157.6C137.4 160.2 131.8 161.5 117.9 161.5Z" fill="#C4D3E0" fill-opacity="0.2"/>
<path d="M160.8 80.8V118.4C160.8 133.4 159.2 138.8 156.3 144.3C153.4 149.8 149.1 154.1 143.6 157C138.1 159.9 132.7 161.5 117.8 161.5H80.4V80.8H160.8Z" fill="#DEF2FE"/>
<path d="M80.4 0.100006H117.8C132.7 0.100006 138.1 1.70001 143.6 4.60001C149.1 7.50001 153.3 11.8 156.3 17.3C159.2 22.8 160.8 28.2 160.8 43.2V80.8H80.4V0.100006Z" fill="#57BCFD"/>
<path d="M43 0.100006H80.4V161.5H43C28.1 161.5 22.7 159.9 17.2 157C11.7 154.1 7.5 149.8 4.5 144.3C1.6 138.8 0 133.4 0 118.4V43.2C0 28.2 1.6 22.8 4.5 17.3C7.4 11.8 11.7 7.50001 17.2 4.60001C22.7 1.70001 28.1 0.100006 43 0.100006Z" fill="#1CA7FD"/>
</svg>
}
  />

  <Card
    title="Fathom"
    href="/integrations/analytics/fathom"
    icon={
<svg
className="h-6 w-6"
width="256"
height="256"
viewBox="0 0 256 256"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M50.4139 36.0859H40.3871C31.7927 36.105 22.7513 37.7857 15.3869 42.8984C11.5551 45.5505 8.45289 49.125 6.36656 53.292C4.0486 58.1293 2.89794 63.4429 3.0071 68.8058V212.667C3.0071 213.984 3.53027 215.247 4.46151 216.178C5.39275 217.109 6.65579 217.632 7.97276 217.632H27.5661C28.8831 217.632 30.1461 217.109 31.0774 216.178C32.0086 215.247 32.5318 213.984 32.5318 212.667V111.31H50.4063C51.0584 111.31 51.7041 111.182 52.3065 110.932C52.909 110.682 53.4564 110.317 53.9175 109.856C54.3786 109.394 54.7444 108.847 54.9939 108.245C55.2435 107.642 55.3719 106.996 55.3719 106.344V89.5566C55.3719 88.2396 54.8488 86.9766 53.9175 86.0453C52.9863 85.1141 51.7232 84.5909 50.4063 84.5909H32.5394V71.8349C32.4457 69.708 32.7382 67.5817 33.4027 65.5591C33.6012 64.974 33.9349 64.444 34.3767 64.0121C35.0566 63.4655 35.8835 63.1331 36.7526 63.0571C38.4628 62.845 40.1867 62.7639 41.9092 62.8146H50.4196C51.7366 62.8146 52.9996 62.2914 53.9309 61.3602C54.8621 60.4289 55.3853 59.1659 55.3853 57.8489V41.0592C55.3853 39.7423 54.8621 38.4792 53.9309 37.548C52.9996 36.6167 51.7366 36.0936 50.4196 36.0936"
fill="currentColor"
/>
<path
d="M168.815 128.261C168.982 122.018 167.781 115.814 165.296 110.084C162.812 104.354 159.105 99.2374 154.434 95.0918C145.198 87.0379 132.23 82.712 116.98 82.7178C101.466 82.7178 88.0641 87.1582 78.2799 94.9409C73.4171 98.7218 69.4331 103.513 66.6032 108.985C63.7733 114.456 62.165 120.476 61.8894 126.63C61.8575 127.301 61.9625 127.972 62.1977 128.602C62.433 129.232 62.7937 129.807 63.258 130.294C63.7223 130.78 64.2806 131.167 64.8989 131.431C65.5172 131.695 66.1827 131.831 66.855 131.83H87.6019C88.8467 131.832 90.0466 131.366 90.9642 130.525C91.8817 129.684 92.4499 128.529 92.5561 127.288C92.7767 124.972 93.4898 122.729 94.6475 120.71C95.8053 118.691 97.3811 116.943 99.2693 115.583C104.448 111.964 110.667 110.136 116.98 110.378C124.718 110.378 130.282 112.479 133.83 115.564C135.624 117.142 137.044 119.1 137.987 121.296C138.93 123.491 139.372 125.869 139.281 128.257V128.958C139.296 129.537 139.232 130.115 139.09 130.677L138.899 131.106C138.545 131.474 138.1 131.743 137.61 131.885C134.826 132.791 131.95 133.381 129.035 133.644C124.833 134.202 119.373 134.779 112.57 135.69H112.581C100.098 137.369 87.3498 139.41 77.0193 145.239C71.7347 148.136 67.3067 152.375 64.1812 157.527C60.8001 163.529 59.1166 170.338 59.311 177.224C59.2225 183.496 60.4876 189.713 63.02 195.452C66.6423 203.293 72.8442 209.656 80.5908 213.477C88.8782 217.474 97.9927 219.456 107.191 219.262C119.128 219.274 128.181 216.497 134.846 212.251C136.408 211.261 137.892 210.155 139.287 208.941V212.66C139.287 213.977 139.81 215.24 140.741 216.171C141.672 217.102 142.936 217.625 144.253 217.625H153.79L168.812 161.735L168.815 128.261ZM139.283 166.03C139.404 169.288 138.883 172.539 137.748 175.596C136.613 178.652 134.887 181.456 132.669 183.845C128.204 188.349 121.149 191.569 109.984 191.601C102.793 191.613 97.4741 190.033 94.2941 187.753C92.8266 186.744 91.6254 185.395 90.7933 183.821C89.9498 182.118 89.5217 180.241 89.5443 178.341V178.293V178.213C89.4842 176.061 90.0395 173.937 91.1447 172.09C93.1437 169.263 95.9722 167.127 99.2388 165.979C103.667 164.269 108.293 163.122 113.007 162.564C120.085 161.569 127.367 160.514 133.404 159.317C135.561 158.895 137.482 158.442 139.289 157.969L139.283 166.03Z"
fill="currentColor"
/>
<path
d="M251.975 21.9481C251.51 21.3425 250.913 20.8518 250.228 20.514C249.544 20.1763 248.791 20.0004 248.027 20H223.077C221.982 19.9988 220.917 20.3596 220.048 21.0263C219.18 21.6929 218.556 22.628 218.273 23.6861L168.813 207.74L166.375 216.833L163.015 229.322C162.816 230.059 162.789 230.832 162.937 231.581C163.085 232.33 163.404 233.035 163.868 233.641C164.333 234.247 164.931 234.737 165.616 235.074C166.301 235.411 167.055 235.586 167.818 235.584H192.769C193.863 235.586 194.927 235.226 195.796 234.56C196.665 233.895 197.289 232.961 197.572 231.904L252.831 26.2644C253.027 25.5271 253.053 24.7545 252.904 24.0059C252.756 23.2573 252.438 22.5527 251.975 21.9462"
fill="#7166F6"
/>
</svg>
}
  />

  <Card
    title="Google Analytics 4"
    href="/integrations/analytics/google-analytics"
    icon={
  <svg
    className="h-6 w-6"
    xmlns="http://www.w3.org/2000/svg"
    width="64"
    height="64"
    viewBox="0 0 64 64"
  >
    <g transform="matrix(.363638 0 0 .363636 -3.272763 -2.909091)">
      <path
        d="M130 29v132c0 14.77 10.2 23 21 23 10 0 21-7 21-23V30c0-13.54-10-22-21-22s-21 9.33-21 21z"
        fill="#f9ab00"
      />
      <g fill="#e37400">
        <path d="M75 96v65c0 14.77 10.2 23 21 23 10 0 21-7 21-23V97c0-13.54-10-22-21-22s-21 9.33-21 21z" />
        <circle cx="41" cy="163" r="21" />
      </g>
    </g>
  </svg>
}
  />

  <Card
    title="Google Tag Manager"
    href="/integrations/analytics/google-tag-manager"
    icon={
  <svg
    className="h-6 w-6"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    x="0px"
    y="0px"
    width="192px"
    height="192px"
    viewBox="0 0 192 192"
    enableBackground="new 0 0 192 192"
  >
    <rect fill="none" width="192" height="192" />
    <g>
      <polygon
        fill="#8AB4F8"
        points="111.31,176.79 80.76,147 146.37,80 178,111 	"
      />
      <path
        fill="#4285F4"
        d="M111.44,45.08L81,14L14.44,79.93c-8.58,8.58-8.58,22.49,0,31.08L80,177l31-29L61.05,95.47L111.44,45.08z"
      />
      <path
        fill="#8AB4F8"
        d="M177.56,80.44l-66-66c-8.59-8.59-22.52-8.59-31.11,0c-8.59,8.59-8.59,22.52,0,31.11l66,66
c8.59,8.59,22.52,8.59,31.11,0C186.15,102.96,186.15,89.03,177.56,80.44z"
      />
      <circle fill="#246FDB" cx="95.5" cy="162.5" r="21.5" />
    </g>
  </svg>
}
  />

  <Card
    title="Heap"
    href="/integrations/analytics/heap"
    icon={
  <svg
    className="h-6 w-6"
    width="32"
    height="32"
    viewBox="0 0 256 256"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      d="M78.7 55.2H49V200.2H78.7V55.2ZM142.9 0H113.3V110.5H142.9V0Z"
      fill="black"
    />
    <path
      d="M142.9 144.9H113.3V255.4H142.9V144.9ZM207.1 55.2002H177.5V200.2H207.1V55.2002Z"
      fill="#31D891"
    />
  </svg>
}
  />

  <Card
    title="Hightouch"
    href="/integrations/analytics/hightouch"
    icon={
  <svg
    className="h-6 w-6"
    xmlns="http://www.w3.org/2000/svg"
    width="97"
    height="97"
    viewBox="0 0 97 97"
    fill="none"
  >
    <path
      d="M33 3.75C33 2.7835 33.7835 2 34.75 2H93.25C94.2165 2 95 2.7835 95 3.75V62.25C95 63.2165 94.2165 64 93.25 64H33V3.75Z"
      fill="currentColor"
    />
    <path
      d="M33 93.25C33 94.2165 32.2165 95 31.25 95L3.75 95C2.7835 95 2 94.2165 2 93.25L2 65.75C2 64.7835 2.7835 64 3.75 64L33 64L33 93.25Z"
      fill="currentColor"
    />
  </svg>
}
  />

  <Card
    title="Hotjar"
    href="/integrations/analytics/hotjar"
    icon={
  <svg
    className="h-6 w-6"
    width="51"
    height="57"
    viewBox="0 0 51 57"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      d="M20.9743 23.3016C27.5805 19.6488 36.6281 14.645 36.6281 0.0820312H25.6725C25.6725 8.23006 21.687 10.4338 15.6538 13.7698C9.0477 17.4239 0 22.4256 0 36.99H10.9556C10.9556 28.8414 14.9412 26.6376 20.9743 23.3016Z"
      fill="#FF3C00"
    />
    <path
      d="M39.9362 19.9551C39.9362 28.1035 35.9506 30.3073 29.9175 33.6428C23.3131 37.2956 14.2637 42.2987 14.2637 56.8628H25.2189C25.2189 48.7143 29.2044 46.5106 35.2375 43.1746C41.8436 39.5218 50.8909 34.5193 50.8909 19.9551H39.9362Z"
      fill="#FF3C00"
    />
  </svg>
}
  />

  <Card
    title="LogRocket"
    href="/integrations/analytics/logrocket"
    icon={
  <svg
    className="h-7 w-5"
    width="102"
    height="159"
    viewBox="0 0 102 159"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      d="M33.7001 18.4998C38.1001 11.4998 44.0001 5.3998 50.9001 0.799805C57.7001 5.2998 63.5001 11.2998 67.9001 18.1998C79.4001 34.1998 85.2001 53.4998 84.4001 73.1998C88.0001 76.0998 91.7001 78.8998 95.2001 81.7998C100.2 86.2998 102.6 93.0998 101.4 99.6998C99.7001 107.9 98.1001 116.1 96.3001 124.3C95.1001 127.9 91.2001 129.8 87.7001 128.6C87.1001 128.4 86.5001 128.1 86.0001 127.7C80.2001 123.1 74.6001 118.3 68.8001 113.6C58.9001 123 43.5001 123.1 33.5001 113.8C29.4001 116.8 25.5001 120.5 21.5001 123.8C19.7001 125.5 17.8001 127.1 15.6001 128.3C12.1001 129.7 8.10011 127.9 6.80011 124.4C6.70011 124.2 6.7001 124 6.6001 123.9C4.8001 115.9 2.8001 107.9 1.0001 99.8998C-0.399898 92.8998 2.1001 85.7998 7.5001 81.1998C10.6001 78.6998 13.8001 76.1998 17.0001 73.6998C17.9001 73.1998 17.4001 72.1998 17.5001 71.4998C17.1001 52.5998 22.8001 33.9998 33.7001 18.4998ZM39.4001 43.2998C35.2001 48.6998 35.7001 56.3998 40.6001 61.1998C46.2001 66.5998 55.1001 66.7998 60.9001 61.5998C65.0001 57.8998 66.4001 51.9998 64.5001 46.7998C62.5001 41.7998 57.9001 38.2998 52.5001 37.8998C47.4001 37.2998 42.5001 39.3998 39.4001 43.2998Z"
      fill="#764ABC"
    />
    <path
      d="M31.7002 130.6C31.8002 128.7 33.5002 127.3 35.3002 127.5C35.8002 127.5 36.3002 127.7 36.7002 127.9C45.6002 132.2 56.0002 132.2 65.0002 127.9C66.7002 127 68.7002 127.7 69.6002 129.3C69.8002 129.6 69.9002 130 70.0002 130.4C70.0002 135.4 70.0002 140.4 70.0002 145.4C69.8002 147.2 68.1002 148.6 66.3002 148.4C65.7002 148.3 65.2002 148.1 64.7002 147.8C63.2002 146.5 61.9002 145.1 60.4002 143.8C58.1002 148.1 56.0002 152.4 53.7002 156.7C52.7002 158.3 50.6002 158.7 49.0002 157.7C48.6002 157.5 48.3002 157.1 48.1002 156.8C45.8002 152.5 43.7002 148.2 41.3002 143.9C39.9002 145.3 38.5002 146.7 37.0002 147.9C35.5002 149 33.3002 148.6 32.3002 147C32.0002 146.5 31.8002 146 31.7002 145.4C31.7002 140.5 31.7002 135.5 31.7002 130.6Z"
      fill="#764ABC"
    />
    <path
      d="M50.7998 58.5005C54.5998 58.6005 57.6998 55.6005 57.7998 51.8005C57.6998 48.0005 54.5998 45.0005 50.7998 45.0005C46.9998 44.9005 43.8998 47.9005 43.7998 51.7005C43.7998 55.5005 46.9998 58.6005 50.7998 58.5005Z"
      fill="#764ABC"
    />
  </svg>
}
  />

  <Card
    title="Microsoft Clarity"
    href="/integrations/analytics/clarity"
    icon={
  <svg className="h-6 w-6" width="23" height="23" viewBox="0 0 23 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0H23V23H0V0Z" fill="#F3F3F3"/>
<path d="M1 1H11V11H1V1Z" fill="#F35325"/>
<path d="M12 1H22V11H12V1Z" fill="#81BC06"/>
<path d="M1 12H11V22H1V12Z" fill="#05A6F0"/>
<path d="M12 12H22V22H12V12Z" fill="#FFBA08"/>
</svg>
}
  />

  <Card
    title="Mixpanel"
    href="/integrations/analytics/mixpanel"
    icon={
  <svg
    className="h-6 w-6"
    width="24"
    height="24"
    style={{ fill: "#7856ff" }}
    viewBox="0 0 98 98"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path d="M24.2391 58.7912C29.877 58.7912 34.4475 54.2207 34.4475 48.5828C34.4475 42.9449 29.877 38.3745 24.2391 38.3745C18.6012 38.3745 14.0308 42.9449 14.0308 48.5828C14.0308 54.2207 18.6012 58.7912 24.2391 58.7912Z"></path>
    <path d="M54.7787 55.7046C58.7675 55.7046 62.0011 52.4716 62.0011 48.4834C62.0011 44.4952 58.7675 41.2622 54.7787 41.2622C50.7899 41.2622 47.5563 44.4952 47.5563 48.4834C47.5563 52.4716 50.7899 55.7046 54.7787 55.7046Z"></path>
    <path d="M78.6018 52.0652C80.547 52.0652 82.1239 50.4883 82.1239 48.5431C82.1239 46.5979 80.547 45.021 78.6018 45.021C76.6566 45.021 75.0798 46.5979 75.0798 48.5431C75.0798 50.4883 76.6566 52.0652 78.6018 52.0652Z"></path>
  </svg>
}
  />

  <Card
    title="Pirsch"
    href="/integrations/analytics/pirsch"
    icon={
  <>
    <svg
      className="h-6 w-6 dark:hidden"
      width="1"
      height="1"
      viewBox="0 0 1 1"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <g clipPath="url(https://mintlify.s3.us-west-1.amazonaws.com/mintlify/integrations/analytics#clip0_2199_68)">
        <path
          d="M0.184082 0.631579C0.358477 0.631579 0.499871 0.490184 0.499871 0.315789C0.499871 0.141395 0.358477 0 0.184082 0V0.631579ZM0.815661 0.368421C0.641266 0.368421 0.499871 0.509816 0.499871 0.684211C0.499871 0.858605 0.641266 1 0.815661 1V0.368421Z"
          fill="black"
        />
        <path
          d="M0.710681 0.288549C0.78335 0.288549 0.842259 0.229639 0.842259 0.15697C0.842259 0.0843005 0.78335 0.0253906 0.710681 0.0253906C0.638011 0.0253906 0.579102 0.0843005 0.579102 0.15697C0.579102 0.229639 0.638011 0.288549 0.710681 0.288549Z"
          fill="black"
        />
        <path
          d="M0.289294 0.974095C0.361963 0.974095 0.420873 0.915185 0.420873 0.842516C0.420873 0.769847 0.361963 0.710938 0.289294 0.710938C0.216625 0.710938 0.157715 0.769847 0.157715 0.842516C0.157715 0.915185 0.216625 0.974095 0.289294 0.974095Z"
          fill="black"
        />
      </g>
      <defs>
        <clipPath id="clip0_2199_68">
          <rect width="1" height="1" fill="black" />
        </clipPath>
      </defs>
    </svg>
    <svg
      className="hidden h-6 w-6 dark:block"
      width="1"
      height="1"
      viewBox="0 0 1 1"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <g clipPath="url(https://mintlify.s3.us-west-1.amazonaws.com/mintlify/integrations/analytics#clip0_2199_68)">
        <path
          d="M0.184082 0.631579C0.358477 0.631579 0.499871 0.490184 0.499871 0.315789C0.499871 0.141395 0.358477 0 0.184082 0V0.631579ZM0.815661 0.368421C0.641266 0.368421 0.499871 0.509816 0.499871 0.684211C0.499871 0.858605 0.641266 1 0.815661 1V0.368421Z"
          fill="white"
        />
        <path
          d="M0.710681 0.288549C0.78335 0.288549 0.842259 0.229639 0.842259 0.15697C0.842259 0.0843005 0.78335 0.0253906 0.710681 0.0253906C0.638011 0.0253906 0.579102 0.0843005 0.579102 0.15697C0.579102 0.229639 0.638011 0.288549 0.710681 0.288549Z"
          fill="white"
        />
        <path
          d="M0.289294 0.974095C0.361963 0.974095 0.420873 0.915185 0.420873 0.842516C0.420873 0.769847 0.361963 0.710938 0.289294 0.710938C0.216625 0.710938 0.157715 0.769847 0.157715 0.842516C0.157715 0.915185 0.216625 0.974095 0.289294 0.974095Z"
          fill="white"
        />
      </g>
      <defs>
        <clipPath id="clip0_2199_68">
          <rect width="1" height="1" fill="white" />
        </clipPath>
      </defs>
    </svg>
  </>
}
  />

  <Card
    title="Plausible"
    href="/integrations/analytics/plausible"
    icon={
  <svg className="h-6 w-6" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="62.4 0 387.18 512">
<path d="M448.6 192.9c-9.3 89.2-87.3 155.5-177 155.5H237v81.7c0 45.2-36.7 81.9-81.9 81.9h-64c-15.8 0-28.7-12.8-28.7-28.7V315.2l43-60.3c7.8-10.9 22.1-15 34.4-9.8l24.5 10.2c12.3 5.2 26.6 1.1 34.3-9.8l57.3-80.4c7.7-10.9 22-14.9 34.3-9.7l47.1 19.8c12.3 5.2 26.6 1.1 34.3-9.8l55.1-77.3c17.4 30.4 25.9 66.5 21.9 104.8" style={{ fill: "#6d6aef" }} />
<path d="M90.6 246.4c7-9.9 17.2-17.4 29.1-19.7 9.3-1.8 18.4-.8 26.9 2.7l24.4 10.2c1.4.6 2.9.9 4.4.9 3.7 0 7.2-1.8 9.4-4.8l56.3-78.9c7-9.8 17.2-17.4 29.1-19.7 9.2-1.8 18.3-.8 26.7 2.7l47.1 19.8c1.4.6 2.9.9 4.4.9 3.7 0 7.2-1.8 9.4-4.8l59-82.8C385.3 28.7 333.7 0 275.3 0H91.1C75.3 0 62.5 12.8 62.5 28.7v257.1z" style={{ fill: "#6d6aef" }} />
</svg>
}
  />

  <Card
    title="PostHog"
    href="/integrations/analytics/posthog"
    icon={
  <svg
    className="h-6 w-6"
    width="50"
    height="30"
    viewBox="0 0 50 30"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      d="M10.8914 17.2057c-.3685.7371-1.42031.7371-1.78884 0L8.2212 15.443c-.14077-.2815-.14077-.6129 0-.8944l.88136-1.7627c.36853-.7371 1.42034-.7371 1.78884 0l.8814 1.7627c.1407.2815.1407.6129 0 .8944l-.8814 1.7627zM10.8914 27.2028c-.3685.737-1.42031.737-1.78884 0L8.2212 25.44c-.14077-.2815-.14077-.6129 0-.8944l.88136-1.7627c.36853-.7371 1.42034-.7371 1.78884 0l.8814 1.7627c.1407.2815.1407.6129 0 .8944l-.8814 1.7628z"
      fill="#1D4AFF"
    />
    <path
      d="M0 23.4082c0-.8909 1.07714-1.3371 1.70711-.7071l4.58338 4.5834c.62997.63.1838 1.7071-.7071 1.7071H.999999c-.552284 0-.999999-.4477-.999999-1v-4.5834zm0-4.8278c0 .2652.105357.5196.292893.7071l9.411217 9.4112c.18753.1875.44189.2929.70709.2929h5.1692c.8909 0 1.3371-1.0771.7071-1.7071L1.70711 12.7041C1.07714 12.0741 0 12.5203 0 13.4112v5.1692zm0-9.99701c0 .26521.105357.51957.292893.7071L19.7011 28.6987c.1875.1875.4419.2929.7071.2929h5.1692c.8909 0 1.3371-1.0771.7071-1.7071L1.70711 2.70711C1.07715 2.07715 0 2.52331 0 3.41421v5.16918zm9.997 0c0 .26521.1054.51957.2929.7071l17.994 17.99401c.63.63 1.7071.1838 1.7071-.7071v-5.1692c0-.2652-.1054-.5196-.2929-.7071l-17.994-17.994c-.63-.62996-1.7071-.18379-1.7071.70711v5.16918zm11.7041-5.87628c-.63-.62997-1.7071-.1838-1.7071.7071v5.16918c0 .26521.1054.51957.2929.7071l7.997 7.99701c.63.63 1.7071.1838 1.7071-.7071v-5.1692c0-.2652-.1054-.5196-.2929-.7071l-7.997-7.99699z"
      fill="#F9BD2B"
    />
    <path
      d="M42.5248 23.5308l-9.4127-9.4127c-.63-.63-1.7071-.1838-1.7071.7071v13.1664c0 .5523.4477 1 1 1h14.5806c.5523 0 1-.4477 1-1v-1.199c0-.5523-.4496-.9934-.9973-1.0647-1.6807-.2188-3.2528-.9864-4.4635-2.1971zm-6.3213 2.2618c-.8829 0-1.5995-.7166-1.5995-1.5996 0-.8829.7166-1.5995 1.5995-1.5995.883 0 1.5996.7166 1.5996 1.5995 0 .883-.7166 1.5996-1.5996 1.5996z"
      fill="#000"
    />
    <path
      d="M0 27.9916c0 .5523.447715 1 1 1h4.58339c.8909 0 1.33707-1.0771.70711-1.7071l-4.58339-4.5834C1.07714 22.0711 0 22.5173 0 23.4082v4.5834zM9.997 10.997L1.70711 2.70711C1.07714 2.07714 0 2.52331 0 3.41421v5.16918c0 .26521.105357.51957.292893.7071L9.997 18.9946V10.997zM1.70711 12.7041C1.07714 12.0741 0 12.5203 0 13.4112v5.1692c0 .2652.105357.5196.292893.7071L9.997 28.9916V20.994l-8.28989-8.2899z"
      fill="#1D4AFF"
    />
    <path
      d="M19.994 11.4112c0-.2652-.1053-.5196-.2929-.7071l-7.997-7.99699c-.6299-.62997-1.70709-.1838-1.70709.7071v5.16918c0 .26521.10539.51957.29289.7071l9.7041 9.70411v-7.5834zM9.99701 28.9916h5.58339c.8909 0 1.3371-1.0771.7071-1.7071L9.99701 20.994v7.9976zM9.99701 10.997v7.5834c0 .2652.10539.5196.29289.7071l9.7041 9.7041v-7.5834c0-.2652-.1053-.5196-.2929-.7071L9.99701 10.997z"
      fill="#F54E00"
    />
  </svg>
}
  />

  <Card
    title="Segment"
    href="/integrations/analytics/segment"
    icon={
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none">
<path
fill="#93C8A2"
fill-rule="evenodd"
d="M22.69 10.396H8.64a1.184 1.184 0 0 1-1.173-1.187c0-.653.528-1.188 1.173-1.188h14.05c.645 0 1.173.535 1.173 1.188 0 .653-.527 1.187-1.173 1.187Z"
clip-rule="evenodd"
/>
<path
fill="#43AF79"
fill-rule="evenodd"
d="M1.923 10.396A1.184 1.184 0 0 1 .75 9.209c0-.12.03-.238.059-.356C2.275 4.015 6.646.75 11.66.75c1.144 0 2.288.178 3.374.505.615.207.968.86.762 1.484-.205.623-.85.979-1.466.771a8.962 8.962 0 0 0-2.67-.415c-3.989 0-7.45 2.582-8.594 6.44-.176.505-.616.86-1.144.86Z"
clip-rule="evenodd"
/>
<path
fill="#93C8A2"
fill-rule="evenodd"
d="M19.786 4.667c0 .653-.528 1.188-1.173 1.188a1.184 1.184 0 0 1-1.173-1.188c0-.653.528-1.187 1.173-1.187s1.173.534 1.173 1.187ZM1.173 13.604h14.05c.645 0 1.173.534 1.173 1.187s-.528 1.188-1.173 1.188H1.173A1.184 1.184 0 0 1 0 14.79c0-.653.528-1.187 1.173-1.187Z"
clip-rule="evenodd"
/>
<path
fill="#43AF79"
fill-rule="evenodd"
d="M21.94 13.604c.645 0 1.173.534 1.173 1.187 0 .12-.029.238-.058.357-1.467 4.837-5.837 8.102-10.853 8.102-1.144 0-2.288-.178-3.373-.505-.616-.207-.968-.86-.763-1.483.205-.624.85-.98 1.467-.772.85.267 1.76.415 2.669.415 3.989 0 7.45-2.582 8.594-6.44.176-.505.616-.86 1.144-.86Z"
clip-rule="evenodd"
/>
<path
fill="#93C8A2"
fill-rule="evenodd"
d="M4.077 19.332c0-.653.528-1.187 1.173-1.187.646 0 1.174.534 1.174 1.187S5.896 20.52 5.25 20.52a1.184 1.184 0 0 1-1.173-1.188Z"
clip-rule="evenodd"
/>
</svg>
}
  />
</CardGroup>

## Setup

Add your analytics provider credentials to the `integrations` object in `docs.json`. Only include the platforms you want to use.

<Note>
  Analytics integrations only require public API keys, which are accessible to anyone viewing your documentation site. Your private API keys, which pair with the public keys on the analytics providers' end, must remain private. Do not include private API keys in your `docs.json`.
</Note>

```json docs.json theme={null}
"integrations": {
    "adobe": {
        "launchUrl": "required"
    },
    "amplitude": {
        "apiKey": "required"
    },
    "clarity": {
        "projectId": "required"
    },
    "clearbit": {
        "publicApiKey": "required"
    },
    "cookies": {
      "key": "required",
      "value": "required"
    },
    "fathom": {
        "siteId": "required"
    },
    "ga4": {
        "measurementId": "required"
    },
    "gtm": {
        "tagId": "required"
    },
    "heap": {
        "appId": "required"
    },
    "hightouch": {
        "apiKey": "required",
        "apiHost": "optional"
    },
    "hotjar": {
        "hjid": "required",
        "hjsv": "required"
    },
    "logrocket": {
        "appId": "required"
    },
    "mixpanel": {
        "projectToken": "required"
    },
    "pirsch": {
        "id": "required"
    },
    "plausible": {
        "domain": "required"
    },
    "posthog": {
        "apiKey": "required",
        "apiHost": "optional"
    },
    "segment": {
      "key": "required"
    },
    "telemetry": {
      "enabled": "boolean"
    }
}
```

### Example configuration

```json docs.json theme={null}
{
  "integrations": {
    "ga4": {
      "measurementId": "G-XXXXXXXXXX"
    },
    "posthog": {
      "apiKey": "phc_xxxxxxxxxxxxx",
      "apiHost": "https://app.posthog.com"
    },
    "mixpanel": {
      "projectToken": "xxxxxxxxxxxxx"
    }
  }
}
```

### Verify your setup

After you deploy your updated `docs.json`, load a page on your live site and confirm events are flowing in your provider's real-time or debug view. If events do not appear, check that:

* You are using the public key or ID from the provider, not a private or server key.
* The property name in `docs.json` matches the one documented for your provider.
* The value is not wrapped in extra quotes or whitespace.

## Tracked events

All tracked events use the `docs.` prefix.

### Navigation and page views

| Event name                              | Description                                                                       |
| :-------------------------------------- | :-------------------------------------------------------------------------------- |
| `docs.content.view`                     | User views a page. Only sent to providers that don't track page views by default. |
| `docs.content.md.view`                  | User views Markdown version of a page.                                            |
| `docs.navitem.click`                    | User clicks a header navigation item.                                             |
| `docs.navitem.cta_click`                | User clicks a call to action button.                                              |
| `docs.footer.powered_by_mintlify_click` | User clicks the "Powered by Mintlify" link.                                       |

### Search

| Event name                 | Description                   |
| :------------------------- | :---------------------------- |
| `docs.search.query`        | User performs a search query. |
| `docs.search.close`        | User closes the search bar.   |
| `docs.search.result_click` | User clicks a search result.  |

### Code and API playground

| Event name                    | Description                                      |
| :---------------------------- | :----------------------------------------------- |
| `docs.code_block.copy`        | User copies code from a code block.              |
| `docs.code_block.ask_ai`      | User asks the assistant to explain a code block. |
| `docs.api_playground.request` | User makes an API request in the API playground. |

### Interactive components

| Event name              | Description                |
| :---------------------- | :------------------------- |
| `docs.accordion.open`   | User opens an accordion.   |
| `docs.accordion.close`  | User closes an accordion.  |
| `docs.expandable.open`  | User opens an expandable.  |
| `docs.expandable.close` | User closes an expandable. |

### Assistant and agent

| Event name                                | Description                                                        |
| :---------------------------------------- | :----------------------------------------------------------------- |
| `docs.assistant.enter`                    | User opens the AI assistant.                                       |
| `docs.assistant.completed`                | Chat session completes.                                            |
| `docs.assistant.source_click`             | User clicks a citation in a chat response.                         |
| `docs.assistant.suggestion_click`         | User clicks a suggested question.                                  |
| `docs.assistant.ask_ai_on_text_selection` | User selects text and clicks "Ask AI."                             |
| `docs.assistant.shared`                   | User shares a chat conversation.                                   |
| `docs.assistant.thumbs_up`                | User clicks the positive feedback button on an assistant response. |
| `docs.assistant.thumbs_down`              | User clicks the negative feedback button on an assistant response. |
| `docs.assistant.spam_detected`            | The assistant detects spam in a user message.                      |
| `docs.autopilot.suggestion.created`       | The agent creates a documentation suggestion.                      |
| `docs.autopilot.suggestion.no_suggestion` | The agent determines the documentation does not need updating.     |

### Contextual menu

| Event name                               | Description                                                                           |
| :--------------------------------------- | :------------------------------------------------------------------------------------ |
| `docs.context_menu.copy_page`            | User copies the current page as Markdown.                                             |
| `docs.context_menu.copy_mcp_link`        | User copies the hosted MCP server link.                                               |
| `docs.context_menu.copy_add_mcp_command` | User copies the `npx add-mcp` command to install the MCP server.                      |
| `docs.context_menu.ai_provider_click`    | User clicks an AI provider to create a conversation with the current page as context. |
| `docs.context_menu.install_mcp_server`   | User installs the hosted MCP server on code editors.                                  |


# Pirsch
Source: https://www.mintlify.com/docs/integrations/analytics/pirsch

Integrate Pirsch with your Mintlify documentation for GDPR-compliant, cookie-free analytics that tracks page views without collecting personal data.

Add the following to your `docs.json` file to send analytics to Pirsch.

You can get your site ID from Settings > Developer > Identification Code.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "pirsch": {
          "id": "required"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "pirsch": {
          "id": "8Kw7OKxBfswOjnKGZa7P9Day8JmVYwTp"
      }
  }
  ```
</CodeGroup>


# Plausible
Source: https://www.mintlify.com/docs/integrations/analytics/plausible

Integrate Plausible Analytics with your Mintlify documentation for lightweight, privacy-respecting visitor tracking without cookies or consent banners.

Add your site's domain to `docs.json` to send analytics to Plausible.

<Info>
  Do not include `https://` for the domain or server.
</Info>

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "plausible": {
          "domain": "your-documentation-domain",
          "server": "optional - your self-hosted Plausible server hostname"
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "plausible": {
          "domain": "docs.domain.com"
      }
  }
  ```
</CodeGroup>

## Configuration options

<ParamField type="string">
  Your documentation site's domain. For example, `docs.example.com`. Do not include `https://`.
</ParamField>

<ParamField type="string">
  The hostname of your self-hosted Plausible instance. For example, `plausible.example.com`. Only required if you self-host Plausible. Omit this field to use `plausible.io`. Do not include `https://`.
</ParamField>


# PostHog
Source: https://www.mintlify.com/docs/integrations/analytics/posthog

Integrate PostHog with your Mintlify documentation site to track product analytics, feature usage, and user behavior with your API key.

Add the following to your `docs.json` file to send analytics to PostHog.

You only need to include `apiHost` if you are self-hosting PostHog. By default, Mintlify proxies events through `https://ph.mintlify.com` to your PostHog project.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "posthog": {
          "apiKey": "YOUR_POSTHOG_PROJECT_API_KEY",
          "apiHost": "optional",
          "sessionRecording": true
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "posthog": {
          "apiKey": "phc_TXdpocbYTeZVm5VJmMzHTMrCofBQu3e0kN7HGMNGTVW"
      }
  }
  ```
</CodeGroup>

## Configuration options

<ParamField type="string">
  Your PostHog project API key. Must start with `phc_`.

  This key is a client-side token meant to be public. It's the same key your browser sends with every analytics event. It's safe to commit to your documentation repository.
</ParamField>

<ParamField type="string">
  The URL of your PostHog instance. Only required if you are self-hosting PostHog. Defaults to `https://ph.mintlify.com` (Mintlify's PostHog proxy).
</ParamField>

<ParamField type="boolean">
  Enable or disable session recording. Set to `false` to disable session recordings while keeping analytics enabled.
</ParamField>

## Session recordings

Configuring PostHog enables session recordings by default. To disable session recordings while keeping analytics enabled, set `sessionRecording` to `false` in your configuration.

```json Disable session recordings theme={null}
"integrations": {
    "posthog": {
        "apiKey": "phc_your-key",
        "sessionRecording": false
    }
}
```

You need to add the URL for your docs website to PostHog's "Authorized domains for recordings" before you can receive session recordings. The option to add your URL is in PostHog's project settings.


# Segment
Source: https://www.mintlify.com/docs/integrations/analytics/segment

Integrate Segment with your Mintlify documentation to route analytics events to downstream tools like warehouses, CRMs, and marketing platforms.

Add your Segment write key to your `docs.json` file to send analytics to Segment.

<CodeGroup>
  ```json Analytics options in docs.json theme={null}
  "integrations": {
      "segment": {
          "key": "required",
      }
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "segment": {
          "key": "nqJxiRG15Y6M594P8Sb8ESEciU3VC2"
      }
  }
  ```
</CodeGroup>


# Osano
Source: https://www.mintlify.com/docs/integrations/privacy/osano

Integrate Osano with your Mintlify documentation site to manage cookie consent banners, privacy preferences, and regulatory compliance.

Add [Osano](https://www.osano.com/) cookie consent to your docs with a [custom JavaScript file](/docs/customize/custom-scripts#custom-javascript) in your repository.

## Setup

Create an `osano.js` file inside your content directory with the following content.

<CodeGroup>
  ```js Format theme={null}
  var script = document.createElement("script");
  script.src = "OSANO_SCRIPT_URL";
  document.head.appendChild(script);
  ```

  ```js Example theme={null}
  var script = document.createElement("script");
  script.src = "https://cmp.osano.com/your-tenant-id/your-site-id/osano.js";
  document.head.appendChild(script);
  ```
</CodeGroup>

Replace `OSANO_SCRIPT_URL` with your Osano script URL. Your script URL is the `src` value in the code snippet that Osano generates. Your script URL always starts with `https://cmp.osano.com/` and ends with `/osano.js`.

## Troubleshooting

<Accordion title="Pages not loading with Strict compliance mode">
  If your documentation pages aren't loading properly when using Osano's **Strict** compliance mode, you'll need to add Mintlify's domain to your allowlist to allow images and other assets to load.

  <Steps>
    <Step title="Navigate to Managed Rules">
      In your Osano dashboard, go to **Scripts** → **Managed Rules**.
    </Step>

    <Step title="Add Mintlify domain">
      Add `.mintlify.site/` as a managed rule.

      <Frame>
        <img alt="Osano managed rule" />
      </Frame>

      <Info>
        This ensures that all Mintlify-served assets, including images, stylesheets, and other documentation resources, remain essential and load even when Osano blocks uncategorized third-party content.
      </Info>
    </Step>
  </Steps>
</Accordion>


# Privacy integrations
Source: https://www.mintlify.com/docs/integrations/privacy/overview

Connect your Mintlify documentation site to privacy platforms like Osano and Transcend to manage cookie consent, compliance banners, and user preferences.

<Card title="Osano" href="/integrations/privacy/osano" icon={<svg width="32" height="32" className="h-6 w-6" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg"><path fillRule="evenodd" clipRule="evenodd" d="M128 256C198.692 256 256 198.692 256 128C256 57.3076 198.692 0 128 0C57.3076 0 0 57.3076 0 128C0 198.692 57.3076 256 128 256ZM128 192C163.346 192 192 163.346 192 128C192 92.6538 163.346 64 128 64C92.6538 64 64 92.6538 64 128C64 163.346 92.6538 192 128 192Z" fill="#7764FA"/></svg>}>
  Manage cookie consent with [Osano](https://www.osano.com/).
</Card>

<Card title="Transcend" href="/integrations/privacy/transcend" icon="shield-check">
  Manage cookie consent with [Transcend](https://transcend.io/).
</Card>

## Cookie consent and disabling telemetry

To check whether a user has already consented to cookies for General Data Protection Regulation (GDPR) compliance, specify a local storage key and value under `cookies`:

```json theme={null}
  "integrations": {
    "cookies": {
      "key": "LOCAL STORAGE KEY",
      "value": "LOCAL STORAGE VALUE"
    }
  }
```

If you set these values, your site checks local storage for the specified key and value to determine if a user consented to cookies. If a user has not consented to cookies, your site disables telemetry for that user.

If you'd like to disable telemetry for all users, add the following to your `docs.json` file:

```json theme={null}
  "integrations": {
    "telemetry": {
      "enabled": false
    }
  }
```

<Note>
  If you disable telemetry, you cannot collect feedback on your documentation pages, even if you enable feedback in your dashboard.
</Note>


# Transcend
Source: https://www.mintlify.com/docs/integrations/privacy/transcend

Integrate Transcend Consent Management with your Mintlify docs to gate analytics behind visitor consent using your existing Transcend bundle.

Use [Transcend](https://transcend.io/) to manage cookie consent on your documentation site. When you configure Transcend, Mintlify loads your Transcend bundle, shows Transcend's consent banner, and only loads analytics and feedback after visitors grant consent for the Analytics purpose.

Configure Transcend if you already use it as your consent management platform (CMP) and want a single, consistent consent experience across your product and docs.

<Note>
  When Transcend is configured, Transcend owns the consent banner. Mintlify's built-in consent banner does not appear, so visitors only see one prompt.
</Note>

## Setup

<Steps>
  <Step title="Get your Transcend bundle ID">
    In your Transcend dashboard, go to **Consent Management** and copy the bundle ID for the deployment you want to use with your docs. The bundle ID appears in your Airgap script URL: `https://transcend-cdn.com/cm/<bundleId>/airgap.js`.
  </Step>

  <Step title="Add Transcend to your docs.json">
    Add a `transcend` object under `integrations` in your `docs.json`:

    ```json theme={null}
    "integrations": {
      "transcend": {
        "bundleId": "YOUR_BUNDLE_ID"
      }
    }
    ```

    You can also configure Transcend from your dashboard under **Analytics** → **Add integration** → **Compliance**.
  </Step>

  <Step title="Verify the banner loads">
    Deploy your docs and open the site. The Transcend consent banner should appear on the first visit. Accept, reject, and revoke analytics consent to confirm that analytics scripts follow the visitor's selection.
  </Step>
</Steps>

## Configuration

| Field              | Type   | Required | Description                                                                                                                              |
| ------------------ | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `bundleId`         | string | Yes      | Your Transcend bundle ID. Can only contain letters, numbers, hyphens, and underscores.                                                   |
| `analyticsPurpose` | string | No       | The Transcend purpose name that gates analytics and feedback. Defaults to `Analytics`. Set this if you renamed the purpose in Transcend. |

### Custom analytics purpose

If you renamed the Analytics purpose in your Transcend instance, pass the exact purpose name so Mintlify waits for consent on the right purpose:

```json theme={null}
"integrations": {
  "transcend": {
    "bundleId": "YOUR_BUNDLE_ID",
    "analyticsPurpose": "Product Analytics"
  }
}
```

## How consent gating works

* Analytics and feedback scripts do not load until Transcend resolves the visitor's consent for the configured purpose.
* If a visitor grants consent and later revokes it, the page reloads so already-loaded analytics scripts are torn down.
* If Transcend fails to load or a visitor never resolves the banner, analytics stay off.


# Speakeasy
Source: https://www.mintlify.com/docs/integrations/sdks/speakeasy

Display autogenerated SDK code samples from Speakeasy in your API playground with multi-language examples for Python, TypeScript, Go, and more.

You can integrate autogenerated code snippets from Speakeasy SDKs directly into Mintlify API reference documentation. SDK usage snippets appear in the [interactive playground](/docs/api-playground/overview) of Mintlify-powered documentation sites.

<Frame>
  <img alt="A Mintlify API playground with Speakeasy code snippets." />
</Frame>

## Prerequisites

To integrate Mintlify with Speakeasy, you'll need the following:

* A [Mintlify documentation repository](/docs/quickstart).
* A Speakeasy-generated SDK with a configured [automated code sample URL](https://www.speakeasy.com/docs/code-samples/automated-code-sample-urls).

## Set up the integration

To integrate Speakeasy with Mintlify, you must get the API's combined spec public URL from the registry and update your `docs.json` configuration file.

### Get the API's combined spec public URL from the registry

Go to your [Speakeasy Dashboard](https://app.speakeasy.com) and open the **API Registry** tab. Open the `*-with-code-samples` entry for the API.

<Frame>
  <img alt="Screenshot of the Speakeasy API Registry page. A red square and the number 1 emphasize the API Registry tab, and a red square and the number 2 emphasize the entry for the API." />
</Frame>

<Note>
  If the entry is not labeled **Combined Spec**, ensure that the API has an [automatic code sample URL](https://www.speakeasy.com/docs/code-samples/automated-code-sample-urls) configured.
</Note>

From the registry entry's page, copy the provided public URL.

<Frame>
  <img alt="Screenshot showing the combined spec registry entry with the copy URL function emphasized with a red square." />
</Frame>

### Update your `docs.json` configuration file

Add the combined spec URL to an **Anchors** or **Tabs** section in your `docs.json` file.

Add the combined spec URL to an anchor by updating the `anchor` field in your `docs.json` file as follows:

```json docs.json theme={null}
{
  "anchors": [
    {
      "name": "API Reference",
      // !mark
      "openapi": "SPEAKEASY_COMBINED_SPEC_URL",
      "url": "api-reference",
      "icon": "square-terminal"
    }
  ]
}
```

Add the combined spec URL to a tab by updating the `tab` field in the `docs.json` file as follows:

```json docs.json theme={null}
{
  "tabs": [
    {
      "name": "API Reference",
      "url": "api-reference",
      // !mark
      "openapi": "SPEAKEASY_COMBINED_SPEC_URL"
    }
  ]
}
```

You can now view Speakeasy-generated code snippets in your API docs and interact with them in the playground.

## Verify the integration

After you redeploy your documentation, open any endpoint in your API reference and confirm that language snippets appear in the playground. The set of available languages matches the SDK targets configured in your Speakeasy project.

If snippets do not appear, check that:

* The `openapi` URL in `docs.json` points to the `*-with-code-samples` combined spec entry, not the source OpenAPI file.
* The combined spec URL is publicly reachable from the browser.
* Your Speakeasy project has an [automated code sample URL](https://www.speakeasy.com/docs/code-samples/automated-code-sample-urls) configured and at least one SDK target enabled.


# Stainless
Source: https://www.mintlify.com/docs/integrations/sdks/stainless

Display autogenerated SDK code samples from Stainless in your API playground with type-safe examples across Python, TypeScript, and other SDKs.

## Prerequisites

* Have a [Stainless](https://app.stainless.com) account.

## Set up the integration

<Steps>
  <Step title="Set up OpenAPI decoration in Stainless.">
    In your `stainless.yml` config file, add `openapi.code_samples: 'mintlify'`. See the [Stainless documentation](https://www.stainless.com/docs/docs-integrations/mintlify) for more information.
  </Step>

  <Step title="Publish the URL to your OpenAPI spec.">
    In your Stainless project:

    1. Click the **Release** tab.
    2. Click **Setup OpenAPI publishing**.
    3. Copy the URL to your publicly accessible OpenAPI spec.

    <img alt="Stainless release page with the OpenAPI spec URL highlighted with a green box." />
  </Step>

  <Step title={<>Add your OpenAPI spec URL to your <code>docs.json</code>.</>}>
    In your `docs.json` file, add the URL from Stainless to the `openapi` field. See [OpenAPI Setup](/docs/api-playground/openapi-setup) for more information.
  </Step>
</Steps>


# Front
Source: https://www.mintlify.com/docs/integrations/support/front

Integrate Front chat with your Mintlify documentation site so visitors can start customer support conversations directly from your docs pages.

Add the following to your `docs.json` file to add a [Front Chat](https://front.com) widget.

<CodeGroup>
  ```json Integration options in docs.json theme={null}
  "integrations": {
      "frontchat": "CHAT_ID"
  }
  ```

  ```json Example theme={null}
  "integrations": {
      "frontchat": "1365d046d7c023e9b030ce90d02d093a"
  }
  ```
</CodeGroup>


# Intercom
Source: https://www.mintlify.com/docs/integrations/support/intercom

Integrate the Intercom chat widget into your Mintlify documentation site to provide real-time customer messaging, support, and onboarding help.

Add the following to your `docs.json` file to add an [Intercom](https://www.intercom.com) widget.

<CodeGroup>
  ```json Integration options in docs.json theme={null}
  "integrations": {
        "intercom": {
              "appId": "APP_ID"
        }
  }
  ```

  ```json Example theme={null}
  "integrations": {
        "intercom": {
              "appId": "abc123def4"
        }
  }
  ```
</CodeGroup>


# Support integrations
Source: https://www.mintlify.com/docs/integrations/support/overview

Connect your Mintlify documentation to support platforms like Intercom and Front so visitors can get live help directly from your docs pages.

<CardGroup>
  <Card title="Intercom" href="/integrations/support/intercom" icon={<svg className="h-6 w-6" width="2500" height="2500" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M221.867 140.748a8.534 8.534 0 0 1-17.067 0V64a8.534 8.534 0 0 1 17.067 0v76.748zm-2.978 53.413c-1.319 1.129-32.93 27.655-90.889 27.655-57.958 0-89.568-26.527-90.887-27.656a8.535 8.535 0 0 1-.925-12.033 8.53 8.53 0 0 1 12.013-.942c.501.42 28.729 23.563 79.8 23.563 51.712 0 79.503-23.31 79.778-23.545 3.571-3.067 8.968-2.655 12.033.925a8.534 8.534 0 0 1-.923 12.033zM34.133 64A8.534 8.534 0 0 1 51.2 64v76.748a8.534 8.534 0 0 1-17.067 0V64zm42.668-17.067a8.534 8.534 0 0 1 17.066 0v114.001a8.534 8.534 0 0 1-17.066 0v-114zm42.666-4.318A8.532 8.532 0 0 1 128 34.082a8.532 8.532 0 0 1 8.534 8.533v123.733a8.534 8.534 0 0 1-17.067 0V42.615zm42.667 4.318a8.534 8.534 0 0 1 17.066 0v114.001a8.534 8.534 0 0 1-17.066 0v-114zM224 0H32C14.327 0 0 14.327 0 32v192c0 17.672 14.327 32 32 32h192c17.673 0 32-14.328 32-32V32c0-17.673-14.327-32-32-32z" fill="#1F8DED"/></svg>} />

  <Card
    href="/integrations/support/front"
    title="Front"
    icon={<svg className="h-6 w-6" width="754" height="754" viewBox="0 0 754 754" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M124 135.5C124 69 177.9 15 244.5 15H630.8V186.4C630.8 219.7 603.8 246.6 570.6 246.6H413.6C381.6 246.6 355.7 272.5 355.7 304.5V678.7C355.7 712 328.7 738.9 295.5 738.9H124V135.5Z" fill="#001B38"/>
<path d="M415 462.4C501.377 462.4 571.4 392.377 571.4 306C571.4 219.623 501.377 149.6 415 149.6C328.623 149.6 258.6 219.623 258.6 306C258.6 392.377 328.623 462.4 415 462.4Z" fill="url(https://mintlify.s3.us-west-1.amazonaws.com/mintlify/integrations/support#paint0_linear_66_11)"/>
<path opacity="0.5" d="M415 462.4C501.377 462.4 571.4 392.377 571.4 306C571.4 219.623 501.377 149.6 415 149.6C328.623 149.6 258.6 219.623 258.6 306C258.6 392.377 328.623 462.4 415 462.4Z" fill="url(https://mintlify.s3.us-west-1.amazonaws.com/mintlify/integrations/support#paint1_linear_66_11)"/>
<defs>
<linearGradient id="paint0_linear_66_11" x1="301.703" y1="191.962" x2="536.873" y2="428.762" gradientUnits="userSpaceOnUse">
<stop stopColor="#FF0057" stopOpacity="0.16"/>
<stop offset="0.86" stopColor="#FF0057"/>
</linearGradient>
<linearGradient id="paint1_linear_66_11" x1="301.703" y1="191.962" x2="536.873" y2="428.762" gradientUnits="userSpaceOnUse">
<stop stopColor="#FF0057" stopOpacity="0.16"/>
<stop offset="0.86" stopColor="#FF0057"/>
</linearGradient>
</defs>
</svg>
}
  />
</CardGroup>

## Enable support integrations

Integrate customer support widgets into your documentation. Add the `integrations` field to your `docs.json` file with your respective app ID or chat ID. See each integration's documentation for instructions on finding your ID.


# PDF exports
Source: https://www.mintlify.com/docs/optimize/pdf-exports

Export your entire documentation site as a single PDF with a navigable table of contents for offline reading, sharing, and print distribution.

<Info>
  PDF exports are available on [Enterprise plans](https://mintlify.com/pricing).
</Info>

You can export your docs as a single PDF file for offline viewing. The PDF contains all the content in the docs, including images and links, and a navigable table of contents.

Full-site PDF exports include all pages regardless of group restrictions, so anyone with access to the exported PDF can read content that might otherwise sit behind user group restrictions.

<Tip>
  To let users download individual pages as PDFs, use the [contextual menu's](/docs/ai/contextual-menu) `download-pdf` option.
</Tip>

## Export all content

1. Navigate to the [Exports](https://app.mintlify.com/settings/deployment/export-docs) page in your dashboard.
2. Click **Export all content**.
3. Optionally, customize the export options:
   * **Page format**: Choose the page size of the PDF.
   * **Scale percent**: Adjust the scale of the PDF.
   * **Include footer**: Include a footer with the page number and total pages.
   * **Language**: If your content is available in multiple languages, choose which language to export.
4. Click **Export**.
5. When the export completes, Mintlify sends you an email with a link to download the PDF file.

<DownloadPDFButton />

## Export select pages

1. Navigate to the [Exports](https://app.mintlify.com/settings/deployment/export-docs) page in your dashboard.
2. Click **New export**.
3. Select the pages you want to export.
4. Optionally, customize the export options:
   * **Page format**: Choose the page size of the PDF.
   * **Scale percent**: Adjust the scale of the PDF.
   * **Include footer**: Include a footer with the page number and total pages.
   * **Language**: If your content is available in multiple languages, choose which language to export.
5. Click **Export**.
6. When the export completes, Mintlify sends you an email with a link to download the PDF file.


# Configure in-product search ranking, results, and filters
Source: https://www.mintlify.com/docs/optimize/search

Configure the in-product search bar on your Mintlify docs site: ranking boosts, maximum results per query, and product and version search filters.

Configure how the search bar on your Mintlify-hosted documentation site behaves. These settings only affect in-product search. They do not change how external search engines index your pages.

## Boost search ranking

Use `boost` to bias the in-product search ranking of specific pages or sections. The value is a numeric multiplier applied to each chunk's relevance score: `boost: 3` makes a chunk three times as relevant as it would be without a boost.

### Boost a single page

Set `boost` in a page's [frontmatter](/docs/organize/pages) to multiply its search ranking.

```mdx theme={null}
---
title: "Custom domain"
description: "Connect your custom domain to your Mintlify documentation."
boost: 3
---
```

### Boost a navigation group

Set `boost` on a group in your `docs.json` navigation to apply the multiplier to every page under it.

```json theme={null}
{
  "navigation": {
    "groups": [
      {
        "group": "Get started",
        "boost": 5,
        "pages": [
          "quickstart",
          "concepts"
        ]
      }
    ]
  }
}
```

A page inherits the boost factor from its nearest ancestor that sets one. A child page or nested group can override the inherited boost by setting its own `boost` value. A page's frontmatter `boost` always wins over a value inherited from the navigation.

### De-prioritize content

Use a value below `1` to push pages further down in search results. For example, `boost: 0.5` halves a page's relevance score relative to other pages. A `boost` of `1` is equivalent to no boost.

```mdx theme={null}
---
title: "Deprecated API"
description: "Documentation for the deprecated v1 API."
boost: 0.25
---
```

<Note>
  Boost factors compose with the existing relevance score. Use them sparingly. Large multipliers can cause less-relevant pages to dominate search results and degrade overall search quality.
</Note>

### Recommended boost range

`boost` accepts any positive number. In practice, keep values between `0.1` and `10`:

* `0.1`–`0.9`: de-prioritize legacy, deprecated, or supporting content.
* `1`: no change (equivalent to omitting `boost`).
* `2`–`5`: prioritize a key landing page, quickstart, or heavily used reference.
* `5`–`10`: reserve for a handful of top-level pages that should almost always appear first.

Avoid values greater than `10`. Very large multipliers overwhelm the underlying relevance score and cause boosted pages to appear in search results even when they don't match the query well.

## Exclude a page from search

Pages are searchable by default. The `searchable` field is optional and defaults to `true`. Set `searchable: false` in a page's [frontmatter](/docs/organize/pages) to exclude it from your documentation site's search results. `searchable` is a page-level field only. To exclude every page under a navigation tab or group, hide the tab or group instead. See [Hidden pages](/docs/organize/hidden-pages) for tab- and group-level controls.

```mdx theme={null}
---
title: "Internal notes"
description: "Reference material we don't want surfacing in search."
searchable: false
---
```

Unlike `noindex`, `searchable: false` doesn't affect external SEO. The page is still:

* Crawlable by external search engines
* Listed in your `sitemap.xml`

It's removed from your documentation site's search results and the AI assistant context.

Use `searchable: false` for pages that should stay reachable through direct links or external search engines but shouldn't surface when users search inside your docs. Examples include deep reference pages, legacy content, and supporting material that would otherwise crowd out more relevant results.

To exclude a page from both in-product search and external indexing, use [`noindex: true`](/docs/optimize/seo#disable-indexing) instead.

## Maximum search results

Control how many results the search bar returns per query from your dashboard. The default is `6` results. You can set any value between `1` and `100`.

Navigate to the [Search](https://app.mintlify.com/settings/deployment/search) settings page in your dashboard. In the "Maximum search results" section, set **Results per query** to your desired value.

<Frame>
  <img alt="The Search settings page in the dashboard with the Maximum search results stepper set to 6." />

  <img alt="The Search settings page in the dashboard with the Maximum search results stepper set to 6." />
</Frame>

Higher values surface more matches per query, which is useful for sites with broad topic coverage where users expect to scan many candidates. Lower values keep the results panel compact and push users toward the top-ranked match.

## Search filters

<Note>
  Search filters require an [Enterprise plan](https://mintlify.com/pricing?ref=search-filters).
</Note>

Search filters add product and version dropdowns to search results so users can narrow results to a single product or version. Filters are useful for sites that maintain distinct products or versions, where a search query might otherwise return matches across content the user isn't looking for.

Enable or disable search filters on the [Search](https://app.mintlify.com/settings/deployment/search) settings page in your dashboard.

Which dropdowns appear depends on your navigation configuration.

* The **product** filter appears when your navigation defines more than one [product](/docs/organize/navigation#products).
* The **version** filter appears when your navigation defines [versions](/docs/organize/navigation#versions).

If your navigation has neither products nor versions, enabling search filters has no visible effect.


# SEO
Source: https://www.mintlify.com/docs/optimize/seo

Configure meta tags, Open Graph properties, canonical URLs, and page-level SEO settings to improve your documentation's search engine ranking.

Mintlify automatically handles many SEO best practices, including:

* Meta tag generation
* Structured data (JSON-LD) generation
* Sitemap and `robots.txt` file generation
* Semantic HTML structure
* Mobile optimization

You can fully customize your site's meta tags by adding the `metatags` field to your `docs.json` or a page's frontmatter.

## Automatically generated meta tags

Mintlify generates the following meta tags for every page. You can override these meta tags by specifying them in your `docs.json` or a page's frontmatter.

**Basic metadata:**

* `charset: utf-8` - Character encoding
* `og:type: website` - Open Graph type
* `og:site_name` - Your documentation site name
* `twitter:card: summary_large_image` - Twitter card type

**Page-specific metadata:**

* `title` - Page title, formatted as "Page Title - Site Name"
* `og:title` - Open Graph title, defaults to page title
* `twitter:title` - Twitter title, falls back to `og:title`, then page title
* `description` - Page description
* `og:description` - Open Graph description, falls back to page description
* `twitter:description` - Twitter description, falls back to `og:description`, then page description

**URL and canonical:**

* `canonical` - Automatically built from page URL
* `og:url` - Set to canonical URL

**SEO and indexing:**

* `robots` - Generated from page metadata
* `noindex` - Generated from page metadata
* `keywords` - Generated from page metadata

**Images:**

* `og:image` - Open Graph image, `og:image:width` set to 1200 and `og:image:height` 630
* `twitter:image` - Twitter image, `twitter:image:width` set to 1200 and `twitter:image:height` 630

**Browser and app metadata:**

* `applicationName` - Your documentation site name
* `generator: Mintlify` - Identifies the site generator as Mintlify
* `apple-mobile-web-app-title` - iOS home screen app name
* `msapplication-TileColor` - Windows tile color
* Favicons and icons from your config
* Sitemap reference link

Any meta tags in your `docs.json` `seo.metatags` configuration are also automatically injected into every page, such as `google-site-verification` for search console validation.

## Structured data

Mintlify adds [schema.org](https://schema.org) structured data to every indexable page as a JSON-LD script. This structured data helps search engines display rich results for your pages.

Each page emits a connected `@graph` of entities with stable `@id`s:

* `Organization`: The publisher of your site. Derived from your site name, logo, and site URL, or configured explicitly with [`seo.organization`](/docs/organize/settings-seo#seo).
* `WebSite`: Your site.
* `WebPage`: The current page, including its description and modification dates.
* `BreadcrumbList`: The page's location in your navigation hierarchy, generated from your `docs.json` navigation.
* The main content entity: `TechArticle` for documentation pages or `APIReference` for pages generated from API specifications (pages with `api`, `openapi`, or `asyncapi` frontmatter).

Mintlify generates the structured data from page frontmatter and `docs.json` configurations, including the page title, description, keywords, canonical URL, last updated date, site name, and logo. The structured data doesn't include any fields without a corresponding value. Pages with `noindex: true` do not include structured data.

To change structured data, update the corresponding frontmatter fields or `docs.json` configurations. To control the publisher entity, including a stable `@id`, legal name, canonical logo, and `sameAs` profile links, set [`seo.organization`](/docs/organize/settings-seo#seo) in your `docs.json`.

## OG images

Mintlify automatically generates an Open Graph (OG) image for every page. This image appears as the social preview when you share a link on social media platforms and messaging apps.

Default OG image properties:

* Width: 1200px
* Height: 630px
* Your site logo from the `logo` field in `docs.json`
* The page title from the page's `title` frontmatter
* The page description from the page's `description` frontmatter
* Your site's primary color from the `colors` field in `docs.json`

### Custom OG images

There are three ways to customize OG images, depending on the level of control you need.

**Custom background image**

To use a custom background image while keeping the auto-generated logo, title, and description overlay, set `thumbnails.background` in your `docs.json`.

```json Example docs.json theme={null}
"thumbnails": {
  "background": "/images/og-background.png"
}
```

See [`thumbnails`](/docs/organize/settings-appearance#thumbnails) for the full list of customization options.

**Static OG image for all pages**

To replace the auto-generated image entirely with a single static image across all pages, set `og:image` in your global meta tags.

```json Example docs.json theme={null}
"seo": {
  "metatags": {
    "og:image": "https://example.com/og-image.png"
  }
}
```

**Static OG image for a specific page**

To override the OG image for a single page, set `og:image` in that page's frontmatter.

```yaml Example frontmatter theme={null}
---
title: "Your page title"
description: "Your page description"
"og:image": "https://example.com/custom-og.png"
---
```

<Note>
  Setting `og:image` in meta tags, globally or per-page, replaces the auto-generated social preview with a static image. If you want Mintlify to automatically overlay your logo, page title, and description on a custom background, use [`thumbnails.background`](/docs/organize/settings-appearance#param-thumbnails-background) instead.
</Note>

## Global meta tags

To set default meta tags for all pages, add the `metatags` field to your `docs.json`.

```json theme={null}
"seo": {
    "metatags": {
        "og:image": "link to your default meta tag image"
    }
}
```

### Verify site ownership

To verify your site with services like Google Search Console, Bing Webmaster Tools, or other search engines, add the verification meta tag to `seo.metatags` in your `docs.json`. Mintlify injects the tag into every page.

```json theme={null}
"seo": {
    "metatags": {
        "google-site-verification": "your_verification_token"
    }
}
```

### Set a canonical URL

A canonical URL tells search engines which version of your documentation is the primary one. This improves SEO when your documentation is accessible from multiple URLs and prevents issues with duplicate content.

**Global canonical**

If you're using a custom domain, set the `canonical` meta tag in your `docs.json` to ensure search engines index your preferred domain. Mintlify appends each page's path to this base URL.

```json theme={null}
"seo": {
    "metatags": {
        "canonical": "https://www.your-custom-domain-here.com"
    }
}
```

**Per-page canonical**

To set a canonical URL for a specific page, add `canonical` to that page's frontmatter. This overrides the global canonical and any auto-generated canonical for that page. This is useful for versioned documentation where you want older version pages to point to their equivalent on the latest version.

```yaml theme={null}
---
title: "My Page"
canonical: "https://docs.example.com/latest/my-page"
---
```

<Note>
  Always verify canonical URL behavior on your deployed site. Local builds add `/src/_props` to URLs as an artifact that are not part of the canonical URL.
</Note>

## Page-specific meta tags

To set page-specific meta tags, add them to a page's frontmatter.

Page-specific meta tags include:

* `title` - Page title
* `description` - Page description appears below the title on the page and in some search engine results
* `canonical` - Canonical URL for this page, overrides the auto-generated canonical
* `keywords` - Comma-separated keywords
* `og:title` - Open Graph title for social sharing
* `og:description` - Open Graph description, falls back to `description`
* `og:image` - Open Graph image URL
* `og:url` - Open Graph URL
* `og:type` - Open Graph type like "article" or "website"
* `og:image:width` - Open Graph image width
* `og:image:height` - Open Graph image height
* `twitter:title` - Twitter card title, falls back to `og:title`, then `title`
* `twitter:description` - Twitter card description, falls back to `og:description`, then `description`
* `twitter:image` - Twitter card image
* `twitter:card` - Twitter card type like `summary` or `summary_large_image`
* `twitter:site` - Twitter site handle
* `twitter:image:width` - Twitter image width
* `twitter:image:height` - Twitter image height
* `noindex` - Set to `true` to prevent search engine indexing
* `robots` - Robots meta tag value

<Tip>
  Twitter meta tags automatically inherit from their Open Graph equivalents. For example, if you set `og:title` but not `twitter:title`, the Twitter card uses your `og:title` value. Set `twitter:title` or `twitter:description` explicitly only when you want different text on Twitter than on other platforms.
</Tip>

```mdx theme={null}
---
title: "Your example page title"
description: "Page-specific description"
"og:title": "Social media title"
"og:description": "Custom description for social sharing"
"og:image": "link to your meta tag image"
"twitter:title": "Twitter-specific title"
keywords: ["keyword1", "keyword2"]
---
```

<Note>
  You must wrap meta tags with colons in quotes. For example, `og:title: "Social media title"`.

  You must format the `keywords` field as a YAML array. For example, `keywords: ["keyword1", "keyword2", "keyword3"]`.
</Note>

## Common meta tags reference

Below is a comprehensive list of meta tags you can add to your `docs.json`. These meta tags help improve your site's SEO, social sharing, and browser compatibility.

<Tip>
  Setting `og:image` in meta tags replaces the auto-generated social preview with a static image. If you want a custom **background image** that Mintlify automatically overlays with your logo, page title, and description, use [`thumbnails.background`](/docs/organize/settings-reference#thumbnails-background) in your `docs.json` instead.
</Tip>

You can preview how your meta tags appear on different platforms using [metatags.io](https://metatags.io/).

```json expandable theme={null}
"seo": {
    "metatags": {
      "robots": "noindex",
      "charset": "UTF-8",
      "viewport": "width=device-width, initial-scale=1.0",
      "description": "Page description",
      "keywords": "keyword1, keyword2, keyword3",
      "author": "Author Name",
      "robots": "index, follow",
      "googlebot": "index, follow",
      "google": "notranslate",
      "google-site-verification": "verification_token",
      "generator": "Mintlify",
      "theme-color": "#000000",
      "color-scheme": "light dark",
      "canonical": "https://your-custom-domain-here.com",
      "format-detection": "telephone=no",
      "referrer": "origin",
      "refresh": "30",
      "rating": "general",
      "revisit-after": "7 days",
      "language": "en",
      "copyright": "Copyright 2024",
      "reply-to": "email@example.com",
      "distribution": "global",
      "coverage": "Worldwide",
      "category": "Technology",
      "target": "all",
      "HandheldFriendly": "True",
      "MobileOptimized": "320",
      "apple-mobile-web-app-capable": "yes",
      "apple-mobile-web-app-status-bar-style": "black",
      "apple-mobile-web-app-title": "App Title",
      "application-name": "App Name",
      "msapplication-TileColor": "#000000",
      "msapplication-TileImage": "path/to/tile.png",
      "msapplication-config": "path/to/browserconfig.xml",
      "og:title": "Open Graph Title",
      "og:type": "website",
      "og:url": "https://example.com",
      "og:image": "https://example.com/image.jpg",
      "og:description": "Open Graph Description",
      "og:site_name": "Site Name",
      "og:locale": "en_US",
      "og:video": "https://example.com/video.mp4",
      "og:audio": "https://example.com/audio.mp3",
      "twitter:card": "summary",
      "twitter:site": "@username",
      "twitter:creator": "@username",
      "twitter:title": "Twitter Title",
      "twitter:description": "Twitter Description",
      "twitter:image": "https://example.com/image.jpg",
      "twitter:image:alt": "Image Description",
      "twitter:player": "https://example.com/player",
      "twitter:player:width": "480",
      "twitter:player:height": "480",
      "twitter:app:name:iphone": "App Name",
      "twitter:app:id:iphone": "12345",
      "twitter:app:url:iphone": "app://",
      "article:published_time": "2024-01-01T00:00:00+00:00",
      "article:modified_time": "2024-01-02T00:00:00+00:00",
      "article:expiration_time": "2024-12-31T00:00:00+00:00",
      "article:author": "Author Name",
      "article:section": "Technology",
      "article:tag": "tag1, tag2, tag3",
      "book:author": "Author Name",
      "book:isbn": "1234567890",
      "book:release_date": "2024-01-01",
      "book:tag": "tag1, tag2, tag3",
      "profile:first_name": "John",
      "profile:last_name": "Doe",
      "profile:username": "johndoe",
      "profile:gender": "male",
      "music:duration": "205",
      "music:album": "Album Name",
      "music:album:disc": "1",
      "music:album:track": "1",
      "music:musician": "Artist Name",
      "music:song": "Song Name",
      "music:song:disc": "1",
      "music:song:track": "1",
      "video:actor": "Actor Name",
      "video:actor:role": "Role Name",
      "video:director": "Director Name",
      "video:writer": "Writer Name",
      "video:duration": "120",
      "video:release_date": "2024-01-01",
      "video:tag": "tag1, tag2, tag3",
      "video:series": "Series Name"
  }
}
```

## Sitemaps and robots.txt files

Mintlify automatically generates a `sitemap.xml` file and a `robots.txt` file. You can view your sitemap by appending `/sitemap.xml` to your documentation site's URL.

By default, Mintlify indexes only the pages you include in your `docs.json` navigation. It excludes [hidden pages](/docs/organize/hidden-pages) that exist in your repository but are not listed in your navigation from the following locations:

* Search engine sitemaps
* Internal documentation search
* [AI assistant](/docs/assistant/index) context
* [MCP server](/docs/ai/model-context-protocol) search results

To include hidden pages in search indexing, add `seo.indexing` to your `docs.json`:

```json theme={null}
"seo": {
    "indexing": "all"
}
```

To include only the pages under a specific hidden tab or group, set `searchable: true` on that tab or group. See [Search, SEO, and AI indexing](/docs/organize/hidden-pages#search-seo-and-ai-indexing) for details.

<Note>
  For documentation sites that require authentication, users must authenticate to access sitemaps and `robots.txt` files. Sitemaps exclude pages that belong to [user groups](/docs/deploy/authentication-setup#control-access-with-groups).
</Note>

### Trailing slash URLs

If your hosting setup serves every page with a trailing slash, such as `/quickstart/` instead of `/quickstart`, enable `seo.trailingSlash` in your `docs.json`. This makes the URLs Mintlify emits for SEO match.

```json theme={null}
"seo": {
    "trailingSlash": true
}
```

### Content-Signal directives

The auto-generated `robots.txt` includes [Content-Signal](https://contentsignals.org) directives that tell AI crawlers how they can use your documentation. These signals follow the Cloudflare Content Signals Policy and apply to all user agents:

```txt theme={null}
User-agent: *
Content-Signal: ai-train=yes, search=yes, ai-input=yes
```

The default signals opt your documentation in to:

* `ai-train=yes`: Training AI models.
* `search=yes`: Building search indexes.
* `ai-input=yes`: Generating AI answers, including in retrieval-augmented generation and AI assistants.

These defaults help AI tools like ChatGPT, Claude, and Perplexity discover and cite your documentation. To change the signals, [add a custom `robots.txt`](#custom-sitemaps-and-robotstxt-files) at the root of your project. Mintlify serves custom files as-is, without the default Content-Signal directives.

### Custom sitemaps and robots.txt files

To add a custom `sitemap.xml` or `robots.txt`, create the file at the root of your project. The custom file overrides the automatically generated file of the same name. If you delete it, the default file applies again.

<Tip>
  If your custom `robots.txt` blocks AI user agents like `GPTBot`, `ClaudeBot`, or `PerplexityBot`, AI tools cannot crawl your documentation and cannot cite it in answers. See [Allow AI agents in robots.txt](/docs/guides/geo#allow-ai-agents-in-robotstxt) for details.
</Tip>

## Disable indexing

To prevent search engines from indexing a page, add `noindex: true` to the [frontmatter](/docs/organize/pages) of the page.

```yaml theme={null}
---
noindex: true
---
```

<Tip>
  Mintlify automatically treats pages with `hidden: true` in their frontmatter as `noindex: true`. See [Hidden pages](/docs/organize/hidden-pages) for more details.
</Tip>

You can also specify `noindex` for all pages in your docs by setting the `metatags.robots` field to `"noindex"` in your `docs.json`:

```json theme={null}
"seo": {
    "metatags": {
      "robots": "noindex"
    }
  }
```

### Disable indexing for the entire project

To hide your entire deployment from search engines while keeping it publicly accessible, enable **Don't index project** on the [Add-ons](https://app.mintlify.com/settings/deployment/addons) page of your dashboard.

When enabled, your site:

* Renders every page with `noindex, nofollow` robots meta tags.
* Returns an empty `sitemap.xml`.
* Returns `404` for `llms.txt` and `llms-full.txt`.
* Clears your search index so pages no longer appear in internal search, the [assistant](/docs/assistant/index), or your [search MCP server](/docs/ai/model-context-protocol).
* Serves a site-wide disallow `robots.txt`:

Disable indexing when you need to keep a deployment online for internal review, staging, or limited sharing. This prevents the site from appearing in public search results or being used by AI tools as training or retrieval data.

<Note>
  Enabling or disabling indexing redeploys your site. Changes to indexing take effect after the redeployment completes.
</Note>

This setting works alongside other indexing controls:

* **Per-page `noindex`**: Page-level `noindex: true` in frontmatter continues to apply when the project-level setting is off. Project-level settings override per-page settings when enabled.
* **Custom `robots.txt`**: If you have a [custom `robots.txt`](#custom-sitemaps-and-robotstxt-files) at the root of your project, Mintlify serves it unchanged. Project-level settings do not replace custom `robots.txt` files, so you must update or remove custom files for crawler rules to match.

## SEO best practices

<AccordionGroup>
  <Accordion title="Write descriptive titles and descriptions">
    * Use clear, descriptive page titles (50-60 characters)
    * Write compelling descriptions (150-160 characters)
    * Include relevant keywords
    * Make each page title and description unique
  </Accordion>

  <Accordion title="Optimize your content structure">
    * Use proper heading hierarchy (H1 → H2 → H3)
    * Write for humans first, search engines second
    * Include relevant keywords in headings and content
    * Keep URLs short, descriptive, and organized hierarchically
    * Break up long content with subheadings and lists
  </Accordion>

  <Accordion title="Internal linking strategy">
    * Link to related pages within your documentation
    * Use descriptive anchor text instead of "click here"
    * Create topic clusters by linking related concepts
    * Use the automatic cross-referencing features
  </Accordion>

  <Accordion title="Image SEO">
    * Use descriptive filenames for images
    * Always include alt text for accessibility and SEO
    * Optimize image file sizes for faster loading
    * Use relevant images that support your content
  </Accordion>
</AccordionGroup>


# Concepts
Source: https://www.mintlify.com/docs/reference/concepts

Learn how Mintlify connects your organization, documentation repository, editing workflows, previews, deployments, analytics, and AI features.

Mintlify turns content in a Git repository into a documentation site. You can work from the editor in your browser, your local development environment, or prompt the Mintlify agent in Slack. All three workflows update the same repository. Mintlify builds your repository content into optimized experiences for people and agents.

```mermaid theme={null}
flowchart LR
  Editors["Browser editors, local editors, and Mintlify agent"] --> Repo[("Documentation repository")]
  Repo --> Build["Build and deployment"]
  Build --> Site["Live documentation site"]
  Site --> Readers["People"]
  Site --> AI["AI agents"]
```

## Organizations, deployments, and sites

An **organization** is the workspace for your team. It contains your members, organization-level settings, and one or more deployments.

A **deployment** is a documentation project in your organization. It connects a repository, content directory, and deployment branch to a published site. An organization can have multiple deployments for separate products or documentation properties.

A **live site** is the published output of a deployment. Mintlify provides a `.mintlify.site` URL by default. You can connect a [custom domain](/docs/customize/custom-domain) for your site. Sites include your content, navigation, search, and any features you enable, such as the assistant or API playground.

<Note>
  The documentation sometimes uses **project** as a general name for a deployment and its connected repository, configuration, and site.
</Note>

## The repository is the source of truth

Your documentation repository contains the files that define your site. Mintlify reads these files during every build.

* **Pages** are `.mdx` files. Each page contains content and frontmatter metadata.
* `docs.json` is the required configuration file. It controls navigation, appearance, integrations, API settings, and other site-wide behavior.
* **Assets** include images, videos, fonts, and downloadable files referenced by your pages.
* **API specifications** can generate API reference pages and interactive playgrounds from OpenAPI, AsyncAPI, or GraphQL schemas.
* **Reusable files** include snippets and custom React components that pages can import.

Your repository can contain unpublished files. A page appears in the site navigation only when you reference it in your [`docs.json`](/docs/organize/navigation) navigation; otherwise it is hidden. [Hidden pages](/docs/organize/hidden-pages) are reachable only by a direct link.

## Pages and navigation are separate

A **page** supplies the content at a URL. Its [frontmatter](/docs/organize/pages) controls page-level metadata and behavior, including its title, description, icon, and layout.

**Navigation** determines how readers move through pages. Configure navigation in your `docs.json` file using elements such as groups, tabs, dropdowns, products, versions, and languages. The file path identifies a page and its position in `docs.json` determines where it appears in the navigation.

This separation lets you reorganize the reader experience without moving files. It also lets you exclude utility pages from the navigation while keeping them available by URL.

## Editing and publishing are different stages

You can edit the same content through two primary workflows.

| Workflow          | Where you edit                     | How changes reach Git                                 | How you preview            |
| ----------------- | ---------------------------------- | ----------------------------------------------------- | -------------------------- |
| Editor            | Mintlify dashboard in your browser | The editor creates commits and can open pull requests | Live preview in the editor |
| Local development | Your preferred editor              | You commit and push with Git                          | `mint dev` CLI command     |

In the editor, changes **save** automatically but do not immediately update your repository or live site. When you **publish**, the editor writes the changes to Git. What happens next depends on your current branch and branch protection settings.

* On the **deployment branch**, publishing can trigger a build of the live site directly.
* On a **feature branch**, publishing can save changes to the branch or create a pull request for review.
* A **preview deployment** renders a pull request at a temporary URL so reviewers can inspect the result before merging.
* Merging a pull request into the deployment branch triggers a production deployment.

See [Branching and publishing](/docs/editor/branching-and-publishing) for the complete workflow.

## A build turns source files into reader experiences

When content reaches the deployment branch, Mintlify validates the project, renders the pages, and deploys the site. The same source content supports several ways of finding and consuming information:

* The documentation site renders pages for people on desktop and mobile.
* Search indexes the site so readers can find relevant pages.
* The assistant answers questions from the documentation and cites its sources.
* Markdown versions of pages, `llms.txt`, and `skill.md` help AI tools understand the content.
* A public MCP server lets compatible AI tools retrieve documentation as structured context.

Run [`mint validate`](/docs/cli/commands#mint-validate) and [`mint broken-links`](/docs/cli/commands#mint-broken-links) before publishing to catch common problems locally.

## Mintlify's AI features have different roles

Mintlify provides separate AI features for reading, writing, automation, and external tool access.

| Feature                                         | Used by                   | Purpose                                                                          | Changes content |
| ----------------------------------------------- | ------------------------- | -------------------------------------------------------------------------------- | --------------- |
| [Assistant](/docs/assistant)                         | Documentation readers     | Answers questions from your content                                              | No              |
| [Agent](/docs/agent)                                 | Documentation maintainers | Researches and proposes content or configuration updates                         | Yes             |
| [Automations](/docs/automations/index)               | Documentation maintainers | Runs the agent from a schedule, repository update, or integration event          | Yes             |
| [Search MCP server](/docs/ai/model-context-protocol) | Agents                    | Retrieves context from one published documentation site                          | No              |
| [Admin MCP server](/docs/ai/mintlify-mcp)            | Agents                    | Reads and updates deployments through authenticated tools                        | Yes             |
| [Mintlify Index](/docs/search-index)                 | Agents                    | Retrieves current technical context across all public Mintlify sites and the web | No              |

## Learn the terminology

See the [glossary](/docs/reference/glossary) for definitions of Mintlify, Git, publishing, navigation, API, and AI terms used throughout the documentation.


# Glossary
Source: https://www.mintlify.com/docs/reference/glossary

Definitions for Mintlify product, content, navigation, deployment, Git, API playground, and AI terminology used throughout the documentation.

Use this glossary as a quick reference for terms used in Mintlify and throughout this documentation. For an overview of how the parts fit together, see [Concepts](/docs/reference/concepts).

## A

### Admin MCP server

An authenticated [Model Context Protocol](#model-context-protocol-mcp) server that lets authorized AI tools read and update content and settings across one or more deployments in an organization. Changes happen on a branch and require a pull request to merge. See [Admin MCP server](/docs/ai/mintlify-mcp).

### Agent

An AI tool for documentation maintainers that researches, writes, validates, and publishes proposed changes. The agent can open a pull request or commit to the deployment branch, depending on your configuration. See [Agent](/docs/agent).

### Anchor

A persistent top-level navigation link to an internal or external destination. Anchors are one of the primary navigation patterns available in `docs.json`. See [Anchors](/docs/organize/navigation#anchors).

### Assistant

An AI interface for documentation readers that answers questions from your content. It cites relevant pages and can navigate users directly to the relevant content. The assistant does not edit your documentation. See [Assistant](/docs/assistant).

### Automation

A configured agent task that runs on a schedule, after a repository update, or in response to an event from a connected integration. See [Automations](/docs/automations/index).

## B

### Branch

A separate line of work in a Git repository. Use branches to make and review changes without affecting the live site. See [Git concepts](/docs/guides/git-concepts#branch).

### Build

The process that validates your project files and turns them into a deployable documentation site. A build can produce the live site or a preview deployment.

## C

### Commit

A saved snapshot of changes in a Git repository. Publishing from the web editor creates a commit. See [Git concepts](/docs/guides/git-concepts#commit).

### Component

A reusable MDX element for presenting structured or interactive content, such as a card, callout, accordion, tab, or code group. See [Components](/docs/components).

### Content directory

The directory in a repository that contains `docs.json` and the files for a Mintlify deployment. It can be the repository root or a configured subdirectory, such as `docs/` in a monorepo. See [Monorepo setup](/docs/deploy/monorepo).

### Context repository

An additional repository that the agent can read for background information when it performs a task. A context repository does not become part of the documentation site.

### Credits

Units that measure use of Mintlify AI features. Credits are pooled across an organization and shared by its deployments and members. See [Credits](/docs/credits).

### Custom domain

A domain, subdomain, or subpath that you connect to a Mintlify site instead of using its default `.mintlify.site` address. See [Custom domain](/docs/customize/custom-domain).

## D

### Dashboard

The authenticated Mintlify application where your team edits content, monitors deployments, manages members, and configures project and organization settings.

### Deployment

A documentation project within a Mintlify organization. A deployment connects source content and a deployment branch to a live site. The term can also refer to a specific build being published.

### Deployment branch

The Git branch used to build the live site, typically `main`. Changes pushed or merged into this branch trigger a production deployment. See [Deployment branch](/docs/guides/git-concepts#deployment-branch).

### `docs.json`

The required configuration file for a Mintlify site. It controls navigation, appearance, integrations, API settings, redirects, and other global behavior. See [`docs.json`](/docs/organize/settings).

### Dropdown

A top-level navigation structure that groups related sections in a menu. See [Dropdowns](/docs/organize/navigation#dropdowns).

## E

### Editor

The browser-based editor in the Mintlify dashboard. It provides collaborative editing, automatic saving, live previews, Git synchronization, and publishing workflows. See [Editor overview](/docs/editor).

## F

### Feature branch

Any branch other than the deployment branch that you use to prepare changes. Feature branches keep unfinished work separate from the live site.

### Frontmatter

YAML metadata at the beginning of an MDX page, enclosed by `---` lines. Frontmatter controls properties such as the page title, description, icon, and layout. See [Pages](/docs/organize/pages).

## G

### Group

A labeled collection of pages or nested groups in the sidebar. Groups organize related content within a navigation section. See [Groups](/docs/organize/navigation#groups).

## I

### Index

A search service for coding agents that retrieves current technical context from publisher-maintained documentation and the web through an MCP server or REST API. See [Index](/docs/search-index).

### Integration

A connection between Mintlify and another service. Integrations can provide analytics, chat, privacy controls, SDK examples, automation context, or automation triggers.

## L

### Language

A locale-specific version of your documentation configured in navigation. Languages create locale-based routes and a language switcher. See [Languages](/docs/organize/navigation#languages).

### Live preview

The continuously updated rendering of your unpublished edits inside the web editor. A live preview is not publicly deployed. See [Live preview](/docs/editor/live-preview).

### Live site

The production documentation site built from the deployment branch and available to readers at a Mintlify or custom domain.

### `llms.txt`

A generated text file that helps AI tools discover the most useful pages in a documentation site. `llms-full.txt` includes the content of all pages in one file. See [`llms.txt`](/docs/ai/llmstxt).

## M

### Markdown

A plain-text syntax for formatting content with elements such as headings, lists, links, and code blocks. Published Mintlify pages are also available as Markdown by appending `.md` to their URL.

### MDX

Markdown extended with JSX. Mintlify uses `.mdx` page files so you can combine standard Markdown with components and custom React elements.

### Merge

The Git operation that combines changes from one branch into another. Merging a feature branch into the deployment branch publishes its changes through a new build.

### Model Context Protocol (MCP)

An open protocol that lets AI applications connect to tools and data sources. Mintlify offers a read-only public MCP server for each published site and an authenticated admin MCP server for managing deployments.

## N

### Navigation

The hierarchy readers use to move through a documentation site. Configure navigation in your `docs.json` file with pages, groups, tabs, dropdowns, products, versions, languages, and anchors. See [Navigation](/docs/organize/navigation).

## O

### OpenAPI

A standard format for describing HTTP APIs. Mintlify can generate endpoint pages, request examples, and an interactive API playground from an OpenAPI document. See [OpenAPI setup](/docs/api-playground/openapi-setup).

### Organization

A Mintlify workspace that contains team members, organization-level settings, shared credits, and one or more deployments.

## P

### Page

An `.mdx` file that renders as a route on your documentation site. A page combines frontmatter, Markdown content, and optional components. See [Pages](/docs/organize/pages).

### Preview deployment

A temporary, shareable version of a site built from a pull request or selected branch. It lets reviewers inspect changes before they reach the live site. See [Preview deployments](/docs/deploy/preview-deployments).

### Product

A top-level navigation structure for publishing documentation for multiple distinct products in one deployment. Each product has its own navigation. See [Products](/docs/organize/navigation#products).

### Project

A general term for a Mintlify deployment and its connected repository, configuration, and site. In dashboard settings and APIs, **deployment** is usually the more specific term.

### Publish

To write documentation changes to Git so they can progress toward the live site. Depending on the branch and review settings, publishing can deploy directly, save a commit to a branch, or create a pull request.

### Pull request

A proposal to merge changes from one Git branch into another. Pull requests support review, discussion, automated checks, and preview deployments before changes reach the deployment branch. GitLab calls this a **merge request**.

## R

### Redirect

A rule that sends visitors from an old or alternate URL to a new destination. Redirects preserve working links when content moves. See [Redirects](/docs/create/redirects).

### Repository

A collection of files and their Git history. The documentation repository is the source of truth for a Mintlify site and contains its pages, configuration, and assets.

### Reusable snippet

Content stored in a separate file and imported into one or more MDX pages. Updating the source snippet updates every page that uses it. See [Reusable snippets](/docs/create/reusable-snippets).

## S

### `skill.md`

A generated file that describes a product's capabilities and documentation for AI agents. Users can install it as an agent skill to improve results when working with the product. See [`skill.md`](/docs/ai/skillmd).

### Source repository

The repository that contains the product code, API definitions, or other material described by the documentation. The agent can use a connected source repository as context without publishing its files on the documentation site.

## T

### Tab

A top-level navigation section for parallel areas of documentation that serve the same audience, such as guides and API reference. See [Tabs](/docs/organize/navigation#tabs).

### Theme

The base layout and visual system for a documentation site. A theme controls the overall presentation, while colors, fonts, logos, and other settings customize it. See [Themes](/docs/customize/themes).

## V

### Version

A navigation structure for publishing multiple versions of the same documentation in parallel, such as `v1` and `v2`. See [Versions](/docs/organize/navigation#versions).


# Connect Mintlify Index to your coding agent
Source: https://www.mintlify.com/docs/search-index/connect

Set up the Mintlify Index MCP server in Claude Code, Cursor, VS Code, Codex, OpenCode, Windsurf, or Zed with the CLI or manual configuration.

Connect your coding agent to Mintlify Index so it can retrieve current technical documentation and web context while it plans and writes code. Index supports Claude Code, Cursor, VS Code, Codex, OpenCode, Windsurf, and Zed.

<Info>
  You do not need a Mintlify account or API key to connect to the public Index MCP server.
</Info>

## Set up with the CLI

Run the Index setup command to configure one or more coding agents in a single step:

```bash theme={null}
npx mint index
```

The command detects which supported coding agents you have installed and prompts you to select which ones to configure. For each selected agent, it adds the Index MCP server to that agent's configuration and installs a rule telling the agent when to use the `context` tool.

To skip the picker, pass one or more agent flags instead:

```bash theme={null}
npx mint index --claude --cursor
```

| Flag         | Coding agent |
| ------------ | ------------ |
| `--claude`   | Claude Code  |
| `--cursor`   | Cursor       |
| `--vscode`   | VS Code      |
| `--codex`    | Codex        |
| `--opencode` | OpenCode     |
| `--windsurf` | Windsurf     |
| `--zed`      | Zed          |

<Tip>
  Add `--yes` to configure every detected agent without prompting, or `--project` to write the configuration to the current project instead of your global agent settings. Not every agent supports project-level configuration. Those agents always receive the global configuration.
</Tip>

Run the command again to update an existing setup or add another agent.

## Set up manually

To configure Claude Code or Cursor manually, or to verify what the CLI changed, follow the steps for your agent.

<Tabs>
  <Tab title="Claude Code" icon="terminal">
    <Steps>
      <Step title="Add the server">
        Run the following command:

        ```bash theme={null}
        claude mcp add --transport http mintlify-index https://index.mintlify.com
        ```
      </Step>

      <Step title="Verify the connection">
        List your configured MCP servers:

        ```bash theme={null}
        claude mcp list
        ```

        The output should include `mintlify-index` with a connected status.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Cursor" icon="mouse-pointer-2">
    Click **Install in Cursor**, review the MCP configuration, and approve the installation.

    <PreviewButton href="cursor://anysphere.cursor-deeplink/mcp/install?name=mintlify-index&config=eyJ1cmwiOiJodHRwczovL2luZGV4Lm1pbnRsaWZ5LmNvbSJ9">Install in Cursor</PreviewButton>

    To configure Cursor manually instead:

    <Steps>
      <Step title="Open MCP settings">
        1. Open the command palette with <kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> on Windows).
        2. Search for **Open MCP settings**.
        3. Click **Add custom MCP** to open `mcp.json`.
      </Step>

      <Step title="Add Mintlify Index">
        Add the following server:

        ```json theme={null}
        {
          "mcpServers": {
            "mintlify-index": {
              "url": "https://index.mintlify.com"
            }
          }
        }
        ```
      </Step>

      <Step title="Verify the connection">
        Reload Cursor, then open **Settings → Tools & MCP**. The `mintlify-index` server should show as connected with the `context` tool available.
      </Step>
    </Steps>
  </Tab>
</Tabs>

## Use Index in a session

Ask an implementation question and tell your agent to use Index when you want to ensure it retrieves current sources. For example:

```text theme={null}
Use Mintlify Index to find the current recommended way to configure caching in Next.js 16. Cite the sources you use.
```

The agent calls the Index `context` tool when it needs technical context and includes the returned source links in its work.

## Remove the connection

<Tabs>
  <Tab title="Claude Code" icon="terminal">
    Run the following command:

    ```bash theme={null}
    claude mcp remove mintlify-index
    ```
  </Tab>

  <Tab title="Cursor" icon="mouse-pointer-2">
    Open **Settings → Tools & MCP**, then delete the `mintlify-index` entry from `mcp.json`.
  </Tab>
</Tabs>

For VS Code, Codex, OpenCode, Windsurf, or Zed, remove the `mintlify-index` entry from that agent's MCP server configuration.

See the [Index MCP reference](/docs/search-index/mcp) for tool inputs and rate limits.


# Index
Source: https://www.mintlify.com/docs/search-index/index

Give coding agents current technical context from publisher-maintained documentation and the web through one MCP server or REST API.

Mintlify Index gives coding agents one search layer for technical knowledge. It routes questions about indexed products to publisher-maintained documentation hosted on Mintlify and uses web search for questions outside that corpus.

Use Index through the public MCP server or the access-controlled REST API.

* **MCP server**: Connect an AI tool and let it retrieve source-cited context while you work. Publicly available. Does not require an API key.
* **REST API**: Search for ranked sources, assemble context within a token budget, or retrieve the contents of selected results. Access-controlled. Requires an [Index API key](/docs/api/search-index/introduction#authentication).

## Get started

<CardGroup>
  <Card title="Connect your coding agent" icon="plug-zap" href="/search-index/connect">
    Add Index to Claude Code, Codex, Cursor, and other coding agents.
  </Card>

  <Card title="MCP reference" icon="book-open" href="/search-index/mcp">
    Review the `context` tool, input fields, output, and rate limits.
  </Card>

  <Card title="REST API" icon="file-braces" href="/api/search-index/introduction">
    Use `search`, `context`, and `contents` in an application or agent.
  </Card>
</CardGroup>

## How Index retrieves context

<Steps>
  <Step title="Route the question">
    Index identifies whether the question concerns a product in its documentation collection or requires broader web results.
  </Step>

  <Step title="Retrieve relevant sources">
    Product-specific questions search current documentation from the publisher. Other questions search the web.
  </Step>

  <Step title="Return agent-ready context">
    Index ranks the results and returns source URLs with the relevant content. The MCP `context` tool and REST `context` endpoint assemble that content within a token budget.
  </Step>
</Steps>

## Choose a retrieval operation

* **[`context`](/docs/api/search-index/context)**: Use this for most agent tasks. It returns a compact set of cited source material in one request.
* **[`search`](/docs/api/search-index/search)**: Use this when your application needs ranked results and controls which sources to read. Available through the REST API.
* **[`contents`](/docs/api/search-index/contents)**: Use this after `search` to retrieve content for selected Mintlify result IDs or result URLs. Available through the REST API.


# Mintlify Index MCP server
Source: https://www.mintlify.com/docs/search-index/mcp

Reference for the public Mintlify Index MCP server: connection URL, the context tool, parameters, response format, rate limits, and usage examples.

The Mintlify Index MCP server gives AI tools read-only access to technical documentation and web context. Connect to it at:

```text theme={null}
https://index.mintlify.com
```

You do not need to authenticate to the public server. See [Connect](/docs/search-index/connect) for Claude Code and Cursor setup instructions.

<Note>
  The Index MCP searches across covered product documentation and the technical web. To search only the content on a specific Mintlify-hosted site, use that site's [search MCP server](/docs/ai/model-context-protocol).
</Note>

## `context` tool

Use `context` to research an implementation task and return compact, source-cited context in one call. The tool is read-only and can access the open web.

<ParamField type="string">
  Implementation question to research.
</ParamField>

<ParamField type="string">
  Product or company name to use as an additional retrieval hint.
</ParamField>

<ParamField type="string[]">
  Domains to include in retrieval. When set, retrieval limits results to these domains.
</ParamField>

<ParamField type="string[]">
  Domains to exclude from retrieval.
</ParamField>

<ParamField type="integer">
  Maximum number of tokens to return. The maximum value is `6000`. Use the default for focused questions and a larger budget for complex, multi-part tasks.
</ParamField>

### Output

The tool returns Markdown-formatted context assembled from ranked sources. Each section includes a title, source URL, and the relevant source content.

```text theme={null}
### Configure caching

Source: https://nextjs.org/docs/app/getting-started/caching-and-revalidating

Relevant source content appears here.

--------------------------------
```

The MCP server returns source material for the connected agent to use. The agent decides how to apply that context to your task.

## Rate limits

Index applies the following per-IP limits to the public MCP server:

| Window     |          Limit |
| ---------- | -------------: |
| Per second |    10 requests |
| Per day    | 1,000 requests |

Requests exceeding either limit return `429 Too Many Requests`. Wait before retrying, and use exponential backoff for automated clients.

## Protocol behavior

The Index MCP uses stateless Streamable HTTP:

* Send each JSON Remote Procedure Call (JSON-RPC) request as an HTTP `POST`.
* Send one JSON-RPC request per HTTP request. Batching is not supported.
* Do not persist or send an MCP session ID between requests.


# Get unique visitors
Source: https://www.mintlify.com/docs/api/analytics/visitors

analytics.openapi.json GET /v1/analytics/{projectId}/visitors
Returns per-path and site-wide approximate distinct visitors by traffic type. The `total` field is deduplicated across human and AI (union of distinct visitor IDs with any qualifying content view).

Authenticate with an admin API key.

## Usage

Use this endpoint to export unique visitor analytics. Results include both site-wide totals and per-page breakdowns, split by human and AI traffic. The `total` field is deduplicated across human and AI traffic.

Paginate through results using offset-based pagination. Increment `offset` by `limit` while `hasMore` is true.

## Filtering

Filter visitor data by date range using `dateFrom` and `dateTo` parameters.

## Rate limits

This endpoint allows 100 requests per organization per hour. All analytics endpoints share this limit.


# Generate export bundle
Source: https://www.mintlify.com/docs/api/static-export/generate-bundle

static-export-openapi.json POST /static-export/jobs/{jobId}/bundle
Package a completed static export job into a single archive and return a download link. The link is a presigned S3 URL — download it before `expiresAt`.

The job must have a `status` of `completed` before a bundle can be generated.

Static export is available on Enterprise plans.

Authenticate with an admin API key.

<Info>
  This endpoint is in private beta and requires an enterprise agreement. Please contact [sales@mintlify.com](mailto:sales@mintlify.com) to inquire further.
</Info>


# Get static export job status
Source: https://www.mintlify.com/docs/api/static-export/get-job-status

static-export-openapi.json GET /static-export/jobs/{jobId}
Retrieve the current status and progress of a static export job. Poll this endpoint after starting a job until `status` is `completed` (or `failed`).

Static export is available on Enterprise plans.

Authenticate with an admin API key.

<Info>
  This endpoint is in private beta and requires an enterprise agreement. Please contact [sales@mintlify.com](mailto:sales@mintlify.com) to inquire further.
</Info>


# Static export
Source: https://www.mintlify.com/docs/api/static-export/overview

Generate a self-contained static export of your documentation and download it as a single bundle through the Mintlify REST API for self-hosting.

<Info>
  Static export is in private beta and requires an enterprise agreement. Please contact [sales@mintlify.com](mailto:sales@mintlify.com) to inquire further.
</Info>

Use the static export API to programmatically pre-render your site into a self-contained set of static files and download the result as a single bundle. The exported bundle is pure HTML, CSS, and JavaScript with no runtime dependencies, so you can host it on any static file storage or CDN.

## Page URLs in static bundles

Static exports use `.html` URLs that match the files in the bundle. For example, `/guides/getting-started` becomes `/guides/getting-started.html`. This happens automatically and requires no configuration.

<Note>
  Canonical and sitemap URLs remain extensionless. CloudFront resolves these URLs automatically, but other static hosts may require rewrite rules.
</Note>

## How static export works

A static export runs as an asynchronous job. You start the job, poll for its status, and then generate a downloadable bundle once the job completes.

<Steps>
  <Step title="Start a static export job">
    Call [Start static export job](/docs/api/static-export/start-job) with the domain you want to export. The API queues the job and returns a `jobId`.
  </Step>

  <Step title="Query the job status">
    Poll [Get static export job status](/docs/api/static-export/get-job-status) with the `jobId` until `status` is `completed`. The response includes live `progress` and `pageCount` while the job runs.
  </Step>

  <Step title="Generate the bundle">
    Call [Generate export bundle](/docs/api/static-export/generate-bundle) with the `jobId`. The API packages the export into a single archive and returns `bundleUrl`, a presigned S3 link to the static export bundle, alongside an `expiresAt` timestamp. Download the bundle before the `expiresAt` time. After the `expiresAt` time, call [Generate export bundle](/docs/api/static-export/generate-bundle) again to get a fresh link. The underlying job and its files remain reusable. Only the link is time-limited.
  </Step>
</Steps>

## Feature support by deployment

Which features are available depends on how you host your deployment. Air-gapped deployments have no outbound network access, so anything that relies on Mintlify's cloud services is unavailable. Features labeled **Configurable** have different availability depending on your environment's setup.

| Feature                   |         Cloud         |     Client-hosted     |       Air-gapped      |
| ------------------------- | :-------------------: | :-------------------: | :-------------------: |
| Documentation search      | <Icon icon="check" /> |      Configurable     |   <Icon icon="x" />   |
| AI assistant              | <Icon icon="check" /> |      Configurable     |   <Icon icon="x" />   |
| Web analytics             | <Icon icon="check" /> |      Configurable     |   <Icon icon="x" />   |
| API playground ("Try it") | <Icon icon="check" /> | <Icon icon="check" /> |      Configurable     |
| Static export bundle      | <Icon icon="check" /> | <Icon icon="check" /> | <Icon icon="check" /> |

## Endpoints

* [Start static export job](/docs/api/static-export/start-job): Start a static export job for a deployment.
* [Get static export job status](/docs/api/static-export/get-job-status): Poll the status and progress of a running job.
* [Generate export bundle](/docs/api/static-export/generate-bundle): Package a completed job and return a single S3 link to the bundle.

## Authentication

Authenticate requests with your admin API key. Generate an admin API key on the [API keys page](https://app.mintlify.com/settings/organization/api-keys) in your dashboard. Admin API keys begin with the `mint_` prefix and are server-side secrets—do not expose them in client-side code.

## Deploy the bundle to your Enterprise Helm chart

Self-hosted Mintlify deploys with the Helm chart in the [`mintlify/enterprise`](https://github.com/mintlify/enterprise) repository. Once a static export job produces a bundle, you point the chart at the bundle and the deployment serves it from your own infrastructure.

<Steps>
  <Step title="Add the bundle reference to your values">
    Set the static export fields in your `values.yaml` to the `bundleUrl` returned by [Generate export bundle](/docs/api/static-export/generate-bundle). The chart fetches the bundle on startup and serves it as the active version.

    ```yaml values.yaml theme={null}
    staticExport:
      enabled: true
      # Presigned S3 link returned by the Generate export bundle endpoint.
      bundleUrl: "https://mintlify-static-exports.s3.amazonaws.com/se_3f9a2c1b8e7d4a06/bundle.tar.gz"
      # Optional: pin to a specific export version for reproducible rollouts.
      version: "2024-06-01"
    ```
  </Step>

  <Step title="Roll out the chart">
    Apply the updated values with a `helm upgrade`. The deployment downloads the bundle, swaps it in as the live site, and serves it from your cluster.

    ```bash theme={null}
    helm upgrade --install mintlify mintlify/enterprise \
      --namespace mintlify \
      --create-namespace \
      -f values.yaml
    ```
  </Step>
</Steps>

Because presigned links expire, regenerate the bundle and re-run the upgrade whenever you publish new content or automate the loop with GitHub Actions.

## Automate with a GitHub Action

The following template workflow runs the full export loop on a schedule or on demand. It starts a job, polls until the export completes, generates a bundle, and rolls the new `bundleUrl` into the Helm chart.

```yaml .github/workflows/static-export.yml theme={null}
name: Publish static export

on:
  workflow_dispatch:
  schedule:
    - cron: "0 6 * * *" # Daily at 06:00 UTC

jobs:
  export:
    runs-on: ubuntu-latest
    steps:
      - name: Start static export job
        id: start
        run: |
          JOB_ID=$(curl -s -X POST https://api.mintlify.com/v1/static-export/jobs \
            -H "Authorization: Bearer ${{ secrets.MINTLIFY_ADMIN_KEY }}" \
            -H "Content-Type: application/json" \
            -d '{"domain": "docs.example.com"}' | jq -r '.jobId')
          echo "job_id=$JOB_ID" >> "$GITHUB_OUTPUT"

      - name: Wait for the job to complete
        run: |
          for i in $(seq 1 60); do
            STATUS=$(curl -s https://api.mintlify.com/v1/static-export/jobs/${{ steps.start.outputs.job_id }} \
              -H "Authorization: Bearer ${{ secrets.MINTLIFY_ADMIN_KEY }}" | jq -r '.status')
            echo "status=$STATUS"
            [ "$STATUS" = "completed" ] && exit 0
            [ "$STATUS" = "failed" ] && exit 1
            sleep 10
          done
          echo "Timed out waiting for the export job to complete." >&2
          exit 1

      - name: Generate the bundle
        id: bundle
        run: |
          BUNDLE_URL=$(curl -s -X POST \
            https://api.mintlify.com/v1/static-export/jobs/${{ steps.start.outputs.job_id }}/bundle \
            -H "Authorization: Bearer ${{ secrets.MINTLIFY_ADMIN_KEY }}" | jq -r '.bundleUrl')
          echo "bundle_url=$BUNDLE_URL" >> "$GITHUB_OUTPUT"

      - name: Deploy to the Helm chart
        run: |
          helm upgrade --install mintlify mintlify/enterprise \
            --namespace mintlify \
            --set staticExport.enabled=true \
            --set staticExport.bundleUrl="${{ steps.bundle.outputs.bundle_url }}"
```

Store your admin API key as the `MINTLIFY_ADMIN_KEY` repository secret. Before deploying, configure cluster credentials, for example with `azure/setup-helm` and your Kubernetes configuration file (`kubeconfig`).


# Start static export job
Source: https://www.mintlify.com/docs/api/static-export/start-job

static-export-openapi.json POST /static-export/jobs
Start a static export job for a deployment. The job pre-renders your documentation into a self-contained set of static HTML, RSC, and asset files. Returns a job ID you can use to poll status and, once complete, generate a downloadable bundle.

Static export is available on Enterprise plans.

Authenticate with an admin API key.

<Info>
  This endpoint is in private beta and requires an enterprise agreement. Please contact [sales@mintlify.com](mailto:sales@mintlify.com) to inquire further.
</Info>


# Changelogs
Source: https://www.mintlify.com/docs/create/changelogs

Create product changelogs with date-based entries, RSS feed support, and subscriber notifications to keep users informed about updates.

Create a changelog for your docs by adding [Update components](/docs/components/update) to a page.

See the [Mintlify changelog](/docs/changelog) as an example: you can include links, images, text, and demos of your new features in each update.

## Set up your changelog

<Steps>
  <Step title="Create a page for your changelog">
    1. Create a new page in your docs such as `changelog.mdx` or `updates.mdx`.
    2. Add your changelog page to your navigation scheme in your `docs.json`.
  </Step>

  <Step title="Add Update components to your changelog">
    Add an `Update` for each changelog entry.

    Include relevant information like feature releases, bug fixes, or other announcements.
  </Step>
</Steps>

```mdx Example changelog.mdx theme={null}
---
title: "Changelog"
description: "Product updates and announcements"
---
<Update label="March 2025" description="v0.0.10">
  Added a new Wintergreen flavor.

  Released a new version of the Spearmint flavor, now with 10% more mint.
</Update>

<Update label="February 2025" description="v0.0.09">
  Released a new version of the Spearmint flavor.
</Update>
```

## Customize your changelog

Control how people navigate your changelog and stay up to date with your product information.

### Table of contents

Each `label` property for an `Update` automatically creates an entry in the right sidebar's table of contents. This is the default navigation for your changelog.

<Frame>
  <img alt="Changelog with table of contents displayed in light mode." />

  <img alt="Changelog with table of contents displayed in dark mode." />
</Frame>

### Tag filters

Add `tags` to your `Update` components to replace the table of contents with tag filters. Users can filter the changelog by selecting one or more tags.

When a user selects multiple tags, the changelog shows only updates that include every selected tag. The changelog hides updates without tags whenever a filter is active.

Selected tags are reflected in the page URL as a `?tags=` query parameter, so users can share deep links to a filtered view of the changelog. Opening a link like `/changelog?tags=Spearmint` activates matching sidebar filters on load, and updating filters keeps the URL in sync. Separate multiple tags with commas, for example `/changelog?tags=Spearmint,Peppermint`.

```mdx Tag filters example wrap theme={null}
<Update label="March 2025" description="v0.0.10" tags={["Wintergreen", "Spearmint"]}>
  Added a new Wintergreen flavor.

  Released a new version of the Spearmint flavor, now with 10% more mint.
</Update>

<Update label="February 2025" description="v0.0.09" tags={["Spearmint"]}>
  Released a new version of the Spearmint flavor.
</Update>

<Update label="January 2025" description="v0.0.08" tags={["Peppermint", "Spearmint"]}>
  Deprecated the Peppermint flavor.

  Released a new version of the Spearmint flavor.
</Update>
```

<Frame>
  <img alt="Changelog in light mode with the Peppermint tag filter selected." />

  <img alt="Changelog in dark mode with the Peppermint tag filter selected." />
</Frame>

<Tip>
  Using `custom`, `center`, or `wide` page modes hides the table of contents and changelog filters. Learn more about [page modes](/docs/organize/pages#page-mode).
</Tip>

### Subscribable changelogs

<Note>RSS feeds are only available on public documentation.</Note>

Use `Update` components to create a subscribable RSS feed at your page URL with `/rss.xml` appended. For example, `mintlify.com/docs/changelog/rss.xml`.

The RSS feed publishes entries when you add new `Update` components and when you modify headings inside of existing `Update` components.

RSS feed entries contain pure Markdown only. They exclude components, code, and HTML elements. Use the `rss` property to provide alternative text descriptions for RSS subscribers when your updates contain excluded content.

```xml Example RSS feed theme={null}
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Product updates]]></title>
    <description><![CDATA[New updates and improvements]]></description>
    <link>https://mintlify.com/docs</link>
    <generator>RSS for Node</generator>
    <lastBuildDate>Mon, 21 Jul 2025 21:21:47 GMT</lastBuildDate>
    <atom:link href="https://mintlify.com/docs/changelog/rss.xml" rel="self" type="application/rss+xml"/>
    <copyright><![CDATA[Mintlify]]></copyright>
    <docs>https://mintlify.com/docs</docs>
    <item>
      <title><![CDATA[June 2025]]></title>
      <link>https://mintlify.com/docs/changelog#june-2025</link>
      <guid isPermaLink="true">https://mintlify.com/docs/changelog#june-2025</guid>
      <pubDate>Mon, 23 Jun 2025 16:54:22 GMT</pubDate>
    </item>
  </channel>
</rss>
```

RSS feeds can integrate with Slack, email, or other subscription tools to notify users of product changes. Some options include:

* [Slack](https://slack.com/help/articles/218688467-Add-RSS-feeds-to-Slack)
* [Email](https://zapier.com/apps/email/integrations/rss/1441/send-new-rss-feed-entries-via-email) via Zapier
* Discord bots like [Readybot](https://readybot.io) or [RSS Feeds to Discord Bot](https://rss.app/en/bots/rssfeeds-discord-bot)

To make the RSS feed discoverable, you can display an RSS icon button that links to the feed at the top of the page. Add `rss: true` to the page frontmatter:

```mdx theme={null}
---
rss: true
---
```

<Frame>
  <img alt="Changelog page in light mode with RSS feed button enabled." />

  <img alt="Changelog page in dark mode with RSS feed button enabled." />
</Frame>


# How to create accessible documentation
Source: https://www.mintlify.com/docs/guides/accessibility

Create accessible documentation following WCAG guidelines with semantic HTML, keyboard navigation, alt text, and inclusive content practices.

Design accessible documentation so as many people as possible can use it, regardless of how they access and interact with it.

Accessible documentation improves the experience for everyone. Your content is clearer, better structured, and easier to navigate. This applies whether users access it with a screen reader, keyboard navigation, mobile device, or slow network connection.

This guide covers best practices for accessible documentation. Accessibility is an ongoing process. Technologies and standards evolve, and there are always opportunities to improve. Start with high-impact changes and build accessibility into your workflow.

## What is accessibility?

Accessibility is the practice of designing and building websites and tools that as many people as possible can use. The term is sometimes abbreviated as a11y, using the 11 letters between the first and last letters of "accessibility." People with temporary or permanent disabilities should have the same level of access to digital technologies. Accessibility also benefits everyone, including people who access your website on mobile devices or slow networks.

Accessible documentation follows web accessibility standards, primarily the [Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/WCAG22/quickref/). These guidelines help ensure your content is perceivable, operable, understandable, and robust.

## Get started with accessibility

Making your documentation accessible is a process. You don't have to fix everything all at once and you can't do it only once.

If you're just beginning to implement accessibility practices for your documentation, consider a phased approach where you start with high-impact changes and build from there.

### First steps

Here are three things you can do right now to improve the accessibility of your documentation:

1. **Run `mint a11y`** to identify accessibility issues in your content.
2. **Add alt text** to all images.
3. **Check your heading hierarchy** to ensure one H1 per page and headings follow sequential order.

### Plan your accessibility work

The best workflow is the one that works for your team. Here is one way that you can approach accessibility work:

**Phase 1: Images and structure**

* Review all images for descriptive alt text.
* Audit link text and replace generic phrases like "click here."
* Fix heading hierarchy issues across your documentation.

**Phase 2: Navigation and media**

* Test keyboard navigation on your documentation.
* Test screen reader support.
* Add captions and transcripts to embedded videos.
* Review color contrast.

**Phase 3: Build it into your workflow**

* Run `mint a11y` before publishing new content.
* Include accessibility checks in your content review process.
* Test keyboard navigation when adding interactive features.
* Verify new external links and embeds include proper titles and descriptions.

Starting small and building accessibility into your regular workflow makes it sustainable. Each improvement helps more users access your documentation successfully.

## Structure your content

Well-structured content is easier to navigate and understand, especially for screen reader users who rely on headings to move through pages and people who use keyboard navigation.

### Use proper heading hierarchy

Each page should have a single H1 heading, which comes from the `title:` property in a page's frontmatter. Use additional headings in order without skipping. For example, don't skip from H2 to H4.

```mdx theme={null}
<!-- Good -->
# Page title (H1)

## Main section (H2)

### Subsection (H3)

### Another subsection (H3)

## Another main section (H2)

<!-- Bad -->
# Page title (H1)

## Main section (H2)

#### Subsection (H4)

### Another subsection (H3)
```

Headings at the same level should have unique names.

```mdx theme={null}
<!-- Good -->
## Accessibility tips (H2)

### Write effective alt text (H3)

### Use proper color contrast (H3)

<!-- Bad -->
## Accessibility tips (H2)

### Tip (H3)

### Tip (H3)
```

### Write descriptive link text

Link text should be meaningful and connected to the destination. Avoid vague phrases like "click here" or "read more."

```mdx theme={null}
<!-- Good -->
Learn how to [configure your navigation](/organize/navigation).

<!-- Unclear relation between link text and destination -->
[Learn more](/organize/navigation).
```

### Keep content scannable

* Break up long paragraphs.
* Use lists for steps and options.
* Highlight information with callouts.

### Use proper table structure

Use tables sparingly and only for tabular data that has meaning inherited from the column and row headers.

When using tables, include headers so screen readers can associate data with the correct column:

<CodeGroup>
  ```mdx Good table structure theme={null}
  | Feature | Status | Last updated |
  | ------- | ------ | ------------ |
  | Search  | Active | 2024-03-15   |
  | Analytics | Active | 2024-03-10 |
  | Exports | Beta | 2024-03-20 |
  ```

  ```mdx Poor table structure theme={null}
  | Search | Active | 2024-03-15 |
  | Analytics | Active | 2024-03-10 |
  | Exports | Beta | 2024-03-20 |
  ```
</CodeGroup>

The poor example lacks headers, making it impossible for screen readers to announce what each column represents.

## Write descriptive alt text

Alt text makes images accessible to screen reader users and appears when images fail to load. Images in your documentation should have alt text that describes the image and makes it clear why you included the image. Even with alt text, you should not rely on images alone to convey information. Make sure your content describes what the image communicates.

<Tip>
  Learn more about working with images in the [media guide](/docs/guides/media).
</Tip>

### Write effective alt text

* **Be specific**: Describe what the image shows, not just that it's an image.
* **Be concise**: Aim for one to two sentences.
* **Avoid redundancy**: Don't start with "Image of" because screen readers already know that the alt text belongs to an image. However, you should include descriptions like "Screenshot of" or "Diagram of" if that context is important to the image.

```mdx theme={null}
<!-- Good -->
![Screenshot of the dashboard showing three active projects and two pending invitations](/images/dashboard.png)

<!-- Not helpful -->
![Dashboard screenshot](/images/dashboard.png)
```

### Add alt text to images

For Markdown images, include alt text in the square brackets:

```mdx theme={null}
![Description of the image](/path/to/image.png)
```

For HTML images, use the `alt` attribute:

```html theme={null}
<img
  src="/images/screenshot.png"
  alt="Settings panel with accessibility options enabled. The options are emphasized with an orange rectangle."
/>
```

### Add titles to embedded content

Iframes and video embeds require descriptive titles:

```html theme={null}
<iframe
  src="https://www.youtube.com/embed/example"
  title="Tutorial: Setting up your first documentation site"
></iframe>
```

## Design for readability

Visual design choices affect how accessible your documentation is to users with low vision, color blindness, or other visual disabilities.

### Ensure sufficient color contrast

If you customize your theme colors, verify the contrast ratios meet WCAG requirements:

* Body text: minimum 4.5:1 contrast ratio
* Large text: minimum 3:1 contrast ratio
* Interactive elements: minimum 3:1 contrast ratio

Test both light and dark mode. The `mint a11y` command checks for color contrast.

<CodeGroup>
  ```json Good contrast example theme={null}
  {
    "colors": {
      "primary": "#0066CC",
      "background": {
        "light": "#FFFFFF",
        "dark": "#1A1A1A"
      }
    }
  }
  ```

  ```json Poor contrast example theme={null}
  {
    "colors": {
      "primary": "#FFCC00",
      "background": {
        "light": "#FFFFFF",
        "dark": "#333333"
      }
    }
  }
  ```
</CodeGroup>

In the poor example, yellow (#FFCC00) on white has insufficient contrast. The dark mode background (#333333) is too light for optimal readability.

### Don't rely on color alone

If you use color to convey information, include a text label or icon as well. For example, don't mark errors only with red text. Include an error icon or the word "Error."

### Use clear, concise language

* Write in plain language.
* Define technical terms when first used.
* Avoid run-on sentences.
* Use active voice.

<Tip>
  See the [style and tone guide](/docs/guides/style-and-tone) for more writing best practices.
</Tip>

## Make code examples accessible

Code blocks are a core part of technical documentation, but they require specific accessibility considerations to ensure screen reader users can understand them. In general, follow these guidelines:

* Break long code examples into smaller, logical chunks.
* Comment complex logic within the code.
* Consider providing a text description for complex algorithms.
* When showing file structure, use actual code blocks with language labels rather than ASCII art.

### Specify the programming language

Always declare the language for syntax highlighting. This helps screen readers announce the code context to users:

````mdx theme={null}
```javascript
function getUserData(id) {
  return fetch(`/api/users/${id}`);
}
```
````

### Provide context around code

Provide clear context for code blocks:

````mdx theme={null}
The following function fetches user data from the API:

```javascript
function getUserData(id) {
  return fetch(`/api/users/${id}`);
}
```

This returns a promise that resolves to the user object.
````

## Video and multimedia accessibility

Videos, animations, and other multimedia content need text alternatives so all users can access the information they contain.

### Add captions to videos

Captions make video content accessible to users who are deaf or hard of hearing. They also help users in sound-sensitive environments and non-native speakers:

* Use captions for all spoken content in videos.
* Include relevant sound effects in captions.
* Ensure captions are synchronized with the audio.
* Use proper punctuation and speaker identification when multiple people speak.

Most video hosting platforms support adding captions. Upload caption files or use auto-generated captions as a starting point, then review for accuracy.

### Provide transcripts

Transcripts offer an alternative way to access video content. They're searchable, easier to reference, and accessible to screen readers:

```mdx theme={null}
<iframe
  src="https://www.youtube.com/embed/example"
  title="Tutorial: Setting up authentication"
></iframe>

<Accordion title="Video transcript">
In this tutorial, we'll walk through setting up authentication...
</Accordion>
```

Place transcripts near the video or provide a clear link to access them.

### Consider alternatives to video-only content

If critical information only appears in a video:

* Provide the same information in text form.
* Include key screenshots with descriptive alt text.
* Create a written tutorial that covers the same material.

This ensures users who can't access video content can still complete their task.

## Test your documentation

Regular testing helps you catch accessibility issues before users encounter them.

### Check for accessibility issues with `mint a11y`

Use the `mint a11y` CLI command to automatically scan your documentation for common accessibility issues:

```bash theme={null}
mint a11y
```

The command checks for:

* Missing alt text on images and videos.
* Insufficient color contrast.

#### Interpret the output

When the scan completes, you'll see a report like this:

```bash theme={null}
Accessibility Issues Found:

❌ Missing alt text (3 issues)
  - /guides/quickstart.mdx:45 - Image missing alt text
  - /api-reference/users.mdx:12 - Image missing alt text
  - /guides/setup.mdx:89 - Video missing title attribute

⚠️  Color contrast (2 issues)
  - Primary color (#FFCC00) on light background fails WCAG AA (2.1:1)
  - Link color (#FF6B6B) on dark background fails WCAG AA (3.2:1)

✅ 0 issues found in 15 other pages
```

#### Fix common issues

**Missing alt text**: Add descriptive alt text to the image or video:

```mdx theme={null}
<!-- Before -->
![](/images/dashboard.png)

<!-- After -->
![Dashboard showing three active projects and two pending invitations](/images/dashboard.png)
```

**Color contrast failures**: Update your theme colors in `docs.json`:

```json theme={null}
{
  "colors": {
    "primary": "#0066CC",  // Changed from #FFCC00
    "light": "#3399FF",
    "dark": "#004C99"
  }
}
```

Run `mint a11y` again to verify your fixes.

#### Use flags for targeted checks

Use flags to check for specific accessibility issues:

```bash theme={null}
# Check only for missing alt text
mint a11y --skip-contrast

# Check only for color contrast issues
mint a11y --skip-alt-text

# Fail CI/CD pipeline if issues are found
mint a11y --fail-on-error
```

### Basic keyboard navigation test

Navigate through your documentation using only your keyboard:

1. Press <kbd>Tab</kbd> to move forward through interactive elements.
2. Press <kbd>Shift</kbd> + <kbd>Tab</kbd> to move backward.
3. Press <kbd>Enter</kbd> to activate links and buttons.
4. Verify all interactive elements are reachable and have visible focus indicators.

### Go deeper with accessibility testing

For more comprehensive testing:

* **Screen readers**: Test with [NVDA (Windows)](https://www.nvaccess.org/) or [VoiceOver (Mac)](https://www.apple.com/accessibility/voiceover/).
* **Browser extensions**: Install [axe DevTools](https://www.deque.com/axe/browser-extensions/) or [WAVE](https://wave.webaim.org/extension/) to scan pages for issues.
* **WCAG guidelines**: Review the [Web Content Accessibility Guidelines](https://www.w3.org/WAI/WCAG22/quickref/) for detailed standards.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Do I need to make my documentation WCAG AA or AAA compliant?">
    Most organizations aim for WCAG 2.1 Level AA compliance, which is the standard for many legal requirements and provides a good balance of accessibility and feasibility. Level AAA is more stringent and may not be achievable for all content types.

    Start with Level AA as your baseline. The `mint a11y` command checks for common Level AA requirements like color contrast and alt text.
  </Accordion>

  <Accordion title="How do I test my documentation with a screen reader?">
    On Mac, use the built-in VoiceOver (press <kbd>Cmd</kbd> + <kbd>F5</kbd> to enable). On Windows, download [NVDA](https://www.nvaccess.org/) (free and open source). Navigate through your documentation using only the screen reader and listen for proper heading announcements, descriptive link text, alt text on images, and logical reading order. You don't need to be an expert to catch major issues.
  </Accordion>

  <Accordion title="What's the difference between alt text and image captions?">
    Screen readers read **alt text**, and it appears when images fail to load. It describes what the image shows and why it's relevant. Alt text is a requirement for accessibility.

    **Captions** appear below images for all users. They provide additional context, attribution, or explanation. Captions are optional and supplement alt text.

    Use both when an image needs description (alt text) and additional context (caption).
  </Accordion>

  <Accordion title="Can I use emojis in accessible documentation?">
    Yes, but sparingly. Screen readers announce emoji names out loud, so multiple emojis in a row become disruptive. For example, 🎉 becomes "party popper" and 🚀 becomes "rocket" so 🎉 🚀 becomes "party popper rocket." Avoid using emojis to convey critical information. If you remove the emoji, the meaning should still be clear. When in doubt, use text instead.
  </Accordion>

  <Accordion title="How do I handle accessibility for code examples?">
    Specify the language on every code block for syntax highlighting. Provide context before and after code blocks so screen reader users understand what the code does—screen readers often skim code itself. Break long examples into smaller chunks and use descriptive variable names that make sense when read aloud.
  </Accordion>

  <Accordion title="What if I can't fix all accessibility issues right away?">
    Prioritize by impact. Fix missing alt text, broken keyboard navigation, and insufficient color contrast first—these affect the most users. Poor heading hierarchy and vague link text come next. Document known issues with a plan to address them. Progress is better than perfection.
  </Accordion>
</AccordionGroup>

## Additional resources

Continue learning about accessibility with these trusted resources:

* **[WebAIM](https://webaim.org/)**: Practical articles and tutorials on web accessibility
* **[The A11y Project](https://www.a11yproject.com/)**: Community-driven accessibility resources and checklist
* **[W3C Web Accessibility Initiative (WAI)](https://www.w3.org/WAI/)**: Official accessibility standards and guidance


# Tutorial: Build an in-app documentation assistant
Source: https://www.mintlify.com/docs/guides/assistant-embed

Build and embed an in-app documentation assistant that answers user questions with cited information from your Mintlify documentation site.

## What you'll build

A reusable widget that embeds the [assistant](/docs/assistant/index) directly in your application. The widget provides:

* A floating button that opens a chat panel when clicked
* Real-time streaming responses based on information from your documentation
* Message rendering with Markdown support

Users can use the widget to get help with your product without leaving your application.

<Frame>
  <img alt="Demo of the assistant widget being opened and the user typing in How do I get started? Then the assistant responds." />
</Frame>

## Prerequisites

* The Mintlify assistant enabled
* Your domain name, which appears at the end of your dashboard URL. For example, if your dashboard URL is `https://app.mintlify.com/org-name/domain-name`, your domain name is `domain-name`
* An [assistant API key](https://app.mintlify.com/settings/organization/api-keys)
* Node.js v18 or higher and npm installed
* Basic React knowledge

### Get your assistant API key

1. Navigate to the [API keys](https://app.mintlify.com/settings/organization/api-keys) page in your dashboard.
2. Click **Create Assistant API Key**.
3. Copy the assistant API key (starts with `mint_dsc_`) and save it securely.

<Note>
  Your assistant API key controls access to your assistant quota. This tutorial keeps the key server-side using a backend proxy so it never reaches the client bundle.
</Note>

## Set up the example

Clone the [example repository](https://github.com/mintlify/assistant-embed-example) and customize it for your needs.

<Steps>
  <Step title="Clone the repository">
    ```bash theme={null}
    git clone https://github.com/mintlify/assistant-embed-example.git
    cd assistant-embed-example
    ```
  </Step>

  <Step title="Choose your development tool">
    The repository includes Next.js and Vite examples. Choose the tool you prefer to use.

    <CodeGroup>
      ```bash title="Next.js" theme={null}
      cd nextjs
      npm install
      ```

      ```bash title="Vite" theme={null}
      cd vite
      npm install
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure your project">
    Open `src/config.js` and update with your Mintlify project details.

    ```js src/config.js theme={null}
    export const ASSISTANT_CONFIG = {
      domain: 'your-domain',
      docsURL: 'https://yourdocs.mintlify.site',
    };
    ```

    Replace:

    * `your-domain` with your Mintlify project domain found at the end of your dashboard URL.
    * `https://yourdocs.mintlify.site` with your actual documentation URL.
  </Step>

  <Step title="Set up your API key">
    Store your assistant API key as a server-side environment variable. Avoid the `VITE_` prefix, which bundles the value into your client code:

    ```bash .env theme={null}
    MINTLIFY_TOKEN=mint_dsc_your_token_here
    ```

    Replace `mint_dsc_your_token_here` with your assistant API key.

    Then add a backend route (for example, `/api/assistant`) to proxy requests to the Mintlify API:

    1. Accept the user's message from the widget.
    2. Attach the `Authorization: Bearer $MINTLIFY_TOKEN` header and forward the request to `https://api.mintlify.com/discovery/v1/assistant/{domain}/message`.
    3. Stream the upstream response back to the client unchanged, so token streaming and `X-Thread-Id` / `X-Thread-Key` headers reach the widget.
    4. Point the widget's `api` option at your backend route instead of the Mintlify API directly.
  </Step>

  <Step title="Start the development server">
    ```bash theme={null}
    npm run dev
    ```

    Open your application in a browser and click the **Ask** button to open the assistant widget.
  </Step>
</Steps>

## Customization ideas

### Source citations

Extract and display sources from assistant responses:

```jsx theme={null}
const extractSources = (parts) => {
  return parts
    ?.filter(p => p.type === 'tool-invocation' && p.toolInvocation?.toolName === 'search')
    .flatMap(p => p.toolInvocation?.result || [])
    .map(source => ({
      url: source.url || source.path,
      title: source.metadata?.title || source.path,
    })) || [];
};

// In your message rendering:
{messages.map((message) => {
  const sources = message.role === 'assistant' ? extractSources(message.parts) : [];
  return (
    <div key={message.id}>
      {/* message content */}
      {sources.length > 0 && (
        <div className="mt-2 text-xs">
          <p className="font-semibold">Sources:</p>
          {sources.map((s, i) => (
            <a key={i} href={s.url} target="_blank" rel="noopener noreferrer" className="text-blue-600">
              {s.title}
            </a>
          ))}
        </div>
      )}
    </div>
  );
})}
```

### Track conversation threads

Store thread IDs and thread keys to maintain conversation history across sessions.

When a user creates a new conversation thread, the server returns two values in the response headers:

* `X-Thread-Id`: The thread identifier
* `X-Thread-Key`: A secret key for the thread (only returned once, when you create the thread)

You must capture and persist both values on the first response. On every subsequent message, include both `threadId` and `threadKey` in the request body. If you send a `threadId` without the corresponding `threadKey`, the server returns a `404` error.

<Warning>
  You must store the `X-Thread-Key` header immediately. The server only returns it when you create a new thread. You cannot retrieve it later.
</Warning>

```jsx theme={null}
import { useState, useEffect } from 'react';

export function AssistantWidget({ domain, docsURL }) {
  const [threadId, setThreadId] = useState(null);
  const [threadKey, setThreadKey] = useState(null);

  useEffect(() => {
    // Retrieve saved thread ID and key from localStorage
    const savedId = localStorage.getItem('assistant-thread-id');
    const savedKey = localStorage.getItem('assistant-thread-key');
    if (savedId && savedKey) {
      setThreadId(savedId);
      setThreadKey(savedKey);
    }
  }, []);

  const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
    api: '/api/assistant',
    body: {
      fp: 'anonymous',
      retrievalPageSize: 5,
      ...(threadId && { threadId }),
      ...(threadKey && { threadKey }),
    },
    streamProtocol: 'data',
    sendExtraMessageFields: true,
    fetch: async (url, options) => {
      const response = await fetch(url, options);
      const newThreadId = response.headers.get('x-thread-id');
      const newThreadKey = response.headers.get('x-thread-key');
      if (newThreadId) {
        setThreadId(newThreadId);
        localStorage.setItem('assistant-thread-id', newThreadId);
      }
      if (newThreadKey) {
        setThreadKey(newThreadKey);
        localStorage.setItem('assistant-thread-key', newThreadKey);
      }
      return response;
    },
  });

  // ... rest of component
}
```

### Add keyboard shortcuts

Allow users to open the widget and submit messages with keyboard shortcuts:

```jsx theme={null}
useEffect(() => {
  const handleKeyDown = (e) => {
    // Cmd/Ctrl + Shift + I to toggle widget
    if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === 'I') {
      e.preventDefault();
      setIsOpen((prev) => !prev);
    }

    // Enter (when widget is focused) to submit
    if (e.key === 'Enter' && !e.shiftKey && document.activeElement.id === 'assistant-input') {
      e.preventDefault();
      handleSubmit();
    }
  };

  window.addEventListener('keydown', handleKeyDown);
  return () => window.removeEventListener('keydown', handleKeyDown);
}, [handleSubmit]);
```


# Work with branches
Source: https://www.mintlify.com/docs/guides/branches

Create and manage documentation branches to preview changes, collaborate with teammates, and merge updates before publishing to production.

Branches are a feature of version control that point to specific commits in your repository. Your deployment branch, usually called `main`, represents the content used to build your live documentation site. All other branches are independent of your live docs unless you choose to merge them into your deployment branch.

Branches let you create separate instances of your documentation to make changes, get reviews, and try new approaches before publishing. Your team can work on branches to update different parts of your documentation simultaneously without affecting what users see on your live site.

The following diagram shows an example of a branch workflow where you create a feature branch, make changes, and then merge the feature branch into the main branch.

```mermaid theme={null}
gitGraph
    commit id: "Initial commit"
    commit id: "Branch created"
    branch feature-branch
    checkout feature-branch
    commit id: "Add Changes"
    commit id: "Add more changes"
    checkout main
    checkout feature-branch
    commit id: "Add reviewer feedback"
    checkout main
    merge feature-branch id: "Merge into main" type: HIGHLIGHT
    commit id: "Live docs"
```

Always work from branches when updating documentation to keep your live site stable and enable review workflows.

## Branch naming conventions

Use clear, descriptive names that explain the purpose of a branch.

**Use**:

* `fix-broken-links`
* `add-webhooks-guide`
* `reorganize-getting-started`
* `ticket-123-oauth-guide`

**Avoid**:

* `temp`
* `my-branch`
* `updates`
* `branch1`

## Create a branch

<Tabs>
  <Tab title="Using web editor">
    1. Click the branch name in the editor toolbar.
    2. Click **Create new branch**.
    3. Enter a descriptive name.
    4. If you have unsaved changes, choose whether to bring them to the new branch or leave them on your current branch.
    5. Click **Create branch**.
  </Tab>

  <Tab title="Using local development">
    <Steps>
      <Step title="Create a branch from your terminal">
        ```bash theme={null}
        git checkout -b branch-name
        ```

        This creates the branch and switches to it in one command.
      </Step>

      <Step title="Push the branch to GitHub">
        ```bash theme={null}
        git push -u origin branch-name
        ```

        The `-u` flag sets up tracking so future pushes just need `git push`.
      </Step>
    </Steps>
  </Tab>
</Tabs>

## Save changes on a branch

<Tabs>
  <Tab title="Using web editor">
    Click the **Save as commit** button in the top-right of the editor toolbar. This creates a commit and pushes your work to your branch automatically.
  </Tab>

  <Tab title="Using local development">
    Stage, commit, and push your changes.

    ```bash theme={null}
    git add .
    git commit -m "Describe your changes"
    git push
    ```
  </Tab>
</Tabs>

## Switch branches

<Tabs>
  <Tab title="Using web editor">
    1. Click the branch name in the editor toolbar to open the branch dropdown.
    2. Search for a branch by name or scroll through the list.
    3. Click the branch you want to switch to.

    Each branch in the dropdown displays a status indicator so you can see whether it is ready, syncing, or failed.

    <Warning>
      Unsaved changes are lost when switching branches. Save your work first.
    </Warning>
  </Tab>

  <Tab title="Using local development">
    Switch to an existing branch:

    ```bash theme={null}
    git checkout branch-name
    ```

    Or create and switch in one command:

    ```bash theme={null}
    git checkout -b new-branch-name
    ```
  </Tab>
</Tabs>

## Merge branches

Once your changes are ready to publish, create a pull request to merge your branch into the deployment branch.


# Write documentation with Claude Code
Source: https://www.mintlify.com/docs/guides/claude-code

Configure Claude Code with CLAUDE.md project instructions to write, review, and update your Mintlify documentation following your style guide.

Claude Code is an agentic command line tool that can help you maintain your documentation. It can write new content, review existing pages, and keep docs up to date.

You can train Claude Code to understand your documentation standards and workflows by adding a `CLAUDE.md` file to your project and refining it over time.

## Getting started

**Prerequisites:**

* Active Claude subscription (Pro, Max, or API access)

**Setup:**

1. Install Claude Code:

```bash theme={null}
npm install -g @anthropic-ai/claude-code
```

2. Navigate to your docs directory.
3. (Optional) Add the `CLAUDE.md` file below to your project.
4. Run `claude` to start.

<Tip>
  Once Claude Code is running, paste the following prompt to load the Mintlify skill, [search MCP](/docs/ai/model-context-protocol), and [admin MCP](/docs/ai/mintlify-mcp) into the session. This gives Claude full context on Mintlify components and your site's content.
</Tip>

<Prompt description="Install the Mintlify skill and MCP servers for AI coding tools.">
  Install the Mintlify skill for context on project structure, components, and documentation best practices:

  npx skills add [https://mintlify.com/docs](https://mintlify.com/docs)

  Add the Mintlify Docs MCP server for documentation search:

  [https://mintlify.com/docs/mcp](https://mintlify.com/docs/mcp)

  Add the Mintlify MCP server for dashboard access and content management:

  [https://mcp.mintlify.com](https://mcp.mintlify.com)
</Prompt>

To confirm your setup, send a prompt to Claude Code like `List the Mintlify components you can use`.

## Template for CLAUDE.md

Save a `CLAUDE.md` file at the root of your docs directory to help Claude Code understand your project. This file trains Claude Code on your documentation standards, preferences, and workflows. See [Manage Claude's memory](https://docs.anthropic.com/en/docs/claude-code/memory) in the Anthropic docs for more information.

Copy this example template or make changes for your docs specifications:

```mdx theme={null}
# Mintlify documentation

## Working relationship
- You can push back on ideas-this can lead to better documentation. Cite sources and explain your reasoning when you do so
- ALWAYS ask for clarification rather than making assumptions
- NEVER lie, guess, or make up anything

## Project context
- Format: MDX files with YAML frontmatter
- Config: docs.json for navigation, theme, settings
- Components: Mintlify components

## Content strategy
- Document just enough for user success - not too much, not too little
- Prioritize accuracy and usability
- Make content evergreen when possible
- Search for existing content before adding anything new. Avoid duplication unless it is done for a strategic reason
- Check existing patterns for consistency
- Start by making the smallest reasonable changes

## docs.json

- Refer to the [docs.json schema](https://mintlify.com/docs.json) when building the docs.json file and site navigation

## Frontmatter requirements for pages
- title: Clear, descriptive page title
- description: Concise summary for SEO/navigation

## Writing standards
- Second-person voice ("you")
- Prerequisites at start of procedural content
- Test all code examples before publishing
- Match style and formatting of existing pages
- Include both basic and advanced use cases
- Language tags on all code blocks
- Alt text on all images
- Relative paths for internal links

## Git workflow
- NEVER use --no-verify when committing
- Ask how to handle uncommitted changes before starting
- Create a new branch when no clear branch exists for changes
- Commit frequently throughout development
- NEVER skip or disable pre-commit hooks

## Do not
- Skip frontmatter on any MDX file
- Use absolute URLs for internal links
- Include untested code examples
- Make assumptions - always ask for clarification
```

## Sample prompts

Once you have Claude Code set up, try these prompts to see how it can help with common documentation tasks. You can copy and paste these examples directly, or adapt them for your specific needs.

### Convert notes to polished docs

Turn rough drafts into proper Markdown pages with components and frontmatter.

**Example prompt:**

```text wrap theme={null}
Convert this text into a properly formatted MDX page: [paste your text here]
```

### Review docs for consistency

Get suggestions to improve style, formatting, and component usage.

**Example prompt:**

```text wrap theme={null}
Review the files in docs/ and suggest improvements for consistency and clarity
```

### Update docs when features change

Keep documentation current when your product evolves.

**Example prompt:**

```text wrap theme={null}
Our API now requires a version parameter. Update our docs to include version=2024-01 in all examples
```

### Generate comprehensive code examples

Create multi-language examples with error handling.

**Example prompt:**

```text wrap theme={null}
Create code examples for [your API endpoint] in JavaScript, Python, and cURL with error handling
```

## Extend Claude Code

Beyond manually prompting Claude Code, you can integrate it with your existing workflows.

### Automate with GitHub Actions

Run Claude Code automatically when code changes to keep docs up to date. You can trigger documentation reviews on pull requests or update examples when APIs change.

### Multi-instance workflows

Use separate Claude Code sessions for different tasks - one for writing new content and another for reviewing and quality assurance. This helps maintain consistency and catch issues that a single session might miss.

### Team collaboration

Share your refined `CLAUDE.md` file with your team to ensure consistent documentation standards across all contributors. Teams often develop project-specific prompts and workflows that become part of their documentation process.

### Custom commands

Create reusable slash commands in `.claude/commands/` for frequently used documentation tasks specific to your project or team.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Do I need a CLAUDE.md file to use Claude Code with Mintlify?">
    No, but it significantly improves output quality. Without a CLAUDE.md, Claude Code works from general context and may not follow your specific style guide, component preferences, or terminology. A CLAUDE.md file trains Claude Code on your project's standards so you don't need to re-explain them in every prompt.
  </Accordion>

  <Accordion title="How is Claude Code different from Cursor or Devin Desktop for documentation?">
    Claude Code is a command-line tool designed for agentic, multi-step tasks across an entire repository. It's well-suited for tasks like auditing all pages for missing alt text, updating a parameter name across every code example, or reviewing a set of files for consistency. Cursor and Devin Desktop are IDE-based tools better suited for editing individual files with inline suggestions. Both approaches work—the right choice depends on whether your work is file-by-file or across the whole repo.
  </Accordion>

  <Accordion title="Can I use Claude Code to generate documentation from code automatically?">
    Yes. Claude Code can read your source code and generate corresponding documentation. Point it at an API endpoint, a configuration file, or a set of functions and ask it to produce matching documentation following your CLAUDE.md standards. Review and refine the output—automated generation works best when you treat Claude Code as a first draft author, not a final publisher.
  </Accordion>

  <Accordion title="How do I share my CLAUDE.md configuration with my team?">
    Commit the CLAUDE.md file to your documentation repository. Anyone who clones the repo and runs Claude Code automatically uses your project's configuration. This makes documentation standards consistent across contributors without requiring each person to set up their own context.
  </Accordion>
</AccordionGroup>


# Write documentation with Codex
Source: https://www.mintlify.com/docs/guides/codex

Configure OpenAI Codex CLI with project instructions and MCP to write Mintlify documentation that follows your style guide and MDX standards.

Use OpenAI's Codex CLI to write and maintain Mintlify documentation from the terminal. Project instructions in `AGENTS.md` give Codex persistent context about your documentation standards, components, and style guide.

## Getting started

**Prerequisites:**

* An OpenAI account with access to Codex

**Setup:**

1. Install the Codex CLI:

```bash theme={null}
npm install -g @openai/codex
```

2. Navigate to your docs directory.
3. (Optional) Add the `AGENTS.md` file below to your project.
4. Run `codex` to start a session.

See the [Codex CLI documentation](https://developers.openai.com/codex/cli) for installation alternatives and authentication options.

<Tip>
  Once Codex is running, paste the following prompt to load the Mintlify [skill](/docs/ai/skillmd), [search MCP](/docs/ai/model-context-protocol), and [admin MCP](/docs/ai/mintlify-mcp) into the session. This gives Codex full context on Mintlify components and your site's content.
</Tip>

<Prompt description="Install the Mintlify skill and MCP servers for AI coding tools.">
  Install the Mintlify skill for context on project structure, components, and documentation best practices:

  npx skills add [https://mintlify.com/docs](https://mintlify.com/docs)

  Add the Mintlify Docs MCP server for documentation search:

  [https://mintlify.com/docs/mcp](https://mintlify.com/docs/mcp)

  Add the Mintlify MCP server for dashboard access and content management:

  [https://mcp.mintlify.com](https://mcp.mintlify.com)
</Prompt>

## Use Codex with Mintlify

Codex reads `AGENTS.md` files from your repository to understand project-specific rules and conventions before it starts working. You can place an `AGENTS.md` at the root of your docs repo to give Codex context about Mintlify components, your writing standards, and how you structure your documentation.

Codex discovers `AGENTS.md` files at multiple levels:

* **Global instructions** in `~/.codex/AGENTS.md` apply to all your projects.
* **Project instructions** in your repo root (or any subdirectory) apply to work done in that scope.

Codex concatenates these files from root to the current directory, so project-level instructions extend or override global ones.

Create an `AGENTS.md` at the root of your docs repo and commit it so all contributors benefit from the same context. See [AGENTS.md](https://developers.openai.com/codex/guides/agents-md) in the Codex documentation for complete details.

## Example AGENTS.md

This file gives Codex context about Mintlify components and technical writing standards.

Customize it for your documentation:

* **Writing standards**: Update language guidelines to match your style guide.
* **Component patterns**: Add project-specific components or modify existing examples.
* **Code examples**: Replace generic examples with real API calls and responses for your product.
* **Style and tone preferences**: Adjust terminology, formatting, and other rules.

Save this as `AGENTS.md` at the root of your docs repo.

```markdown AGENTS.md theme={null}
# Mintlify documentation project

## Project context

- This is a documentation project on the Mintlify platform
- We use MDX files with YAML frontmatter
- Navigation is configured in `docs.json`
- We follow technical writing best practices

## Writing standards

- Use second person ("you") for instructions
- Write in active voice and present tense
- Use sentence case for headings ("Getting started", not "Getting Started")
- Start procedures with prerequisites
- Include expected outcomes for major steps
- Keep sentences concise but informative
- Never use marketing language ("powerful", "seamless", "robust")

## Required page structure

Every page must start with frontmatter:

---
title: "Clear, specific title"
description: "Concise description for SEO and navigation."
keywords: ["relevant", "keywords", "here"]
---

## Mintlify components

### docs.json

- Refer to the [docs.json schema](https://mintlify.com/docs.json) when modifying navigation or site settings

### Callouts

- `<Note>` for helpful supplementary information
- `<Warning>` for important cautions and breaking changes
- `<Tip>` for best practices and expert advice
- `<Info>` for neutral contextual information
- `<Check>` for success confirmations

### Code examples

- All code blocks must have a language tag
- Use `<CodeGroup>` for multiple language examples
- Use `<RequestExample>` and `<ResponseExample>` for API docs

### Procedures

- Use `<Steps>` for sequential instructions
- Include verification steps with `<Check>` when relevant

### Content organization

- Use `<Tabs>` for platform-specific content
- Use `<Accordion>` for progressive disclosure
- Use `<Card>` and `<CardGroup>` for highlighting content
- Wrap images in `<Frame>` with descriptive alt text

## Internal links

Use root-relative paths: `/guides/quickstart`, not `../quickstart` or full URLs.

## Quality checklist

Before finishing any documentation task:
- Verify all code blocks have language tags
- Check that frontmatter includes title, description, and keywords
- Confirm internal links use root-relative paths
- Read changes aloud to catch awkward phrasing
```

## Working with Codex

Once your `AGENTS.md` is in place, Codex picks it up automatically when you start a session in your docs repo.

### Example prompts

**Writing new content**:

```text wrap theme={null}
Create a new page at guides/authentication.mdx explaining how to authenticate with our API. Include code examples in JavaScript and Python.
```

**Improving existing content**:

```text wrap theme={null}
Review docs/quickstart.mdx and suggest improvements for clarity. Focus on making the steps easier to follow and ensuring components are used correctly.
```

**Updating navigation**:

```text wrap theme={null}
I added a new page at guides/webhooks.mdx. Add it to the Guides section in docs.json after guides/authentication.
```

**Maintaining consistency**:

```text wrap theme={null}
Check whether this new page follows the writing standards in AGENTS.md and flag any issues.
```

## Enhance with MCP server

Connect the Mintlify MCP server to Codex to give it access to search the Mintlify documentation while helping you write. When you connect the MCP server, Codex can look up component usage and configuration options without you leaving the terminal.

Add the MCP server to your global Codex config at `~/.codex/config.toml`. Create the file if it does not exist.

```toml theme={null}
[mcp_servers.mintlify]
url = "https://mintlify.com/docs/mcp"
```

To connect to your own documentation site's MCP server instead, replace the URL with your site's MCP endpoint:

```toml theme={null}
[mcp_servers.my-docs]
url = "https://your-docs.mintlify.site/mcp"
```

Restart your `codex` session for the config change to take effect. To confirm the MCP server connected, ask Codex `Which MCP servers do you have access to?`. It should list the entry you added.

See [Model Context Protocol](/docs/ai/model-context-protocol) for more information about MCP servers and how to find your site's MCP endpoint.


# Configure automerge for GitHub Apps
Source: https://www.mintlify.com/docs/guides/configure-automerge

Set up GitHub workflows to automatically merge Mintlify pull requests by adding the Mintlify bot to your repository's ruleset bypass list.

Add the Mintlify GitHub App to a ruleset's bypass list so that the app can create and merge pull requests without review and status check requirements blocking it. This lets you configure [automations](/docs/automations/index) to automatically merge changes to `main`.

<Note>
  The Mintlify GitHub App must have bypass permissions on **every** ruleset that targets your deploy branch, including rulesets defined at the organization level and the repository level. If any ruleset is missing the bypass entry, the automation creates a PR, but does not merge it.
</Note>

## Prerequisites

* Repository admin access (and organization admin access if there are org-level rulesets)
* [Mintlify GitHub App](/docs/deploy/github) installed on the repository
* One or more rulesets targeting the `main` branch (at the org or repo level)

## Steps

Repeat these steps for every ruleset that applies to your deploy branch. Both **organization-level** and **repository-level** rulesets.

<Steps>
  <Step title="Navigate to rulesets">
    * **Repository rulesets**: On GitHub, go to your repository's **Settings** -> **Rules** -> **Rulesets**.
    * **Organization rulesets**: Go to your organization's **Settings** -> **Rules** -> **Rulesets**.
  </Step>

  <Step title="Select the ruleset">
    Click a ruleset that targets your deploy branch, which is usually `main`.
  </Step>

  <Step title="Add the Mintlify GitHub App to the bypass list">
    1. Under **Bypass list**, click **Add bypass**.
    2. Search for and select the Mintlify GitHub App.
    3. Set the bypass mode to **Always**.
  </Step>

  <Step title="Save">
    Click **Save changes**.
  </Step>

  <Step title="Repeat for remaining rulesets">
    If you have additional rulesets at the org or repo level that target your deploy branch, repeat steps 2–4 for each one.
  </Step>
</Steps>

## Verify the setup

1. **For contributors**: Open a PR targeting `main`. Confirm that it still requires approval and passing status checks before you can merge.
2. **For automations**: Trigger an automation with automerge enabled. Confirm that the automation runs and successfully merges a PR.


# Documentation content templates
Source: https://www.mintlify.com/docs/guides/content-templates

Copy and modify ready-to-use MDX templates for how-to guides, tutorials, concept explanations, and API reference pages in your documentation.

Use these templates as starting points for creating documentation. Customize the templates for your documentation and your audience.

1. Copy the template that matches your content type.
2. Replace placeholders and example content with your actual content.
3. Adjust sections as needed.
4. Remove any sections that don't apply.

<Tip>
  Not sure which template to use? Read about [content types](/docs/guides/content-types) to understand when to use each one.
</Tip>

## How-to guide template

Use how-to guides when users need to accomplish a specific task and already have some familiarity with your product. How-tos are goal-driven and get straight to the solution.

````mdx How-to guide template theme={null}
---
title: "[Titles should start with a verb]"
description: "[Do specific task] to [achieve outcome]."
---

Start with a brief statement of what this guide helps users accomplish.

## Prerequisites (optional)

List only what's necessary:

- Required setup or configuration
- Permissions needed
- Related features that should be configured first

## [Action-oriented heading describing the task]

Provide direct instructions focused on achieving the goal.

1. Open [location] and navigate to [specific place]
2. Click [button or option]
3. Enter [required information]
4. Click [confirmation button]

```language
// Include code examples that users can copy and modify
```

<Tip>
  Include practical tips that help users avoid common mistakes or work more efficiently.
</Tip>

## Verify the result (optional)

If success is ambiguous, explain how users can confirm they completed the task successfully.

## Troubleshooting (optional)

Address common issues users might encounter:

- **Problem description**: Solution or workaround
- **Another common issue**: How to resolve it

## Related tasks

Link to related how-to guides or next steps.
````

## Tutorial template

Use tutorials when you want to help new users learn through hands-on practice. Tutorials guide users step-by-step through a complete learning experience with a clear outcome.

````mdx Tutorial template theme={null}
---
title: "[Action verb] [specific outcome]"
description: "Learn how to [specific outcome] by [method or approach]."
---

Use an introduction paragraph to explain what users can expect to learn and what they can do after completing this tutorial.

## Prerequisites

List what users need before starting:

- Required knowledge or skills
- Tools, accounts, or permissions
- Time commitment (optional)

## Step 1: [First action]

Provide clear, specific instructions for the first step.

```language
// Include code examples where helpful
```

Explain what this step accomplishes and why it matters.

## Step 2: [Second action]

Continue with sequential steps that build on previous work.

Point out milestones and progress markers so users know they're on track.

## Step 3: [Third action]

Keep steps focused on concrete actions rather than theory.

Minimize choices that users need to make.

## Next steps

Summarize what users learned and suggest logical next steps:

- Related tutorials to try
- How-to guides for common tasks
- Additional resources for deeper learning
````

## Explanation template

Use explanations when users need to understand concepts, design decisions, or how complex features work. Explanations provide context and deepen understanding rather than giving step-by-step instructions.

```mdx Explanation template theme={null}
---
title: "About [concept or feature]"
description: "Understand [concept] and how it works within [product or context]."
---

Start with a clear statement of what this explanation covers and why understanding it matters.

Define the concept in plain language. Explain what it is, what it does, and why it exists.

Use analogies or comparisons to familiar concepts when helpful.

## How [concept] works

Explain the underlying mechanics, architecture, or process.

<Frame>
  <img src="/path/to/diagram.png" alt="Diagram showing how [concept] works" />
</Frame>

Break down complex ideas into digestible sections.

## Why [design decision or approach]

Provide context about why things work the way they do.

Discuss trade-offs, alternatives that were considered, or constraints that influenced the design.

## When to use [concept]

Help users understand when this concept or approach is most appropriate.

- **Use case 1**: When this approach makes sense
- **Use case 2**: Another scenario where this is the right choice
- **Not recommended for**: Situations where alternatives are better

## Relationship to other features

Draw connections to related concepts or features in your product.

Explain how this concept fits into the broader system or workflow.

## Common misconceptions

Address misunderstandings or clarify subtle distinctions.

## Further reading

Link to related explanations, tutorials, or reference documentation.
```

## Reference template

Use reference documentation when users need to look up specific details about your product's features. Reference docs prioritize accuracy, consistency, and scannability.

````mdx Reference template theme={null}
---
title: "[Feature or API name] reference"
description: "Complete reference for [feature or API] properties, parameters, and options."
---

Provide a one-sentence description of what this feature or API does.

## Properties

<ParamField body="property1" type="string" required>
  Brief description of the property.
</ParamField>

<ParamField body="property2" type="number">
  Brief description with default value if applicable.
</ParamField>

<ParamField body="property3" type="boolean" default="false">
  Brief description.
</ParamField>

## Parameters

<ParamField body="parameterName" type="string">
  Description of what this parameter does and when to use it.

```language
// Example showing typical usage
```
</ParamField>

<ParamField body="anotherParameter" type="object">
  Description of the parameter.

  Available options:

  - `option1`: Description of this option.
  - `option2`: Description of this option.
</ParamField>

## Examples

### Basic example

```language title="Basic usage"
// Minimal example showing common use case
```

### Advanced example

```language title="Advanced configuration"
// Example with multiple options configured
```

## Response

If documenting an API, describe the response structure.

<ResponseField name="field1" type="string" required>
  Description of the response field.
</ResponseField>

<ResponseField name="field2" type="number">
  Description of another response field.
</ResponseField>

Example response:

```json
{
  "field1": "value",
  "field2": 123
}
```

## Related references

Link to related reference documentation.
````

## Related pages

<CardGroup>
  <Card title="Content types" icon="shapes" href="/guides/content-types">
    Choose the right content type for your documentation goals.
  </Card>

  <Card title="Style and tone" icon="pen" href="/guides/style-and-tone">
    Write effective documentation with consistent style.
  </Card>

  <Card title="Format text" icon="text" href="/create/text">
    Learn how to format text and style content.
  </Card>
</CardGroup>


# Documentation content types
Source: https://www.mintlify.com/docs/guides/content-types

Choose the right documentation type for each page using the Diátaxis framework: tutorials, how-to guides, reference, and explanation.

Not all documentation serves the same purpose. A tutorial that walks a new user through their first deployment is fundamentally different from an API reference a developer consults every day. Mixing these purposes in a single page creates content that serves neither goal well.

The [Diátaxis framework](https://diataxis.fr) provides a practical system for categorizing documentation by the user's need in the moment.

## The four documentation types

<Frame>
  <img alt="A diagram of the Diátaxis framework showing four quadrants that correspond to the four content types: Tutorials, How-To Guides, Reference, and Explanation." />
</Frame>

### Tutorials (learning-oriented)

Tutorials teach through doing. The user's goal is to learn something new, and the tutorial's goal is to give them a successful experience—not to document every option or explain every detail.

A good tutorial:

* Assumes no prior knowledge of the specific task
* Takes the user through one complete, working example from start to finish
* Minimizes choices—tell users exactly what to do rather than offering alternatives
* Marks progress at meaningful milestones ("You've now configured authentication")
* Explains just enough to keep the user moving, not everything there is to know

Tutorials are the highest-investment content type to write and maintain, but they have an outsized impact on whether new users succeed with your product.

### How-to guides (task-oriented)

How-to guides help users accomplish a specific goal. Unlike tutorials, they assume the user already has some context and wants to do a particular thing, not learn a concept.

A good how-to guide:

* Addresses one specific task in the title and throughout
* Assumes prior knowledge of the prerequisites
* Provides a clear sequence of steps without unnecessary context
* Describes what to do, not how the system works underneath

The distinction from tutorials matters in practice: a tutorial on "Getting started with authentication" walks a new user through the whole process step by step. A how-to guide on "Rotate your API keys" assumes the user knows what API keys are and just needs the steps.

### Reference (information-oriented)

Reference documentation describes the system accurately and completely. Users consult it to look something up—they aren't reading sequentially, and they aren't learning.

Good reference documentation:

* Prioritizes completeness and accuracy above all else
* Is scannable: tables, consistent formatting, short descriptions
* Avoids explanatory or conceptual content
* Documents everything, including defaults, limits, and edge cases
* Stays close to the structure of what it documents (an API reference follows the API's structure)

API references, configuration option lists, and CLI command references are all reference content.

### Explanation (understanding-oriented)

Explanations deepen understanding of a concept. Users read them when they want to understand why something works the way it does, not how to do a specific task.

Good explanation content:

* Addresses the context and motivation behind a design decision
* Acknowledges tradeoffs and alternatives
* Connects concepts across the broader system
* Takes opinionated positions where appropriate

Architecture overviews, concept guides, and "how X works" pages are all explanation content. They're distinct from how-to guides in that a reader finishing an explanation article shouldn't feel instructed to do something—they should feel they understand something better.

## Choose the right type for each page

| Question                                    | Tutorial               | How-to                   | Reference                | Explanation          |
| ------------------------------------------- | ---------------------- | ------------------------ | ------------------------ | -------------------- |
| What is the user's goal?                    | Learn through practice | Solve a specific problem | Find precise information | Understand a concept |
| What level of knowledge does the user have? | Beginner               | Intermediate             | Experienced              | Any                  |
| Is the content task-oriented?               | Yes, guided            | Yes, specific            | No                       | No                   |
| Is it sequential?                           | Yes                    | Usually                  | No                       | No                   |

When in doubt about which type fits a page, ask: "What does the user do after reading this?" If they've completed a task, it's a how-to or tutorial. If they now understand something and may go on to take action elsewhere, it's an explanation. If they've looked up a specific detail, it's reference.

## Writing for each type

### Writing tutorials

Set expectations at the start: what do users build or accomplish by the end? Use `<Steps>` components for sequential progress and celebrate completion at natural milestones. Minimize decisions—where there are multiple valid approaches, pick one and say so.

### Writing how-to guides

Lead with the task in the title: "How to configure webhooks," "How to migrate from v1 to v2." Write from the user's perspective, not the product's. Skip context that does not affect the steps. Link to explanation or reference content for users who want to understand more.

### Writing reference

Structure reference docs around the thing you describe, not around user journeys. Use consistent formatting across all entries. Every parameter, flag, or option should have a type, default value, and one-line description. Keep it scannable.

### Writing explanation

Start with the question you're answering. For example, ask "Why does authentication work this way?" or "What's the difference between organizations and workspaces?" Acknowledge that multiple approaches exist. Explain why the product makes its choices. Link to how-to guides for users who want to act on what they've learned.

## Tips for maintaining type consistency

* **Assign a content type before writing.** Deciding in advance shapes every other writing decision, including structure, length, tone, and what to include or exclude.
* **Review mixed-purpose pages.** Pages that explain a concept, include a tutorial, and reference a list of options all at once are hard to maintain. They are also hard to use. Split them or pick a primary type.
* **Adapt the framework to your product.** Diátaxis is a starting point, not a rigid rule. Products with unusual structures may need hybrid approaches. The underlying principle—match content to the user's need in the moment—applies universally.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Do I need all four content types for every feature?">
    No. Small features may only need a how-to guide and a reference entry. The types describe needs users might have, not a checklist you must complete. Start with what your users actually need. Usually, that means a how-to guide and reference. Add tutorials and explanations where users consistently struggle to get started or understand something.
  </Accordion>

  <Accordion title="What's the difference between a tutorial and a how-to guide?">
    Tutorials are learning experiences. The user starts without knowledge and ends having built or completed something, with the tutorial doing most of the pedagogical work. How-to guides are task references. The user knows what they want to do and needs the steps to do it. A tutorial on "Build your first integration" and a how-to guide on "Connect a new integration" can cover similar actions but serve entirely different users in entirely different contexts.
  </Accordion>

  <Accordion title="Can a single page serve multiple content types?">
    In practice, pages often mix types, especially getting started content that blends tutorial and how-to. The question is whether the mix serves users or confuses them. If a page needs to both teach a concept (explanation) and walk through setup (tutorial), a clear section structure can work. If the content is too mixed to organize cleanly, splitting it into separate pages usually produces better results.
  </Accordion>

  <Accordion title="How detailed should reference documentation be?">
    Comprehensive enough that users don't need to read source code or contact support to understand a parameter or option. Every configurable value should have a description, type, default, and example. Reference documentation that omits edge cases or limits forces users to discover those limits through trial and error—that's a documentation failure, not a user error.
  </Accordion>
</AccordionGroup>

## Related pages

<CardGroup>
  <Card title="Content templates" icon="file-code" href="/guides/content-templates">
    Copy and modify templates for each content type.
  </Card>

  <Card title="Style and tone" icon="pen" href="/guides/style-and-tone">
    Write effective documentation with consistent style.
  </Card>

  <Card title="Understand your audience" icon="users" href="/guides/understand-your-audience">
    Research and define your documentation audience.
  </Card>

  <Card title="Navigation" icon="compass" href="/guides/navigation">
    Organize your documentation structure effectively.
  </Card>

  <Card title="Improve your docs" icon="chart-line" href="/guides/improving-docs">
    Use data and metrics to improve documentation.
  </Card>
</CardGroup>


# Write documentation with Cursor
Source: https://www.mintlify.com/docs/guides/cursor

Configure Cursor with project rules to write Mintlify documentation that follows your style guide, component usage, and MDX conventions.

Transform Cursor into a documentation expert that knows your components, style guide, and best practices.

## Use Cursor with Mintlify

Cursor rules provide persistent context about your documentation, ensuring more consistent suggestions that fit your standards and style.

* **Project rules** live in your documentation repository, so your whole team shares them.
* **User rules** apply to your personal Cursor environment.

Create project rules for your docs so that all contributors have access to the same rules.

Create rules files in the `.cursor/rules` directory of your docs repo. See the [Cursor Rules documentation](https://docs.cursor.com/context/rules) for complete setup instructions.

## Example project rule

This rule provides Cursor with context to properly format Mintlify components and follow technical writing best practices.

You can use this example as-is or customize it for your documentation:

* **Writing standards**: Update language guidelines to match your style guide.
* **Component patterns**: Add project-specific components or modify existing examples.
* **Code examples**: Replace generic examples with real API calls and responses for your product.
* **Style and tone preferences**: Adjust terminology, formatting, and other rules.

Add this rule with any modifications as an `.mdc` file in the `.cursor/rules` directory of your docs repo.

````mdx wrap theme={null}
# Mintlify technical writing rule

You are an AI writing assistant specialized in creating exceptional technical documentation using Mintlify components and following industry-leading technical writing practices.

## Core writing principles

### Language and style requirements

- Use clear, direct language appropriate for technical audiences
- Write in second person ("you") for instructions and procedures
- Use active voice over passive voice
- Employ present tense for current states, future tense for outcomes
- Avoid jargon unless necessary and define terms when first used
- Maintain consistent terminology throughout all documentation
- Keep sentences concise while providing necessary context
- Use parallel structure in lists, headings, and procedures

### Content organization standards

- Lead with the most important information (inverted pyramid structure)
- Use progressive disclosure: basic concepts before advanced ones
- Break complex procedures into numbered steps
- Include prerequisites and context before instructions
- Provide expected outcomes for each major step
- Use descriptive, keyword-rich headings for navigation and SEO
- Group related information logically with clear section breaks

### User-centered approach

- Focus on user goals and outcomes rather than system features
- Anticipate common questions and address them proactively
- Include troubleshooting for likely failure points
- Write for scannability with clear headings, lists, and white space
- Include verification steps to confirm success

## Mintlify component reference

### docs.json

- Refer to the [docs.json schema](https://mintlify.com/docs.json) when building the docs.json file and site navigation

### Callout components

#### Note - Additional helpful information

<Note>
Supplementary information that supports the main content without interrupting flow
</Note>

#### Tip - Best practices and pro tips

<Tip>
Expert advice, shortcuts, or best practices that enhance user success
</Tip>

#### Warning - Important cautions

<Warning>
Critical information about potential issues, breaking changes, or destructive actions
</Warning>

#### Info - Neutral contextual information

<Info>
Background information, context, or neutral announcements
</Info>

#### Check - Success confirmations

<Check>
Positive confirmations, successful completions, or achievement indicators
</Check>

### Code components

#### Single code block

Example of a single code block:

```javascript config.js
const apiConfig = {
  baseURL: 'https://api.example.com',
  timeout: 5000,
  headers: {
    'Authorization': `Bearer ${process.env.API_TOKEN}`
  }
};
```

#### Code group with multiple languages

Example of a code group:

<CodeGroup>
```javascript Node.js
const response = await fetch('/api/endpoint', {
  headers: { Authorization: `Bearer ${apiKey}` }
});
```

```python Python
import requests
response = requests.get('/api/endpoint', 
  headers={'Authorization': f'Bearer {api_key}'})
```

```curl cURL
curl -X GET '/api/endpoint' \
  -H 'Authorization: Bearer YOUR_API_KEY'
```
</CodeGroup>

#### Request/response examples

Example of request/response documentation:

<RequestExample>
```bash cURL
curl -X POST 'https://api.example.com/users' \
  -H 'Content-Type: application/json' \
  -d '{"name": "John Doe", "email": "john@example.com"}'
```
</RequestExample>

<ResponseExample>
```json Success
{
  "id": "user_123",
  "name": "John Doe", 
  "email": "john@example.com",
  "created_at": "2024-01-15T10:30:00Z"
}
```
</ResponseExample>

### Structural components

#### Steps for procedures

Example of step-by-step instructions:

<Steps>
<Step title="Install dependencies">
  Run `npm install` to install required packages.
  
  <Check>
  Verify installation by running `npm list`.
  </Check>
</Step>

<Step title="Configure environment">
  Create a `.env` file with your API credentials.
  
  ```bash
  API_KEY=your_api_key_here
  ```
  
  <Warning>
  Never commit API keys to version control.
  </Warning>
</Step>
</Steps>

#### Tabs for alternative content

Example of tabbed content:

<Tabs>
<Tab title="macOS">
  ```bash
  brew install node
  npm install -g package-name
  ```
</Tab>

<Tab title="Windows">
  ```powershell
  choco install nodejs
  npm install -g package-name
  ```
</Tab>

<Tab title="Linux">
  ```bash
  sudo apt install nodejs npm
  npm install -g package-name
  ```
</Tab>
</Tabs>

#### Accordions for collapsible content

Example of accordion groups:

<AccordionGroup>
<Accordion title="Troubleshooting connection issues">
  - **Firewall blocking**: Ensure ports 80 and 443 are open
  - **Proxy configuration**: Set HTTP_PROXY environment variable
  - **DNS resolution**: Try using 8.8.8.8 as DNS server
</Accordion>

<Accordion title="Advanced configuration">
  ```javascript
  const config = {
    performance: { cache: true, timeout: 30000 },
    security: { encryption: 'AES-256' }
  };
  ```
</Accordion>
</AccordionGroup>

### Cards and columns for emphasizing information

Example of cards and card groups:

<Card title="Getting started guide" icon="rocket" href="/quickstart">
Complete walkthrough from installation to your first API call in under 10 minutes.
</Card>

<CardGroup cols={2}>
<Card title="Authentication" icon="key" href="/auth">
  Learn how to authenticate requests using API keys or JWT tokens.
</Card>

<Card title="Rate limiting" icon="clock" href="/rate-limits">
  Understand rate limits and best practices for high-volume usage.
</Card>
</CardGroup>

### API documentation components

#### Parameter fields

Example of parameter documentation:

<ParamField path="user_id" type="string" required>
Unique identifier for the user. Must be a valid UUID v4 format.
</ParamField>

<ParamField body="email" type="string" required>
User's email address. Must be valid and unique within the system.
</ParamField>

<ParamField query="limit" type="integer" default="10">
Maximum number of results to return. Range: 1-100.
</ParamField>

<ParamField header="Authorization" type="string" required>
Bearer token for API authentication. Format: `Bearer YOUR_API_KEY`
</ParamField>

#### Response fields

Example of response field documentation:

<ResponseField name="user_id" type="string" required>
Unique identifier assigned to the newly created user.
</ResponseField>

<ResponseField name="created_at" type="timestamp">
ISO 8601 formatted timestamp of user creation.
</ResponseField>

<ResponseField name="permissions" type="array">
List of permission strings assigned to this user.
</ResponseField>

#### Expandable nested fields

Example of nested field documentation:

<ResponseField name="user" type="object">
Complete user object with all associated data.

<Expandable title="User properties">
  <ResponseField name="profile" type="object">
  User profile information including personal details.
  
  <Expandable title="Profile details">
    <ResponseField name="first_name" type="string">
    User's first name as entered during registration.
    </ResponseField>
    
    <ResponseField name="avatar_url" type="string | null">
    URL to user's profile picture. Returns null if no avatar is set.
    </ResponseField>
  </Expandable>
  </ResponseField>
</Expandable>
</ResponseField>

### Media and advanced components

#### Frames for images

Wrap all images in frames:

<Frame>
<img src="/images/dashboard.png" alt="Main dashboard showing analytics overview" />
</Frame>

<Frame caption="The analytics dashboard provides real-time insights">
<img src="/images/analytics.png" alt="Analytics dashboard with charts" />
</Frame>

#### Videos

Use the HTML video element for self-hosted video content:

<video
  controls
  className="w-full aspect-video rounded-xl"
  src="link-to-your-video.com"
></video>

Embed YouTube videos using iframe elements:

<iframe
  className="w-full aspect-video rounded-xl"
  src="https://www.youtube.com/embed/4KzFe50RQkQ"
  title="YouTube video player"
  frameBorder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowFullScreen
></iframe>

#### Tooltips

Example of tooltip usage:

<Tooltip tip="Application Programming Interface - protocols for building software">
API
</Tooltip>

#### Updates

Use updates for changelogs:

<Update label="Version 2.1.0" description="Released March 15, 2024">
## New features
- Added bulk user import feature
- Improved error messages with actionable suggestions

## Bug fixes
- Fixed pagination issue with large datasets
- Resolved authentication timeout problems
</Update>

## Required page structure

Every documentation page must begin with YAML frontmatter:

```yaml
---
title: "Clear, specific, keyword-rich title"
description: "Concise description explaining page purpose and value"
---
```

## Content quality standards

### Code examples requirements

- Always include complete, runnable examples that users can copy and execute
- Show proper error handling and edge case management
- Use realistic data instead of placeholder values
- Include expected outputs and results for verification
- Test all code examples thoroughly before publishing
- Specify language and include filename when relevant
- Add explanatory comments for complex logic
- Never include real API keys or secrets in code examples

### API documentation requirements

- Document all parameters including optional ones with clear descriptions
- Show both success and error response examples with realistic data
- Include rate limiting information with specific limits
- Provide authentication examples showing proper format
- Explain all HTTP status codes and error handling
- Cover complete request/response cycles

### Accessibility requirements

- Include descriptive alt text for all images and diagrams
- Use specific, actionable link text instead of "click here"
- Ensure proper heading hierarchy starting with H2
- Provide keyboard navigation considerations
- Use sufficient color contrast in examples and visuals
- Structure content for easy scanning with headers and lists

## Component selection logic

- Use **Steps** for procedures and sequential instructions
- Use **Tabs** for platform-specific content or alternative approaches
- Use **CodeGroup** when showing the same concept in multiple programming languages
- Use **Accordions** for progressive disclosure of information
- Use **RequestExample/ResponseExample** specifically for API endpoint documentation
- Use **ParamField** for API parameters, **ResponseField** for API responses
- Use **Expandable** for nested object properties or hierarchical information
````

## Enhance with MCP server

Connect the Mintlify MCP server to Cursor to give it access to search the Mintlify documentation while helping you write. When you connect the MCP server, Cursor searches the up-to-date Mintlify documentation for context so you don't have to leave your IDE to reference documentation.

See [Model Context Protocol](/docs/ai/model-context-protocol#example%3A-connect-to-the-mintlify-mcp-server) for complete setup instructions.


# Headless docs with a custom frontend
Source: https://www.mintlify.com/docs/guides/custom-frontend

Build a headless documentation frontend with Astro while using Mintlify for content management, AI-powered search, and assistant features.

Mintlify's headless mode lets you control how your documentation looks and behaves while using Mintlify to manage your content. Instead of using Mintlify's hosted frontend, you can build your own custom frontend with [Astro](https://astro.build) and render your MDX content and `docs.json` configuration however you want.

This headless approach is useful when you need full control over your documentation's design, layout, or behavior. For example, use it to match an existing design system or embed documentation into a larger site. You still get Mintlify's publishing, search, MDX components, and AI features.

The `@mintlify/astro` integration reads your `docs.json` config and MDX content at build time, then processes everything into a format that Astro can render. Build your own layouts, components, and styles on top of it.

This guide walks you through setting up a headless Mintlify project with the starter template and getting it running locally.

<Expandable title="Feature availability for headless projects">
  | Feature                                     | Availability  | Notes                                                                                                                                                                    |
  | ------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | Mintlify components                         | Included      | Use components like `<Card>`, `<Steps>`, and `<Tabs>` in your MDX files without importing them.                                                                          |
  | Content processing                          | Included      | The `@mintlify/astro` integration reads your `docs.json` and MDX files and processes them at build time.                                                                 |
  | Search                                      | Included      | The `SearchBar` component connects to Mintlify's search API using your project subdomain.                                                                                |
  | AI assistant                                | Included      | The `Assistant` component provides an AI chat interface powered by your content.                                                                                         |
  | Layouts and styling                         | Custom build  | Header, footer, sidebar, table of contents, page templates, and all CSS. The starter template includes examples built with Tailwind CSS.                                 |
  | Routing and navigation                      | Custom build  | A catch-all Astro route renders each page. Use `resolvePageData()` and `unwrapNav()` from `@mintlify/astro/helpers` to resolve navigation state from `docs.json`.        |
  | Deployment and hosting                      | Custom build  | Deploy your Astro site to any hosting provider.                                                                                                                          |
  | SEO                                         | You build     | Meta tags, Open Graph tags, sitemap, and `robots.txt` are your responsibility to generate.                                                                               |
  | Third-party integrations                    | Custom build  | Add integrations directly to your Astro layout. Tools configured in `docs.json` for hosted projects do not apply in headless.                                            |
  | `llms.txt`, `llms-full.txt`, and `skill.md` | Custom build  | For headless projects, you must generate and serve these files.                                                                                                          |
  | Dashboard analytics                         | Custom build  | If you use the `Assistant` component, assistant usage analytics are available in your dashboard. For page traffic, add your own analytics provider to your Astro layout. |
  | Web editor                                  | Not available | Requires Mintlify's hosted rendering environment.                                                                                                                        |
  | Authentication and password protection      | Not available | Only available for sites hosted on a Mintlify subdomain or custom domain pointed at Mintlify.                                                                            |
  | API playground                              | Not available | Only available for sites hosted on the Mintlify platform.                                                                                                                |
  | User feedback                               | Not available | The page feedback feature is part of Mintlify's hosted rendering layer.                                                                                                  |
  | Preview deployments                         | Not available | Use your hosting provider's preview environment.                                                                                                                         |
  | PDF export                                  | Not available | Not available for headless projects.                                                                                                                                     |
</Expandable>

## Prerequisites

* A [Mintlify account](https://app.mintlify.com)
* A [GitHub account](https://github.com)
* [Node.js](https://nodejs.org) v20.17.0 or later (LTS versions recommended)
* Familiarity with [Astro](https://docs.astro.build)

## Set up your project

<Steps>
  <Step title="Create a repository from the starter template">
    Navigate to the [mintlify-astro-starter](https://github.com/mintlify/mintlify-astro-starter) repository on GitHub and click **Use this template** to create a new repository on your account.

    Clone the repository to your local machine.
  </Step>

  <Step title="Sign up for Mintlify">
    If you don't have a Mintlify account, sign up at [app.mintlify.com/signup](https://app.mintlify.com/signup).
  </Step>

  <Step title="Install the GitHub App">
    On the [Git settings](https://app.mintlify.com/settings/deployment/git-settings) page of your Mintlify dashboard, install the [Mintlify GitHub App](/docs/deploy/github). If you already have the app installed, uninstall it and reinstall it so that you are ready to connect your new repository.
  </Step>

  <Step title="Connect your repository">
    1. On the [Git settings](https://app.mintlify.com/settings/deployment/git-settings) page, select the repository you created from the starter template.
    2. Enable the **Set up as monorepo** toggle.
    3. Enter `/docs` as the path to the directory containing your `docs.json` file.
    4. Click **Save changes**.

    <Frame>
      <img alt="Repository settings in the Git settings page." />

      <img alt="Repository settings in the Git settings page." />
    </Frame>
  </Step>

  <Step title="Configure environment variables">
    Clone your new repository locally and create a `.env` file at the project root with your Mintlify credentials:

    ```bash .env theme={null}
    PUBLIC_MINTLIFY_SUBDOMAIN=your-subdomain
    PUBLIC_MINTLIFY_ASSISTANT_KEY=your-assistant-api-key
    ```

    Your subdomain is the domain name of your project. It is the part of your dashboard URL after the organization name. For example, if your dashboard URL is `https://app.mintlify.com/org-name/domain-name`, your subdomain is `domain-name`.

    Generate an assistant API key on the [API keys](https://app.mintlify.com/settings/organization/api-keys) page of your dashboard. The assistant API key starts with `mint_dsc_`.
  </Step>

  <Step title="Start the dev server">
    Install dependencies and start the local development server in your cloned repository:

    ```bash theme={null}
    cd path/to/your-repository
    npm install
    npm run dev
    ```

    Your site now runs locally at `http://localhost:4321`.
  </Step>
</Steps>

## How it works

The integration connects three parts: the Astro build system, your content in the `docs/` directory, and the Mintlify packages that process and render that content.

### Astro configuration

Configure the `mintlify()` integration in `astro.config.mjs` with the path to your docs directory:

```javascript astro.config.mjs theme={null}
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import mdx from '@astrojs/mdx';
import { mintlify } from '@mintlify/astro';

export default defineConfig({
  integrations: [mintlify({ docsDir: './docs' }), react(), mdx()],
});
```

At build time, the integration reads your `docs.json` and MDX files from the `docsDir` path and processes them into `.mintlify/docs/`, where Astro's content collections pick them up.

### Content structure

Your documentation content lives in the `docs/` directory, structured the same way as any other Mintlify project:

```text theme={null}
docs/
├── docs.json          # Navigation and site configuration
├── index.mdx          # MDX pages for content
├── quickstart.mdx
└── guides/            # Directories for organizing pages
    ├── setup.mdx
    └── troubleshooting.mdx
```

MDX files use standard Mintlify [frontmatter](/docs/organize/pages#page-metadata) and can use Mintlify components without importing them.

### Routing and navigation

A catch-all route renders each MDX page. The `@mintlify/astro/helpers` package provides functions to resolve navigation state from your `docs.json`.

* `resolvePageData()`: Returns tabs, sidebar navigation, footer links, and anchors for a given page path.
* `unwrapNav()`: Flattens the navigation tree into a list for sidebar rendering.

### Layouts and styling

You control the full presentation layer. The starter template includes layouts, a sidebar, table of contents, and styles built with Tailwind CSS, but you can replace any of these with your own.

Key files to customize:

| File                                 | Purpose                                     |
| ------------------------------------ | ------------------------------------------- |
| `src/layouts/Layout.astro`           | Root HTML layout                            |
| `src/pages/[...slug].astro`          | Page template and data loading              |
| `src/components/Header.astro`        | Site header                                 |
| `src/components/Sidebar/`            | Sidebar navigation                          |
| `src/components/TableOfContents.tsx` | On-page table of contents                   |
| `src/styles/`                        | Global styles, typography, and color scheme |

## Connect search and assistant

The starter template includes search and assistant components that connect to Mintlify's APIs using the environment variables you configure during setup.

* **Search**: The `SearchBar` component in `src/components/SearchBar.tsx` queries the Mintlify search API.
* **Assistant**: The `Assistant` component in `src/components/Assistant/` provides an AI chat interface that answers questions using your documentation content.

Both require the `PUBLIC_MINTLIFY_SUBDOMAIN` and `PUBLIC_MINTLIFY_ASSISTANT_KEY` environment variables.

## Next steps

After setting up your project:

1. Replace the starter content in `docs/` with your own MDX files and `docs.json` configuration.
2. Customize layouts and styles to match your design system.
3. Deploy your Astro site to your preferred hosting provider.


# Build custom page layouts
Source: https://www.mintlify.com/docs/guides/custom-layouts

Use page modes and components to build custom landing pages, marketing pages, and other non-standard layouts in your Mintlify documentation.

Mintlify pages use a standard layout by default, with a sidebar, content area, and table of contents. Customize this layout with [page modes](/docs/organize/pages#page-mode) to create landing pages, feature showcases, or any page that needs a unique design.

This guide covers how to use page modes, Tailwind CSS, and components to build custom layouts.

## Choose a page mode

Set the `mode` field in your page's frontmatter to control which UI elements appear.

| Mode      | Sidebar | Table of contents | Footer   | Theme support                | Best for                                               |
| --------- | ------- | ----------------- | -------- | ---------------------------- | ------------------------------------------------------ |
| `default` | Yes     | Yes               | Yes      | All themes                   | Standard documentation pages                           |
| `wide`    | Yes     | No                | Yes      | All themes                   | Pages without headings or needing extra width          |
| `custom`  | No      | No                | No       | All themes                   | Landing pages, marketing pages, or full-canvas layouts |
| `frame`   | Yes     | No                | Modified | Aspen, Almond, Luma, Sequoia | Custom content that still needs sidebar navigation     |
| `center`  | No      | No                | Yes      | Mint, Linden, Willow, Maple  | Changelogs, focused reading experiences                |

For landing pages, `custom` mode gives you the most control. It removes all UI elements except the top navbar, giving you a blank canvas to build on.

```yaml Example page frontmatter theme={null}
---
title: "Welcome"
mode: "custom"
---
```

## Build a landing page

A typical landing page combines a hero section, feature cards, and calls to action.

### Set up the page

Create an MDX file with `custom` mode:

```yaml Example landing page frontmatter theme={null}
---
title: "Documentation"
description: "Everything you need to build with our platform."
mode: "custom"
---
```

### Create a hero section

Use HTML with Tailwind CSS classes to build a centered hero section:

```mdx Example hero section theme={null}
<div className="px-4 py-16 lg:py-32 max-w-3xl mx-auto text-center">
  <h1 className="text-4xl font-medium text-gray-900 dark:text-zinc-50 tracking-tight">
    Documentation
  </h1>
  <p className="mt-4 text-lg text-gray-500 dark:text-zinc-500">
    Everything you need to build, deploy, and scale your application.
  </p>
</div>
```

<Tip>
  Include both light and dark mode styles. Use `dark:` prefixed Tailwind classes to handle dark mode.
</Tip>

### Add navigation cards

Use the [Card](/docs/components/cards) and [Columns](/docs/components/columns) components to create a grid of links below the hero section:

```mdx Example navigation cards theme={null}
<div className="max-w-4xl mx-auto px-6">
  <Columns cols={2}>
    <Card title="Quickstart" icon="rocket" href="/quickstart">
      Get up and running in under five minutes.
    </Card>
    <Card title="API reference" icon="code" href="/api-reference">
      Explore endpoints, parameters, and examples.
    </Card>
    <Card title="Guides" icon="book" href="/guides">
      Step-by-step tutorials for common tasks.
    </Card>
    <Card title="Components" icon="puzzle" href="/components">
      Reusable UI components for your docs.
    </Card>
  </Columns>
</div>
```

### Use images with dark mode support

Show different images for light and dark mode using Tailwind's visibility classes:

```mdx Example images with dark mode support theme={null}
<img
  src="/images/hero-light.png"
  alt="Platform overview showing the main dashboard."
  className="block dark:hidden"
/>
<img
  src="/images/hero-dark.png"
  alt="Platform overview showing the main dashboard."
  className="hidden dark:block"
/>
```

## Use React components for interactive layouts

For reusable or interactive elements, define [React components](/docs/customize/react-components) directly in your MDX file:

```mdx Example React component theme={null}
export const FeatureCard = ({ title, description, href }) => (
  <a className="group block p-6 rounded-xl border border-gray-200 dark:border-zinc-800 hover:border-gray-300 dark:hover:border-zinc-700 transition-colors" href={href}>
    <h3 className="font-medium text-gray-900 dark:text-zinc-50 group-hover:underline">
      {title}
    </h3>
    <p className="mt-2 text-sm text-gray-500 dark:text-zinc-500">
      {description}
    </p>
  </a>
);

<div className="max-w-4xl mx-auto px-6 grid sm:grid-cols-2 gap-4">
  <FeatureCard
    title="Authentication"
    description="Set up OAuth, API keys, and session management."
    href="/guides/authentication"
  />
  <FeatureCard
    title="Webhooks"
    description="Receive real-time notifications for events."
    href="/guides/webhooks"
  />
</div>
```

<Warning>
  Avoid using the `style` prop on HTML elements. It can cause a layout shift on page load. Use Tailwind CSS classes or a [custom CSS file](/docs/customize/custom-scripts) instead.
</Warning>

## Add custom CSS

For styles that Tailwind doesn't cover, add a CSS file to your repository. Mintlify applies CSS files site-wide, making their class names available in all MDX files.

<Note>
  Mintlify does not support Tailwind CSS arbitrary values (for example, `w-[350px]`). Use a custom CSS file for values that Tailwind's utility classes don't cover.
</Note>

```css Example custom CSS file theme={null}
.landing-hero {
  background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
  padding: 4rem 2rem;
}

@media (prefers-color-scheme: dark) {
  .landing-hero {
    background: linear-gradient(135deg, #0c1222 0%, #1a1a2e 100%);
  }
}
```

Then reference the class in your MDX:

```mdx Example custom CSS usage theme={null}
<div className="landing-hero">
  <h1>Welcome to the docs</h1>
</div>
```

See [Custom scripts](/docs/customize/custom-scripts) for more on custom CSS and the available CSS selectors.

## Full example

Here's a complete landing page that combines a hero section with navigation cards:

```mdx Example landing page theme={null}
---
title: "Documentation"
description: "Everything you need to build with our platform."
mode: "custom"
---

export const HeroCard = ({ title, description, href, icon }) => (
  <a className="group block p-6 rounded-xl border border-gray-200 dark:border-zinc-800 hover:border-gray-300 dark:hover:border-zinc-700 transition-colors" href={href}>
    <h3 className="font-medium text-gray-900 dark:text-zinc-50">
      {title}
    </h3>
    <p className="mt-2 text-sm text-gray-500 dark:text-zinc-500">
      {description}
    </p>
  </a>
);

<div className="px-4 py-16 lg:py-32 max-w-3xl mx-auto text-center">
  <h1 className="text-4xl font-medium text-gray-900 dark:text-zinc-50 tracking-tight">
    Documentation
  </h1>
  <p className="mt-4 text-lg text-gray-500 dark:text-zinc-500 max-w-xl mx-auto">
    Everything you need to build, deploy, and scale your application.
  </p>
</div>

<div className="max-w-4xl mx-auto px-6 pb-16 grid sm:grid-cols-2 gap-4">
  <HeroCard
    title="Quickstart"
    description="Get up and running."
    href="/quickstart"
  />
  <HeroCard
    title="API reference"
    description="Explore endpoints, parameters, and examples."
    href="/api-reference"
  />
  <HeroCard
    title="Guides"
    description="Step-by-step tutorials for common tasks."
    href="/guides"
  />
  <HeroCard
    title="SDKs"
    description="Client libraries for every major language."
    href="/sdks"
  />
</div>
```

## Tips

* **Test light and dark mode.** Preview your custom layout in both light and dark mode to catch missing `dark:` styles.
* **Use `max-w-*` classes** to constrain content width and keep text readable.
* **Keep it responsive.** Use Tailwind's responsive prefixes (`sm:`, `md:`, `lg:`) so your layout works on all screen sizes.
* **Combine modes.** Use `custom` mode for your docs home page and `default` mode for everything else. You set the mode per page, so different pages can use different layouts.
* **Check for layout shifts.** If elements jump on page load, replace inline `style` props with Tailwind classes or custom CSS.


# Create developer documentation
Source: https://www.mintlify.com/docs/guides/developer-documentation

Build developer documentation that helps engineers integrate with your APIs, SDKs, and tools, including quickstarts, references, and guides.

Developer documentation helps people understand and integrate with your product. Good documentation helps people do more with your product, reduces support burden, speeds up adoption, and improves developer experience.

Mintlify provides infrastructure built for developer documentation.

* **API reference generation**: Generate interactive [API references](/docs/api-playground/overview) from OpenAPI specifications that let developers test endpoints in your documentation.
* **Code blocks with explanations**: The [assistant](/docs/assistant/index) explains code examples in context, helping developers understand implementation details.
* **Git sync**: Keep documentation in sync with your codebase using [GitHub](/docs/deploy/github), [GitLab](/docs/deploy/gitlab), or [Bitbucket Cloud](/docs/deploy/bitbucket).
* **Versioning**: Maintain documentation for multiple [versions](/docs/organize/navigation#versions) so developers on older versions can still find accurate information.

## Prerequisites

If you haven't created a Mintlify project yet, see the [Quickstart](/docs/quickstart) to deploy your site.

* Your API specification in OpenAPI format (if documenting an API)
* A Git repository for your documentation
* Admin access to your Mintlify organization

## Migrate existing documentation

If you're creating documentation from scratch, skip to [Plan your documentation structure](#plan-your-documentation-structure).

### Audit existing content

Review your current documentation to understand what you have and what you need to migrate.

* **API reference**: Is it generated from a spec or hand-written? What endpoints do you document?
* **Guides and tutorials**: What integration guides exist? Are they current?
* **Code examples**: What languages and frameworks do you use?
* **SDK documentation**: Do you have separate documentation for each SDK?
* **Changelog**: Do you maintain a changelog or release notes?
* **Metadata**: Do you have metadata for your content like dates, authors, and tags?

### Export your existing content

* Export to **Markdown** for the simplest migration to Mintlify.
* Export **OpenAPI specs** for API reference content.
* Export to **HTML** if Markdown isn't available, then convert to Markdown.

## Plan your documentation structure

Developer documentation typically includes several content types. Structure your navigation around how your users understand your product.

```json docs.json example theme={null}
{
  "navigation": {
    "groups": [
      {
        "group": "Get Started",
        "pages": [
          "introduction",
          "quickstart",
          "authentication"
        ]
      },
      {
        "group": "Guides",
        "pages": [
          "guides/webhooks",
          "guides/error-handling",
          "guides/rate-limits",
          "guides/pagination"
        ]
      },
      {
        "group": "API Reference",
        "pages": [
          "api-reference/overview",
          "api-reference/users",
          "api-reference/orders",
          "api-reference/products"
        ]
      },
      {
        "group": "SDKs",
        "pages": [
          "sdks/javascript",
          "sdks/python",
          "sdks/go"
        ]
      }
    ]
  }
}
```

See [Navigation](/docs/organize/navigation) for more configuration options.

## Set up your API reference

If you have an API, generate an interactive reference from your OpenAPI specification.

<Steps>
  <Step title="Add your OpenAPI spec">
    Add your OpenAPI specification file to your project. You can use YAML or JSON format.

    ```text theme={null}
    your-project/
    ├── docs.json
    ├── openapi.yaml
    └── api-reference/
        └── overview.mdx
    ```
  </Step>

  <Step title="Configure the spec in docs.json">
    Reference your OpenAPI file in your `docs.json` configuration.

    ```json Configuration example theme={null}
    {
      "openapi": "openapi.yaml"
    }
    ```
  </Step>

  <Step title="Add endpoints to navigation">
    Add the endpoints to your `docs.json` navigation. See [OpenAPI setup](/docs/api-playground/openapi-setup) for configuration options.

    ```json Navigation example theme={null}
    {
      "group": "API Reference",
      "pages": [
        "api-reference/overview",
        "api-reference/users/list-users",
        "api-reference/users/get-user",
        "api-reference/users/create-user"
      ]
    }
    ```
  </Step>
</Steps>

## Set up the assistant

The assistant helps developers find answers and understand code examples. Configure it from your [dashboard](https://app.mintlify.com/products/assistant/settings).

* **Sample questions**: Add developer-focused questions like "How do I authenticate API requests?" or "Show me how to handle webhooks."

- **Code explanations**: The assistant can explain code blocks in context when developers ask questions about specific examples.

## Set up versioning

If you maintain multiple API versions, configure versioning so developers find documentation for their version.

```json Versioning example theme={null}
{
  "versions": ["v2", "v1"],
  "navigation": {
    "groups": [
      {
        "group": "API Reference",
        "version": "v2",
        "pages": ["v2/api-reference/users"]
      },
      {
        "group": "API Reference",
        "version": "v1",
        "pages": ["v1/api-reference/users"]
      }
    ]
  }
}
```

See [Versions](/docs/organize/navigation#versions) for more information.

## Connect to your repository

Install the Mintlify [GitHub App](/docs/deploy/github) to keep documentation in sync with your codebase and enable contributions.

<Steps>
  <Step title="Connect your repository">
    Link your GitHub repository in the [dashboard](https://app.mintlify.com). This enables automatic deployments when you push changes.
  </Step>

  <Step title="Configure branch settings">
    Set your production branch and enable preview deployments for pull requests. This lets you review documentation changes before they go live.
  </Step>
</Steps>

<Note>
  If you use GitLab, see [GitLab](/docs/deploy/gitlab) for configuration instructions.
</Note>

## Maintain your documentation

Developer documentation needs regular updates so that information is accurate and usable.

<Steps>
  <Step title="Keep the API reference current">
    Update your OpenAPI specification whenever you release changes. If you generate your specification from code, automate this in your release process.
  </Step>

  <Step title="Update code examples">
    Review code examples when you release new SDK versions or product updates. Outdated examples cause integration failures and support requests.
  </Step>

  <Step title="Maintain a changelog">
    Document breaking changes, new features, and deprecations. Developers rely on changelogs to understand what changed between versions. See [Changelogs](/docs/create/changelogs) for more information.
  </Step>

  <Step title="Monitor feedback">
    Review assistant conversations and search analytics to identify gaps in your documentation. If developers repeatedly ask about the same topic, improve that section. See [Maintenance](/docs/guides/maintenance) for more information.
  </Step>
</Steps>

## Next steps

Your developer documentation is ready to launch. After deploying:

1. Announce the documentation to your developer community.
2. Monitor search patterns and assistant conversations for gaps.
3. Set up a process to update docs with each API release.
4. Gather feedback from developers to improve content over time.


# Write documentation with Devin Desktop
Source: https://www.mintlify.com/docs/guides/devin-desktop

Configure Devin Desktop's Cascade AI with workspace rules to write Mintlify documentation that follows your style guide and MDX standards.

Transform Devin Desktop into a documentation expert that understands your style guide, components, and project context through workspace rules and memories.

<Info>
  Cognition acquired Windsurf and rebranded it as [Devin Desktop](https://devin.ai/desktop). The Cascade AI assistant and workspace rules system remain the same.
</Info>

## Use Devin Desktop with Mintlify

You can tune Devin Desktop's Cascade AI assistant to write documentation according to your standards using Mintlify components. Workspace rules and memories provide persistent context about your project, ensuring more consistent suggestions from Cascade.

* **Workspace rules** live in your documentation repository, so your whole team shares them.
* **Memories** provide individual context that builds up over time.

Set up workspace rules for shared documentation standards. You can develop memories as you work, but since they are not shared, they are not consistent across team members.

Create workspace rules in the `.devin/rules` directory of your docs repo. Devin Desktop still supports rules from `.windsurf/rules` for backward compatibility. See [Memories & Rules](https://docs.devin.ai/desktop/cascade/memories) in the Devin Desktop documentation for more information.

## Example workspace rule

This rule provides Cascade with context about Mintlify components and general technical writing best practices.

You can use this example rule as-is or customize it for your documentation:

* **Writing standards**: Update language guidelines to match your style guide.
* **Component patterns**: Add project-specific components or modify existing examples.
* **Code examples**: Replace generic examples with real API calls and responses for your product.
* **Style and tone preferences**: Adjust terminology, formatting, and other rules.

Save your rule as a `.md` file in the `.devin/rules` directory of your docs repo.

````mdx theme={null}
# Mintlify technical writing rule

## Project context

- This is a documentation project on the Mintlify platform
- We use MDX files with YAML frontmatter  
- Navigation is configured in `docs.json`
- We follow technical writing best practices

## Writing standards

- Use second person ("you") for instructions
- Write in active voice and present tense
- Start procedures with prerequisites
- Include expected outcomes for major steps
- Use descriptive, keyword-rich headings
- Keep sentences concise but informative

## Required page structure

Every page must start with frontmatter:

```yaml
---
title: "Clear, specific title"
description: "Concise description for SEO and navigation"
---
```

## Mintlify components

### docs.json

- Refer to the [docs.json schema](https://mintlify.com/docs.json) when building the docs.json file and site navigation

### Callouts

- `<Note>` for helpful supplementary information
- `<Warning>` for important cautions and breaking changes
- `<Tip>` for best practices and expert advice  
- `<Info>` for neutral contextual information
- `<Check>` for success confirmations

### Code examples

- When appropriate, include complete, runnable examples
- Use `<CodeGroup>` for multiple language examples
- Specify language tags on all code blocks
- Include realistic data, not placeholders
- Use `<RequestExample>` and `<ResponseExample>` for API docs

### Procedures

- Use `<Steps>` component for sequential instructions
- Include verification steps with `<Check>` components when relevant
- Break complex procedures into smaller steps

### Content organization

- Use `<Tabs>` for platform-specific content
- Use `<Accordion>` for progressive disclosure
- Use `<Card>` and `<CardGroup>` for highlighting content
- Wrap images in `<Frame>` components with descriptive alt text

## API documentation requirements

- Document all parameters with `<ParamField>` 
- Show response structure with `<ResponseField>`
- Include both success and error examples
- Use `<Expandable>` for nested object properties
- Always include authentication examples

## Quality standards

- Test all code examples before publishing
- Use relative paths for internal links
- Include alt text for all images
- Ensure proper heading hierarchy (start with h2)
- Check existing patterns for consistency
````

## Working with Cascade

Once your rules are set up, you can use Cascade to assist with various documentation tasks. See [Cascade](https://docs.devin.ai/desktop/cascade/cascade) in the Devin Desktop documentation for more information.

### Example prompts

**Writing new content**:

```text wrap theme={null}
Create a new page explaining how to authenticate with our API. Include code examples in JavaScript, Python, and cURL.
```

**Improving existing content**:

```text wrap theme={null}
Review this page and suggest improvements for clarity and component usage. Focus on making the steps easier to follow.
```

**Creating code examples**:

```text wrap theme={null}
Generate a complete code example showing error handling for this API endpoint. Use realistic data and include expected responses.
```

**Maintaining consistency**:

```text wrap theme={null}
Check if this new page follows our documentation standards and suggest any needed changes.
```

## Enhance with MCP server

Connect the Mintlify MCP server to Devin Desktop to give Cascade access to search the Mintlify documentation while helping you write. When you connect the MCP server, Cascade searches the up-to-date Mintlify documentation for context so you don't have to leave your IDE to reference documentation.

Add the MCP server to `~/.codeium/windsurf/mcp_config.json`:

```json theme={null}
{
  "mcpServers": {
    "mintlify": {
      "serverUrl": "https://mintlify.com/docs/mcp"
    }
  }
}
```

See [Model Context Protocol](https://docs.devin.ai/desktop/cascade/mcp) in the Devin Desktop documentation and [Model Context Protocol](/docs/ai/model-context-protocol) in the Mintlify documentation for more details.


# GEO guide: Optimize docs for AI search and answer engines
Source: https://www.mintlify.com/docs/guides/geo

Optimize your documentation for AI-powered answer engines like ChatGPT, Perplexity, and Google AI Overviews with Generative Engine Optimization techniques.

AI-powered tools like ChatGPT, Perplexity, and Google AI Overviews increasingly answer users' questions directly, citing sources rather than listing links. When a developer asks "how do I authenticate with \[your product]," AI systems cite a well-optimized documentation page in the answer. AI systems skip poorly structured pages, even if they rank well in traditional search.

Generative Engine Optimization (GEO) is the practice of structuring content so AI systems can understand, trust, and cite it accurately.

## How GEO differs from SEO

Traditional SEO optimizes for search engines that rank and link to pages. GEO optimizes for AI systems that read, summarize, and cite pages in generated answers.

The mechanics differ in important ways:

|                   | SEO                                 | GEO                                     |
| ----------------- | ----------------------------------- | --------------------------------------- |
| Goal              | Rank in search results              | Get cited in AI-generated answers       |
| Key signals       | Backlinks, keywords, page authority | Content accuracy, structure, directness |
| User action       | Click a link                        | Read an AI-generated answer             |
| Format preference | Any well-structured content         | Scannable, question-answering content   |

The fundamentals overlap heavily. Accurate, well-structured content that directly answers questions performs well in both. GEO is less about tricks and more about writing clarity.

## How AI systems decide what to cite

AI answer engines evaluate content based on a few key factors:

**Directness.** AI systems prioritize content that answers the question immediately. A page that buries the answer after three paragraphs of context is less likely to earn citations than one that leads with the answer.

**Accuracy and trust signals.** AI systems favor content from authoritative sources that appears factually reliable. For documentation, this means technical accuracy, consistent versioning, and content that matches what the product actually does.

**Structural clarity.** Content that's logically organized, with meaningful headings, lists, and code blocks, is easier for AI systems to parse and excerpt correctly.

**Specificity.** Vague, high-level content ("this feature is flexible and powerful") is less citable than specific, detailed content ("this endpoint returns a 429 status code when requests exceed the rate limit of 100 per minute").

## Write content AI systems can cite

### Lead with the answer

Structure each section so the most important information comes first. Users asking AI tools want direct answers. Avoid preambles, unnecessary context, and caveats before the point.

````mdx theme={null}
<!-- Leads with the answer -->
## How to authenticate API requests

Include your API key in the Authorization header of every request:

```bash
curl -H "Authorization: Bearer YOUR_API_KEY" https://api.example.com/endpoint
```

<!-- Buries the answer -->
## Authentication

Authentication is an important part of using our API. Before you can make any requests, you'll need to understand how our authentication system works. Our API uses bearer tokens...
````

### Use headings that match questions

Write H2 and H3 headings as the questions users ask, not as topic labels. AI systems match user queries to heading text when deciding what content to surface.

```mdx theme={null}
<!-- Query-matching heading -->
## How do I rotate my API keys?

<!-- Topic label — weaker -->
## API key management
```

### Be specific with numbers, limits, and examples

Vague descriptions don't get cited. Specific, accurate details do. AI systems can cite "rate limit: 100 requests per minute per API key" accurately. "Our API has rate limits" gives the AI nothing useful to quote.

For every configuration option, parameter, or behavior:

* State the exact value or range
* Describe what happens at the boundary
* Show a concrete code example

### Use consistent terminology

AI systems build context across a page. If you call the same thing "API key," "access token," and "API token" interchangeably, the AI's summary may use the wrong term. It may also get confused about whether these are the same thing. Use one name per concept throughout the page to help AI systems represent your content accurately.

## Format for AI parsing

### Use sequential, non-skipping heading hierarchy

Don't skip from H2 to H4. AI systems use heading hierarchy to understand how topics relate. A flat, consistent structure is easier to parse correctly.

### Label all code blocks

Always declare the programming language on code blocks. This helps AI systems understand what they're reading and surface the right example for the user's context.

````mdx theme={null}
```python
import requests
response = requests.get(url, headers={"Authorization": f"Bearer {api_key}"})
```
````

### Write alt text for images and diagrams

AI systems can't see images. If a diagram is the primary explanation of a concept, add a text description that conveys the same information. Alt text that describes what a diagram shows—not just "architecture diagram"—gives AI systems something to work with.

### Use specific references instead of pronouns

Write "the API key" instead of "it" or "this value." AI systems excerpt content and lose surrounding context. Specific noun references stay accurate when excerpted; pronouns become ambiguous.

## Mintlify configuration for GEO

### Add descriptive page metadata

Page titles and descriptions are among the most important signals AI systems use to understand a page's topic. Write them as if answering the question "what does this page help users do?"

```mdx theme={null}
---
title: "How to authenticate API requests"
description: "Add your API key to the Authorization header to authenticate requests. Includes examples in JavaScript, Python, and cURL."
---
```

### Control indexing settings

By default, Mintlify indexes pages included in your `docs.json` navigation. To include hidden pages in AI assistant context and search:

```json docs.json theme={null}
{
  "seo": {
    "indexing": "all"
  }
}
```

### llms.txt

Mintlify automatically generates an `llms.txt` file for your documentation. The file works similarly to `sitemap.xml` for traditional search. It provides AI systems with a structured index of your documentation. No configuration is required.

You can view your `llms.txt` file by appending `/llms.txt` to your documentation URL.

### Allow AI agents in robots.txt

Your `robots.txt` file controls which bots can crawl your site. If it blocks AI user agents, tools like ChatGPT, Claude, and Perplexity cannot read your documentation nor cite it in answers.

Mintlify's auto-generated `robots.txt` allows all crawlers by default and includes [Content-Signal directives](/docs/optimize/seo#content-signal-directives) that opt your documentation in to AI training, search indexing, and AI answer generation. If you use a [custom robots.txt file](/docs/optimize/seo#custom-sitemaps-and-robotstxt-files), make sure it does not block AI agents. The most common AI user agents include:

* `GPTBot`, `OAI-SearchBot`, `ChatGPT-User` (OpenAI)
* `ClaudeBot`, `Claude-User` (Anthropic)
* `PerplexityBot` (Perplexity)
* `Google-Extended` (Gemini)

A `robots.txt` that blocks all crawlers also blocks AI agents:

```txt Bad — blocks all AI agents theme={null}
User-agent: *
Disallow: /
```

To block specific scrapers while allowing AI agents, target only the bots you want to restrict:

```txt Good — allows AI agents theme={null}
User-agent: BadBot
Disallow: /

User-agent: *
Disallow: /private/
```

Run [`mint score`](/docs/cli/commands#mint-score) to check whether your site's `robots.txt` allows AI agents. The `robotsTxtAllowsAI` check passes when no AI user agents are blocked.

## Test how AI tools represent your docs

Regularly test whether AI tools are citing your documentation accurately.

Ask specific questions about your product in ChatGPT, Perplexity, and Claude:

* "How do I authenticate API requests using \[your product]?"
* "What happens when I exceed the rate limit in \[your product]?"
* "Show me how to handle errors in \[your product]'s API."

Check the responses for:

* Whether your documentation is cited at all
* Whether the cited content is accurate
* Whether the code examples are correct
* Whether the AI is recommending the right approach

When AI tools give wrong answers about your product, it often signals that your documentation is ambiguous, missing, or contradictory rather than that the AI is broken.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Does GEO replace SEO?">
    No. Traditional search still drives significant traffic, and many users prefer clicking through to documentation rather than reading AI-generated summaries. GEO and SEO are complementary. Well-structured, accurate documentation that directly answers questions performs well in both. The practices reinforce each other.
  </Accordion>

  <Accordion title="How long does it take for GEO improvements to show up?">
    Faster than SEO in many cases. AI systems like Perplexity and ChatGPT crawl and index content more frequently than traditional search engines. Improvements to content clarity and structure can show up in AI-generated answers within days to weeks. That said, AI systems do factor in domain authority and link signals that take longer to build.
  </Accordion>

  <Accordion title="Do I need to do anything special for Google AI Overviews specifically?">
    Google AI Overviews use the same signals as Google Search with additional weight on content that directly answers the specific query. Pages that already rank well in Google Search for a query are more likely to appear in AI Overviews for the same query. The main GEO practices also apply here: lead with the answer, provide specific details, and use a clear structure.
  </Accordion>

  <Accordion title="Should I write differently for AI versus human readers?">
    No. Content that's clear and direct for humans is clear and direct for AI systems. Optimizing specifically for AI at the expense of human readability is counterproductive and tends to produce content that's neither enjoyable to read nor well-cited. Write for your users first; GEO follows naturally from good technical writing.
  </Accordion>

  <Accordion title="What is llms.txt, and do I need to configure it?">
    The `llms.txt` file is a convention similar to `robots.txt` for providing AI systems with a structured index of your documentation. Mintlify generates it automatically. You don't need to configure it. You can view your `llms.txt` file at `https://your-docs-domain.com/llms.txt`.
  </Accordion>
</AccordionGroup>


# Git concepts for documentation
Source: https://www.mintlify.com/docs/guides/git-concepts

Learn Git version control fundamentals for docs-as-code workflows, including repositories, branches, commits, and pull request collaboration.

Git is a version control system that tracks changes to your documentation and enables team collaboration. With Git, you can see what changed over time in files, who made the changes, when they made changes, and why. Git also makes it easy to revert to previous versions of files if you need to undo changes.

The web editor performs Git operations behind the scenes. With an understanding of Git, you can work more effectively with the web editor and collaborate with team members who use local development.

## Why Git for documentation?

Git provides essential capabilities for managing documentation.

* **Version history**: See what changed, when, and why for every file.
* **Collaboration**: Multiple people can work on different parts simultaneously.
* **Safety**: Experiment without breaking live documentation.
* **Review workflows**: Team members can review changes before publishing.
* **Recovery**: Undo mistakes or restore previous versions.

## New to Git?

If you're completely new to Git and version control, here's a path to get started.

<Steps>
  <Step title="Use the web editor first.">
    The [web editor](/docs/editor/index) handles Git operations automatically.

    * See any changes visually as you make them.
    * Create branches with one click.
    * Publish and create pull requests without using Git commands.

    This lets you learn Git concepts without using the command line.
  </Step>

  <Step title="Learn by doing.">
    As you use the web editor, you're using Git.

    * **Save changes** creates a commit.
    * **Create branch** creates a Git branch.
    * **Publish** opens a pull request for review.
  </Step>

  <Step title="Explore local development when it is useful.">
    You can manage your documentation entirely with the web editor and dashboard, but you can customize your workflow by working in your local environment.

    * Create and edit files in your favorite editor.
    * Use command line Git, GitHub desktop, or an extension in your editor.
    * Preview changes locally before publishing.
    * Integrate with other tools like support tickets, issue tracking, and design systems.
  </Step>
</Steps>

## Core Git concepts

<AccordionGroup>
  <Accordion title="Branch">
    A branch points to a specific commit in your repository. Your live documentation builds from a deployment branch. You can have any number of other branches with changes that are not yet published to your live documentation. If you want to incorporate the changes from a branch into your live documentation, you can merge the branch into your deployment branch through a pull request.

    Use branches to work on changes without affecting your live documentation, safely experiment with new features, and get reviews before publishing.
  </Accordion>

  <Accordion title="Clone">
    Download a complete copy of a repository to your computer, including all files and full history. When you clone, you get everything needed to work locally.

    ```bash theme={null}
    git clone https://github.com/your-org/your-repo
    ```
  </Accordion>

  <Accordion title="Commit">
    A saved snapshot of your changes at a specific point in time. Each commit includes a message describing what changed and creates a permanent record in your project history.
  </Accordion>

  <Accordion title="Conflict">
    Occurs when two people change the same part of a file differently. Git asks you to manually choose which change to keep or combine both changes.
  </Accordion>

  <Accordion title="Deployment branch">
    The primary branch of your project. Changes to this branch automatically publish to your documentation site. Often called `main`, but you can set any branch as your deployment branch.
  </Accordion>

  <Accordion title="Diff">
    A diff (or difference) shows the changes between two versions of a file. When reviewing pull requests, diffs highlight what is different from the original version of the file.
  </Accordion>

  <Accordion title="Merge">
    Combine changes from one branch into another. Usually done via pull request after review to incorporate feature work into your deployment branch.
  </Accordion>

  <Accordion title="Pull">
    Get the latest changes from the remote repository to your local copy. Keeps you up to date with other people's work.

    ```bash theme={null}
    git pull
    ```
  </Accordion>

  <Accordion title="Pull request">
    A way to propose merging your changes on a branch into your live documentation. Allows for review and discussion before changes go live. Commonly called a PR, and also called a merge request in GitLab.
  </Accordion>

  <Accordion title="Push">
    Send your local commits to the remote repository. This makes your changes available to others and can trigger automatic deployments.

    ```bash theme={null}
    git push
    ```
  </Accordion>

  <Accordion title="Remote">
    A version of your repository hosted on a server. Your local repository connects to a remote repository to push and pull changes.
  </Accordion>

  <Accordion title="Repository">
    Your documentation's source code with all the files, and their history, that make up the pages of your documentation site. The web editor connects to your documentation repository to access and modify content.
  </Accordion>

  <Accordion title="Stage">
    Prepare specific changes to include in your next commit. Staging lets you organize changes into logical commits.

    ```bash theme={null}
    git add filename.mdx
    ```
  </Accordion>
</AccordionGroup>

## How the web editor uses Git

The web editor connects to your Git repository through the [GitHub App](/docs/deploy/github), [GitLab integration](/docs/deploy/gitlab), or [Bitbucket Cloud integration](/docs/deploy/bitbucket) and automates common Git operations.

When you:

* **Open a file**: The editor fetches the latest version from your repository, ensuring you're always working with up-to-date content.
* **Make changes**: The editor tracks your changes and turns them into a commit when you save your work.
* **Save changes**: The editor makes a commit with your changes, preserving your work in the project history.
* **Create a branch**: The editor creates a new branch in your repository that anyone with access to the repository can use to collaborate and review changes.
* **Publish on your deployment branch**: The editor commits and pushes directly to your deployment branch, which publishes your changes immediately.
* **Publish on other branches**: The editor creates a pull request, which lets you get feedback from others before merging your changes into your deployment branch.

## Common workflows

### Publish directly to your deployment branch

<Tabs>
  <Tab title="Using web editor">
    1. Open file in the [web editor](https://app.mintlify.com/editor).
    2. Make changes.
    3. Click **Publish**.
    4. Changes appear in the repository and deploy automatically.
  </Tab>

  <Tab title="Using local development">
    1. Pull the latest changes: `git pull`
    2. Edit file in your editor.
    3. Stage changes: `git add filename.mdx`
    4. Commit: `git commit -m "Update documentation"`
    5. Push: `git push`
    6. Changes deploy automatically.
  </Tab>
</Tabs>

### Work on a feature branch

<Tabs>
  <Tab title="Using web editor">
    <Note>
      To create pull requests from the web editor, you must have a branch protection rule enabled that requires pull requests before changes can merge into your deployment branch. Without branch protection rules, changes on branches merge to your deployment branch when published.
    </Note>

    1. Create branch from the branch dropdown in the editor toolbar.
    2. Make and save changes on the branch.
    3. Click **Publish** to create a pull request.
    4. Merge the pull request when ready.
  </Tab>

  <Tab title="Using local development">
    1. Create a branch: `git checkout -b feature-name`
    2. Make and commit changes.
    3. Push branch: `git push -u origin feature-name`
    4. Create a pull request.
    5. Merge the pull request when ready.
  </Tab>
</Tabs>

### Review changes before publishing

<Steps>
  <Step title="Create a feature branch.">
    Work on changes in a branch separate from your deployment branch so that you can share and review the changes before publishing.
  </Step>

  <Step title="Make your changes.">
    Edit files and commit changes to the feature branch.
  </Step>

  <Step title="Create a pull request.">
    Create a pull request to propose merging the changes on your feature branch into the deployment branch.
  </Step>

  <Step title="Review the diff.">
    Check your changes. The pull request shows line-by-line differences from the original version of the file.
  </Step>

  <Step title="Get team feedback.">
    Team members can comment on specific lines or overall changes. Make any changes and commit them to the feature branch.
  </Step>

  <Step title="Merge when approved.">
    Merge the pull request to publish changes to your live documentation.
  </Step>
</Steps>

## Git best practices

Every team develops their own workflows and preferences, but these are some general best practices to get started.

* **Write descriptive commit messages**: Be specific about what changed using active language. `Fix broken link in API docs` is more informative than `update page`.
* **Use descriptive branch names**: Branch names should explain the purpose of the branch. Use informative names like `update-api-reference` instead of generic names like `temp` or `my-branch`.
* **Keep branches focused**: Keep the changes on a branch focused on a specific task or project. This makes reviews easier and reduces conflicts.
* **Delete branches after merging**: Delete branches when you no longer need them to keep your repository tidy.
* **Pull before you push**: Always pull the latest changes before pushing to avoid conflicts. The web editor does this automatically.
* **Review your own changes first**: Check the diff before creating a pull request.


# Create a help center
Source: https://www.mintlify.com/docs/guides/help-center

Build a self-service help center on Mintlify that helps customers find answers, reduces support ticket volume, and scales with your team.

A help center helps customers troubleshoot and find information about your product. When customers can find answers themselves, they get help faster and your support team can focus on complex issues that require their expertise.

Mintlify provides infrastructure for help centers that scale with your customer base.

* **AI-powered search**: The [assistant](/docs/assistant/index) answers customer questions using your support content, so people can get answers quickly without knowing exactly where to look or specific terms to search for.
* **Feedback collection**: Built-in [feedback widgets](/docs/optimize/feedback) let customers rate articles and report issues so you can improve content.
* **Analytics**: Track which articles get views, what questions customers ask, and where they struggle in the [analytics dashboard](/docs/analytics).
* **Authentication**: Use [SSO or OAuth](/docs/deploy/authentication-setup) to show personalized content based on customer plans or account types.

## Start from a template

The fastest way to create a new help center is with the `mint new --template` command. Run the command and select the help center starter template.

```bash theme={null}
mint new your-help-center-name --template help-center-starter
```

This creates a new project pre-configured for a help center, including navigation structure, sample pages, and directory listings. See the [live example](https://help-center-starter.mintlify.site/) or browse the [template source](https://github.com/mintlify/templates/tree/main/help-center-starter).

If you prefer to configure a help center in an existing project, continue with the steps below.

## Prerequisites

If you haven't created a Mintlify project yet, see the [Quickstart](/docs/quickstart) to deploy your site.

* Content for your most common support topics
* Admin access to your Mintlify organization
* Domain for hosting your help center

## Migrate existing content

If you're creating a help center from scratch, skip to [Plan your help center structure](#plan-your-help-center-structure).

### Audit existing content

Review your current support resources to understand what to migrate.

* **Help articles**: What topics do you address? Which articles get the most views?
* **FAQs**: Do you have frequently asked questions that should become articles?
* **Support tickets**: What questions do customers ask repeatedly? These should become self-service content.
* **Product documentation**: Is there overlap between support content and product docs?

### Export your existing content

* Export to **Markdown** for the simplest migration to Mintlify.
* Export to **HTML** if Markdown isn't available, then convert to Markdown.
* Export **ticket data** to identify common questions that need documentation.

## Plan your help center structure

Organize your help center around customer problems, not product features. Customers arrive with questions and goals, so structure content that aligns with how they think about your product and common tasks.

<Tip>
  Review your support tickets to understand what customers actually ask about. This helps you prioritize content and structure navigation around real problems.
</Tip>

Use the `directory` property to create index pages for each group in your navigation. When you use the `directory` property, every `root` page displays a directory listing for the other pages in the same navigation group. This gives customers an overview of the content in each section that they can click through to the specific pages they need.

Set `directory` to `"card"` for a horizontal card layout or `"accordion"` for a list. The value passes down through the navigation tree unless you specifically override it on a later level.

```json Example navigation structure theme={null}
{
  "navigation": {
    "directory": "card",
    "groups": [
      {
        "group": "Get Started",
        "root": "getting-started/index",
        "pages": [
          "getting-started/quick-setup",
          "getting-started/first-steps"
        ]
      },
      {
        "group": "Account",
        "root": "account/index",
        "pages": [
          "account/billing",
          "account/plans",
          "account/team-management",
          "account/security"
        ]
      },
      {
        "group": "Using the Product",
        "root": "product/index",
        "pages": [
          "product/feature-one",
          "product/feature-two",
          "product/integrations"
        ]
      },
      {
        "group": "Troubleshooting",
        "root": "troubleshooting/index",
        "pages": [
          "troubleshooting/common-errors",
          "troubleshooting/connectivity",
          "troubleshooting/performance"
        ]
      }
    ]
  }
}
```

See [Navigation](/docs/organize/navigation) and [Directory listings](/docs/organize/navigation#directory-listings) for more configuration options.

## Write effective support content

Support content should help customers solve problems quickly. Every article should answer one specific question or solve one specific problem. Organize related content into groups instead of creating overly long pages that have too much information.

### Structure articles for scanning

Customers scan support pages looking for their specific issue. Use clear headings and short paragraphs.

```mdx Example support page theme={null}
---
title: "Fix login issues"
description: "Troubleshoot common problems signing in to your account"
---

## Reset your password

If you forgot your password, request a reset link from the login page.

1. Go to the login page.
2. Click **Forgot password**.
3. Enter your email address.
4. Check your inbox for the reset link.

## Clear browser cache

Old cached data can cause login problems. Clear your browser cache and try again.

## Check account status

If your account is suspended or deactivated, you'll see an error when logging in.
Contact support if you believe this is a mistake.
```

### Include step-by-step instructions

When explaining how to do something, use numbered steps.

<Steps>
  <Step title="Go to Settings">
    Click the gear icon in the toolbar.
  </Step>

  <Step title="Select Billing">
    Click **Billing** in the navigation menu.
  </Step>

  <Step title="Update payment method">
    Click **Update** next to your current payment method and enter new details.
  </Step>
</Steps>

### Add visual aids

Screenshots and diagrams help customers confirm they're in the right place.

```mdx Example screenshot theme={null}
![Settings page with billing section highlighted](/images/billing-settings.png)
```

## Set up the assistant

The assistant answers customer questions using your support content. Configure it from your [dashboard](https://app.mintlify.com/products/assistant/settings).

<Steps>
  <Step title="Add sample questions">
    Add common questions customers ask, such as:

    * "How do I cancel my subscription?"
    * "Why was my payment declined?"
    * "How do I add team members?"

    Sample questions appear as quick-access buttons, helping customers get answers with one click.
  </Step>

  <Step title="Set a deflection email">
    Configure a support email for questions the assistant can't answer. This ensures customers can still reach your team when self-service isn't enough.
  </Step>

  <Step title="Review conversations">
    Check assistant conversations regularly to identify:

    * Questions the assistant can't answer (content gaps)
    * Incorrect or incomplete answers (content to improve)
    * Common question patterns (content to prioritize)
  </Step>
</Steps>

## Enable feedback collection

Feedback helps you understand which pages are helpful and which need improvement. Review [feedback](/docs/optimize/feedback) to see which pages customers find helpful and which need improvement. Read all comments and update pages based on valid feedback.

## Set up analytics

Monitor the [analytics](/docs/analytics) in your dashboard to see how customers use your help center and improve content over time.

* **Popular articles**: Which articles get the most views? Keep these accurate and well-maintained.
* **Search queries**: What do customers search for? Create content for common searches that return no results.
* **Assistant conversations**: What questions does the assistant receive? Use this to identify content gaps.

## Restrict content by customer segment

If you have different customer tiers or product plans, show relevant content to each segment using group-based access control.

<Steps>
  <Step title="Set up authentication">
    Configure [authentication](/docs/deploy/authentication-setup) to identify customers when they visit your help center.
  </Step>

  <Step title="Configure user groups">
    Return group information in your user data to define customer segments based on plan type, account status, or other attributes. See [User data format](/docs/deploy/authentication-setup#user-data-format) for details.
  </Step>

  <Step title="Tag content by group">
    Use frontmatter to specify which groups can see each article.

    ```mdx theme={null}
    ---
    title: "Enterprise SSO setup"
    groups: ["enterprise"]
    ---
    ```
  </Step>
</Steps>

## Maintain your help center

Support content becomes outdated as your product changes. Establish processes to keep content accurate.

<Steps>
  <Step title="Update with product releases">
    When you ship product changes, update affected support articles. Include documentation updates in your release process.
  </Step>

  <Step title="Review feedback regularly">
    Check article ratings and customer feedback weekly. Address negative feedback promptly. It often indicates confusing or incorrect content.
  </Step>

  <Step title="Monitor support tickets">
    If customers submit tickets for issues covered in your help center, investigate why self-service didn't work. The article might be hard to find, unclear, or incomplete.
  </Step>

  <Step title="Archive outdated content">
    Remove or archive articles about deprecated features. Outdated content confuses customers and reduces trust in your help center.
  </Step>
</Steps>

## Next steps

Your help center is ready to launch. After deploying:

1. Link to your help center from your product and website.
2. Monitor assistant conversations and search queries to find content gaps.
3. Review feedback ratings weekly and improve low-rated articles.
4. Track ticket volume to measure self-service effectiveness.

A good help center reduces support costs while improving customer satisfaction. Invest in content that answers common questions effectively.


# How to measure and improve documentation quality
Source: https://www.mintlify.com/docs/guides/improving-docs

Use analytics, user feedback, and content audits to identify documentation gaps and improve the pages that matter most to your users.

Good documentation is never finished. Products change, users' needs evolve, and content that worked six months ago may no longer reflect how the product behaves. Measuring documentation systematically helps you focus improvement efforts where they'll have the most impact, rather than guessing.

This guide covers how to use quantitative metrics, qualitative feedback, and business signals to find and fix the pages that matter most.

## Use quantitative metrics

Analytics give you a broad view of how documentation is performing. The most useful metrics are signals, not answers—they tell you where to look, not exactly what to fix.

### Page views and traffic

High-traffic pages are your most important documentation investment. Problems on a page with 10,000 monthly views affect far more users than the same problems on a page with 200 views.

Watch for:

* **Unexpected high traffic on error or troubleshooting pages.** Users shouldn't need to read about errors constantly. High traffic on these pages often signals a product UX problem worth reporting to your team.
* **Low traffic on pages you expect to be popular.** If a key getting started page has few views, users may not be finding it—check your navigation and internal links.

### Time on page

Long time on page can mean engagement or confusion. Short time can mean users found what they needed immediately or gave up and left.

Interpret time on page in context:

* Long reference pages should have shorter average time—users are scanning
* Tutorial content should have longer time—users are following steps
* If a simple how-to page has unusually high time, users may be struggling to complete the task

### Bounce rate

Bounce rate measures users who visit one page and leave without navigating further. A high bounce rate isn't inherently bad—users who find exactly what they need and return to their work represent a successful interaction.

Combine bounce rate with feedback scores to interpret it correctly. High bounce with low ratings signals failure. High bounce with high ratings signals success.

### Correlate traffic and satisfaction

Mintlify's analytics lets you see feedback scores alongside traffic data. Use this to prioritize:

* **High traffic, low satisfaction:** Popular pages with a poor user experience. Fix these first—they affect the most users.
* **Low traffic, high satisfaction:** Content that works but users aren't finding. Check whether navigation and internal links direct users there.
* **High traffic, high satisfaction:** Your best-performing pages. Review them for patterns to apply elsewhere.

## Collect qualitative feedback

Numbers tell you that something is wrong. Qualitative feedback tells you what.

### In-page ratings and comments

Enable feedback on your documentation pages so readers can signal when something isn't working. Open-ended comment fields surface specific issues—unclear steps, outdated screenshots, missing information—that ratings alone can't identify.

See [Feedback](/docs/optimize/feedback) to configure feedback collection.

### Stakeholder input

Teams closest to users have information that analytics can't surface:

* **Support teams** know which documentation topics generate the most tickets and where users consistently get stuck
* **Customer success teams** see which pages new users struggle with during onboarding
* **Engineering teams** know when documentation describes behavior that's changed

Regular syncs with these teams—even monthly or quarterly—reveal gaps that user data alone misses.

### User research

Direct conversations with users provide depth that analytics and ratings can't. Ask users to walk through a specific task using only the documentation and narrate their thought process. Their instincts about where to look and where they get confused reveal structural and terminology problems that feel invisible to people who know the product well.

See [Understand your audience](/docs/guides/understand-your-audience) for more on research methods.

## Align documentation with business goals

Documentation quality also shows up in business metrics. Connecting documentation work to business outcomes builds the case for documentation investment.

### Support efficiency

Track whether documentation improvements reduce support ticket volume for specific topics. When a how-to guide improves significantly, ticket volume for that topic should drop. This makes documentation return on investment (ROI) visible and measurable.

### User onboarding and activation

Documentation is often the critical path for new users activating the product. If onboarding analytics show users dropping off at a specific step, the documentation for that step is a likely cause.

### Retention signals

Documentation that's consistently inaccurate or incomplete erodes trust in the product, not just the docs. Users who encounter wrong documentation lose confidence in the reliability of the product itself. Documentation quality is part of product quality.

## Prioritize and act

Measuring is only useful if it drives action. A few frameworks for deciding what to fix first:

* **Fix high-traffic problems first.** The same hour of improvement work affects far more users on a page with 5,000 monthly views than a page with 50.
* **Respond to specific feedback.** When users leave specific comments—"this example doesn't work" or "this step is missing information"—those are high-precision signals that take little investigation to act on.
* **Focus on key user journeys.** Identify the three to five tasks that are most critical for your product's success and ensure the documentation supporting those tasks is excellent before worrying about the rest.

<Tip>
  Use [automations](/docs/automations) to automate recurring improvements—like opening a pull request with suggested fixes for pages flagged by low feedback scores.
</Tip>

## Frequently asked questions

<AccordionGroup>
  <Accordion title="How do I know which documentation pages to prioritize?">
    Start with the intersection of high traffic and low satisfaction scores. These pages affect the most users and have the clearest signal that something isn't working. If you don't have feedback scores yet, start with your support team—they know which pages generate the most confusion without needing any analytics setup.
  </Accordion>

  <Accordion title="What's a good documentation satisfaction score?">
    There's no universal benchmark. Track your own baseline over time and treat consistent improvement as the goal. A page rated positively by 80% of users is a reasonable target for important content. What matters more than the absolute score is the direction of the trend and how your most important pages compare to your average.
  </Accordion>

  <Accordion title="How often should I review documentation metrics?">
    Monthly for high-traffic pages and overall satisfaction trends. Quarterly for a deeper content audit that looks at navigation patterns, search queries with no results, and pages without recent updates. Real-time review isn't necessary unless you've just shipped a major change.
  </Accordion>

  <Accordion title="What should I do if users give negative feedback but don't explain why?">
    Look at the page analytically. High time on page combined with negative ratings often means users are struggling to follow instructions. Low time combined with negative ratings often means users didn't find what they were looking for. Cross-reference with support ticket topics for that page to get more specific signal. When you can't diagnose the problem from data, a short user interview session usually answers it quickly.
  </Accordion>
</AccordionGroup>

## Related pages

<CardGroup>
  <Card title="Analytics overview" icon="chart-line" href="/analytics">
    View analytics and track documentation performance.
  </Card>

  <Card title="Feedback" icon="message-square" href="/optimize/feedback">
    Collect and analyze user feedback on your docs.
  </Card>

  <Card title="Understand your audience" icon="users" href="/guides/understand-your-audience">
    Research and define your documentation audience.
  </Card>

  <Card title="SEO" icon="search" href="/guides/seo">
    Optimize your documentation for search engines.
  </Card>
</CardGroup>


# Guides
Source: https://www.mintlify.com/docs/guides/index

Browse guides on documentation best practices, content strategy, SEO optimization, accessibility, and docs-as-code workflows for your team.

The guides in this section contain advice for creating documentation that helps your users succeed. Whether you're starting from scratch or improving existing docs, these guides help you plan, write, and maintain your documentation.

Above all else, consider your users' needs and goals. Document what helps them use your product and get back to their tasks.

## Topics

### AI tools

Use AI-powered tools to accelerate your documentation workflow.

* [Build an in-app assistant](/docs/guides/assistant-embed): Tutorial that teaches how to add an AI chat bot in a React app to help users find answers from your documentation.
* [Configure automerge](/docs/guides/configure-automerge): Add the Mintlify GitHub App to a ruleset bypass list to enable automatic merging for automations.
* [Use automations](/docs/guides/use-automations): Choose the right automation trigger, write effective instructions, and get consistent results from automated content maintenance.
* [Claude Code](/docs/guides/claude-code), [Codex](/docs/guides/codex), [Cursor](/docs/guides/cursor), [Devin Desktop](/docs/guides/devin-desktop): Guides for using AI coding assistants to maintain documentation.
* [GEO](/docs/guides/geo): Best practices for optimizing your documentation for AI search and answer engines.

### API documentation

Create API documentation that lets users test and learn how to use your API, and is easy to maintain.

* [Migrate from MDX to OAS](/docs/guides/migrating-from-mdx): Move your API documentation from individual MDX pages to autogenerated pages from an OpenAPI specification.

### Best practices

Make your documentation best in class.

* [Accessibility](/docs/guides/accessibility): Make your docs accessible to as many users as possible.
* [Content types](/docs/guides/content-types): Choose the right format for tutorials, how-tos, references, and explanations.
* [Content templates](/docs/guides/content-templates): Copy and modify templates for each content type.
* [Custom page layouts](/docs/guides/custom-layouts): Use page modes and components to build landing pages and other custom layouts.
* [Improve your docs](/docs/guides/improving-docs): Use data and feedback to continuously improve your documentation.
* [Internationalization](/docs/guides/internationalization): Set up multi-language documentation to reach global audiences.
* [Linking](/docs/guides/linking): Create internal links, reference API endpoints, and maintain link integrity across your documentation.
* [Maintenance](/docs/guides/maintenance): Keep your documentation accurate and up-to-date.
* [Media](/docs/guides/media): Add images, videos, and other media effectively while managing maintenance burden.
* [Organize navigation](/docs/guides/navigation): Design information architecture that works for your users.
* [SEO](/docs/guides/seo): Optimize your docs for search engines.
* [Style and tone](/docs/guides/style-and-tone): Write with a consistent voice.
* [Understand your audience](/docs/guides/understand-your-audience): Research and serve your users' needs and goals.

### Git workflows

Understand Git to get the most out of Mintlify and a docs-as-code approach to documentation.

* [Git concepts](/docs/guides/git-concepts): Learn the fundamentals of Git for documentation.
* [Branches](/docs/guides/branches): Use branches to manage documentation changes.

### Use cases

Learn how Mintlify supports different use cases and find a solution that works for you.

* [Create developer documentation](/docs/guides/developer-documentation): Help your users get the most from your product or API with developer documentation that answers questions and gets people back to their main tasks.
* [Create a knowledge base](/docs/guides/knowledge-base): Set up an internal knowledge base to consolidate information for your team, improve search, and reduce maintenance burden.
* [Create a help center](/docs/guides/help-center): Build a self-service help center that enables users to self-serve answers, reduces ticket volume, and improves customer satisfaction.
* [Create a custom frontend](/docs/guides/custom-frontend): Use the Mintlify Astro integration to render your documentation with a fully custom frontend.

## Where to start

<CardGroup>
  <Card title="New to documentation?" icon="rocket" href="/guides/content-types">
    Learn about content types to understand how to structure your docs.
  </Card>

  <Card title="Improving existing docs?" icon="chart-line" href="/guides/improving-docs">
    Learn how to use metrics and feedback to make your docs better.
  </Card>

  <Card title="Working with a team?" icon="git-merge" href="/guides/git-concepts">
    Learn Git workflows for collaborative documentation.
  </Card>
</CardGroup>


# How to set up multi-language documentation
Source: https://www.mintlify.com/docs/guides/internationalization

Set up multi-language documentation with locale-based routing, language switcher navigation, and translated content to reach global audiences.

Internationalization (i18n) is the process of designing software or content to work for different languages and locales. This guide explains how to structure files, configure navigation, and maintain translations effectively so that you can help users access your documentation in their preferred language and improve global reach.

## File structure

Organize translated content in language-specific directories to keep your documentation maintainable and structure your navigation by language.

Create a separate directory for each language using [ISO 639-1 language codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). Place translated files in these directories with the same structure as your default language.

<Expandable title="Supported language codes">
  * `ar` - Arabic
  * `ca` - Catalan
  * `zh` or `zh-Hans` or `zh-CN` - Chinese (Simplified)
  * `zh-Hant` or `zh-TW` - Chinese (Traditional)
  * `cs` - Czech
  * `da` - Danish
  * `de` - German
  * `en` - English
  * `es` - Spanish
  * `fi` - Finnish
  * `fr` - French
  * `fr-CA` - French (Canadian)
  * `he` - Hebrew
  * `hi` - Hindi
  * `hu` - Hungarian
  * `id` - Indonesian
  * `it` - Italian
  * `ja` or `ja-JP` - Japanese
  * `ko` - Korean
  * `lv` - Latvian
  * `nl` - Dutch
  * `no` - Norwegian
  * `pl` - Polish
  * `pt` or `pt-BR` - Portuguese
  * `ro` - Romanian
  * `ru` - Russian
  * `sv` - Swedish
  * `tr` - Turkish
  * `uk` - Ukrainian
  * `uz` - Uzbek
  * `vi` - Vietnamese
</Expandable>

```text Example file structure theme={null}
docs/
├── index.mdx                    # English (default)
├── quickstart.mdx
├── fr/
│   ├── index.mdx               # French
│   ├── quickstart.mdx
├── es/
│   ├── index.mdx               # Spanish
│   ├── quickstart.mdx
└── zh/
    ├── index.mdx               # Chinese
    └── quickstart.mdx
```

<Tip>
  Keep the same filenames and directory structure across all languages. This makes it easier to maintain translations and identify missing content.
</Tip>

## Configure the language switcher

To add a language switcher to your documentation, configure the `languages` array in your `docs.json` navigation.

```json docs.json theme={null}
{
  "navigation": {
    "languages": [
      {
        "language": "en",
        "groups": [
          {
            "group": "Getting started",
            "pages": ["index", "quickstart"]
          }
        ]
      },
      {
        "language": "es",
        "groups": [
          {
            "group": "Comenzando",
            "pages": ["es/index", "es/quickstart"]
          }
        ]
      }
    ]
  }
}
```

Each language entry in the `languages` array requires:

* `language`: ISO 639-1 language code
* Full navigation structure
* Paths to translated files

The navigation structure can differ between languages to accommodate language-specific content needs.

<Warning>
  Do not use the same page path in more than one language. Duplicating paths across languages results in undefined behavior. Each page path must appear in only one language's navigation.
</Warning>

### Set default language

Mintlify uses the first language in the `languages` array as the default. To use a different language as the default, either reorder the array or add the `default` property:

```json docs.json theme={null}
{
  "navigation": {
    "languages": [
      {
        "language": "es",
        "groups": [...]
      },
      {
        "language": "en",
        "groups": [...]
      }
    ]
  }
}
```

Alternatively, use the `default` property to override the order:

```json docs.json theme={null}
{
  "navigation": {
    "languages": [
      {
        "language": "en",
        "groups": [...]
      },
      {
        "language": "es",
        "default": true,
        "groups": [...]
      }
    ]
  }
}
```

### Single language documentation

If you only want one language available without a language switcher, remove the `languages` field from your navigation configuration. Instead, define your navigation structure directly:

```json docs.json theme={null}
{
  "navigation": {
    "tabs": [
      {
        "tab": "Documentation",
        "groups": [
          {
            "group": "Getting started",
            "pages": ["index", "quickstart"]
          }
        ]
      }
    ]
  }
}
```

This displays your documentation in a single language without the language switcher UI.

<Tip>
  Translate navigation labels like group or tab names to match the language of the content. This creates a fully localized experience for your users.
</Tip>

### Global navigation

To add global navigation elements that appear across all languages, configure the `global` object in your `docs.json` navigation.

```json docs.json theme={null}
{
  "navigation": {
    "global": {
      "anchors": [
        {
          "anchor": "Documentation",
          "href": "https://example.com/docs"
        },
        {
          "anchor": "Blog",
          "href": "https://example.com/blog"
        }
      ]
    },
    "languages": [
      // Language-specific navigation
    ]
  }
}
```

### Localized footer and navbar

Customize the footer and navbar for each language to display translated content and region-specific links.

Add `footer` and `navbar` properties to each language configuration:

```json docs.json theme={null}
{
  "navigation": {
    "languages": [
      {
        "language": "en",
        "footer": {
          "socials": {
            "x": "https://x.com/mintlify"
          },
          "links": [
            {
              "header": "Resources",
              "items": [
                { "label": "Documentation", "href": "/en/docs" },
                { "label": "Blog", "href": "https://mintlify.com/blog" }
              ]
            }
          ]
        },
        "navbar": {
          "links": [
            { "label": "Docs", "href": "/en/docs" }
          ],
          "primary": {
            "type": "button",
            "label": "Get Started",
            "href": "/en/quickstart"
          }
        },
        "groups": [
          {
            "group": "Getting started",
            "pages": ["en/quickstart", "en/index"]
          }
        ]
      },
      {
        "language": "es",
        "footer": {
          "socials": {
            "x": "https://x.com/mintlify"
          },
          "links": [
            {
              "header": "Recursos",
              "items": [
                { "label": "Documentación", "href": "/es/docs" },
                { "label": "Blog", "href": "https://mintlify.com/blog" }
              ]
            }
          ]
        },
        "navbar": {
          "links": [
            { "label": "Documentación", "href": "/es/docs" }
          ],
          "primary": {
            "type": "button",
            "label": "Comenzar",
            "href": "/es/quickstart"
          }
        },
        "groups": [
          {
            "group": "Comenzando",
            "pages": ["es/quickstart", "es/index"]
          }
        ]
      }
    ]
  }
}
```

Language-specific `footer` and `navbar` override the global settings for that language. If a language doesn't define these properties, it inherits the global configuration.

You can also configure a language-specific `banner` using the same pattern.

## Maintain translations

Keep translations accurate and synchronized with your source content.

### Translation workflow

1. Update source content in your primary language.
2. Identify changed content.
3. Translate changed content.
4. Review translations for accuracy.
5. Update translated files.
6. Verify navigation and links work.

### Automated translations

For automated translation solutions, [set up an automation](/docs/automations) to run the agent on a schedule or in response to repository pushes.

### External translation providers

If you work with your own translation vendors or regional translators, you can integrate their workflow with your Mintlify documentation using GitHub Actions or similar CI/CD tools.

1. **Export source content**: Extract MDX files that need translation.
2. **Send to translators**: Provide files to your translation provider.
3. **Receive translations**: Get translated MDX files back.
4. **Import and deploy**: Add translated files to language directories and update navigation.

This GitHub Actions workflow automatically exports changed English content for translation when PRs merge to main.

```yaml .github/workflows/export-for-translation.yml theme={null}
name: Export content for translation

on:
  push:
    branches: [main]
    paths:
      - '*.mdx'
      - '!es/**'
      - '!fr/**'
      - '!zh/**'

# Prevent concurrent workflow runs to avoid race conditions
concurrency:
  group: translation-export-${{ github.ref }}
  cancel-in-progress: false

jobs:
  export:
    runs-on: ubuntu-latest
    
    # Early exit if no changes detected (optional - acts as additional safety)
    outputs:
      files-changed: ${{ steps.changed.outputs.has-files }}
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 2

      - name: Get changed MDX files
        id: changed
        run: |
          # Check if parent commit exists (handles initial push)
          if ! git rev-parse HEAD~1 >/dev/null 2>&1; then
            echo "has-files=false" >> $GITHUB_OUTPUT
            echo "files=" >> $GITHUB_OUTPUT
            echo "No parent commit found - skipping export"
            exit 0
          fi
          
          # Get list of changed MDX files (excluding translation dirs)
          files=$(git diff --name-only HEAD~1 HEAD -- '*.mdx' ':!es/' ':!fr/' ':!zh/' | tr '\n' ' ')
          
          if [ -z "$files" ]; then
            echo "has-files=false" >> $GITHUB_OUTPUT
            echo "files=" >> $GITHUB_OUTPUT
            echo "No MDX files changed - skipping export"
          else
            echo "has-files=true" >> $GITHUB_OUTPUT
            echo "files=$files" >> $GITHUB_OUTPUT
            echo "Found changed files: $files"
          fi
        shell: bash

      - name: Create translation package directory
        if: steps.changed.outputs.has-files == 'true'
        run: |
          mkdir -p translation-export
          echo "Created translation-export directory"

      - name: Copy changed files to export directory
        if: steps.changed.outputs.has-files == 'true'
        run: |
          failed_count=0
          for file in ${{ steps.changed.outputs.files }}; do
            if [ -f "$file" ]; then
              target_dir="translation-export/$(dirname "$file")"
              mkdir -p "$target_dir"
              cp "$file" "$target_dir/"
              echo "✓ Copied: $file"
            else
              echo "✗ File not found: $file"
              ((failed_count++))
            fi
          done
          
          if [ $failed_count -gt 0 ]; then
            echo "Warning: $failed_count file(s) could not be copied"
          fi
        shell: bash

      - name: Validate translation package
        if: steps.changed.outputs.has-files == 'true'
        run: |
          echo "Translation package contents:"
          find translation-export -type f -name "*.mdx" | sort
          echo ""
          file_count=$(find translation-export -type f -name "*.mdx" | wc -l)
          echo "Total MDX files: $file_count"

      - name: Upload translation package
        if: steps.changed.outputs.has-files == 'true'
        uses: actions/upload-artifact@v4
        with:
          name: translation-export-${{ github.sha }}
          path: translation-export/
          retention-days: 30
          if-no-files-found: error
          compression-level: 9

      - name: Print job summary
        if: steps.changed.outputs.has-files == 'true'
        run: |
          echo "## Translation Export Complete" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Artifact:** \`translation-export-${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Changed Files:**" >> $GITHUB_STEP_SUMMARY
          echo "${{ steps.changed.outputs.files }}" | tr ' ' '\n' | sed 's/^/- /' >> $GITHUB_STEP_SUMMARY
```

This GitHub Actions workflow validates and imports translated content when added via PR.

```yaml .github/workflows/import-translations.yml theme={null}
name: Import translations

on:
  pull_request:
    paths:
      - 'es/**'
      - 'fr/**'
      - 'zh/**'

# Define explicit permissions
permissions:
  contents: read
  pull-requests: write

jobs:
  validate:
    runs-on: ubuntu-latest
    
    outputs:
      validation-status: ${{ steps.final-check.outputs.status }}
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history to ensure origin/main is available

      - name: Fetch origin/main reference
        run: |
          git fetch origin main:origin/main 2>/dev/null || echo "origin/main not available, using latest"
        continue-on-error: true

      - name: Get changed translation files
        id: changed-files
        run: |
          # Get all changed MDX files in translation directories
          files=$(git diff --name-only origin/main..HEAD -- 'es/**/*.mdx' 'fr/**/*.mdx' 'zh/**/*.mdx' | sort)
          
          if [ -z "$files" ]; then
            echo "No translation MDX files detected in this PR"
            echo "files=" >> $GITHUB_OUTPUT
            echo "count=0" >> $GITHUB_OUTPUT
          else
            echo "Found $(echo "$files" | wc -l) translation files"
            echo "$files"
            echo "files=$files" >> $GITHUB_OUTPUT
            echo "count=$(echo "$files" | wc -l)" >> $GITHUB_OUTPUT
          fi
        shell: bash

      - name: Validate frontmatter
        id: frontmatter
        if: steps.changed-files.outputs.count > 0
        run: |
          failed_files=()
          success_count=0
          total=${{ steps.changed-files.outputs.count }}
          
          while IFS= read -r file; do
            if [ ! -f "$file" ]; then
              echo "✗ File not found: $file"
              failed_files+=("$file")
              continue
            fi
            
            # Check for valid frontmatter (lines 1-2 must be ---)
            first_line=$(sed -n '1p' "$file")
            second_line=$(sed -n '2p' "$file")
            last_line=$(awk 'NF' "$file" | tail -1)
            
            if [ "$first_line" = "---" ] && grep -q "^---$" "$file"; then
              echo "✓ Valid frontmatter: $file"
              ((success_count++))
            else
              echo "✗ Invalid frontmatter in $file"
              echo "  Line 1: '$first_line'"
              failed_files+=("$file")
            fi
          done <<< "${{ steps.changed-files.outputs.files }}"
          
          echo ""
          echo "Frontmatter check: $success_count/$total passed"
          
          if [ ${#failed_files[@]} -gt 0 ]; then
            echo "frontmatter_valid=false" >> $GITHUB_OUTPUT
            printf 'failed_files=%s\n' "${failed_files[@]}" >> $GITHUB_OUTPUT
          else
            echo "frontmatter_valid=true" >> $GITHUB_OUTPUT
          fi
        shell: bash

      - name: Check file structure
        id: structure
        if: steps.changed-files.outputs.count > 0
        run: |
          missing_sources=()
          orphaned_count=0
          
          while IFS= read -r translated_file; do
            # Extract language and relative path
            # e.g., "es/docs/guide.mdx" -> lang="es", relative_path="docs/guide.mdx"
            lang=$(echo "$translated_file" | cut -d'/' -f1)
            relative_path=$(echo "$translated_file" | cut -d'/' -f2-)
            source_file="$relative_path"
            
            if [ ! -f "$source_file" ]; then
              echo "Missing source: $translated_file -> $source_file"
              missing_sources+=("$translated_file")
              ((orphaned_count++))
            else
              echo "✓ Found source: $translated_file -> $source_file"
            fi
          done <<< "${{ steps.changed-files.outputs.files }}"
          
          echo ""
          echo "Structure check: $orphaned_count orphaned file(s)"
          
          if [ $orphaned_count -gt 0 ]; then
            echo "structure_valid=false" >> $GITHUB_OUTPUT
            printf 'missing_sources=%s\n' "${missing_sources[@]}" >> $GITHUB_OUTPUT
          else
            echo "structure_valid=true" >> $GITHUB_OUTPUT
          fi
        shell: bash

      - name: Validate file integrity
        id: integrity
        if: steps.changed-files.outputs.count > 0
        run: |
          integrity_passed=true
          
          while IFS= read -r file; do
            # Check file is readable and not empty
            if [ ! -r "$file" ] || [ ! -s "$file" ]; then
              echo "✗ File integrity issue: $file (not readable or empty)"
              integrity_passed=false
            fi
            
            # Basic check: file should have content after frontmatter
            line_count=$(wc -l < "$file")
            if [ "$line_count" -lt 5 ]; then
              echo "File is suspiciously short: $file ($line_count lines)"
            fi
          done <<< "${{ steps.changed-files.outputs.files }}"
          
          if [ "$integrity_passed" = true ]; then
            echo "integrity_valid=true" >> $GITHUB_OUTPUT
          else
            echo "integrity_valid=false" >> $GITHUB_OUTPUT
          fi
        shell: bash

      - name: Generate validation report
        if: always()
        run: |
          echo "## Translation Validation Report" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Files Changed:** ${{ steps.changed-files.outputs.count }}" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          
          if [ "${{ steps.changed-files.outputs.count }}" = "0" ]; then
            echo "No translation MDX files found in this PR" >> $GITHUB_STEP_SUMMARY
            echo "" >> $GITHUB_STEP_SUMMARY
            echo "> This could mean:" >> $GITHUB_STEP_SUMMARY
            echo "- Only non-MDX files in es/, fr/, or zh/ directories were changed" >> $GITHUB_STEP_SUMMARY
            echo "- Workflow was triggered but no translation content to validate" >> $GITHUB_STEP_SUMMARY
          else
            echo "### Validation Results" >> $GITHUB_STEP_SUMMARY
            echo "- Frontmatter: ${{ steps.frontmatter.outputs.frontmatter_valid }}" >> $GITHUB_STEP_SUMMARY
            echo "- File Structure: ${{ steps.structure.outputs.structure_valid }}" >> $GITHUB_STEP_SUMMARY
            echo "- File Integrity: ${{ steps.integrity.outputs.integrity_valid }}" >> $GITHUB_STEP_SUMMARY
            echo "" >> $GITHUB_STEP_SUMMARY
          fi
        shell: bash

      - name: Final validation check
        id: final-check
        # Only run this check if we actually had MDX files to validate
        if: steps.changed-files.outputs.count > 0
        run: |
          validation_failed=false
          
          if [ "${{ steps.frontmatter.outputs.frontmatter_valid }}" != "true" ]; then
            echo "Frontmatter validation failed"
            validation_failed=true
          fi
          
          if [ "${{ steps.structure.outputs.structure_valid }}" != "true" ]; then
            echo "File structure validation failed"
            validation_failed=true
          fi
          
          if [ "${{ steps.integrity.outputs.integrity_valid }}" != "true" ]; then
            echo "File integrity validation failed"
            validation_failed=true
          fi
          
          if [ "$validation_failed" = true ]; then
            echo "status=failed" >> $GITHUB_OUTPUT
            exit 1
          else
            echo "status=passed" >> $GITHUB_OUTPUT
            echo "All validations passed"
          fi
        shell: bash

      - name: Handle no-files-to-validate case
        # Run only when there are no MDX files to validate
        if: steps.changed-files.outputs.count == 0
        run: |
          echo "No translation MDX files to validate - PR is valid"
          echo "status=no-changes" >> ${{ steps.final-check.outputs }}
        shell: bash
```

**Best practices for external translation workflows**

* **Preserve frontmatter**: Ensure translators keep YAML frontmatter intact, translating only `title` and `description` values.
* **Protect code blocks**: Mark code blocks as "do not translate" for your vendors.
* **Use translation memory**: Provide glossaries with technical terms that should remain in English or have specific translations.
* **Automate validation**: Use CI checks to verify MDX syntax and frontmatter before merging translations.
* **Version control**: Track the source version for each translation to identify outdated content.

### Images and media

Store translated images in language-specific directories.

```
images/
├── dashboard.png          # English version
├── fr/
│   └── dashboard.png     # French version
└── es/
    └── dashboard.png     # Spanish version
```

Reference images using relative paths in your translated content.

```mdx es/index.mdx theme={null}
![Captura de pantalla del panel de control](/images/es/dashboard.png)
```

## SEO for multi-language sites

Optimize each language version for search engines.

### Page metadata

Include translated metadata in each file's frontmatter:

```mdx fr/index.mdx theme={null}
---
title: "Commencer"
description: "Apprenez à commencer avec notre produit."
keywords: ["démarrage", "tutoriel", "guide"]
---
```

## Best practices

### Date and number formats

Consider locale-specific formatting for dates and numbers.

* Date formats: MM/DD/YYYY (month/day/year) vs DD/MM/YYYY (day/month/year)
* Number formats: 1,000.00 vs 1.000,00
* Currency symbols: \$100.00 vs 100,00€

Include examples in the appropriate format for each language or use universally understood formats.

### Maintain consistency

* Maintain content parity across all languages to ensure every user gets the same quality of information.
* Create a translation glossary for technical terms.
* Keep the same content structure across languages.
* Match the tone and style of your source content.
* Use Git branches to manage translation work separately from main content updates.

### Layout differences

Some languages require more or less space than English. Test your translated content on different screen sizes to ensure:

* Navigation fits properly.
* Code blocks don't overflow.
* Tables and other formatted text remain readable.
* Images scale appropriately.

### Character encoding

Ensure your development environment and deployment pipeline support UTF-8 encoding to properly display all characters in languages with different alphabets and special characters.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Do I need to translate every page before launching a new language?">
    No. You can launch a language with partial coverage and expand over time. A common approach is to translate your most-visited pages first, such as getting started content, authentication, and top how-to guides. Leave lower-traffic reference content in the default language until translations are ready. Users generally prefer some translated content over none.
  </Accordion>

  <Accordion title="What happens when a translated page is missing?">
    If you navigate to a translated URL that doesn't exist, you'll see a 404. To avoid this, either only include translated pages in your language-specific navigation or maintain parity between your default language and translated content. Using the same file structure across languages makes it easy to identify which translations are missing.
  </Accordion>

  <Accordion title="Should navigation labels be translated?">
    Yes. Navigation labels—group names, tab titles, anchor text—should match the language of the content. An English "Getting started" label in a Spanish documentation section creates a jarring experience. Mintlify supports language-specific navigation structures, so each language can have fully translated labels.
  </Accordion>

  <Accordion title="How do I handle code examples in translated content?">
    Do not translate code itself—variable names, function calls, and syntax are language-agnostic. Translate comments within code blocks if they explain concepts users need to understand. Fully translate instructions surrounding code blocks.
  </Accordion>

  <Accordion title="Does adding more languages affect site performance?">
    Mintlify serves each language version as a separate set of static pages, so a reader visiting `/es/quickstart` only loads the Spanish content for that page—not every translation. Adding languages does not change page weight or runtime performance for end users.

    Adding languages does grow your repository and your build's working set. To keep authoring and CI fast:

    * Store translated images in language-specific directories so unused locales aren't pulled into other locales' content.
    * In larger repos, scope `mint broken-links` and other CI checks to changed files rather than the full tree.
  </Accordion>
</AccordionGroup>


# Create a knowledge base
Source: https://www.mintlify.com/docs/guides/knowledge-base

Host your internal knowledge base on Mintlify to consolidate information for your team, improve search, and reduce maintenance burden.

An internal knowledge base helps your team find answers and maintain a source of truth. If your team has information spread across different channels and platforms, people might find inaccurate or no information when they search for answers. A centralized knowledge base solves this by putting answers where everyone can find them and giving your team a specific place to record shared knowledge.

Mintlify provides the infrastructure for knowledge bases that your entire team can contribute to.

* **AI-powered search**: The [assistant](/docs/assistant/index) answers questions using your knowledge base content, so people find answers without knowing exactly where to look.
* **Slack integrations**: Add the [agent](/docs/agent/slack) to Slack to ask questions and capture knowledge from conversations.
* **Low-barrier contributions**: The [web editor](/docs/editor) and [agent](/docs/agent/index) let anyone on your team update content without learning Git or Markdown.
* **Authentication built-in**: Control access with [SSO or OAuth](/docs/deploy/authentication-setup), and use [groups](/docs/deploy/authentication-setup#control-access-with-groups) to show different content to different teams.

## Prerequisites

If you haven't created a Mintlify project yet, see the [Quickstart](/docs/quickstart) to deploy your site.

* An authentication system (SSO or OAuth provider like Okta or Azure AD)
* Control over your domain for hosting
* Admin access to your Mintlify organization

## Migrate existing content

If you're creating a knowledge base from scratch, skip to [Design the navigation structure](#design-the-navigation-structure).

### Audit existing content

Catalog the content you currently have in your existing knowledge base. A catalog helps you understand what content to migrate, plan how to organize it, identify gaps, and confirm that you moved everything to your new knowledge base.

* **Total number of articles**: Helps estimate migration effort and track completeness.
* **Topics and content**: Informs your navigation structure and content organization.
* **Current organization**: See how your content is currently organized and whether it matches your desired structure.
* **Content types**: Determine any content conversion requirements for text, PDFs, videos, and embedded content.
* **Metadata**: Identify any metadata to preserve like dates, authors, and tags.
* **Access requirements**: Determine the best authentication approach for your knowledge base.

### Export your existing content

Most knowledge base platforms support exporting content in standard formats. The format you choose depends on your current platform and your priorities.

* Export to **Markdown** for the simplest migration to Mintlify. (recommended)
* Export to **HTML** if Markdown isn't available. You must convert your content to Markdown later.
* Export to **JSON or CSV** if you have structured metadata to preserve.

## Design the navigation structure

Your navigation structure determines how people find content in your knowledge base. You can recreate your existing structure or redesign it to better match how your team thinks about the content.

<Tip>
  Migrating is a good time to improve your structure. Consider whether your current organization actually works for your team, or if you can reorganize to make information easier to find.
</Tip>

Your `docs.json` file defines the navigation structure of your knowledge base. Create this file at the root of your project repository.

```json theme={null}
{
  "navigation": {
    "groups": [
      {
        "group": "Finance",
        "pages": [
            "finance/overview",
            "finance/budgeting-process",
            "finance/expense-reports",
            "finance/cost-allocation"
        ]
      },
      {
        "group": "HR",
        "pages": [
            "hr/overview",
            "hr/onboarding",
            "hr/benefits",
            "hr/time-off-policy"
        ]
      },
      {
        "group": "Engineering",
        "pages": [
          "engineering/overview",
          "engineering/dev-setup",
          "engineering/deployment",
          "engineering/code-standards"
        ]
      }
    ]
  }
}
```

See [Navigation](/docs/organize/navigation) for more information on how to structure your knowledge base.

## Set up authentication

Determine who needs access to what content in your knowledge base.

If everyone should have access to the entire knowledge base, set up only [authentication](/docs/deploy/authentication-setup).

If you need to restrict access to certain content to specific users or groups, set up authentication with [group-based access control](/docs/deploy/authentication-setup#control-access-with-groups).

## Migrate your content

Move your exported content into a folder structure that matches the navigation structure you designed. Convert content to Markdown if needed, add any missing frontmatter, and set up internal links.

<Steps>
  <Step title="Organize files">
    Create folders that match your `docs.json` structure. For example, if your `docs.json` has a Finance group, create a `finance/` folder:

    ```text theme={null}
    your-project/
    ├── docs.json
    ├── finance/
    │   ├── overview.mdx
    │   ├── budgeting-process.mdx
    │   ├── expense-reports.mdx
    │   └── cost-allocation.mdx
    ├── hr/
    │   ├── overview.mdx
    │   ├── onboarding.mdx
    │   ├── benefits.mdx
    │   └── time-off-policy.mdx
    └── engineering/
        ├── overview.mdx
        ├── dev-setup.mdx
        ├── deployment.mdx
        └── code-standards.mdx
    ```

    Place each article in its corresponding folder. The path must match the path in your `docs.json`. For example, if `docs.json` references `"finance/expense-reports"`, the file should be `finance/expense-reports.mdx` in your project repository.
  </Step>

  <Step title="Add frontmatter to each article">
    Every `.mdx` file needs frontmatter at the top with metadata. Every page requires a title and description. See [Pages](/docs/organize/pages) for more information on page metadata.

    ```mdx theme={null}
    ---
    title: "Expense Report Process"
    description: "How to submit and track expense reports"
    ---

    Your content here...
    ```
  </Step>

  <Step title="Set up internal links">
    Link between pages using paths from your project root.

    ```mdx theme={null}
    See [Onboarding Guide](/hr/onboarding) for new employee setup.

    For questions, contact [HR Benefits Team](/hr/benefits#common-questions).
    ```
  </Step>

  <Step title="Convert HTML and other formats to Markdown">
    If you exported your content as HTML, convert it to Markdown. Some tools that can help include:

    * **Pandoc**: Command-line tool that converts between many formats.
    * **CloudConvert**: Online converter supporting HTML, DOCX, PDF, and more.
    * **VS Code extensions**: Search for "HTML to Markdown" in extensions.
  </Step>

  <Step title="Handle multiple content formats">
    If you have PDFs, videos, or other media, decide how to include them in your knowledge base.

    * **Embed videos**: Embed videos or link to hosted videos.
    * **Link to PDFs**: Add PDFs to your project repository and link to them from relevant pages.
    * **Convert PDFs to Markdown**: If you want the content of a PDF to be a page, convert PDFs to Markdown.
  </Step>
</Steps>

## Set up the assistant

The assistant is automatically enabled for Pro and Enterprise plans. The assistant lets your team ask questions and get answers with cited sources from your knowledge base.

Configure the assistant from your [dashboard](https://app.mintlify.com/products/assistant/settings):

* **Sample questions**: Add common questions like "how do I submit an expense report" or "what is the vacation policy" so people can get answers with one click.

* **Search sites**: Include additional sites the assistant can search when answering questions.

* **Deflection email**: Set a support email for questions the assistant can't answer.

### Add the assistant to Slack

The [Slack bot](/docs/ai/slack-bot) lets your team ask the assistant questions without leaving Slack. Create a channel where the bot responds to every message or let people @mention the bot in any channel.

## Enable team contributions

A knowledge base stays accurate when everyone can update it, not just the people who set it up. Mintlify provides three ways for team members to contribute quickly to your knowledge base.

### Web editor

The [web editor](/docs/editor) lets anyone create and edit pages in their browser. Contributors can:

* Edit pages visually or in Markdown.
* Drag and drop to reorganize navigation.
* Upload images and media.
* Create branches and pull requests for review.

This works well for subject matter experts who know the content but aren't comfortable with code workflows.

### Agent

The [agent](/docs/agent/index) in your dashboard creates documentation updates from natural language prompts. Describe what you want to change, and the agent creates a pull request with the updates.

For example, you could prompt the agent with "add a section to the expense policy page explaining how to submit receipts for meals over \$50." You could also copy the existing expense policy page into the prompt. The agent would draft the content and open a PR for review.

### Capture knowledge from Slack

Teams share valuable information in Slack that often never makes it into documentation. The [agent in Slack](/docs/agent/slack) can capture this knowledge and convert it into structured documentation.

When someone shares useful information in a Slack thread, any team member can mention `@mintlify` with instructions to document it. The agent reads the conversation, extracts the relevant information, and creates a pull request. This is useful for capturing technical decisions, troubleshooting solutions, and process explanations while the context is still fresh.

For example, if your team discussed how to configure a new integration in a thread, you could reply:

> @mintlify Create a guide for configuring the Acme integration based on this conversation.

The agent uses the thread context to create documentation that captures the key information from the discussion.

### Locally

Anyone with access to your knowledge base repository can work locally in their preferred editor and push changes to your repository.

## Establish maintenance workflows

A knowledge base can decay quickly without maintenance. Set up systems to keep content up to date and help your team contribute to the knowledge base.

<Steps>
  <Step title="Assign content ownership">
    Designate an owner or small team for each section. They don't have to write all the content, but they're responsible for:

    * Reviewing content regularly.
    * Flagging outdated information.
    * Approving new pages in their section.
    * Responding when people report errors.
  </Step>

  <Step title="Set up review cycles and content verification">
    Content becomes stale over time. Establish a review schedule.

    * **Critical content**: Review every 30 days
    * **Standard content**: Review every 90 days
    * **Evergreen content**: Review yearly

    When reviewing, check:

    * Are links still valid?
    * Have systems or processes changed?
    * Are examples current?
    * Is there new information that should be added?
  </Step>

  <Step title="Create contribution guidelines">
    Make it easy for anyone to improve the knowledge base. Your guidelines should cover:

    * **Format**: Do you have specific templates or format requirements?
    * **Process**: How should someone propose and submit changes?
    * **Review**: Who reviews submissions? What's the turnaround time?
    * **Scope**: What types of content are in scope?
  </Step>

  <Step title="Monitor usage metrics">
    Review how your team uses the knowledge base to prioritize content and identify areas for improvement. Set a regular cadence for reviewing usage metrics—monthly or quarterly are good intervals.

    * Which articles get the most views? Invest in keeping these accurate and easy to read.
    * Which articles get no views? Consider removing them or improving discoverability.
    * What's the bounce rate? If people leave immediately, the content might not be helpful or navigation could be improved.
  </Step>
</Steps>

## Next steps

Your knowledge base is ready to launch. After deploying:

1. Announce the knowledge base to your team.
2. Monitor usage and search patterns in your analytics.
3. Encourage contributions when people find gaps.
4. Review and update content regularly.

The most successful knowledge bases evolve based on how teams actually use them.


# How to link documentation pages effectively
Source: https://www.mintlify.com/docs/guides/linking

Create internal links, anchor links, and deep links in your documentation, and maintain link integrity with redirects and broken link checks.

Links connect your documentation into a coherent system. They help users discover related content, navigate efficiently, and follow a logical path through complex topics. Poor links—vague anchor text, missing cross-references, broken URLs—make documentation harder to use and hurt SEO.

This guide covers how to create different types of links in Mintlify and how to maintain link integrity as your documentation grows.

## Internal links

Link to other pages in your documentation using root-relative paths. Root-relative paths start from the root of your documentation directory and work consistently regardless of where the linking page sits in your directory structure.

```mdx theme={null}
- [Quickstart guide](/quickstart)
- [API overview](/api-playground/overview)
- [Custom components](/customize/react-components)
```

Mintlify resolves relative paths (`./` and `../`) based on the source file's location in your project directory. This works for links, images, and JSX elements like `<Card>` and `<a>` tags.

```mdx theme={null}
- [Sibling page](./sibling-page)
- [Parent section page](../other-page)
```

For `index.mdx` files, relative paths resolve from the directory that contains the index file. For example, a `./setup` link in `guides/getting-started/index.mdx` resolves to `/guides/getting-started/setup`.

Links preserve fragments and query strings.

```mdx theme={null}
[Setup instructions](./setup#step-1)
```

<Tip>
  Root-relative paths (starting with `/`) perform better for internal links because they remain correct if you move the linking page to a different directory.
</Tip>

## Anchor links

Anchor links point to specific sections within a page. Every heading automatically generates an anchor based on its text.

### Link to headers on the same page

Reference headers on the current page using the hash symbol:

```mdx theme={null}
[Jump to best practices](#best-practices)
```

### Link to headers on other pages

Combine the page path with the anchor:

```mdx theme={null}
- [Customize your playground](/api-playground/overview#customize-your-playground)
- [Cards properties](/components/cards#properties)
```

### How Mintlify generates anchors

Mintlify automatically creates anchors from header text by converting to lowercase, replacing spaces with hyphens, and removing special characters.

| Header text              | Generated anchor      |
| ------------------------ | --------------------- |
| `## Getting Started`     | `#getting-started`    |
| `### API Authentication` | `#api-authentication` |
| `#### Step 1: Install`   | `#step-1-install`     |

<Note>
  Headers with the `noAnchor` prop do not generate anchor links. See [Format text](/docs/create/text#disable-anchor-links) for details.
</Note>

### Custom anchor IDs

Override the auto-generated anchor for any heading by appending `{#custom-id}` to the header text:

```mdx theme={null}
## Configuration options {#config}
```

This heading is reachable at `#config` instead of `#configuration-options`. Custom IDs keep anchor links stable when you update heading text—useful for headings you link to frequently. See [Format text](/docs/create/text#custom-heading-ids) for more details.

## Deep links

Deep links point to specific states or locations within a page, not just the page itself.

### Accordion deep links

When a user opens an accordion, the URL hash updates to reflect the open state. Visiting a URL with that hash automatically opens and scrolls to the accordion.

By default, the hash derives from the accordion's `title`. Use the `id` property to set a custom hash:

```mdx theme={null}
<Accordion title="Installation steps" id="install">
  ...
</Accordion>
```

This accordion is reachable at `#install` instead of the auto-generated `#installation-steps`. See [Accordions](/docs/components/accordions) for more.

### API playground deep links

To open the API playground in a link, append `?playground=open` to any endpoint page URL:

```text theme={null}
https://your-docs-url/endpoint-path?playground=open
```

The URL updates as users open or close the playground. Use playground deep links in support conversations or onboarding flows to send users directly to an endpoint's interactive playground. See [API playground](/docs/api-playground/overview#parameter-anchor-links) for information on parameter anchor links.

## External links

When linking to external resources, write anchor text that makes the destination clear:

```mdx theme={null}
See the [OpenAPI specification](https://swagger.io/specification/) in the Swagger documentation for details.
```

## Best practices

### Write descriptive anchor text

Anchor text should tell users where they're going before they click. Vague phrases like "click here" or "read more" are also weaker SEO signals than descriptive text.

<CodeGroup>
  ```mdx Good theme={null}
  See [Hidden pages](/organize/hidden-pages) for more information.
  [Configure custom domains](/customize/custom-domain)
  ```

  ```mdx Avoid theme={null}
  [Click here](/api-playground/overview)
  [Read more](/deploy/deployments)
  [See this page](/customize/custom-domain)
  ```
</CodeGroup>

### Link prerequisites explicitly

When a page assumes prior steps, link to them at the top rather than assuming users find them:

```mdx theme={null}
## Prerequisites

Before deploying your documentation, ensure you have:

- Completed the [quickstart guide](/quickstart)
- Configured your [custom domain](/customize/custom-domain)
- Set up [authentication](/deploy/authentication-setup) if needed
```

### Build topic clusters

Link related content together to help users—and search engines—understand how you organize your content:

```mdx theme={null}
## Related topics

- [API authentication](/api-playground/overview#authentication)
- [Adding SDK examples](/api-playground/adding-sdk-examples)
- [Managing page visibility](/api-playground/managing-page-visibility)
```

### Check for broken links

Run the Mintlify CLI before publishing to catch broken internal and external links:

```bash theme={null}
mint broken-links
```

### Update links when reorganizing

When moving or renaming pages:

1. Update the page path in your navigation configuration.
2. Configure redirects from the old path to the new path.
3. Search your documentation for references to the old path.
4. Update all internal links to use the new path.
5. Run `mint broken-links` to verify.

### Use redirects for moved content

When permanently moving content, add redirects to prevent broken links for users who have bookmarked or shared old URLs.

```json theme={null}
{
  "redirects": [
    {
      "source": "/old-path",
      "destination": "/new-path"
    }
  ]
}
```

See [Redirects](/docs/create/redirects) for more information.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Should I use root-relative or absolute URLs for internal links?">
    Root-relative paths (starting with `/`) are the most common choice for internal links in Mintlify. They work consistently regardless of where the linking page sits in your directory, and they don't break if your documentation domain changes. Absolute URLs for internal links create unnecessary brittleness.

    You can use relative paths (`./` and `../`), but because they resolve based on the source file's location they may break more frequently.
  </Accordion>

  <Accordion title="How do I keep anchor links stable when I update headings?">
    Use custom anchor IDs for headings you link to frequently. Appending `{#custom-id}` to a heading decouples the anchor from the heading text, so you can update the heading text without breaking any links that point to it. This is especially useful for headings in high-traffic reference sections where the text may need refinement over time.
  </Accordion>

  <Accordion title="What happens to bookmarked links when I reorganize my documentation?">
    Bookmarked and shared links become 404 errors without redirects. Set up redirects in your `docs.json` whenever you move or rename a page. Redirects are cheap to add and prevent a poor user experience for anyone who linked to your documentation from an external source—blog posts, Stack Overflow answers, internal wikis.
  </Accordion>

  <Accordion title="How many internal links should a page have?">
    Link whenever a related concept is genuinely useful to the user in that moment—not to meet a quota. Too few links leave users without context or next steps. Too many links turn the page into a navigation exercise that pulls users away from what they're trying to do. As a rough heuristic, link the first mention of a concept or tool, and don't repeat the same link multiple times on a single page.
  </Accordion>
</AccordionGroup>

## Related resources

* [Format text](/docs/create/text): Markdown formatting options including heading IDs and anchor behavior.
* [Navigation](/docs/organize/navigation): Configure your documentation structure.
* [Redirects](/docs/create/redirects): Set up redirects for moved content.


# How to maintain documentation over time
Source: https://www.mintlify.com/docs/guides/maintenance

Keep documentation accurate and up-to-date with review schedules, ownership models, automated checks, and content lifecycle practices.

Documentation drifts from the product the moment it's published. Features change, APIs evolve, and UI elements get renamed. Without deliberate maintenance, documentation quietly becomes a liability—users follow outdated steps, encounter errors, and lose trust in your product.

This guide covers how to build maintenance into your workflow so documentation stays accurate without requiring constant team-wide effort.

## Assign ownership

Assign an owner to each section of your docs. Owners keep the content accurate and fix problems as they arise.

Ownership doesn't have to mean a single person writes everything. It means someone is accountable for accuracy. Common ownership models:

* **Centralized:** A documentation team or technical writer owns all content. Works well for smaller teams and products where the docs team has enough context to maintain everything.
* **Distributed:** Product, engineering, or team leads own documentation for their areas. Works well for larger products with specialized domains. Requires a coordinator to ensure consistency and catch gaps.
* **Hybrid:** A docs team owns core content (getting started, navigation, style), while domain teams own technical reference and guides for their features.

Whichever model you use, make ownership visible—in the files themselves, in a shared spreadsheet, or in your project management tool.

## Build a review cadence

Regular reviews catch problems before users do. The right cadence depends on how fast your product changes.

### Trigger-based reviews

The most reliable approach is reviewing documentation whenever the product changes:

* Update docs in the same pull request as the code change
* Include a documentation check in your feature launch checklist
* Require a docs sign-off before closing any ticket that changes user-facing behavior

This is more sustainable than scheduled reviews because the documentation update happens while the change is fresh in the engineer's or product manager's mind.

### Scheduled reviews

For content not tied to a specific feature, scheduled reviews catch accumulating drift:

* **Monthly:** Review high-traffic pages for accuracy. These pages affect the most users, so they're worth more frequent attention.
* **Quarterly:** Audit pages flagged with low feedback scores or high support ticket correlation.
* **Annually:** Full content audit—look for outdated examples, superseded approaches, and content that no longer reflects the product.

### Use automation to surface stale content

Manually tracking review dates across hundreds of pages doesn't scale. Automate what you can:

* Flag pages without updates in over 90 days for review
* Monitor search analytics for queries that return no results—these often signal content that should exist but doesn't
* Use [CI checks](/docs/deploy/ci) to enforce frontmatter requirements and catch broken links on every pull request

<Tip>
  Use [automations](/docs/automations) to run automated maintenance checks on a schedule—flagging stale content, checking for missing metadata, or surfacing pages with consistent low feedback scores.
</Tip>

## Automate what you can

Automation can't replace editorial judgment, but it reduces the manual work required to catch common problems.

* **Broken links:** Run `mint broken-links` before publishing to catch broken internal and external links before users encounter them.
* **Style enforcement:** A linter like [Vale](https://vale.sh) checks prose against configurable rules—terminology consistency, passive voice, missing punctuation—on every pull request. See [Style and tone](/docs/guides/style-and-tone) for more on linting.
* **API reference updates:** If you generate your API reference from an OpenAPI specification, automate spec generation as part of your release pipeline so the reference never falls behind.

## Know when to rewrite

Incremental fixes don't always work. When a page has accumulated too many caveats, workarounds, and contradictions, editing it becomes harder than starting over.

Signs a page needs a rewrite rather than edits:

* Users consistently report confusion despite multiple rounds of editing
* The page has grown to cover multiple distinct topics that should be separate pages
* The product has changed so fundamentally that the page's structure no longer maps to how the feature works
* More than half the content is edge cases, caveats, or "this doesn't apply if" exceptions

A rewrite is less daunting when you start with a structured audit: document what's missing, what's misleading, and what's redundant before writing anything. Complete rewrites in focused sprints rather than trying to do everything at once.

## Remove what no longer belongs

Wrong documentation is worse than no documentation. Users who follow inaccurate steps waste time and lose confidence in your product and your team. When content is completely inaccurate and you can't fix it immediately, remove it rather than leaving it up.

When removing content:

* Set up a redirect from the old URL to the most relevant current page
* Check for internal links pointing to the removed page and update them
* Consider whether a brief note in the changelog is appropriate if the page was widely used

## Frequently asked questions

<AccordionGroup>
  <Accordion title="How do I get engineers to update documentation when they ship features?">
    Make it a required step, not a request. Include documentation in your definition of done for features. Put documentation updates in the same pull request as code changes—this keeps context fresh and makes it easy to review together. When engineers understand that outdated docs generate support tickets that come back to them, the incentive to maintain them becomes clearer.
  </Accordion>

  <Accordion title="How do I handle documentation for deprecated features?">
    Keep deprecated documentation accessible but clearly marked. Add a notice at the top of the page indicating that the team has deprecated the feature, when it goes away, and what users should migrate to. Don't delete the page until you actually remove the feature—users on older versions still need it. After removal, redirect the URL to the migration guide or the replacement feature's documentation.
  </Accordion>

  <Accordion title="What's the minimum viable maintenance process for a small team?">
    Two practices cover most of the value: update documentation in the same PR as code changes, and run `mint broken-links` before every publish. These two habits prevent the most common categories of drift—outdated instructions and dead links—without requiring dedicated documentation infrastructure. Add scheduled reviews and automation as the team and product grow.
  </Accordion>

  <Accordion title="How do I prioritize documentation debt?">
    By impact. A stale page with 5,000 monthly views and low satisfaction scores is more urgent than an outdated page no one reads. Use analytics to rank content by traffic, cross-reference with feedback scores, and correlate with support ticket volume to build a prioritized list. Fix the pages users are actually hitting, not the ones that feel messy to the team.
  </Accordion>
</AccordionGroup>


# How to use images, screenshots, and videos in documentation
Source: https://www.mintlify.com/docs/guides/media

Learn when and how to use screenshots, GIFs, and videos in documentation with guidance on format selection, alt text, and long-term maintenance.

Visual media can make complex workflows clearer than text alone. It also has a maintenance cost. Every screenshot you publish is a commitment to update it when the UI changes. Every video becomes outdated when the flow it shows changes.

The goal is not to avoid media. Use it deliberately so the clarity it adds outweighs the work of keeping it current.

## When to use media

Not every step needs a screenshot. Not every concept needs a diagram. Before adding media, ask whether it genuinely clarifies the content. Clean prose and code examples may serve users just as well.

### Screenshots

Use screenshots for tasks that are difficult to describe in words. They are especially useful for UI-heavy workflows where users need visual orientation or where identifying the right interface element would be ambiguous without an image.

Avoid screenshots for:

* Simple actions users can't easily misidentify ("click Save")
* Content that changes frequently, such as settings pages, dashboards, and feature-heavy UIs
* Decorative purposes where the image doesn't add information

### GIFs

GIFs work well for short, looping demonstrations. Use them to show an animation, reveal a multi-step interaction, or capture a workflow that's easier to follow visually than to describe step by step.

Keep GIFs short. Files over a few seconds become large and slow to load. Long GIFs are harder for users to follow than a short video they can pause and rewind.

### Videos

Use videos for abstract concepts that benefit from narration or for long workflows where the sequence and timing matter. Videos are more accessible than GIFs for complex content. Users can pause, rewind, and control playback speed.

Host videos on an external platform like YouTube or Loom and embed them rather than serving video files directly. Video files significantly increase page load times.

## Guidelines for every media type

### File format and size

* Use **PNG** for screenshots and diagrams. PNG preserves sharp edges and text.
* Use **WebP** for photographs or images where file size matters. WebP is smaller than PNG and JPEG with comparable quality.
* Use **GIF** only when animation is necessary. For static images, GIF offers no advantages over PNG.
* Compress images before adding them to your repository. Tools like [Squoosh](https://squoosh.app) reduce file sizes without visible quality loss.

### Dimensions

* Keep screenshots at their native resolution or scale down. Never scale up, which introduces blurriness.
* Standard documentation width is typically 800–1200px. Wider screenshots scale down automatically but may look small on mobile.
* Crop screenshots tightly to the relevant UI. Surrounding chrome, empty space, and unrelated elements distract from what you're showing.

### Alt text

Every image needs descriptive alt text. Alt text makes images accessible to screen reader users and contributes to SEO.

Write alt text that describes what the image shows and why it matters in context:

```mdx theme={null}
<!-- Descriptive and contextual -->
![The API keys settings page showing a list of three active keys with their creation dates and last-used timestamps](/images/api-keys-settings.png)

<!-- Not useful -->
![Settings page](/images/api-keys-settings.png)
```

See [Accessibility](/docs/guides/accessibility) for more on writing effective alt text.

### File naming

Use descriptive, kebab-case filenames that indicate the content:

```text theme={null}
api-keys-settings.png       ✓
screenshot-2024-01-15.png   ✗
image1.png                  ✗
```

Descriptive filenames make it easier to find and replace outdated images, and they contribute marginally to image SEO.

## Maintenance

Media is the most expensive part of documentation to maintain. A single UI redesign can make dozens of screenshots outdated simultaneously.

A few practices that reduce maintenance burden:

* **Crop tightly to the relevant element.** Tightly cropped screenshots focus on the component under discussion. They go out of date more slowly than full-page captures that include navigation, headers, and surrounding UI.
* **Avoid screenshots for frequently changing content.** If a settings page ships UI changes every quarter, consider whether descriptive prose is more maintainable than a screenshot.
* **Keep source files.** Store uncompressed originals or layered files where possible, so you can update screenshots without recapturing from scratch.
* **Document what each image shows.** A comment in the MDX or a shared image manifest noting what content an image depicts makes it faster to identify outdated assets during review.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Should I use screenshots or text for step-by-step instructions?">
    Prefer text with screenshots as supplements, not replacements. Text is faster to scan, easier to search, and cheaper to update. Add a screenshot when users need to visually identify something in the UI or when a workflow would be genuinely confusing without seeing it. A common pattern is to describe the step in text and include a screenshot only where visual orientation matters.
  </Accordion>

  <Accordion title="How do I handle screenshots when the UI updates?">
    Recapture the specific screenshots that changed rather than batch-updating everything at once. Tightly cropped screenshots that focus on a single element change less frequently than full-page captures. When a major UI redesign ships, treat screenshot updates as a documentation sprint with a defined scope. Do not treat them as an ongoing distraction.
  </Accordion>

  <Accordion title="What's the difference between using GIFs and short videos?">
    GIFs loop automatically, require no user interaction, and embed directly in the page without a player. They work well for simple, short interactions where the loop is useful. Short videos are better for anything longer than a few seconds or anything that benefits from audio. Use video for workflows complex enough that users need to pause and reference specific frames. Videos also have better accessibility support. GIFs have no pause control or alt text equivalent beyond a description in surrounding content.
  </Accordion>

  <Accordion title="Do I need alt text if the image is decorative?">
    If an image adds no information, such as a purely decorative separator or background element, use an empty alt attribute (`alt=""`) to tell screen readers to skip it. Most images in documentation are informational, not decorative. When in doubt, write alt text.
  </Accordion>
</AccordionGroup>


# Migrating MDX API pages to OpenAPI navigation
Source: https://www.mintlify.com/docs/guides/migrating-from-mdx

Migrate your manually written MDX API pages to automated OpenAPI-generated documentation with flexible navigation and endpoint grouping.

If you are currently using individual MDX pages for your API endpoints, you can migrate to autogenerating pages from your OpenAPI specification while retaining the customizability of individual pages. This can help you reduce the number of files you need to maintain and improve the consistency of your API documentation.

You can define metadata and content for each endpoint in your OpenAPI specification and organize endpoints where you want them in your navigation.

## Migration steps

<Steps>
  <Step title="Prepare your OpenAPI specification.">
    Ensure your OpenAPI specification is valid and includes all endpoints you want to document.

    For any endpoints that you want to customize the metadata or content, add the `x-mint` extension to the endpoint. See [x-mint extension](/docs/api-playground/openapi-setup#customize-your-endpoint-pages) for more details.

    For any endpoints that you want to exclude from your documentation, add the `x-hidden` extension to the endpoint.

    <Info>
      Validate your OpenAPI file using the [Swagger Editor](https://editor.swagger.io/) or [Mint CLI](https://www.npmjs.com/package/mint).
    </Info>
  </Step>

  <Step title="Update your navigation structure.">
    Replace MDX page references with OpenAPI endpoints in your `docs.json`.

    ```json theme={null}
    "navigation": {
      "groups": [
        {
          "group": "API Reference",
          "openapi": "/path/to/openapi.json",
          "pages": [
            "overview",
            "authentication",
            "introduction",
            "GET /health",
            "quickstart", 
            "POST /users",
            "GET /users/{id}",
            "advanced-features"
          ]
        }
      ]
    }
    ```
  </Step>

  <Step title="Remove old MDX files.">
    After verifying your new navigation works correctly, remove the MDX endpoint files that you no longer need.
  </Step>
</Steps>

## Navigation patterns

You can customize how your API documentation appears in your navigation.

### Mixed content navigation

Combine automatically generated API pages with other pages:

```json theme={null}
"navigation": {
  "groups": [
    {
      "group": "API Reference",
      "openapi": "openapi.json",
      "pages": [
        "api/overview",
        "GET /users",
        "POST /users", 
        "api/authentication"
      ]
    }
  ]
}
```

### Multiple API versions

Organize different API versions using tabs or groups:

```json theme={null}
"navigation": {
  "tabs": [
    {
      "tab": "API v1",
      "openapi": "specs/v1.json"
    },
    {
      "tab": "API v2", 
      "openapi": "specs/v2.json"
    }
  ]
}
```

## When to use individual MDX pages

Consider keeping individual MDX pages when you need:

* Extensive custom content per endpoint like React components or lengthy examples.
* Unique page layouts.
* Experimental documentation approaches for specific endpoints.

For most use cases, OpenAPI navigation provides better maintainability and consistency.


# How to structure documentation navigation
Source: https://www.mintlify.com/docs/guides/navigation

Design documentation navigation that helps users find what they need with clear information architecture, logical grouping, and validated structure.

Navigation shapes how users build a mental model of your product. Well-designed navigation helps users find answers quickly, understand how pieces of the product relate, and feel confident they're in the right place. Poor navigation sends users to search engines, support tickets, or your competitors' docs.

This guide covers how to design, validate, and maintain documentation navigation that works for real users.

## Start by understanding your users and product

Before organizing pages, align with the people who know your product and users best.

### Map the foundation with stakeholders

Talk with founders, product managers, and engineering leads before making structural decisions. The goal is to understand how the product actually works, not just how it's marketed.

Questions to ask:

* What's the simplest way to explain how the product works?
* What are the product's core building blocks?
* How do users typically adopt the product? Where do they most often get stuck?
* What are the most important integrations or dependencies?
* If you broke the product into different layers, what would they be? Would you organize it by tasks people perform or by features they use?

These conversations surface the natural structure of the product and often reveal where documentation navigation has drifted from how users actually think.

### Know who you're writing for

Navigation decisions depend on your audience. A developer integrating an API navigates differently than an admin configuring settings or a new user following an onboarding flow.

If you have multiple distinct audiences, consider whether they need separate navigation structures or whether a single unified structure can serve them all. See [Understand your audience](/docs/guides/understand-your-audience) for more on defining documentation personas.

## Choose a navigation structure

### Organize by user journey, not product features

The most common navigation mistake is organizing docs the way the product team thinks about the product instead of the way users try to accomplish goals.

Compare these two approaches for an API product:

| Feature-centric (avoid) | Journey-centric (better) |
| ----------------------- | ------------------------ |
| Core API                | Get started              |
| Authentication          | Authenticate             |
| Webhooks                | Send your first request  |
| Rate limiting           | Handle errors            |
| SDKs                    | Go to production         |

Journey-centric navigation tells users where they are in a process. Feature-centric navigation requires users to already know what they're looking for.

### Manage depth and breadth

Navigation depth refers to how many levels users must click through to reach content. Breadth refers to how many items appear at each level.

A few principles:

* **Keep top-level sections to seven or fewer items.** Cognitive load increases as users need to scan and evaluate more options.
* **Prefer depth over breadth.** A top-level section with five subsections is easier to scan than 20 top-level items.
* **Don't hide critical content below two levels.** If users must click through three levels to reach frequently needed pages, consider promoting that content.

### Name navigation items clearly

Navigation labels should match how users describe their goals, not how engineers describe features.

* Use verbs for task-oriented sections ("Authenticate," "Deploy," "Monitor")
* Use nouns for reference sections ("API reference," "SDKs," "Changelog")
* Avoid internal terminology users won't recognize
* Keep labels short—ideally under 4 words

## Validate your assumptions

Your first navigation structure is a hypothesis. Validate it before treating it as permanent.

### Track real user journeys

Use session replay tools like [FullStory](https://www.fullstory.com) or [Hotjar](https://www.hotjar.com) and analytics tools like [Mixpanel](https://mixpanel.com) to study how users actually move through your docs. Look for:

* **Entry points:** Where do users start? Are they coming from search, a support ticket, or directly from your product?
* **Navigation patterns:** Do users follow the expected structure, or do they take unexpected paths?
* **Friction points:** Where do users pause, loop back, or abandon their session?
* **Search behavior:** Are users searching for terms that don't appear in your navigation labels? This signals a terminology mismatch.

### Test with real users

Analytics surface patterns, but direct conversations provide the context behind them.

Ask users to complete a specific task using only the documentation while narrating their thought process. Where they click first and where they get stuck reveals whether your navigation is intuitive.

New hires on your own team make good proxies for users. Before they get too familiar with the product from the inside, ask them to find answers to specific questions using only the docs. Their instincts reveal assumptions your navigation makes that aren't obvious to newcomers.

## Identify and fix common problems

### Overloaded top-level sections

If your top-level navigation has more than 7 or 8 items, users spend more time evaluating options than finding content. Group related topics into sections with meaningful names.

### Buried essential content

If the pages users need most are two or three levels deep, promote them. High-traffic pages should be easy to reach from the top level or visible in the first level of any relevant section.

### Unclear section names

If users hesitate before clicking a navigation item, the label isn't doing its job. Test whether users can predict what they'll find before clicking by describing what's inside.

### Missing pages versus navigation problems

Sometimes what looks like a navigation problem is actually a content gap. If users search for terms that don't match any page, you may be missing content rather than mislabeling it. Distinguish between the two before restructuring.

## Iterate over time

Navigation should evolve with your product and your users. You don't need to get it right on the first attempt.

A practical cadence:

* **Review navigation whenever the product ships major changes.** New features often expose structural gaps.
* **Check search analytics quarterly** for terms users search that aren't reflected in your navigation labels.
* **Revisit top-level structure annually.** As docs grow, what worked at 20 pages may not work at 200.

<Tip>
  Use [automations](/docs/automations) to automate recurring checks like surfacing pages with low feedback scores or flagging navigation items that rarely get clicks.
</Tip>

To configure navigation in Mintlify—tabs, groups, anchors, and page ordering—see the [navigation reference](/docs/organize/navigation).

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Should I organize navigation by product features or user goals?">
    User goals, in most cases. Feature-based navigation makes sense for product teams who already understand the architecture, but users come to docs to accomplish something—not to browse features. Organize around what users are trying to do, and group features under the tasks they enable.
  </Accordion>

  <Accordion title="How many top-level navigation sections should I have?">
    Aim for 5–7. Research on cognitive load suggests users can comfortably evaluate about 7 items before decision fatigue sets in. If you have more, look for natural groupings that you can combine into a single section with subsections.
  </Accordion>

  <Accordion title="How do I handle documentation that serves multiple audiences?">
    First, decide whether your audiences are different enough to need separate structures. If an admin and a developer both need to get started, a shared "Get started" section may work fine with audience-specific subsections. If their journeys are fundamentally different—separate products, separate personas—consider separate documentation sites or tab-based navigation that clearly separates the two paths.
  </Accordion>

  <Accordion title="When should I reorganize my navigation?">
    Reorganize when user data shows consistent navigation failures. Signs include high bounce rates on index pages, frequent searches for terms users should reach by navigation, or support tickets about missing content. Avoid reorganizing based on gut feel alone. The cost of restructuring (broken bookmarks, relearning, rewriting internal links) is real, so make sure the data supports it.
  </Accordion>

  <Accordion title="How do I prevent navigation from getting messy as docs grow?">
    Build a review into your content workflow. When adding new pages, require a decision about where they belong in the navigation before writing begins. It's much easier to maintain a coherent structure by making placement decisions upfront than to reorganize after dozens of pages have accumulated in the wrong places.
  </Accordion>
</AccordionGroup>


# How to improve documentation SEO
Source: https://www.mintlify.com/docs/guides/seo

Improve your documentation's search engine rankings with page titles, keyword research, internal linking, and technical SEO techniques.

Search engines are one of the most reliable ways users find documentation. When someone searches "how to set up authentication with \[your product]," well-optimized documentation can put your content at the top of results. This helps users find your documentation instead of a Stack Overflow post or a competitor's page.

This guide covers the techniques that have the most impact on documentation SEO, from writing better page titles to building a maintainable internal linking strategy.

## Write page titles and descriptions that rank

Page titles are the single most important on-page SEO signal. They tell search engines and users exactly what a page covers.

### Titles (50-60 characters)

Write titles that match how users search, not how your product UI labels things. "Authentication" is a product label. "How to authenticate API requests" is a search query.

* Match the user's intent: use "how to," "guide," or "reference" where appropriate
* Include the primary keyword near the start
* Make each title unique. Duplicate titles confuse search engines.

### Descriptions (130-160 characters)

The description appears below your page title in search results. A good description improves click-through rates even when rankings are equal.

* Summarize what users can accomplish, not just what the page covers
* Include the primary keyword naturally
* Write in active voice: "Learn how to configure" rather than "This page explains"

Mintlify generates meta tags automatically from your `title` and `description` frontmatter. For advanced configuration like Open Graph images, canonical URLs, or custom robots directives, see the [SEO configuration reference](/docs/optimize/seo).

## Do keyword research for your docs

Keyword research helps you understand what users actually type when they're looking for what your documentation covers.

**Start with your own data:** If you have [Google Search Console](https://search.google.com/search-console) connected to your docs, look at the "Search results" report. Your best optimization targets are the queries users are already finding you for and the ones you're appearing for but not ranking well on.

**Find related queries:** Free tools like [Google Keyword Planner](https://ads.google.com/intl/en_us/home/tools/keyword-planner/) and [Ahrefs Free Keyword Generator](https://ahrefs.com/keyword-generator) show you how many people search for a given phrase and suggest related terms.

### Apply keywords where they belong

* The page title and description (highest impact)
* H2 and H3 headings
* The first paragraph of the page
* Alt text for relevant images

Don't repeat keywords mechanically. Documentation should read naturally. If a heading sounds forced, the keyword isn't right for that section.

## Structure content with headings search engines can parse

Heading structure serves two purposes: it helps users scan the page and it tells search engines how topics relate to each other.

Mintlify creates the H1 for each page automatically from the `title:` property in your frontmatter. Never add a manual H1 inside the page body. Structure everything else as H2 and below:

```mdx theme={null}
## Main section (H2)

### Subsection (H3)

#### Detail (H4, use sparingly)
```

**Write headings as questions or intent phrases.** Compare:

| Weak heading   | Stronger heading                  |
| -------------- | --------------------------------- |
| Authentication | How authentication works          |
| Rate limits    | Understanding API rate limits     |
| Configuration  | How to configure your integration |

Headings written as questions are more likely to appear in Google's People Also Ask boxes, which appear before organic results and generate clicks even from lower-ranked pages.

## Build internal links between related pages

Internal links do two things for SEO: they help search engines discover and understand your content, and they pass ranking authority between pages.

**Link to related concepts** from within your content. When you explain a concept that depends on another, link to it with descriptive anchor text:

```mdx theme={null}
<!-- Good -->
Learn how to [configure your sitemap](/optimize/seo#sitemaps-and-robots-txt-files).

<!-- Not helpful for SEO -->
[Click here](/optimize/seo) to learn more.
```

**Look for orphan pages:** Pages with no internal links pointing to them are orphans. Search engines are less likely to discover and rank pages that aren't linked from anywhere. A monthly review of your navigation helps catch these.

**Create topic clusters:** Group related pages with links between them. A getting started page should link to the authentication reference, which links to the API keys page, which links back to the overview. This signals to search engines that these pages cover a coherent topic.

## Add alt text to images

Alt text serves both accessibility and SEO. Search engines can't interpret images, so alt text is how image content contributes to your page's relevance signals.

Write alt text that describes what the image shows in context:

```mdx theme={null}
<!-- Specific and descriptive -->
![API authentication flow showing the token exchange between client, auth server, and API](/images/auth-flow.png)

<!-- Too generic -->
![Diagram](/images/auth-flow.png)
```

Include relevant keywords in alt text where they fit naturally. Don't add keywords that don't describe the image.

## Technical SEO Mintlify handles automatically

Mintlify takes care of several technical SEO foundations:

* **Sitemap generation:** Mintlify generates and updates a `sitemap.xml`. You can submit it directly to [Google Search Console](https://search.google.com/search-console) to speed up indexing.
* **Semantic HTML:** Mintlify renders pages with proper HTML structure, including heading hierarchy and navigation landmarks.
* **Mobile optimization:** Documentation is responsive by default.
* **Canonical URLs:** Mintlify automatically generates canonical tags to prevent duplicate content issues.

For anything you need to configure manually, including global meta tags, per-page overrides, custom sitemaps, and indexing rules, see the [SEO configuration reference](/docs/optimize/seo).

## Keep documentation current

Search engines treat content freshness as a ranking signal, especially for pages covering topics that change over time (API references, configuration guides, integration instructions).

A practical approach:

* When you ship a feature update, update the corresponding docs in the same pull request
* Review high-traffic pages quarterly for accuracy
* Check for broken links with `mint broken-links` before publishing

<Tip>
  Use [automations](/docs/automations) to automate SEO maintenance tasks.
</Tip>

Stale documentation creates a second problem beyond SEO: if users find your page through search but the information is wrong, they lose trust in your docs.

## Monitor your search performance

Set up [Google Search Console](https://search.google.com/search-console) for your documentation domain. It shows you:

* **Impressions and clicks:** Which pages appear in search results and how often users click them
* **Average position:** Where your pages rank for specific queries
* **Queries:** The exact search terms driving traffic, useful for finding new optimization opportunities

Check it monthly. Prioritize pages with high impressions but low clicks. Their titles or descriptions may not be compelling. Also prioritize pages with low positions for important queries. These pages may need more content.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="How long should a documentation page be for SEO?">
    There is no universal ideal length. Pages should be long enough to cover the topic comprehensively and short enough to stay focused. A getting started guide might be 800 words. A detailed API reference might be 3,000 words. The goal is to help users complete their task from the page. If they need to find additional information elsewhere, the page is probably too thin. Pages under 300 words generally struggle to rank for competitive queries because they do not demonstrate topical depth.
  </Accordion>

  <Accordion title="Does documentation SEO work differently from blog SEO?">
    The core principles are the same. Relevant titles, well-structured content, and internal links are important. Documentation has some distinct advantages. It often targets highly specific long-tail queries, such as "how to configure OAuth with \[product]," where there is less competition than for general blog topics. Developers also share documentation pages naturally in Stack Overflow answers, GitHub issues, and community forums. Focus on specificity and accuracy over volume.
  </Accordion>

  <Accordion title="How do I submit my documentation sitemap to Google?">
    In [Google Search Console](https://search.google.com/search-console), go to **Sitemaps** in the left sidebar and enter your sitemap URL. For Mintlify docs, your sitemap is at `https://your-docs-domain.com/sitemap.xml`. Submitting your sitemap does not guarantee immediate indexing. It can speed up discovery and help Google understand your site structure.
  </Accordion>

  <Accordion title="How often should I update documentation for SEO?">
    Update documentation whenever the product changes. Accuracy is the most important signal. For SEO specifically, pages untouched for over a year may benefit from a review. Add missing information, update examples, and expand thin sections. Use Google Search Console to prioritize pages losing traffic or dropping in position. These pages are candidates for a refresh.
  </Accordion>

  <Accordion title="What's the difference between SEO and GEO?">
    SEO (Search Engine Optimization) focuses on ranking in traditional search engines like Google and Bing. GEO (Generative Engine Optimization) focuses on earning citations from AI-powered tools like ChatGPT, Perplexity, and Google AI Overviews. The fundamentals overlap. Accurate, well-structured content performs well in both. GEO also includes practices for formatting content for AI parsing. See the [GEO guide](/docs/guides/geo) for details.
  </Accordion>

  <Accordion title="Does Mintlify automatically handle documentation SEO?">
    Mintlify handles the technical foundation: sitemap generation, semantic HTML, canonical tags, meta tag generation, and mobile optimization. It cannot write better titles, do keyword research, build internal links, or expand thin content. Those tasks require editorial decisions. The [SEO configuration reference](/docs/optimize/seo) covers everything you can control through `docs.json` and page frontmatter.
  </Accordion>
</AccordionGroup>


# How to write technical documentation
Source: https://www.mintlify.com/docs/guides/style-and-tone

Write clear, consistent technical documentation with practical guidance on voice, structure, terminology, and tone for developer and product docs.

Good technical documentation has one job: help users accomplish a goal and get back to work. Style and tone choices either support that goal or get in the way. Clear, consistent writing builds user trust. Inconsistent or unclear writing creates friction and erodes confidence in your product.

This guide covers the core principles behind effective technical writing, with practical guidance on how to apply them.

## Write in second person

Address users directly as "you." Second person makes instructions easier to follow and keeps the focus on what users are doing rather than what the product does.

```mdx theme={null}
<!-- Second person (preferred) -->
You can configure the timeout in your settings file.

<!-- Third person (avoid) -->
Users can configure the timeout in the settings file.
```

Second person also helps expose passive voice: when you write "you," you're forced to say who does what.

## Use active voice

Active voice makes sentences shorter and clearer. In passive voice, the subject receives the action. In active voice, the subject performs it.

```mdx theme={null}
<!-- Active -->
The API returns an error when the token expires.

<!-- Passive -->
An error is returned when the token has expired.
```

Passive voice isn't always wrong. It's appropriate when the actor is unknown or unimportant. But passive voice as a default habit makes documentation harder to read.

A quick test: if you can add "by zombies" after the verb, the sentence is passive. "An error is returned \[by zombies]" is passive. "The API returns \[~~by zombies~~] an error" is active.

## Keep sentences and paragraphs short

Users scan documentation more than they read it. Long sentences and dense paragraphs slow users down when they're trying to find a specific answer.

Guidelines:

* Aim for sentences under 25 words
* One idea per sentence
* Two to four sentences per paragraph
* Break up lists of steps with numbered sequences, not run-on prose

If a sentence requires multiple commas or semicolons to hold together, you can probably split it into two sentences.

## Use headings that match user intent

Headings organize the page for both humans and search engines. Write them to answer the question a user might have, not to label a topic from the product's perspective.

```mdx theme={null}
<!-- Intent-oriented (better) -->
## How to configure authentication

<!-- Topic label (weaker) -->
## Authentication configuration
```

Use sentence case for all headings ("Getting started," not "Getting Started"). Don't skip heading levels—go from H2 to H3, not H2 to H4.

In Mintlify docs, the page's H1 generates automatically from the `title:` frontmatter property. Don't add a manual H1 in the body.

## Use consistent terminology

Pick one term for each concept and use it everywhere. Switching between "API key," "API token," and "access token" to describe the same thing forces users to stop and wonder whether you mean the same thing.

When introducing a term for the first time, define it in place rather than linking away.

```mdx theme={null}
<!-- Define in context -->
Each request requires an API key—a unique token that identifies your account.

<!-- Don't assume prior knowledge -->
Each request requires an API key.
```

If your product has specific names for things (objects, actions, UI elements), use those names exactly as they appear in the product. Capitalize them consistently.

## Calibrate tone to your audience and content type

Tone should match what users are trying to do. A getting started guide for new users benefits from a warmer, more encouraging tone. An API reference for experienced developers benefits from density and precision over warmth.

A few principles that apply across content types:

* **Be direct without being terse.** "Click Save" is better than "Please click the Save button when you're ready to proceed."
* **Avoid filler phrases.** "It's worth noting that," "In order to," "Please note that," and "Simply" add words without adding meaning.
* **Don't editorialize.** "This is a powerful feature" is an opinion. Document what it does, not how impressive it is.
* **Match user vocabulary.** If your users call it a "webhook," don't call it an "event callback" in the docs. Use the word they're already searching for.

## Avoid common mistakes

### Jargon and internal terminology

Teams develop shorthand that users never encounter. Review new content for terms that would be unfamiliar to someone seeing your product for the first time.

### Inconsistent capitalization

Decide whether to capitalize your product's feature names ("the Dashboard," "the API Explorer") and apply it consistently. Inconsistent capitalization signals lack of attention to detail.

### Colloquialisms

Informal phrases and idioms are harder to translate and harder to parse for non-native English speakers. Documentation that reaches an international audience benefits from plain, direct language.

### Spelling and grammar errors

Even a few errors reduce credibility. They signal that no one reviewed the content carefully, which makes users wonder whether the technical content is equally unreliable.

## Enforce standards with tooling

Writing principles only stick if they're part of a repeatable workflow. A few ways to automate enforcement:

* **[Vale](https://vale.sh):** A linter for prose that checks against configurable style rules. You can write rules that enforce your own terminology, flag passive voice, or catch common mistakes.
* **[CI checks](/docs/deploy/ci):** Run Vale or other linters on every pull request to catch style issues before content merges.
* **Existing style guides:** Rather than writing rules from scratch, start from an established guide. The [Google Developer Documentation Style Guide](https://developers.google.com/style), [Microsoft Style Guide](https://learn.microsoft.com/en-us/style-guide/welcome/), and [Splunk Style Guide](https://docs.splunk.com/Documentation/StyleGuide/current/StyleGuide/Howtouse) are free and widely used.

<Tip>
  Use an [automation](/docs/automations) to run a style audit on a schedule or whenever changes push to your docs repository.
</Tip>

## Frequently asked questions

<AccordionGroup>
  <Accordion title="How formal should technical documentation be?">
    Match the formality to your audience and product context. Developer tools for engineers can be direct and lean—skip pleasantries and get to the code. Documentation for less technical users or enterprise products often benefits from a warmer tone that anticipates confusion. Either way, avoid stiff corporate language. "Utilize" doesn't add precision over "use." Write the way a knowledgeable colleague would explain something, not the way a legal document would describe it.
  </Accordion>

  <Accordion title="When is passive voice acceptable?">
    Use passive voice when the actor is unknown or irrelevant, or when the result matters more than who causes it. "The request is validated before processing" is fine if you're describing what happens to a request, not who validates it. Passive voice becomes a problem when it obscures who is responsible for an action the user needs to take.
  </Accordion>

  <Accordion title="Should I write for beginners or experts?">
    Identify the primary audience for each page and write for them. A getting started guide should assume minimal prior knowledge. An API reference should assume the reader knows how APIs work. The mistake is trying to serve both in the same page—adding beginner context to a reference page slows experts down, and assuming expert knowledge in a tutorial loses beginners. If you genuinely have two distinct audiences, consider separate content types for each. See [Content types](/docs/guides/content-types) for guidance.
  </Accordion>

  <Accordion title="How do I keep terminology consistent across a large documentation site?">
    Maintain a terminology list—a simple table of preferred terms and terms to avoid. Share it with everyone who contributes to docs and check it during review. Vale can enforce it automatically with a custom vocabulary file. The investment in maintaining a list pays off quickly in reduced review cycles and fewer user complaints about confusing terminology.
  </Accordion>

  <Accordion title="What's the right length for a documentation page?">
    Long enough to cover the topic completely, short enough to stay focused. If a page covers two distinct tasks, consider splitting it. If it covers one task but the content is thin, it may be missing important detail. Reference content can be long and dense—users scan it. Conceptual content should be shorter—users read it. See [Content types](/docs/guides/content-types) for more on matching page length to content purpose.
  </Accordion>
</AccordionGroup>

## Related pages

<CardGroup>
  <Card title="Content types" icon="folder-tree" href="/guides/content-types">
    Choose the right content type for your documentation goals.
  </Card>

  <Card title="Accessibility" icon="person-standing" href="/guides/accessibility">
    Make your documentation accessible to more users.
  </Card>

  <Card title="Format text" icon="case-sensitive" href="/create/text">
    Learn text formatting and styling options.
  </Card>

  <Card title="SEO best practices" icon="search" href="/guides/seo">
    Improve documentation discoverability.
  </Card>
</CardGroup>


# How to understand your documentation audience
Source: https://www.mintlify.com/docs/guides/understand-your-audience

Define your documentation audience, research their goals and knowledge level, and apply those insights to write content that helps them succeed.

Documentation written for everyone is often useful to no one. The clearest, most accurate content still fails if it assumes the wrong level of knowledge, uses unfamiliar terminology, or addresses goals the reader does not have.

Understanding your audience is the foundation of effective documentation. This guide covers how to define who you are writing for, how to learn about them through research, and how to apply those insights to your content.

## Define your primary audience

Write every page for one specific type of reader. When you try to serve multiple audiences in the same content, you make compromises. You may add beginner context that bores experts or assume knowledge that loses beginners.

Common documentation audiences include:

* **New users** learning the product for the first time, who need orientation, context, and step-by-step guidance
* **Developers integrating your API**, who need technical accuracy, code examples, and reference material rather than general explanation
* **Admins configuring the product**, who need specifics on settings, permissions, and edge cases
* **Technical decision makers evaluating the product**, who need architecture overviews, security information, and capability summaries

Before writing any page, ask: who is reading this, and what are they trying to accomplish? Those two questions shape every decision that follows, including structure, depth, tone, terminology, and what to leave out.

## Research your users

Don't rely on assumptions about your audience. Internal teams have too much context about their own product to be reliable proxies for users.

### Talk directly to users

User interviews surface insights that analytics can't. Ask users:

* How do they describe what your product does in their own words?
* What were they trying to accomplish the last time they consulted the documentation?
* What did they find confusing or missing?
* What terms do they use for the things your product does?

That last question is particularly valuable for documentation. If users call your feature a "webhook" and you're calling it an "event callback" in your docs, users searching for help won't find your content. They also won't recognize it as relevant when they do.

### Embed with your support team

Support teams see documentation failures constantly. Ask them:

* What topics generate the most tickets?
* Where do users most often get confused or stuck?
* What do users say they expected to find but couldn't?

This is often the fastest way to find the highest-impact documentation gaps.

### Use feedback mechanisms

Give readers a way to signal when something isn't working. Thumbs up/down ratings and open-ended comment fields on documentation pages reveal which content resonates and which doesn't. Negative feedback on a high-traffic page is a high-priority fix. See [Improve your docs](/docs/guides/improving-docs) for more on using feedback data.

### Observe real navigation behavior

Session replay tools like [FullStory](https://www.fullstory.com) and [Hotjar](https://www.hotjar.com) show exactly how users navigate your docs. Where they pause, where they scroll back up, and where they abandon sessions reveals gaps that users often won't report directly.

## Apply what you learn

### Write to the right knowledge level

Calibrate your explanations to what your audience already knows, not what your team knows.

A developer integrating your API doesn't need you to explain what an API is. A non-technical admin configuring your enterprise product might. Define technical terms when introducing them for the first time, and link to deeper explanations rather than interrupting every page with foundational context.

```mdx theme={null}
<!-- Define in context for less technical audiences -->
Your API key—a unique token that identifies your account—must be included in every request.

<!-- Skip basics for developer audiences -->
Include your API key in the Authorization header of every request.
```

### Match terminology to your audience's vocabulary

Use the words your users use. If your users call something a "project" and your product calls it a "workspace," your documentation feels foreign to people who haven't internalized your internal vocabulary. Document things with the terms users search for, then introduce your product's terminology alongside it.

### Adjust depth and structure to the task

Audiences at different stages have different needs:

* New users need orientation and reassurance, with clear milestones, limited choices, and frequent confirmation that they're on track
* Experienced users need to scan quickly, with consistent structure, dense information, and minimal context
* Reference documentation readers need completeness above all else

## Build audience awareness into your process

Understanding your audience is not a one-time exercise. Products change, audiences evolve, and new user segments emerge.

A few practices that keep audience understanding current:

* **Review new pages with a support team member** before publishing. They'll quickly identify where assumptions are likely to break down.
* **Include audience assumptions in your writing brief.** Stating "this page is for developers who have already completed authentication" keeps the writing focused during review.
* **Use new hires as proxies.** Before they internalize your product's internal vocabulary, ask them to complete a task using only the docs. Their experience often mirrors that of new users.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="What if my documentation serves multiple audiences?">
    Identify the primary audience for each page rather than trying to serve everyone in the same content. For products with genuinely distinct audiences, consider whether separate documentation sections or navigation paths make sense. These audiences may have separate personas with different goals and knowledge levels. Mintlify supports tab-based navigation that can separate content by audience without requiring entirely separate documentation sites.
  </Accordion>

  <Accordion title="How do I document for both technical and non-technical users?">
    Create separate content for each rather than trying to blend them. A concept explanation for a non-technical decision maker and an API reference for a developer integrating your product serve different purposes and should be different pages. Where overlap is unavoidable, lean toward the more technical version and link out to lighter conceptual content for readers who need it.
  </Accordion>

  <Accordion title="How often should I revisit my audience assumptions?">
    When you ship a major product change, when your user base shifts significantly, or when support ticket patterns change in ways that don't match your existing docs. Quarterly reviews of search analytics and feedback data help catch drift. More frequent check-ins with your support team can catch it faster.
  </Accordion>

  <Accordion title="What's the fastest way to identify documentation gaps?">
    Ask your support team what topics they address most often that aren't covered well in the docs. This surfaces high-impact gaps faster than any analytics tool. User interviews, search analytics showing queries with no results, and session replays showing users scanning pages without finding answers all add more depth from there.
  </Accordion>
</AccordionGroup>


# Use automations
Source: https://www.mintlify.com/docs/guides/use-automations

Use Mintlify automations to automate recurring docs maintenance: choose the right trigger, write effective instructions, and get consistent agent results.

Automations run the agent automatically so your content stays accurate without manual effort. This guide covers how to choose the right automation, configure it effectively, and write instructions that produce consistent results.

## When to use automations

Automations are best for tasks that are:

* **Repetitive**: The same task runs regularly on a predictable schedule or whenever a specific event occurs.
* **Time-consuming**: Tasks that take time to do manually but follow a consistent pattern.
* **Reactive**: Tasks that should happen automatically in response to code or content changes, like updating docs after a feature ships.

For one-off or exploratory tasks, use the agent directly in the [dashboard](https://app.mintlify.com) or from Slack.

## Choose a trigger

Each automation runs on one of three trigger types. Choose the one that matches when you need the work done.

| Trigger         | Use when                                                                                                                        |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Content update  | The task should run whenever your project content changes—translating new pages, fixing broken links, or auditing SEO metadata. |
| Code change     | The task should run when source code changes—updating API specifications or documentation after a PR merges.                    |
| Custom schedule | The task should run on a fixed cadence regardless—publishing weekly changelogs or running periodic grammar checks.              |

## Predefined automations

Mintlify includes predefined automations for the most common content maintenance tasks. Toggle any of them on from the [Automations](https://app.mintlify.com/products/automations) page of your dashboard.

See [Predefined automations](/docs/automations/reference) for more details.

## Custom automations

Create a custom automation for tasks that aren't covered by the predefined options. Custom automations give you full control over the trigger, instructions, and context repositories.

See [Create a custom automation](/docs/automations/create) for setup steps.

### Write effective instructions

Custom automation instructions are prompts the agent follows on every run. The quality of your instructions directly affects the consistency of results.

**Describe the outcome, not just the task.** Tell the agent what done looks like.

<CodeGroup>
  ```text Less effective theme={null}
  Review the API reference pages.
  ```

  ```text More effective theme={null}
  Review every page in the /api-reference directory. For each endpoint, confirm that the request parameters, response fields, and example payloads match the OpenAPI spec in the api/openapi.yaml file. Open a pull request with corrections for any discrepancies you find.
  ```
</CodeGroup>

**Write a procedure.** Agents follow step-by-step instructions more reliably than open-ended prompts.

```text Example procedure theme={null}
1. Read the merged pull request diff from the trigger repository.
2. Identify any changed API endpoints, parameters, or response shapes.
3. Search the documentation for pages that reference those endpoints.
4. Update the affected pages to match the changes in the pull request.
5. Open a pull request with a summary of the pages you changed and why.
```

**Keep scope narrow.** An automation that does one thing well is more reliable than one that tries to do many things. Split complex tasks across multiple automations.

**Specify files and directories.** The more precise you are about where the agent should look, the less time it spends searching.

```text Example with specific paths theme={null}
Check every MDX file in the /content directory for broken internal links (links beginning with /). 
For each broken link, either fix the path or remove the link if no replacement exists.
```

### Use context repositories

For custom automations and some predefined automations, you can add context repositories the agent reads when the automation runs.

Add context repositories when:

* Your content references code, APIs, or configuration that lives in a separate repository.
* You want the agent to compare your content against source code when deciding what to update.
* The automation prompt refers to files outside your Mintlify project repository.

You can add up to 10 context repositories per automation.

### Update mode

Decide how much review you want before changes go live.

* **Automatic**: Changes merge directly into your Mintlify project repository without review. Best for low-risk, high-frequency tasks like translation, grammar checks, and link fixes.
* **Require review**: The agent opens a pull request and a human reviews it before merging. Best for tasks that change content meaning, like syncing with code changes or updating API references.

## Control credit usage

Every automation run consumes credits. For example, most **update from code changes** automation runs cost between 40 and 180 credits. Complex runs that update many pages cost more.

Scheduling cron jobs to run at specific times gives you more precise control over credit usage. For example, run an automation once a day or once a week to know exactly how many pull requests it creates per month. Push-triggered automations can vary more from month to month because they depend on how often content or code changes.

## Review and improve automation results

Automations run automatically, but they benefit from periodic review.

1. Open the **Runs** tab on the [Automations](https://app.mintlify.com/products/automations) page to see recent run history and status.
2. Click a run to read the agent's summary and review any pull requests it opened.
3. If results are inconsistent, refine your instructions: add more specific procedures, narrow the file scope, or split the automation into smaller tasks.

A few review cycles after enabling a new automation are usually enough to dial in the instructions.


# Configure OAuth 2.0 authentication with Auth0
Source: https://www.mintlify.com/docs/help-center/configure-oauth-with-auth0

Set up Auth0 as the OAuth 2.0 identity provider for a private Mintlify docs site: endpoint URLs, callback registration, and group-based access.

Auth0 is an OAuth 2.0 and OIDC-compliant identity provider, so it plugs directly into Mintlify's built-in OAuth 2.0 support. This page maps Auth0's endpoints and settings onto the fields in [Authentication setup](/docs/deploy/authentication-setup#oauth-2-0). Use the canonical setup page for the full flow and refer here for the Auth0-specific values.

OAuth 2.0 authentication is available on the Enterprise plan.

## Prerequisites

* An Auth0 tenant. Note your tenant domain, for example `your-tenant.us.auth0.com`.
* An Auth0 **Regular Web Application** created for your documentation site.
* The client ID and client secret for that application.

## Map Auth0 to Mintlify's OAuth fields

In your Mintlify dashboard, go to [Authentication](https://app.mintlify.com/products/authentication), set site visibility to **Private**, and choose **Custom** → **OAuth**. Fill in the fields with the following Auth0 values. Replace `YOUR_AUTH0_DOMAIN` with your tenant domain.

| Mintlify field          | Auth0 value                                                             |
| ----------------------- | ----------------------------------------------------------------------- |
| Authorization URL       | `https://YOUR_AUTH0_DOMAIN/authorize`                                   |
| Token URL               | `https://YOUR_AUTH0_DOMAIN/oauth/token`                                 |
| Client ID               | Application client ID from Auth0                                        |
| Client Secret           | Application client secret from Auth0                                    |
| Scopes                  | `openid profile email` (add more if your app needs them)                |
| Info API URL (optional) | `https://YOUR_AUTH0_DOMAIN/userinfo`                                    |
| Logout URL (optional)   | `https://YOUR_AUTH0_DOMAIN/v2/logout?returnTo=<url-encoded-return-url>` |

Save the settings. Mintlify redeploys your site with the new authentication configuration.

## Register the redirect URL in Auth0

Copy the **Redirect URL** shown in your Mintlify authentication settings and add it to your Auth0 application under **Application URIs → Allowed Callback URLs**. Save the Auth0 application. Without this step, Auth0 rejects the login flow.

If you set a **Logout URL** in Mintlify, add the same return URL to your Auth0 application's **Allowed Logout URLs**.

## Group-based access control

To restrict pages to specific Auth0 users, you have two options.

* **Token claims (recommended).** Add a groups claim to the ID token or access token with an [Auth0 Action](https://auth0.com/docs/customize/actions) and configure Mintlify to read it. See [Use groups from OAuth token claims](/docs/deploy/authentication-setup#use-groups-from-oauth-token-claims). If you source groups from the ID token, keep `openid` in your scopes.
* **Info API URL.** Point Mintlify at `https://YOUR_AUTH0_DOMAIN/userinfo` or your own endpoint that returns user data in the [User data format](/docs/deploy/authentication-setup#user-data-format). The endpoint must accept `Authorization: Bearer <access_token>` and return groups in the response.

Then tag pages or navigation groups with a matching `groups` value so only members of that group can see them.

## Troubleshooting

* **Callback URL mismatch.** Auth0 blocks the login and shows a callback error. Confirm the redirect URL in Auth0's **Allowed Callback URLs** exactly matches the one shown in your Mintlify authentication settings, including protocol and trailing path.
* **Users log in but see no restricted content.** Your groups claim is not reaching Mintlify. Confirm the Auth0 Action adds the claim, that `source` in Mintlify matches the token you set it on (`id_token` or `access_token`), and that `groupsClaim` matches the claim name.
* **Logout does not redirect back.** Auth0 requires the `returnTo` URL in the logout link to be listed under **Allowed Logout URLs** on the application.


# Fix "Domain already claimed by another organization" error
Source: https://www.mintlify.com/docs/help-center/domain-already-claimed-by-another-organization

Release a custom domain from another Mintlify deployment or request help when adding it fails because another deployment or organization already holds it.

When you try to add a custom domain that is registered to another Mintlify deployment, the dashboard or [`mint add-domain`](/docs/cli/commands#mint-add-domain) returns one of these errors:

* `Domain is already in use by another deployment in your organization` means the domain belongs to another deployment you can access.
* `Domain is already claimed by another organization` means the domain belongs to a deployment in a different Mintlify organization. This can happen when a trial account, unused organization, or deployment created with another work email still holds the domain.

Only one deployment can hold a custom domain at a time. Release the domain from the current deployment before you add it to the destination deployment.

## Release the domain yourself

If you can access the organization that holds the domain:

1. Sign in to the [dashboard](https://app.mintlify.com/) and switch to the organization that holds the domain.
2. Open the [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page for the deployment that holds the domain.
3. Click the <Icon name="trash-2" /> remove icon next to the domain and confirm the removal.
4. Switch to the destination organization and add the domain from its [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page.

Your DNS records remain valid as long as the `CNAME` still points to `cname.mintlify.builders`. If you also want to retire the old deployment, delete it from the [Danger zone](https://app.mintlify.com/settings/organization/danger-zone). See [Delete a deployment](/docs/deploy/deployments#delete-a-deployment).

## Request a release from support

If you cannot access the organization that holds the domain, email <a href="mailto:support@mintlify.com">[support@mintlify.com](mailto:support@mintlify.com)</a> with proof that you own it. This can happen when the organization belongs to a former employee, uses a personal email you no longer access, or was abandoned without releasing the domain.

Include:

* The custom domain, like `docs.example.com`.
* The destination organization and deployment where you want to add it, formatted as `app.mintlify.com/<your-org>/<your-deployment>`.
* Any email addresses or organization names that might hold the domain.
* Proof that you control the domain, such as a screenshot from your DNS provider's admin console. Support may instead ask you to add a verification `TXT` record.

After support releases the domain, add it from the dashboard or with [`mint add-domain`](/docs/cli/commands#mint-add-domain).


# Fix "Failed to fetch OpenAPI file for anchor or tab" error
Source: https://www.mintlify.com/docs/help-center/openapi-url-fetch-fails-during-build

Fix Mintlify builds that fail to download a hosted OpenAPI document because of private hosts, authenticated URLs, TLS, DNS, or CI race conditions.

When your `docs.json` `openapi` field points at a URL instead of a file in your repository, Mintlify downloads that document during every build. If the download fails, the build fails with `Failed to fetch OpenAPI file for anchor or tab`. For an overview of the common causes and the recommended fix, see [API playground troubleshooting](/docs/api-playground/troubleshooting).

This page covers how to narrow down the cause when the fix isn't obvious.

## Reproduce the fetch outside Mintlify

Mintlify builds run from the public internet with no access to your network or credentials. Run these commands from a machine that is not on your VPN or corporate network:

```bash theme={null}
curl -IL "https://example.com/openapi.json"
curl -o openapi.json "https://example.com/openapi.json"
```

Check the response for these signals:

* A connection timeout or DNS failure means the host isn't publicly resolvable.
* A `401` or `403` means the URL requires authentication. Build fetches are unauthenticated and cannot send a token, cookie, or come from an allowlisted IP.
* A certificate error means the TLS chain is incomplete. Browsers often accept a chain that automated clients reject, so a URL that loads for you can still fail during a build.
* A `200` with a truncated or empty body means the origin served a partial response.

Then validate the document you downloaded:

```bash theme={null}
mint validate
```

If validation fails, the problem is the document itself rather than the fetch. See [OpenAPI setup](/docs/api-playground/openapi-setup).

## Rule out a CI race condition

If your pipeline generates the spec and then calls the [Trigger deployment](/docs/api/update/trigger) endpoint, an intermittent failure usually means the deployment starts before the new spec finishes publishing. The build then fetches a stale document, a partial document, or nothing at all.

Sequence the pipeline so the spec is fully published and readable at its public URL before you trigger the deployment. Confirm the upload completed rather than assuming it did. Object storage and CDN uploads often return before the object is served consistently.

This failure mode is intermittent by nature. A build that succeeds on retry without any change to the spec is a strong signal that you're hitting it.

## When the URL can't be public

If you cannot serve the spec from an unauthenticated public URL, commit it into your documentation repository and point the `openapi` field at the repo-relative path. Update the file in the same commit that changes your API so the two stay in sync. See [`mint validate`](/docs/cli/commands#mint-validate) to check the document before you commit it.