# Static export

> Generate a self-contained static export of your documentation and download it as a single bundle through the Mintlify REST API for self-hosting.

:::callout{intent="info"}
Static export is in private beta and requires an enterprise agreement. Contact sales@mintlify.com to request access.
:::

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.

:::callout{intent="note"}
Canonical and sitemap URLs remain extensionless. CloudFront resolves these URLs automatically, but other static hosts may require rewrite rules.
:::

## How static export works

A static export runs as an asynchronous job. You start the job for a project, then poll for its status until the bundle is ready to download.

::::steps
:::step{title="Start a static export job"}
Call [Start static export job](/guides/static-export-start-job) with your project ID. The API queues the job and returns a `jobId`.

A project can have only one active job at a time. If a job is already `queued` or `running` for the project, the endpoint returns `409`. The endpoint is rate-limited to 10 job starts per organization per hour.
:::

:::step{title="Poll the job and download the bundle"}
Poll [Get static export job status](/guides/static-export-get-job-status) with the `jobId` until `status` is `completed`. The completed response includes `bundleUrl`, a time-limited presigned S3 link to the bundle, along with `sizeBytes` and an `expiresAt` timestamp.

Download the bundle before `expiresAt`. After it expires, call the status endpoint again to get a fresh `bundleUrl`. The underlying export files remain reusable. Only the link is time-limited.
:::
::::

## 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[check]{icon="check"} |        Configurable        |     :icon[x]{icon="x"}     |
| AI assistant              | :icon[check]{icon="check"} |        Configurable        |     :icon[x]{icon="x"}     |
| Web analytics             | :icon[check]{icon="check"} |        Configurable        |     :icon[x]{icon="x"}     |
| API playground ("Try it") | :icon[check]{icon="check"} | :icon[check]{icon="check"} |        Configurable        |
| Static export bundle      | :icon[check]{icon="check"} | :icon[check]{icon="check"} | :icon[check]{icon="check"} |

## Endpoints

- [Start static export job](/guides/static-export-start-job): Queue a static export job for a project.
- [Get static export job status](/guides/static-export-get-job-status): Poll job state and, once complete, retrieve a presigned bundle download link.

## 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.

Copy your project ID from the same page and use it as the `projectId` path parameter.

## 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 completes, you point the chart at the `bundleUrl` 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 [Get static export job status](/guides/static-export-get-job-status). 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 Get static export job status endpoint.
  bundleUrl: "https://mintlify-static-export-outputs-prod.s3.amazonaws.com/6520f3a1c9b1a20012ab34cd/export.tar.gz"
  # Optional: pin to a specific export version for reproducible rollouts.
  version: "2024-06-01"
```
:::

:::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
```
:::
::::

Because presigned links expire, re-fetch the job status 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, then 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

env:
  PROJECT_ID: proj_your_project_id

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/${{ env.PROJECT_ID }}/jobs \
            -H "Authorization: Bearer ${{ secrets.MINTLIFY_ADMIN_KEY }}" | jq -r '.jobId')
          echo "job_id=$JOB_ID" >> "$GITHUB_OUTPUT"

      - name: Wait for the job to complete and capture the bundle URL
        id: bundle
        run: |
          for i in $(seq 1 60); do
            RESPONSE=$(curl -s \
              https://api.mintlify.com/v1/static-export/${{ env.PROJECT_ID }}/jobs/${{ steps.start.outputs.job_id }} \
              -H "Authorization: Bearer ${{ secrets.MINTLIFY_ADMIN_KEY }}")
            STATUS=$(echo "$RESPONSE" | jq -r '.status')
            echo "status=$STATUS"
            if [ "$STATUS" = "completed" ]; then
              BUNDLE_URL=$(echo "$RESPONSE" | jq -r '.bundleUrl')
              echo "bundle_url=$BUNDLE_URL" >> "$GITHUB_OUTPUT"
              exit 0
            fi
            [ "$STATUS" = "failed" ] && exit 1
            sleep 10
          done
          echo "Timed out waiting for the export job to complete." >&2
          exit 1

      - 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 and set `PROJECT_ID` to your project's ID. Before deploying, configure cluster credentials, for example with `azure/setup-helm` and your Kubernetes configuration file (`kubeconfig`).

## Related topics

- [Start static export job](/guides/static-export-start-job)
- [Get static export job status](/guides/static-export-get-job-status)
- [Self-host](/guides/manage-your-site-deploy-self-host)

## Related pages

- [Admin](./admin-index.md)
- [Agent](./agent-2-index.md)
- [Agent](./agent-index.md)
- [Agent-ready content](./agent-ready-content-index.md)
- [AI](./ai-index.md)
- [Analytics](./analytics-index.md)
- [API docs](./api-docs-index.md)
- [API reference](./api-reference-index.md)
- [Assistant](./assistant-2-index.md)
- [Assistant](./assistant-index.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
