diff --git a/api/static-export/generate-bundle.mdx b/api/static-export/generate-bundle.mdx
new file mode 100644
index 0000000000..5f8eb219be
--- /dev/null
+++ b/api/static-export/generate-bundle.mdx
@@ -0,0 +1,10 @@
+---
+title: "Generate export bundle"
+openapi: "/static-export-openapi.json POST /static-export/jobs/{jobId}/bundle"
+keywords: ["static export", "bundle", "s3", "download", "enterprise"]
+---
+
+
+ Static export requires an [Enterprise plan](https://mintlify.com/pricing?ref=static-export).
+
+
diff --git a/api/static-export/get-job-status.mdx b/api/static-export/get-job-status.mdx
new file mode 100644
index 0000000000..97e0d49558
--- /dev/null
+++ b/api/static-export/get-job-status.mdx
@@ -0,0 +1,10 @@
+---
+title: "Get static export job status"
+openapi: "/static-export-openapi.json GET /static-export/jobs/{jobId}"
+keywords: ["static export", "job", "status", "progress", "enterprise"]
+---
+
+
+ Static export requires an [Enterprise plan](https://mintlify.com/pricing?ref=static-export).
+
+
diff --git a/api/static-export/overview.mdx b/api/static-export/overview.mdx
new file mode 100644
index 0000000000..f6bcef8bbc
--- /dev/null
+++ b/api/static-export/overview.mdx
@@ -0,0 +1,136 @@
+---
+title: "Static export"
+description: "Generate a self-contained static export of your documentation and download it as a single bundle through the Mintlify REST API."
+keywords: ["static export", "static site", "bundle", "self-host", "enterprise"]
+---
+
+
+ Static export requires an [Enterprise plan](https://mintlify.com/pricing?ref=static-export).
+
+
+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.
+
+## 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.
+
+
+
+ Call [Start static export job](/api/static-export/start-job) with the domain you want to export. The API queues the job and returns a `jobId`.
+
+
+ Poll [Get static export job status](/api/static-export/get-job-status) with the `jobId` until `status` is `completed`. The response includes live `progress` and `pageCount` while the job runs.
+
+
+ Call [Generate export bundle](/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. Download it before the link expires.
+
+
+
+## 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 | | Configurable | |
+| AI assistant | | Configurable | |
+| Web analytics | | Configurable | |
+| API playground ("Try it") | | | Configurable |
+| Static export bundle | | | |
+
+## Endpoints
+
+- [Start static export job](/api/static-export/start-job): Start a static export job for a deployment.
+- [Get static export job status](/api/static-export/get-job-status): Poll the status and progress of a running job.
+- [Generate export bundle](/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 is deployed 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.
+
+
+
+ Set the static export fields in your `values.yaml` to the `bundleUrl` returned by [Generate export bundle](/api/static-export/generate-bundle). The chart fetches the bundle on startup and serves it as the active version.
+
+ ```yaml values.yaml
+ 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"
+ ```
+
+
+ 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
+ helm upgrade --install mintlify mintlify/enterprise \
+ --namespace mintlify \
+ --create-namespace \
+ -f values.yaml
+ ```
+
+
+
+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
+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, and configure cluster credentials (for example, with `azure/setup-helm` and your kubeconfig) before the deploy step.
diff --git a/api/static-export/start-job.mdx b/api/static-export/start-job.mdx
new file mode 100644
index 0000000000..7c91a586bf
--- /dev/null
+++ b/api/static-export/start-job.mdx
@@ -0,0 +1,10 @@
+---
+title: "Start static export job"
+openapi: "/static-export-openapi.json POST /static-export/jobs"
+keywords: ["static export", "job", "start", "bundle", "enterprise"]
+---
+
+
+ Static export requires an [Enterprise plan](https://mintlify.com/pricing?ref=static-export).
+
+
diff --git a/docs.json b/docs.json
index 1e916f1a5d..54c230f4ff 100644
--- a/docs.json
+++ b/docs.json
@@ -359,7 +359,8 @@
"guides/developer-documentation",
"guides/knowledge-base",
"guides/help-center",
- "guides/custom-frontend"
+ "guides/custom-frontend",
+ "api/static-export/overview"
]
}
]
@@ -413,6 +414,15 @@
"api/analytics/views",
"api/analytics/visitors"
]
+ },
+ {
+ "group": "Static export",
+ "icon": "package",
+ "pages": [
+ "api/static-export/start-job",
+ "api/static-export/get-job-status",
+ "api/static-export/generate-bundle"
+ ]
}
]
},
diff --git a/static-export-openapi.json b/static-export-openapi.json
new file mode 100644
index 0000000000..83cb61a293
--- /dev/null
+++ b/static-export-openapi.json
@@ -0,0 +1,304 @@
+{
+ "openapi": "3.0.1",
+ "info": {
+ "title": "Mintlify Static Export API",
+ "description": "Programmatically generate a self-contained static export of your documentation and download it as a single bundle. Available on Enterprise plans.",
+ "version": "1.0.0"
+ },
+ "servers": [
+ {
+ "url": "https://api.mintlify.com/v1"
+ }
+ ],
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "paths": {
+ "/static-export/jobs": {
+ "post": {
+ "summary": "Start static export job",
+ "description": "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.\n\nStatic export is available on Enterprise plans.",
+ "operationId": "startStaticExportJob",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/StartStaticExportRequest"
+ }
+ }
+ }
+ },
+ "responses": {
+ "202": {
+ "description": "The export job was accepted and queued.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/StaticExportJob"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "The request body is invalid. Check that `domain` is a reachable hostname and that `paths` entries are valid page paths.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Static export is not enabled for this organization. Contact sales to enable it on an Enterprise plan.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/static-export/jobs/{jobId}": {
+ "get": {
+ "summary": "Get static export job status",
+ "description": "Retrieve the current status and progress of a static export job. Poll this endpoint after starting a job until `status` is `completed` (or `failed`).\n\nStatic export is available on Enterprise plans.",
+ "operationId": "getStaticExportJob",
+ "parameters": [
+ {
+ "name": "jobId",
+ "in": "path",
+ "description": "The ID of the static export job returned by `Start static export job`.",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The current state of the export job.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/StaticExportJob"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "No job exists with the provided ID.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/static-export/jobs/{jobId}/bundle": {
+ "post": {
+ "summary": "Generate export bundle",
+ "description": "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`.\n\nThe job must have a `status` of `completed` before a bundle can be generated.\n\nStatic export is available on Enterprise plans.",
+ "operationId": "generateStaticExportBundle",
+ "parameters": [
+ {
+ "name": "jobId",
+ "in": "path",
+ "description": "The ID of a completed static export job.",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A presigned S3 link to the static export bundle.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/BundleResponse"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "No job exists with the provided ID.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "409": {
+ "description": "The job has not finished yet, so a bundle cannot be generated.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "securitySchemes": {
+ "bearerAuth": {
+ "type": "http",
+ "scheme": "bearer",
+ "description": "Admin API key. Generate one on the API keys page in your dashboard."
+ }
+ },
+ "schemas": {
+ "StartStaticExportRequest": {
+ "type": "object",
+ "required": ["domain"],
+ "properties": {
+ "domain": {
+ "type": "string",
+ "description": "The domain of the deployment to export, for example `docs.example.com`.",
+ "example": "docs.example.com"
+ },
+ "version": {
+ "type": "string",
+ "description": "An optional version label to tag this export. Defaults to the latest published version.",
+ "example": "2024-06-01"
+ },
+ "paths": {
+ "type": "array",
+ "description": "An optional list of page paths to include. When omitted, every published page is exported.",
+ "items": {
+ "type": "string"
+ },
+ "example": ["index", "guides/getting-started", "api-reference/introduction"]
+ }
+ }
+ },
+ "StaticExportJob": {
+ "type": "object",
+ "required": ["jobId", "status", "progress", "pageCount", "createdAt", "updatedAt"],
+ "properties": {
+ "jobId": {
+ "type": "string",
+ "description": "Unique identifier for the static export job.",
+ "example": "se_3f9a2c1b8e7d4a06"
+ },
+ "status": {
+ "type": "string",
+ "description": "The current state of the job.",
+ "enum": ["queued", "running", "completed", "failed"],
+ "example": "running"
+ },
+ "progress": {
+ "type": "number",
+ "description": "Completion percentage from 0 to 100.",
+ "minimum": 0,
+ "maximum": 100,
+ "example": 42
+ },
+ "pageCount": {
+ "type": "integer",
+ "description": "The number of pages exported so far.",
+ "example": 128
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the job was created."
+ },
+ "updatedAt": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the job was last updated."
+ },
+ "error": {
+ "type": "string",
+ "description": "A human-readable error message. Present only when `status` is `failed`.",
+ "nullable": true
+ }
+ }
+ },
+ "BundleResponse": {
+ "type": "object",
+ "required": ["jobId", "bundleUrl", "sizeBytes", "expiresAt"],
+ "properties": {
+ "jobId": {
+ "type": "string",
+ "description": "The ID of the job this bundle was generated for.",
+ "example": "se_3f9a2c1b8e7d4a06"
+ },
+ "bundleUrl": {
+ "type": "string",
+ "format": "uri",
+ "description": "A presigned S3 link to the static export bundle archive. Download it before the link expires.",
+ "example": "https://mintlify-static-exports.s3.amazonaws.com/se_3f9a2c1b8e7d4a06/bundle.tar.gz?X-Amz-Signature=..."
+ },
+ "sizeBytes": {
+ "type": "integer",
+ "description": "The size of the bundle in bytes.",
+ "example": 18432000
+ },
+ "expiresAt": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the presigned link expires."
+ }
+ }
+ },
+ "Error": {
+ "type": "object",
+ "properties": {
+ "error": {
+ "type": "string",
+ "description": "A human-readable description of the error."
+ }
+ }
+ }
+ }
+ }
+}