You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@superset.apache.org by "rusackas (via GitHub)" <gi...@apache.org> on 2026/01/26 04:44:50 UTC

[PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

rusackas opened a new pull request, #37434:
URL: https://github.com/apache/superset/pull/37434

   ### SUMMARY
   
   Integrates the [docusaurus-openapi-docs](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs) plugin to generate interactive API documentation from Superset's OpenAPI specification. This provides a "Try It Out" experience similar to Swagger UI directly in the documentation site.
   
   **Key changes:**
   - Add `docusaurus-openapi-docs` plugin and theme dependencies
   - Generate MDX files for all 245 API endpoints with interactive request/response examples
   - Create API landing page with quick links to common endpoints (Dashboards, Charts, Databases, Datasets)
   - Update sidebar navigation to include the API reference section
   - Fix OpenAPI spec issues for better plugin compatibility
   - Add helper scripts for spec conversion and sidebar generation
   
   **Benefits:**
   - Users can explore the full API without running a local Superset instance
   - Interactive "Try It Out" functionality for testing requests
   - Auto-generated from the same OpenAPI spec that powers `/swagger/v1`
   - Consistent with the existing docs site styling
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   This adds a new section to the docs. The API reference will be accessible at `/docs/api/` with interactive documentation for all endpoints.
   
   ### TESTING INSTRUCTIONS
   
   1. Build and run the docs locally:
      ```bash
      cd docs
      yarn install
      yarn build
      yarn serve
      ```
   
   2. Navigate to the API Reference section and verify:
      - Landing page loads with quick links
      - Individual endpoint pages have request/response schemas
      - Sidebar shows all API endpoints organized by category
   
   ### ADDITIONAL INFORMATION
   
   - [ ] Has associated issue:
   - [ ] Required feature flags:
   - [ ] Changes UI
   - [ ] Includes DB Migration
   - [x] Introduces new feature or API
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2733742515


##########
docs/docs/api.mdx:
##########
@@ -1,40 +1,590 @@
 ---
-title: API
+title: API Reference
 hide_title: true
 sidebar_position: 10
 ---
 
-import SwaggerUI from 'swagger-ui-react';
-import openapi from '/resources/openapi.json';
-import 'swagger-ui-react/swagger-ui.css';
 import { Alert } from 'antd';
 
-## API
+## REST API Reference
 
-Superset's public **REST API** follows the
-[OpenAPI specification](https://swagger.io/specification/), and is
-documented here. The docs below are generated using
-[Swagger React UI](https://www.npmjs.com/package/swagger-ui-react).
-
-:::resources
-- [Blog: The Superset REST API](https://preset.io/blog/2020-10-01-superset-api/)
-- [Blog: Accessing APIs with Superset](https://preset.io/blog/accessing-apis-with-superset/)
-:::
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
 
 <Alert
   type="info"
-  message={
-    <div>
-      <strong>NOTE! </strong>
-      You can find an interactive version of this documentation on your local Superset
-      instance at <strong>/swagger/v1</strong> (unless disabled)
-    </div>
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
   }
+  style={{ marginBottom: '24px' }}
 />
 
-<br />
-<br />
-<hr />
-<div className="swagger-container">
-  <SwaggerUI spec={openapi} />
-</div>
+---
+
+### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+```bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \
+  -H "Content-Type: application/json" \
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
+  http://localhost:8088/api/v1/dashboard/
+```
+
+#### Security Endpoints
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get the CSRF token](./get-the-csrf-token) | `/api/v1/security/csrf_token/` |

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Broken Documentation Links</b></div>
   <div id="fix">
   
   The updated API documentation includes numerous links to detailed endpoint documentation files (e.g., './get-the-csrf-token') that do not exist in the repository. This will result in broken links for users accessing the docs, potentially causing confusion or incorrect expectations about available documentation.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #d777be</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
docs/yarn.lock:
##########
@@ -14243,16 +15205,44 @@ xss@^1.0.14:
     commander "^2.20.3"
     cssfilter "0.0.10"
 
+y18n@^5.0.5:
+  version "5.0.8"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+  integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
 yallist@^3.0.2:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
   integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
 
-yaml@^1.10.0:
+yaml-ast-parser@0.0.43:
+  version "0.0.43"
+  resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb"
+  integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==
+
+yaml@1.10.2, yaml@^1.10.0:

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Security vulnerability in yaml dependency</b></div>
   <div id="fix">
   
   The yaml package has been updated to version 1.10.2, which is affected by CVE-2023-2251, a high-severity vulnerability that allows denial of service via uncaught exception in the YAML parser. This could impact availability if the package processes untrusted YAML input. Upgrade to yaml version 2.2.2 or later to mitigate this risk.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #d777be</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
docs/yarn.lock:
##########
@@ -8782,6 +9219,13 @@ js-yaml-loader@^1.2.2:
     loader-utils "^1.2.3"
     un-eval "^1.2.0"
 
+js-yaml@4.1.0:

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Security vulnerability in added dep</b></div>
   <div id="fix">
   
   This change adds js-yaml version 4.1.0, which has a known prototype pollution vulnerability (CVE-2025-64718). Although the package.json specifies ^4.1.1, the lock file now includes the vulnerable version, potentially exposing the docs build to attacks if YAML parsing handles untrusted input. Consider updating dependencies to resolve to the patched version.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #d777be</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
docs/scripts/fix-openapi-spec.py:
##########
@@ -0,0 +1,828 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Fix missing schema references in the OpenAPI spec.
+
+This script patches the openapi.json file to add any missing schemas
+that are referenced but not defined.
+"""
+
+import json  # noqa: TID251 - standalone docs script
+import sys
+from pathlib import Path
+from typing import Any
+
+
+def add_missing_schemas(spec: dict[str, Any]) -> tuple[dict[str, Any], list[str]]:
+    """Add missing schema definitions to the OpenAPI spec."""
+    schemas = spec.get("components", {}).get("schemas", {})
+    fixed = []
+
+    # DashboardScreenshotPostSchema - based on superset/dashboards/schemas.py
+    if "DashboardScreenshotPostSchema" not in schemas:
+        schemas["DashboardScreenshotPostSchema"] = {
+            "type": "object",
+            "properties": {
+                "dataMask": {
+                    "type": "object",
+                    "description": "An object representing the data mask.",
+                    "additionalProperties": True,
+                },
+                "activeTabs": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "A list representing active tabs.",
+                },
+                "anchor": {
+                    "type": "string",
+                    "description": "A string representing the anchor.",
+                },
+                "urlParams": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {"type": "string"},
+                        "minItems": 2,
+                        "maxItems": 2,
+                    },
+                    "description": "A list of tuples, each containing two strings.",
+                },
+            },
+        }
+        fixed.append("DashboardScreenshotPostSchema")
+
+    # DashboardNativeFiltersConfigUpdateSchema - based on superset/dashboards/schemas.py
+    if "DashboardNativeFiltersConfigUpdateSchema" not in schemas:
+        schemas["DashboardNativeFiltersConfigUpdateSchema"] = {
+            "type": "object",
+            "properties": {
+                "deleted": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "List of deleted filter IDs.",
+                },
+                "modified": {
+                    "type": "array",
+                    "items": {"type": "object"},
+                    "description": "List of modified filter configurations.",
+                },
+                "reordered": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "List of filter IDs in new order.",
+                },
+            },
+        }
+        fixed.append("DashboardNativeFiltersConfigUpdateSchema")
+
+    # DashboardColorsConfigUpdateSchema - based on superset/dashboards/schemas.py
+    if "DashboardColorsConfigUpdateSchema" not in schemas:
+        schemas["DashboardColorsConfigUpdateSchema"] = {
+            "type": "object",
+            "properties": {
+                "color_namespace": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The color namespace.",
+                },
+                "color_scheme": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The color scheme name.",
+                },
+                "map_label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Mapping of labels to colors.",
+                },
+                "shared_label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Shared label colors across charts.",
+                },
+                "label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Label to color mapping.",
+                },
+                "color_scheme_domain": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "Color scheme domain values.",
+                },
+            },
+        }
+        fixed.append("DashboardColorsConfigUpdateSchema")
+
+    # FormatQueryPayloadSchema - based on superset/sqllab/schemas.py
+    if "FormatQueryPayloadSchema" not in schemas:
+        schemas["FormatQueryPayloadSchema"] = {
+            "type": "object",
+            "required": ["sql"],
+            "properties": {
+                "sql": {
+                    "type": "string",
+                    "description": "The SQL query to format.",
+                },
+                "engine": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The database engine.",
+                },
+                "database_id": {
+                    "type": "integer",
+                    "nullable": True,
+                    "description": "The database id.",
+                },
+                "template_params": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The SQL query template params as JSON string.",
+                },
+            },
+        }
+        fixed.append("FormatQueryPayloadSchema")
+
+    # get_slack_channels_schema - based on superset/reports/schemas.py
+    if "get_slack_channels_schema" not in schemas:
+        schemas["get_slack_channels_schema"] = {
+            "type": "object",
+            "properties": {
+                "search_string": {
+                    "type": "string",
+                    "description": "String to search for in channel names.",
+                },
+                "types": {
+                    "type": "array",
+                    "items": {
+                        "type": "string",
+                        "enum": ["public_channel", "private_channel"],
+                    },
+                    "description": "Types of channels to search.",
+                },
+                "exact_match": {
+                    "type": "boolean",
+                    "description": "Whether to match channel names exactly.",
+                },
+            },
+        }
+        fixed.append("get_slack_channels_schema")
+
+    if "components" not in spec:
+        spec["components"] = {}
+    spec["components"]["schemas"] = schemas
+
+    return spec, fixed
+
+
+def path_to_operation_id(path: str, method: str) -> str:
+    """Convert a path and method to an operationId."""
+    # Remove /api/v1/ prefix
+    clean_path = path.replace("/api/v1/", "").strip("/")
+
+    # Replace path parameters
+    clean_path = clean_path.replace("{", "by_").replace("}", "")
+
+    # Create operation name
+    method_prefix = {
+        "get": "get",
+        "post": "create",
+        "put": "update",
+        "delete": "delete",
+        "patch": "patch",
+    }.get(method.lower(), method.lower())
+
+    return f"{method_prefix}_{clean_path}".replace("/", "_").replace("-", "_")
+
+
+def path_to_summary(path: str, method: str) -> str:
+    """Generate a human-readable summary from path and method."""
+    # Remove /api/v1/ prefix
+    clean_path = path.replace("/api/v1/", "").strip("/")
+
+    # Handle path parameters
+    parts = []
+    for part in clean_path.split("/"):
+        if part.startswith("{") and part.endswith("}"):
+            param = part[1:-1]
+            parts.append(f"by {param}")
+        else:
+            parts.append(part.replace("_", " ").replace("-", " "))
+
+    resource = " ".join(parts)
+
+    method_verb = {
+        "get": "Get",
+        "post": "Create",
+        "put": "Update",
+        "delete": "Delete",
+        "patch": "Update",
+    }.get(method.lower(), method.capitalize())
+
+    return f"{method_verb} {resource}"
+
+
+def add_missing_operation_ids(spec: dict[str, Any]) -> int:
+    """Add operationId and summary to operations that are missing them."""
+    fixed_count = 0
+
+    for path, methods in spec.get("paths", {}).items():
+        for method, details in methods.items():
+            if method not in ["get", "post", "put", "delete", "patch"]:
+                continue
+
+            if not isinstance(details, dict):
+                continue
+
+            summary = details.get("summary")
+            operation_id = details.get("operationId")
+
+            if not summary and not operation_id:
+                details["operationId"] = path_to_operation_id(path, method)
+                details["summary"] = path_to_summary(path, method)
+                fixed_count += 1
+
+    return fixed_count
+
+
+TAG_DESCRIPTIONS = {
+    "Advanced Data Type": "Advanced data type operations and conversions.",
+    "Annotation Layers": "Manage annotation layers and annotations for charts.",
+    "AsyncEventsRestApi": "Real-time event streaming via Server-Sent Events (SSE).",
+    "Available Domains": "Get available domains for the Superset instance.",
+    "CSS Templates": "Manage CSS templates for custom dashboard styling.",
+    "CacheRestApi": "Cache management and invalidation operations.",
+    "Charts": "Create, read, update, and delete charts (slices).",
+    "Current User": "Get information about the authenticated user.",
+    "Dashboard Filter State": "Manage temporary filter state for dashboards.",
+    "Dashboard Permanent Link": "Permanent links to dashboard states.",
+    "Dashboards": "Create, read, update, and delete dashboards.",
+    "Database": "Manage database connections and metadata.",
+    "Datasets": "Manage datasets (tables) used for building charts.",
+    "Datasources": "Query datasource metadata and column values.",
+    "Embedded Dashboard": "Configure embedded dashboard settings.",
+    "Explore": "Chart exploration and data querying endpoints.",
+    "Explore Form Data": "Manage temporary form data for chart exploration.",
+    "Explore Permanent Link": "Permanent links to chart explore states.",
+    "Import/export": "Import and export Superset assets.",
+    "LogRestApi": "Access audit logs and activity history.",
+    "Menu": "Get the Superset menu structure.",
+    "OpenApi": "Access the OpenAPI specification.",
+    "Queries": "View and manage SQL Lab query history.",
+    "Report Schedules": "Configure scheduled reports and alerts.",
+    "Row Level Security": "Manage row-level security rules for data access.",
+    "SQL Lab": "Execute SQL queries and manage SQL Lab sessions.",
+    "SQL Lab Permanent Link": "Permanent links to SQL Lab states.",
+    "Security": "Authentication and token management.",
+    "Security Permissions": "View available permissions.",
+    "Security Permissions on Resources (View Menus)": "Permission-resource mappings.",
+    "Security Resources (View Menus)": "Manage security resources (view menus).",
+    "Security Roles": "Manage security roles and their permissions.",
+    "Security Users": "Manage user accounts.",
+    "Tags": "Organize assets with tags.",
+    "User": "User profile and preferences.",
+}
+
+
+def generate_code_sample(
+    method: str, path: str, has_body: bool = False
+) -> list[dict[str, str]]:
+    """Generate code samples for an endpoint in multiple languages."""
+    # Clean up path for display
+    example_path = path.replace("{pk}", "1").replace("{id_or_slug}", "1")
+
+    samples = []
+
+    # cURL sample
+    curl_cmd = f'curl -X {method.upper()} "http://localhost:8088{example_path}"'
+    curl_cmd += ' \\\n  -H "Authorization: Bearer $ACCESS_TOKEN"'
+    if has_body:
+        curl_cmd += ' \\\n  -H "Content-Type: application/json"'
+        curl_cmd += ' \\\n  -d \'{"key": "value"}\''
+
+    samples.append(
+        {
+            "lang": "cURL",
+            "label": "cURL",
+            "source": curl_cmd,
+        }
+    )
+
+    # Python sample
+    if method.lower() == "get":
+        python_code = f"""import requests
+
+response = requests.get(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.json())"""
+    elif method.lower() == "post":
+        python_code = f"""import requests
+
+response = requests.post(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}},
+    json={{"key": "value"}}
+)
+print(response.json())"""
+    elif method.lower() == "put":
+        python_code = f"""import requests
+
+response = requests.put(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}},
+    json={{"key": "value"}}
+)
+print(response.json())"""
+    elif method.lower() == "delete":
+        python_code = f"""import requests
+
+response = requests.delete(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.status_code)"""
+    else:
+        python_code = f"""import requests
+
+response = requests.{method.lower()}(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.json())"""
+
+    samples.append(
+        {
+            "lang": "Python",
+            "label": "Python",
+            "source": python_code,
+        }
+    )
+
+    # JavaScript sample
+    if method.lower() == "get":
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`
+    }}
+  }}
+);
+const data = await response.json();
+console.log(data);"""
+    elif method.lower() in ["post", "put", "patch"]:
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    method: "{method.upper()}",
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`,
+      "Content-Type": "application/json"
+    }},
+    body: JSON.stringify({{ key: "value" }})
+  }}
+);
+const data = await response.json();
+console.log(data);"""
+    else:
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    method: "{method.upper()}",
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`
+    }}
+  }}
+);
+console.log(response.status);"""
+
+    samples.append(
+        {
+            "lang": "JavaScript",
+            "label": "JavaScript",
+            "source": js_code,
+        }
+    )
+
+    return samples

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Undefined variables in code samples</b></div>
   <div id="fix">
   
   The generated code samples reference undefined variables, causing runtime errors when users copy the examples.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #251f5b</i></small>
   </div><div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Runtime Error in Code Samples</b></div>
   <div id="fix">
   
   The generate_code_sample function produces code samples with undefined variables (access_token in Python, accessToken in JavaScript), leading to runtime errors if users copy and run the samples. This affects all HTTP method branches in the function.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #d777be</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas merged PR #37434:
URL: https://github.com/apache/superset/pull/37434


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on PR #37434:
URL: https://github.com/apache/superset/pull/37434#issuecomment-3797882859

   AI Code Review is in progress (usually takes 3 to 15 minutes unless it's a very large PR).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on PR #37434:
URL: https://github.com/apache/superset/pull/37434#issuecomment-3802522565

   AI Code Review is in progress (usually takes 3 to 15 minutes unless it's a very large PR).
   
   <details>
   <summary>
   Bito Usage Guide
   </summary>
   
   **Commands**
         
   Type the following command in the pull request comment and save the comment.
         
   - `/review` - Manually triggers a full AI review.
   
   - `/pause` - Pauses automatic reviews on this pull request.
   - `/resume` - Resumes automatic reviews.
   - `/resolve` - Marks all Bito-posted review comments as resolved.
   - `/abort` - Cancels all in-progress reviews.
   
         
   Refer to the <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/available-commands" target="_blank" rel="noopener noreferrer">documentation</a> for additional commands.
         
   **Configuration**
   
   This repository uses `Superset` You can customize the agent settings <a href="https://alpha.bito.ai/home/ai-agents/code-review-agent" target="_blank" rel="noopener noreferrer">here</a> or contact your Bito workspace admin at evan@preset.io.
         
   **Documentation & Help**
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/getting-started/install-run-using-bito-cloud/create-or-customize-an-agent-instance" target="_blank" rel="noopener noreferrer">Customize agent settings</a>
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/implementing-custom-code-review-rules" target="_blank" rel="noopener noreferrer">Review rules</a>
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent" target="_blank" rel="noopener noreferrer">General documentation</a>
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/faqs" target="_blank" rel="noopener noreferrer">FAQ</a>
   
   </details>
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on PR #37434:
URL: https://github.com/apache/superset/pull/37434#issuecomment-3807356332

   AI Code Review is in progress (usually takes 3 to 15 minutes unless it's a very large PR).
   
   <details>
   <summary>
   Bito Usage Guide
   </summary>
   
   **Commands**
         
   Type the following command in the pull request comment and save the comment.
         
   - `/review` - Manually triggers a full AI review.
   
   - `/pause` - Pauses automatic reviews on this pull request.
   - `/resume` - Resumes automatic reviews.
   - `/resolve` - Marks all Bito-posted review comments as resolved.
   - `/abort` - Cancels all in-progress reviews.
   
         
   Refer to the <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/available-commands" target="_blank" rel="noopener noreferrer">documentation</a> for additional commands.
         
   **Configuration**
   
   This repository uses `Superset` You can customize the agent settings <a href="https://alpha.bito.ai/home/ai-agents/code-review-agent" target="_blank" rel="noopener noreferrer">here</a> or contact your Bito workspace admin at evan@preset.io.
         
   **Documentation & Help**
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/getting-started/install-run-using-bito-cloud/create-or-customize-an-agent-instance" target="_blank" rel="noopener noreferrer">Customize agent settings</a>
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/implementing-custom-code-review-rules" target="_blank" rel="noopener noreferrer">Review rules</a>
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent" target="_blank" rel="noopener noreferrer">General documentation</a>
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/faqs" target="_blank" rel="noopener noreferrer">FAQ</a>
   
   </details>
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734382815


##########
docs/docs/api.mdx:
##########
@@ -1,40 +1,590 @@
 ---
-title: API
+title: API Reference
 hide_title: true
 sidebar_position: 10
 ---
 
-import SwaggerUI from 'swagger-ui-react';
-import openapi from '/resources/openapi.json';
-import 'swagger-ui-react/swagger-ui.css';
 import { Alert } from 'antd';
 
-## API
+## REST API Reference
 
-Superset's public **REST API** follows the
-[OpenAPI specification](https://swagger.io/specification/), and is
-documented here. The docs below are generated using
-[Swagger React UI](https://www.npmjs.com/package/swagger-ui-react).
-
-:::resources
-- [Blog: The Superset REST API](https://preset.io/blog/2020-10-01-superset-api/)
-- [Blog: Accessing APIs with Superset](https://preset.io/blog/accessing-apis-with-superset/)
-:::
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
 
 <Alert
   type="info"
-  message={
-    <div>
-      <strong>NOTE! </strong>
-      You can find an interactive version of this documentation on your local Superset
-      instance at <strong>/swagger/v1</strong> (unless disabled)
-    </div>
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
   }
+  style={{ marginBottom: '24px' }}
 />
 
-<br />
-<br />
-<hr />
-<div className="swagger-container">
-  <SwaggerUI spec={openapi} />
-</div>
+---
+
+### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+```bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \
+  -H "Content-Type: application/json" \
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
+  http://localhost:8088/api/v1/dashboard/
+```
+
+#### Security Endpoints
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get the CSRF token](./get-the-csrf-token) | `/api/v1/security/csrf_token/` |

Review Comment:
   <!-- Bito Reply -->
   Your explanation is accurate. The links in `docs/docs/api.mdx` now use `./api/${slug}` format, which Docusaurus resolves file-relative from `docs/api.mdx` to `docs/api/${slug}.api.mdx`. The build confirming zero broken links supports this.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "codeant-ai-for-open-source[bot] (via GitHub)" <gi...@apache.org>.
codeant-ai-for-open-source[bot] commented on PR #37434:
URL: https://github.com/apache/superset/pull/37434#issuecomment-3802374160

   ## **Sequence Diagram**
   
   Shows the core flow added in this PR: a script patches the OpenAPI spec, the docusaurus-openapi-docs plugin generates MDX API pages, and helper scripts produce the sidebar and landing index so the docs site can serve the interactive API reference.
   
   ```mermaid
   sequenceDiagram
       participant Developer
       participant FixScript as fix-openapi-spec.py
       participant OpenAPI as openapi.json
       participant GenPlugin as docusaurus-plugin-openapi-docs
       participant SidebarScripts as convert/generate-index scripts
       participant DocsSite as Docusaurus
   
       Developer->>FixScript: Run "yarn generate:api-docs"
       FixScript->>OpenAPI: Read & patch spec (add schemas, tag descriptions, x-codeSamples, servers, examples)
       FixScript-->>Developer: Write updated openapi.json
   
       Developer->>GenPlugin: Run "docusaurus gen-api-docs superset"
       GenPlugin->>OpenAPI: Generate MDX pages under docs/api from spec
       GenPlugin-->>Developer: Generated endpoint & schema MDX (gitignored)
   
       Developer->>SidebarScripts: Run convert-api-sidebar.mjs & generate-api-index.mjs
       SidebarScripts->>DocsSite: Produce sidebar.js and api.mdx landing page
   
       Developer->>DocsSite: Start/build docs (includes docusaurus-theme-openapi-docs)
       DocsSite->>DocsSite: Include CSS to hide non-functional "Send" UI and render API Reference
       DocsSite-->>Developer: Serve API Reference at /docs/api/
   ```
   
   ---
   *Generated by [CodeAnt AI](https://codeant.ai)*
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734366481


##########
docs/yarn.lock:
##########
@@ -8782,6 +9219,13 @@ js-yaml-loader@^1.2.2:
     loader-utils "^1.2.3"
     un-eval "^1.2.0"
 
+js-yaml@4.1.0:

Review Comment:
   This is a transitive dependency pulled in by other packages in the dependency tree. Our `package.json` specifies `"js-yaml": "^4.1.1"`. The lock file is generated by `yarn install` and the resolved version is determined by the dependency tree. Additionally, CVE-2025-64718 doesn't appear to be a verified CVE in the NVD database — this may be a false positive from the bot's vulnerability scanner.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "codeant-ai-for-open-source[bot] (via GitHub)" <gi...@apache.org>.
codeant-ai-for-open-source[bot] commented on PR #37434:
URL: https://github.com/apache/superset/pull/37434#issuecomment-3807060973

   ## **Sequence Diagram**
   
   This PR adds an automated pipeline that patches the OpenAPI spec, generates interactive API docs (MDX) via docusaurus-plugin-openapi-docs, and produces the API index/sidebar so the docs site exposes a comprehensive API Reference. The diagram shows the main success path of the generation flow added by the PR.
   
   ```mermaid
   sequenceDiagram
       participant Developer/CI
       participant fix-openapi-spec.py
       participant OpenAPI_Spec
       participant Docusaurus_Generator
       participant Postprocessors
       participant Docs_Site
   
       Developer/CI->>fix-openapi-spec.py: Run generate:api-docs (yarn)
       fix-openapi-spec.py->>OpenAPI_Spec: Patch spec (schemas, tags, code samples, servers, examples)
       Developer/CI->>Docusaurus_Generator: docusaurus gen-api-docs superset (plugin)
       Docusaurus_Generator->>Postprocessors: Emit generated MDX + sidebar.ts
       Postprocessors->>Postprocessors: convert-api-sidebar.mjs & generate-api-index.mjs (sidebar.js, api.mdx)
       Postprocessors->>Docs_Site: Docs directory populated; plugin/theme + CSS included
       Docs_Site-->>Developer/CI: Serve/build site with API Reference at /docs/api/
   ```
   
   ---
   *Generated by [CodeAnt AI](https://codeant.ai)*
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2729857213


##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Incorrect output file path</b></div>
   <div id="fix">
   
   The output path incorrectly includes an extra 'docs' directory, causing the file to be written to docs/docs/api.mdx instead of docs/api.mdx as referenced in DOCS_CLAUDE.md and the script's comment.
   </div>
   
   
   <details>
   <summary>
   <b>Code suggestion</b>
   </summary>
   <blockquote>Check the AI-generated fix before applying</blockquote>
   <div id="code">
   
   
   ````suggestion
    const OUTPUT_PATH = path.join(__dirname, '..', 'api.mdx');
   ````
   
   </div>
   </details>
   
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #251f5b</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
docs/yarn.lock:
##########
@@ -14089,6 +15026,14 @@ whatwg-fetch@^3.6.20:
   resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
   integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==
 
+whatwg-url@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+  integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
+  dependencies:
+    tr46 "~0.0.3"
+    webidl-conversions "^3.0.0"
+

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Manual yarn.lock edit</b></div>
   <div id="fix">
   
   yarn.lock is auto-generated and should not be edited manually, as it can lead to inconsistent dependency resolution. These additions appear to be for new transitive dependencies, but package.json lacks the corresponding declarations.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #251f5b</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Missing error handling</b></div>
   <div id="fix">
   
   Script lacks error handling for file read/parse failures, which could cause build to fail unexpectedly if OpenAPI spec is invalid.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #251f5b</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
docs/scripts/fix-openapi-spec.py:
##########
@@ -0,0 +1,828 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Fix missing schema references in the OpenAPI spec.
+
+This script patches the openapi.json file to add any missing schemas
+that are referenced but not defined.
+"""
+
+import json  # noqa: TID251 - standalone docs script
+import sys
+from pathlib import Path
+from typing import Any
+
+
+def add_missing_schemas(spec: dict[str, Any]) -> tuple[dict[str, Any], list[str]]:
+    """Add missing schema definitions to the OpenAPI spec."""
+    schemas = spec.get("components", {}).get("schemas", {})
+    fixed = []
+
+    # DashboardScreenshotPostSchema - based on superset/dashboards/schemas.py
+    if "DashboardScreenshotPostSchema" not in schemas:
+        schemas["DashboardScreenshotPostSchema"] = {
+            "type": "object",
+            "properties": {
+                "dataMask": {
+                    "type": "object",
+                    "description": "An object representing the data mask.",
+                    "additionalProperties": True,
+                },
+                "activeTabs": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "A list representing active tabs.",
+                },
+                "anchor": {
+                    "type": "string",
+                    "description": "A string representing the anchor.",
+                },
+                "urlParams": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {"type": "string"},
+                        "minItems": 2,
+                        "maxItems": 2,
+                    },
+                    "description": "A list of tuples, each containing two strings.",
+                },
+            },
+        }
+        fixed.append("DashboardScreenshotPostSchema")
+
+    # DashboardNativeFiltersConfigUpdateSchema - based on superset/dashboards/schemas.py
+    if "DashboardNativeFiltersConfigUpdateSchema" not in schemas:
+        schemas["DashboardNativeFiltersConfigUpdateSchema"] = {
+            "type": "object",
+            "properties": {
+                "deleted": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "List of deleted filter IDs.",
+                },
+                "modified": {
+                    "type": "array",
+                    "items": {"type": "object"},
+                    "description": "List of modified filter configurations.",
+                },
+                "reordered": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "List of filter IDs in new order.",
+                },
+            },
+        }
+        fixed.append("DashboardNativeFiltersConfigUpdateSchema")
+
+    # DashboardColorsConfigUpdateSchema - based on superset/dashboards/schemas.py
+    if "DashboardColorsConfigUpdateSchema" not in schemas:
+        schemas["DashboardColorsConfigUpdateSchema"] = {
+            "type": "object",
+            "properties": {
+                "color_namespace": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The color namespace.",
+                },
+                "color_scheme": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The color scheme name.",
+                },
+                "map_label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Mapping of labels to colors.",
+                },
+                "shared_label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Shared label colors across charts.",
+                },
+                "label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Label to color mapping.",
+                },
+                "color_scheme_domain": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "Color scheme domain values.",
+                },
+            },
+        }
+        fixed.append("DashboardColorsConfigUpdateSchema")
+
+    # FormatQueryPayloadSchema - based on superset/sqllab/schemas.py
+    if "FormatQueryPayloadSchema" not in schemas:
+        schemas["FormatQueryPayloadSchema"] = {
+            "type": "object",
+            "required": ["sql"],
+            "properties": {
+                "sql": {
+                    "type": "string",
+                    "description": "The SQL query to format.",
+                },
+                "engine": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The database engine.",
+                },
+                "database_id": {
+                    "type": "integer",
+                    "nullable": True,
+                    "description": "The database id.",
+                },
+                "template_params": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The SQL query template params as JSON string.",
+                },
+            },
+        }
+        fixed.append("FormatQueryPayloadSchema")
+
+    # get_slack_channels_schema - based on superset/reports/schemas.py
+    if "get_slack_channels_schema" not in schemas:
+        schemas["get_slack_channels_schema"] = {
+            "type": "object",
+            "properties": {
+                "search_string": {
+                    "type": "string",
+                    "description": "String to search for in channel names.",
+                },
+                "types": {
+                    "type": "array",
+                    "items": {
+                        "type": "string",
+                        "enum": ["public_channel", "private_channel"],
+                    },
+                    "description": "Types of channels to search.",
+                },
+                "exact_match": {
+                    "type": "boolean",
+                    "description": "Whether to match channel names exactly.",
+                },
+            },
+        }
+        fixed.append("get_slack_channels_schema")
+
+    if "components" not in spec:
+        spec["components"] = {}
+    spec["components"]["schemas"] = schemas
+
+    return spec, fixed
+
+
+def path_to_operation_id(path: str, method: str) -> str:
+    """Convert a path and method to an operationId."""
+    # Remove /api/v1/ prefix
+    clean_path = path.replace("/api/v1/", "").strip("/")
+
+    # Replace path parameters
+    clean_path = clean_path.replace("{", "by_").replace("}", "")
+
+    # Create operation name
+    method_prefix = {
+        "get": "get",
+        "post": "create",
+        "put": "update",
+        "delete": "delete",
+        "patch": "patch",
+    }.get(method.lower(), method.lower())
+
+    return f"{method_prefix}_{clean_path}".replace("/", "_").replace("-", "_")
+
+
+def path_to_summary(path: str, method: str) -> str:
+    """Generate a human-readable summary from path and method."""
+    # Remove /api/v1/ prefix
+    clean_path = path.replace("/api/v1/", "").strip("/")
+
+    # Handle path parameters
+    parts = []
+    for part in clean_path.split("/"):
+        if part.startswith("{") and part.endswith("}"):
+            param = part[1:-1]
+            parts.append(f"by {param}")
+        else:
+            parts.append(part.replace("_", " ").replace("-", " "))
+
+    resource = " ".join(parts)
+
+    method_verb = {
+        "get": "Get",
+        "post": "Create",
+        "put": "Update",
+        "delete": "Delete",
+        "patch": "Update",
+    }.get(method.lower(), method.capitalize())
+
+    return f"{method_verb} {resource}"
+
+
+def add_missing_operation_ids(spec: dict[str, Any]) -> int:
+    """Add operationId and summary to operations that are missing them."""
+    fixed_count = 0
+
+    for path, methods in spec.get("paths", {}).items():
+        for method, details in methods.items():
+            if method not in ["get", "post", "put", "delete", "patch"]:
+                continue
+
+            if not isinstance(details, dict):
+                continue
+
+            summary = details.get("summary")
+            operation_id = details.get("operationId")
+
+            if not summary and not operation_id:
+                details["operationId"] = path_to_operation_id(path, method)
+                details["summary"] = path_to_summary(path, method)
+                fixed_count += 1
+
+    return fixed_count
+
+
+TAG_DESCRIPTIONS = {
+    "Advanced Data Type": "Advanced data type operations and conversions.",
+    "Annotation Layers": "Manage annotation layers and annotations for charts.",
+    "AsyncEventsRestApi": "Real-time event streaming via Server-Sent Events (SSE).",
+    "Available Domains": "Get available domains for the Superset instance.",
+    "CSS Templates": "Manage CSS templates for custom dashboard styling.",
+    "CacheRestApi": "Cache management and invalidation operations.",
+    "Charts": "Create, read, update, and delete charts (slices).",
+    "Current User": "Get information about the authenticated user.",
+    "Dashboard Filter State": "Manage temporary filter state for dashboards.",
+    "Dashboard Permanent Link": "Permanent links to dashboard states.",
+    "Dashboards": "Create, read, update, and delete dashboards.",
+    "Database": "Manage database connections and metadata.",
+    "Datasets": "Manage datasets (tables) used for building charts.",
+    "Datasources": "Query datasource metadata and column values.",
+    "Embedded Dashboard": "Configure embedded dashboard settings.",
+    "Explore": "Chart exploration and data querying endpoints.",
+    "Explore Form Data": "Manage temporary form data for chart exploration.",
+    "Explore Permanent Link": "Permanent links to chart explore states.",
+    "Import/export": "Import and export Superset assets.",
+    "LogRestApi": "Access audit logs and activity history.",
+    "Menu": "Get the Superset menu structure.",
+    "OpenApi": "Access the OpenAPI specification.",
+    "Queries": "View and manage SQL Lab query history.",
+    "Report Schedules": "Configure scheduled reports and alerts.",
+    "Row Level Security": "Manage row-level security rules for data access.",
+    "SQL Lab": "Execute SQL queries and manage SQL Lab sessions.",
+    "SQL Lab Permanent Link": "Permanent links to SQL Lab states.",
+    "Security": "Authentication and token management.",
+    "Security Permissions": "View available permissions.",
+    "Security Permissions on Resources (View Menus)": "Permission-resource mappings.",
+    "Security Resources (View Menus)": "Manage security resources (view menus).",
+    "Security Roles": "Manage security roles and their permissions.",
+    "Security Users": "Manage user accounts.",
+    "Tags": "Organize assets with tags.",
+    "User": "User profile and preferences.",
+}
+
+
+def generate_code_sample(
+    method: str, path: str, has_body: bool = False
+) -> list[dict[str, str]]:
+    """Generate code samples for an endpoint in multiple languages."""
+    # Clean up path for display
+    example_path = path.replace("{pk}", "1").replace("{id_or_slug}", "1")
+
+    samples = []
+
+    # cURL sample
+    curl_cmd = f'curl -X {method.upper()} "http://localhost:8088{example_path}"'
+    curl_cmd += ' \\\n  -H "Authorization: Bearer $ACCESS_TOKEN"'
+    if has_body:
+        curl_cmd += ' \\\n  -H "Content-Type: application/json"'
+        curl_cmd += ' \\\n  -d \'{"key": "value"}\''
+
+    samples.append(
+        {
+            "lang": "cURL",
+            "label": "cURL",
+            "source": curl_cmd,
+        }
+    )
+
+    # Python sample
+    if method.lower() == "get":
+        python_code = f"""import requests
+
+response = requests.get(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.json())"""
+    elif method.lower() == "post":
+        python_code = f"""import requests
+
+response = requests.post(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}},
+    json={{"key": "value"}}
+)
+print(response.json())"""
+    elif method.lower() == "put":
+        python_code = f"""import requests
+
+response = requests.put(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}},
+    json={{"key": "value"}}
+)
+print(response.json())"""
+    elif method.lower() == "delete":
+        python_code = f"""import requests
+
+response = requests.delete(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.status_code)"""
+    else:
+        python_code = f"""import requests
+
+response = requests.{method.lower()}(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.json())"""
+
+    samples.append(
+        {
+            "lang": "Python",
+            "label": "Python",
+            "source": python_code,
+        }
+    )
+
+    # JavaScript sample
+    if method.lower() == "get":
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`
+    }}
+  }}
+);
+const data = await response.json();
+console.log(data);"""
+    elif method.lower() in ["post", "put", "patch"]:
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    method: "{method.upper()}",
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`,
+      "Content-Type": "application/json"
+    }},
+    body: JSON.stringify({{ key: "value" }})
+  }}
+);
+const data = await response.json();
+console.log(data);"""
+    else:
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    method: "{method.upper()}",
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`
+    }}
+  }}
+);
+console.log(response.status);"""
+
+    samples.append(
+        {
+            "lang": "JavaScript",
+            "label": "JavaScript",
+            "source": js_code,
+        }
+    )
+
+    return samples

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Undefined variables in code samples</b></div>
   <div id="fix">
   
   The generated code samples reference undefined variables, causing runtime errors when users copy the examples.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #251f5b</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
docs/yarn.lock:
##########
@@ -8250,16 +8669,24 @@ infima@0.2.0-alpha.45:
   resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.45.tgz#542aab5a249274d81679631b492973dd2c1e7466"
   integrity sha512-uyH0zfr1erU1OohLk0fT4Rrb94AOhguWNOcD9uGrSpRvNB+6gZXUoJX5J0NtvzBO10YZ9PgvA4NFgt+fYg8ojw==
 
-inherits@2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
-  integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Security: Memory Leak in Dependency</b></div>
   <div id="fix">
   
   The addition of inflight@1.0.6 introduces a known memory leak vulnerability that can lead to denial-of-service via unbounded concurrent callbacks, potentially crashing the Node.js process during docs builds or serves. While exploitation requires many concurrent operations, this affects reliability in high-usage scenarios. Consider updating dependencies to avoid this deprecated package.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #251f5b</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734629179


##########
docs/docs/api.mdx:
##########
@@ -1,40 +1,590 @@
 ---
-title: API
+title: API Reference
 hide_title: true
 sidebar_position: 10
 ---
 
-import SwaggerUI from 'swagger-ui-react';
-import openapi from '/resources/openapi.json';
-import 'swagger-ui-react/swagger-ui.css';
 import { Alert } from 'antd';
 
-## API
+## REST API Reference
 
-Superset's public **REST API** follows the
-[OpenAPI specification](https://swagger.io/specification/), and is
-documented here. The docs below are generated using
-[Swagger React UI](https://www.npmjs.com/package/swagger-ui-react).
-
-:::resources
-- [Blog: The Superset REST API](https://preset.io/blog/2020-10-01-superset-api/)
-- [Blog: Accessing APIs with Superset](https://preset.io/blog/accessing-apis-with-superset/)
-:::
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
 
 <Alert
   type="info"
-  message={
-    <div>
-      <strong>NOTE! </strong>
-      You can find an interactive version of this documentation on your local Superset
-      instance at <strong>/swagger/v1</strong> (unless disabled)
-    </div>
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      The sidebar includes <strong>Schema definitions</strong> for detailed data model documentation.
+    </span>
   }
+  style={{ marginBottom: '24px' }}
 />
 
-<br />
-<br />
-<hr />
-<div className="swagger-container">
-  <SwaggerUI spec={openapi} />
-</div>
+---
+
+### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+```bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \
+  -H "Content-Type: application/json" \
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
+  http://localhost:8088/api/v1/dashboard/
+```
+
+#### Security Endpoints
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get the CSRF token](./api/get-the-csrf-token) | `/api/v1/security/csrf_token/` |
+| `POST` | [Get a guest token](./api/get-a-guest-token) | `/api/v1/security/guest_token/` |
+| `POST` | [Create security login](./api/create-security-login) | `/api/v1/security/login` |
+| `POST` | [Create security refresh](./api/create-security-refresh) | `/api/v1/security/refresh` |
+
+---
+
+### API Endpoints
+
+#### Core Resources
+
+<details>
+<summary><strong>Dashboards</strong> (26 endpoints) — Create, read, update, and delete dashboards.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete dashboards](./api/bulk-delete-dashboards) | `/api/v1/dashboard/` |
+| `GET` | [Get a list of dashboards](./api/get-a-list-of-dashboards) | `/api/v1/dashboard/` |
+| `POST` | [Create a new dashboard](./api/create-a-new-dashboard) | `/api/v1/dashboard/` |
+| `GET` | [Get metadata information about this API resource (dashboard--info)](./api/get-metadata-information-about-this-api-resource-dashboard-info) | `/api/v1/dashboard/_info` |
+| `GET` | [Get a dashboard detail information](./api/get-a-dashboard-detail-information) | `/api/v1/dashboard/{id_or_slug}` |
+| `GET` | [Get a dashboard's chart definitions.](./api/get-a-dashboards-chart-definitions) | `/api/v1/dashboard/{id_or_slug}/charts` |
+| `POST` | [Create a copy of an existing dashboard](./api/create-a-copy-of-an-existing-dashboard) | `/api/v1/dashboard/{id_or_slug}/copy/` |
+| `GET` | [Get dashboard's datasets](./api/get-dashboards-datasets) | `/api/v1/dashboard/{id_or_slug}/datasets` |
+| `DELETE` | [Delete a dashboard's embedded configuration](./api/delete-a-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `GET` | [Get the dashboard's embedded configuration](./api/get-the-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `POST` | [Set a dashboard's embedded configuration](./api/set-a-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `PUT` | [Update dashboard by id_or_slug embedded](./api/update-dashboard-by-id-or-slug-embedded) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `GET` | [Get dashboard's tabs](./api/get-dashboards-tabs) | `/api/v1/dashboard/{id_or_slug}/tabs` |
+| `DELETE` | [Delete a dashboard](./api/delete-a-dashboard) | `/api/v1/dashboard/{pk}` |
+| `PUT` | [Update a dashboard](./api/update-a-dashboard) | `/api/v1/dashboard/{pk}` |
+| `POST` | [Compute and cache a screenshot (dashboard-pk-cache-dashboard-screenshot)](./api/compute-and-cache-a-screenshot-dashboard-pk-cache-dashboard-screenshot) | `/api/v1/dashboard/{pk}/cache_dashboard_screenshot/` |
+| `PUT` | [Update colors configuration for a dashboard.](./api/update-colors-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/colors` |
+| `DELETE` | [Remove the dashboard from the user favorite list](./api/remove-the-dashboard-from-the-user-favorite-list) | `/api/v1/dashboard/{pk}/favorites/` |
+| `POST` | [Mark the dashboard as favorite for the current user](./api/mark-the-dashboard-as-favorite-for-the-current-user) | `/api/v1/dashboard/{pk}/favorites/` |
+| `PUT` | [Update native filters configuration for a dashboard.](./api/update-native-filters-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/filters` |
+| `GET` | [Get a computed screenshot from cache (dashboard-pk-screenshot-digest)](./api/get-a-computed-screenshot-from-cache-dashboard-pk-screenshot-digest) | `/api/v1/dashboard/{pk}/screenshot/{digest}/` |
+| `GET` | [Get dashboard's thumbnail](./api/get-dashboards-thumbnail) | `/api/v1/dashboard/{pk}/thumbnail/{digest}/` |
+| `GET` | [Download multiple dashboards as YAML files](./api/download-multiple-dashboards-as-yaml-files) | `/api/v1/dashboard/export/` |
+| `GET` | [Check favorited dashboards for current user](./api/check-favorited-dashboards-for-current-user) | `/api/v1/dashboard/favorite_status/` |
+| `POST` | [Import dashboard(s) with associated charts/datasets/databases](./api/import-dashboard-s-with-associated-charts-datasets-databases) | `/api/v1/dashboard/import/` |
+| `GET` | [Get related fields data (dashboard-related-column-name)](./api/get-related-fields-data-dashboard-related-column-name) | `/api/v1/dashboard/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>Charts</strong> (20 endpoints) — Create, read, update, and delete charts (slices).</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete charts](./api/bulk-delete-charts) | `/api/v1/chart/` |
+| `GET` | [Get a list of charts](./api/get-a-list-of-charts) | `/api/v1/chart/` |
+| `POST` | [Create a new chart](./api/create-a-new-chart) | `/api/v1/chart/` |
+| `GET` | [Get metadata information about this API resource (chart--info)](./api/get-metadata-information-about-this-api-resource-chart-info) | `/api/v1/chart/_info` |
+| `DELETE` | [Delete a chart](./api/delete-a-chart) | `/api/v1/chart/{pk}` |
+| `GET` | [Get a chart detail information](./api/get-a-chart-detail-information) | `/api/v1/chart/{pk}` |
+| `PUT` | [Update a chart](./api/update-a-chart) | `/api/v1/chart/{pk}` |
+| `GET` | [Compute and cache a screenshot (chart-pk-cache-screenshot)](./api/compute-and-cache-a-screenshot-chart-pk-cache-screenshot) | `/api/v1/chart/{pk}/cache_screenshot/` |
+| `GET` | [Return payload data response for a chart](./api/return-payload-data-response-for-a-chart) | `/api/v1/chart/{pk}/data/` |
+| `DELETE` | [Remove the chart from the user favorite list](./api/remove-the-chart-from-the-user-favorite-list) | `/api/v1/chart/{pk}/favorites/` |
+| `POST` | [Mark the chart as favorite for the current user](./api/mark-the-chart-as-favorite-for-the-current-user) | `/api/v1/chart/{pk}/favorites/` |
+| `GET` | [Get a computed screenshot from cache (chart-pk-screenshot-digest)](./api/get-a-computed-screenshot-from-cache-chart-pk-screenshot-digest) | `/api/v1/chart/{pk}/screenshot/{digest}/` |
+| `GET` | [Get chart thumbnail](./api/get-chart-thumbnail) | `/api/v1/chart/{pk}/thumbnail/{digest}/` |
+| `POST` | [Return payload data response for the given query (chart-data)](./api/return-payload-data-response-for-the-given-query-chart-data) | `/api/v1/chart/data` |
+| `GET` | [Return payload data response for the given query (chart-data-cache-key)](./api/return-payload-data-response-for-the-given-query-chart-data-cache-key) | `/api/v1/chart/data/{cache_key}` |
+| `GET` | [Download multiple charts as YAML files](./api/download-multiple-charts-as-yaml-files) | `/api/v1/chart/export/` |
+| `GET` | [Check favorited charts for current user](./api/check-favorited-charts-for-current-user) | `/api/v1/chart/favorite_status/` |
+| `POST` | [Import chart(s) with associated datasets and databases](./api/import-chart-s-with-associated-datasets-and-databases) | `/api/v1/chart/import/` |
+| `GET` | [Get related fields data (chart-related-column-name)](./api/get-related-fields-data-chart-related-column-name) | `/api/v1/chart/related/{column_name}` |
+| `PUT` | [Warm up the cache for the chart](./api/warm-up-the-cache-for-the-chart) | `/api/v1/chart/warm_up_cache` |
+
+</details>
+
+<details>
+<summary><strong>Datasets</strong> (18 endpoints) — Manage datasets (tables) used for building charts.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete datasets](./api/bulk-delete-datasets) | `/api/v1/dataset/` |
+| `GET` | [Get a list of datasets](./api/get-a-list-of-datasets) | `/api/v1/dataset/` |
+| `POST` | [Create a new dataset](./api/create-a-new-dataset) | `/api/v1/dataset/` |
+| `GET` | [Get metadata information about this API resource (dataset--info)](./api/get-metadata-information-about-this-api-resource-dataset-info) | `/api/v1/dataset/_info` |
+| `DELETE` | [Delete a dataset](./api/delete-a-dataset) | `/api/v1/dataset/{pk}` |
+| `GET` | [Get a dataset](./api/get-a-dataset) | `/api/v1/dataset/{pk}` |
+| `PUT` | [Update a dataset](./api/update-a-dataset) | `/api/v1/dataset/{pk}` |
+| `DELETE` | [Delete a dataset column](./api/delete-a-dataset-column) | `/api/v1/dataset/{pk}/column/{column_id}` |
+| `DELETE` | [Delete a dataset metric](./api/delete-a-dataset-metric) | `/api/v1/dataset/{pk}/metric/{metric_id}` |
+| `PUT` | [Refresh and update columns of a dataset](./api/refresh-and-update-columns-of-a-dataset) | `/api/v1/dataset/{pk}/refresh` |
+| `GET` | [Get charts and dashboards count associated to a dataset](./api/get-charts-and-dashboards-count-associated-to-a-dataset) | `/api/v1/dataset/{pk}/related_objects` |
+| `GET` | [Get distinct values from field data (dataset-distinct-column-name)](./api/get-distinct-values-from-field-data-dataset-distinct-column-name) | `/api/v1/dataset/distinct/{column_name}` |
+| `POST` | [Duplicate a dataset](./api/duplicate-a-dataset) | `/api/v1/dataset/duplicate` |
+| `GET` | [Download multiple datasets as YAML files](./api/download-multiple-datasets-as-yaml-files) | `/api/v1/dataset/export/` |
+| `POST` | [Retrieve a table by name, or create it if it does not exist](./api/retrieve-a-table-by-name-or-create-it-if-it-does-not-exist) | `/api/v1/dataset/get_or_create/` |
+| `POST` | [Import dataset(s) with associated databases](./api/import-dataset-s-with-associated-databases) | `/api/v1/dataset/import/` |
+| `GET` | [Get related fields data (dataset-related-column-name)](./api/get-related-fields-data-dataset-related-column-name) | `/api/v1/dataset/related/{column_name}` |
+| `PUT` | [Warm up the cache for each chart powered by the given table](./api/warm-up-the-cache-for-each-chart-powered-by-the-given-table) | `/api/v1/dataset/warm_up_cache` |
+
+</details>
+
+<details>
+<summary><strong>Database</strong> (31 endpoints) — Manage database connections and metadata.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get a list of databases](./api/get-a-list-of-databases) | `/api/v1/database/` |
+| `POST` | [Create a new database](./api/create-a-new-database) | `/api/v1/database/` |
+| `GET` | [Get metadata information about this API resource (database--info)](./api/get-metadata-information-about-this-api-resource-database-info) | `/api/v1/database/_info` |
+| `DELETE` | [Delete a database](./api/delete-a-database) | `/api/v1/database/{pk}` |
+| `GET` | [Get a database](./api/get-a-database) | `/api/v1/database/{pk}` |
+| `PUT` | [Change a database](./api/change-a-database) | `/api/v1/database/{pk}` |
+| `GET` | [Get all catalogs from a database](./api/get-all-catalogs-from-a-database) | `/api/v1/database/{pk}/catalogs/` |
+| `GET` | [Get a database connection info](./api/get-a-database-connection-info) | `/api/v1/database/{pk}/connection` |
+| `GET` | [Get function names supported by a database](./api/get-function-names-supported-by-a-database) | `/api/v1/database/{pk}/function_names/` |
+| `GET` | [Get charts and dashboards count associated to a database](./api/get-charts-and-dashboards-count-associated-to-a-database) | `/api/v1/database/{pk}/related_objects/` |
+| `GET` | [The list of the database schemas where to upload information](./api/the-list-of-the-database-schemas-where-to-upload-information) | `/api/v1/database/{pk}/schemas_access_for_file_upload/` |
+| `GET` | [Get all schemas from a database](./api/get-all-schemas-from-a-database) | `/api/v1/database/{pk}/schemas/` |
+| `GET` | [Get database select star for table (database-pk-select-star-table-name)](./api/get-database-select-star-for-table-database-pk-select-star-table-name) | `/api/v1/database/{pk}/select_star/{table_name}/` |
+| `GET` | [Get database select star for table (database-pk-select-star-table-name-schema-name)](./api/get-database-select-star-for-table-database-pk-select-star-table-name-schema-name) | `/api/v1/database/{pk}/select_star/{table_name}/{schema_name}/` |
+| `DELETE` | [Delete a SSH tunnel](./api/delete-a-ssh-tunnel) | `/api/v1/database/{pk}/ssh_tunnel/` |
+| `POST` | [Re-sync all permissions for a database connection](./api/re-sync-all-permissions-for-a-database-connection) | `/api/v1/database/{pk}/sync_permissions/` |
+| `GET` | [Get table extra metadata (database-pk-table-extra-table-name-schema-name)](./api/get-table-extra-metadata-database-pk-table-extra-table-name-schema-name) | `/api/v1/database/{pk}/table_extra/{table_name}/{schema_name}/` |
+| `GET` | [Get table metadata](./api/get-table-metadata) | `/api/v1/database/{pk}/table_metadata/` |
+| `GET` | [Get table extra metadata (database-pk-table-metadata-extra)](./api/get-table-extra-metadata-database-pk-table-metadata-extra) | `/api/v1/database/{pk}/table_metadata/extra/` |
+| `GET` | [Get database table metadata](./api/get-database-table-metadata) | `/api/v1/database/{pk}/table/{table_name}/{schema_name}/` |
+| `GET` | [Get a list of tables for given database](./api/get-a-list-of-tables-for-given-database) | `/api/v1/database/{pk}/tables/` |
+| `POST` | [Upload a file to a database table](./api/upload-a-file-to-a-database-table) | `/api/v1/database/{pk}/upload/` |
+| `POST` | [Validate arbitrary SQL](./api/validate-arbitrary-sql) | `/api/v1/database/{pk}/validate_sql/` |
+| `GET` | [Get names of databases currently available](./api/get-names-of-databases-currently-available) | `/api/v1/database/available/` |
+| `GET` | [Download database(s) and associated dataset(s) as a zip file](./api/download-database-s-and-associated-dataset-s-as-a-zip-file) | `/api/v1/database/export/` |
+| `POST` | [Import database(s) with associated datasets](./api/import-database-s-with-associated-datasets) | `/api/v1/database/import/` |
+| `GET` | [Receive personal access tokens from OAuth2](./api/receive-personal-access-tokens-from-o-auth-2) | `/api/v1/database/oauth2/` |
+| `GET` | [Get related fields data (database-related-column-name)](./api/get-related-fields-data-database-related-column-name) | `/api/v1/database/related/{column_name}` |
+| `POST` | [Test a database connection](./api/test-a-database-connection) | `/api/v1/database/test_connection/` |
+| `POST` | [Upload a file and returns file metadata](./api/upload-a-file-and-returns-file-metadata) | `/api/v1/database/upload_metadata/` |
+| `POST` | [Validate database connection parameters](./api/validate-database-connection-parameters) | `/api/v1/database/validate_parameters/` |
+
+</details>
+
+#### Data Exploration
+
+<details>
+<summary><strong>Explore</strong> (1 endpoints) — Chart exploration and data querying endpoints.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Assemble Explore related information in a single endpoint](./api/assemble-explore-related-information-in-a-single-endpoint) | `/api/v1/explore/` |
+
+</details>
+
+<details>
+<summary><strong>SQL Lab</strong> (6 endpoints) — Execute SQL queries and manage SQL Lab sessions.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get the bootstrap data for SqlLab page](./api/get-the-bootstrap-data-for-sql-lab-page) | `/api/v1/sqllab/` |
+| `POST` | [Estimate the SQL query execution cost](./api/estimate-the-sql-query-execution-cost) | `/api/v1/sqllab/estimate/` |
+| `POST` | [Execute a SQL query](./api/execute-a-sql-query) | `/api/v1/sqllab/execute/` |
+| `GET` | [Export the SQL query results to a CSV](./api/export-the-sql-query-results-to-a-csv) | `/api/v1/sqllab/export/{client_id}/` |
+| `POST` | [Format SQL code](./api/format-sql-code) | `/api/v1/sqllab/format_sql/` |
+| `GET` | [Get the result of a SQL query execution](./api/get-the-result-of-a-sql-query-execution) | `/api/v1/sqllab/results/` |
+
+</details>
+
+<details>
+<summary><strong>Queries</strong> (17 endpoints) — View and manage SQL Lab query history.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get a list of queries](./api/get-a-list-of-queries) | `/api/v1/query/` |
+| `GET` | [Get query detail information](./api/get-query-detail-information) | `/api/v1/query/{pk}` |
+| `GET` | [Get distinct values from field data (query-distinct-column-name)](./api/get-distinct-values-from-field-data-query-distinct-column-name) | `/api/v1/query/distinct/{column_name}` |
+| `GET` | [Get related fields data (query-related-column-name)](./api/get-related-fields-data-query-related-column-name) | `/api/v1/query/related/{column_name}` |
+| `POST` | [Manually stop a query with client_id](./api/manually-stop-a-query-with-client-id) | `/api/v1/query/stop` |
+| `GET` | [Get a list of queries that changed after last_updated_ms](./api/get-a-list-of-queries-that-changed-after-last-updated-ms) | `/api/v1/query/updated_since` |
+| `DELETE` | [Bulk delete saved queries](./api/bulk-delete-saved-queries) | `/api/v1/saved_query/` |
+| `GET` | [Get a list of saved queries](./api/get-a-list-of-saved-queries) | `/api/v1/saved_query/` |
+| `POST` | [Create a saved query](./api/create-a-saved-query) | `/api/v1/saved_query/` |
+| `GET` | [Get metadata information about this API resource (saved-query--info)](./api/get-metadata-information-about-this-api-resource-saved-query-info) | `/api/v1/saved_query/_info` |
+| `DELETE` | [Delete a saved query](./api/delete-a-saved-query) | `/api/v1/saved_query/{pk}` |
+| `GET` | [Get a saved query](./api/get-a-saved-query) | `/api/v1/saved_query/{pk}` |
+| `PUT` | [Update a saved query](./api/update-a-saved-query) | `/api/v1/saved_query/{pk}` |
+| `GET` | [Get distinct values from field data (saved-query-distinct-column-name)](./api/get-distinct-values-from-field-data-saved-query-distinct-column-name) | `/api/v1/saved_query/distinct/{column_name}` |
+| `GET` | [Download multiple saved queries as YAML files](./api/download-multiple-saved-queries-as-yaml-files) | `/api/v1/saved_query/export/` |
+| `POST` | [Import saved queries with associated databases](./api/import-saved-queries-with-associated-databases) | `/api/v1/saved_query/import/` |
+| `GET` | [Get related fields data (saved-query-related-column-name)](./api/get-related-fields-data-saved-query-related-column-name) | `/api/v1/saved_query/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>Datasources</strong> (1 endpoints) — Query datasource metadata and column values.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get possible values for a datasource column](./api/get-possible-values-for-a-datasource-column) | `/api/v1/datasource/{datasource_type}/{datasource_id}/column/{column_name}/values/` |
+
+</details>
+
+<details>
+<summary><strong>Advanced Data Type</strong> (2 endpoints) — Endpoints for advanced data type operations and conversions.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Return an AdvancedDataTypeResponse](./api/return-an-advanced-data-type-response) | `/api/v1/advanced_data_type/convert` |
+| `GET` | [Return a list of available advanced data types](./api/return-a-list-of-available-advanced-data-types) | `/api/v1/advanced_data_type/types` |
+
+</details>
+
+#### Organization & Customization
+
+<details>
+<summary><strong>Tags</strong> (15 endpoints) — Organize assets with tags.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete tags](./api/bulk-delete-tags) | `/api/v1/tag/` |
+| `GET` | [Get a list of tags](./api/get-a-list-of-tags) | `/api/v1/tag/` |
+| `POST` | [Create a tag](./api/create-a-tag) | `/api/v1/tag/` |
+| `GET` | [Get metadata information about tag API endpoints](./api/get-metadata-information-about-tag-api-endpoints) | `/api/v1/tag/_info` |
+| `POST` | [Add tags to an object](./api/add-tags-to-an-object) | `/api/v1/tag/{object_type}/{object_id}/` |
+| `DELETE` | [Delete a tagged object](./api/delete-a-tagged-object) | `/api/v1/tag/{object_type}/{object_id}/{tag}/` |
+| `DELETE` | [Delete a tag](./api/delete-a-tag) | `/api/v1/tag/{pk}` |
+| `GET` | [Get a tag detail information](./api/get-a-tag-detail-information) | `/api/v1/tag/{pk}` |
+| `PUT` | [Update a tag](./api/update-a-tag) | `/api/v1/tag/{pk}` |
+| `DELETE` | [Delete tag by pk favorites](./api/delete-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
+| `POST` | [Create tag by pk favorites](./api/create-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
+| `POST` | [Bulk create tags and tagged objects](./api/bulk-create-tags-and-tagged-objects) | `/api/v1/tag/bulk_create` |
+| `GET` | [Get tag favorite status](./api/get-tag-favorite-status) | `/api/v1/tag/favorite_status/` |
+| `GET` | [Get all objects associated with a tag](./api/get-all-objects-associated-with-a-tag) | `/api/v1/tag/get_objects/` |
+| `GET` | [Get related fields data (tag-related-column-name)](./api/get-related-fields-data-tag-related-column-name) | `/api/v1/tag/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>Annotation Layers</strong> (14 endpoints) — Manage annotation layers and annotations for charts.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Delete multiple annotation layers in a bulk operation](./api/delete-multiple-annotation-layers-in-a-bulk-operation) | `/api/v1/annotation_layer/` |
+| `GET` | [Get a list of annotation layers (annotation-layer)](./api/get-a-list-of-annotation-layers-annotation-layer) | `/api/v1/annotation_layer/` |
+| `POST` | [Create an annotation layer (annotation-layer)](./api/create-an-annotation-layer-annotation-layer) | `/api/v1/annotation_layer/` |
+| `GET` | [Get metadata information about this API resource (annotation-layer--info)](./api/get-metadata-information-about-this-api-resource-annotation-layer-info) | `/api/v1/annotation_layer/_info` |
+| `DELETE` | [Delete annotation layer (annotation-layer-pk)](./api/delete-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
+| `GET` | [Get an annotation layer (annotation-layer-pk)](./api/get-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
+| `PUT` | [Update an annotation layer (annotation-layer-pk)](./api/update-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
+| `DELETE` | [Bulk delete annotation layers](./api/bulk-delete-annotation-layers) | `/api/v1/annotation_layer/{pk}/annotation/` |
+| `GET` | [Get a list of annotation layers (annotation-layer-pk-annotation)](./api/get-a-list-of-annotation-layers-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
+| `POST` | [Create an annotation layer (annotation-layer-pk-annotation)](./api/create-an-annotation-layer-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
+| `DELETE` | [Delete annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/delete-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
+| `GET` | [Get an annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/get-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
+| `PUT` | [Update an annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/update-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
+| `GET` | [Get related fields data (annotation-layer-related-column-name)](./api/get-related-fields-data-annotation-layer-related-column-name) | `/api/v1/annotation_layer/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>CSS Templates</strong> (8 endpoints) — Manage CSS templates for custom dashboard styling.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete CSS templates](./api/bulk-delete-css-templates) | `/api/v1/css_template/` |
+| `GET` | [Get a list of CSS templates](./api/get-a-list-of-css-templates) | `/api/v1/css_template/` |
+| `POST` | [Create a CSS template](./api/create-a-css-template) | `/api/v1/css_template/` |
+| `GET` | [Get metadata information about this API resource (css-template--info)](./api/get-metadata-information-about-this-api-resource-css-template-info) | `/api/v1/css_template/_info` |
+| `DELETE` | [Delete a CSS template](./api/delete-a-css-template) | `/api/v1/css_template/{pk}` |
+| `GET` | [Get a CSS template](./api/get-a-css-template) | `/api/v1/css_template/{pk}` |
+| `PUT` | [Update a CSS template](./api/update-a-css-template) | `/api/v1/css_template/{pk}` |
+| `GET` | [Get related fields data (css-template-related-column-name)](./api/get-related-fields-data-css-template-related-column-name) | `/api/v1/css_template/related/{column_name}` |

Review Comment:
   <!-- Bito Reply -->
   Your explanation aligns with the PR changes: the links in `docs/docs/api.mdx` use `./api/${slug}` format, and Docusaurus resolves them filesystem-relative from `docs/api.mdx` to the generated `.api.mdx` files in `docs/api/`. The full build confirming no broken links supports this as a false positive.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734728472


##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.

Review Comment:
   **Update (577ae18):** Further investigation revealed that the `./schemas` link was broken because no landing page exists for the Schemas category (it's just a sidebar grouping). Removed the link entirely — the Alert now says "The sidebar includes **Schema definitions**" instead.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2733482743


##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
+  }
+  style={{ marginBottom: '24px' }}
+/>
+
+---
+
+`;
+
+  // Track which tags we've rendered
+  const renderedTags = new Set();
+
+  // Render Authentication first (it's critical for using the API)
+  mdx += `### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+\`\`\`bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \\
+  -H "Content-Type: application/json" \\
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
+  http://localhost:8088/api/v1/dashboard/
+\`\`\`
+
+#### Security Endpoints
+
+`;
+
+  // Render Security tag endpoints
+  if (tagEndpoints['Security']) {
+    mdx += `| Method | Endpoint | Description |\n`;
+    mdx += `|--------|----------|-------------|\n`;
+    for (const ep of tagEndpoints['Security']) {
+      mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;
+    }
+    mdx += '\n';
+    renderedTags.add('Security');
+  }
+
+  mdx += `---\n\n### API Endpoints\n\n`;
+
+  // Render each category group
+  for (const [groupName, groupTags] of Object.entries(CATEGORY_GROUPS)) {
+    if (groupName === 'Authentication') continue; // Already rendered
+
+    const tagsInGroup = groupTags.filter(tag => tagEndpoints[tag] && !renderedTags.has(tag));
+    if (tagsInGroup.length === 0) continue;
+
+    mdx += `#### ${groupName}\n\n`;
+
+    for (const tag of tagsInGroup) {
+      const description = tagDescriptions[tag] || '';
+      const endpoints = tagEndpoints[tag];
+
+      mdx += `<details>\n`;
+      mdx += `<summary><strong>${tag}</strong> (${endpoints.length} endpoints) — ${description}</summary>\n\n`;
+      mdx += `| Method | Endpoint | Description |\n`;
+      mdx += `|--------|----------|-------------|\n`;
+
+      for (const ep of endpoints) {
+        mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;
+      }
+
+      mdx += `\n</details>\n\n`;
+      renderedTags.add(tag);
+    }
+  }
+
+  // Render any remaining tags not in a group
+  const remainingTags = Object.keys(tagEndpoints).filter(tag => !renderedTags.has(tag));
+  if (remainingTags.length > 0) {
+    mdx += `#### Other\n\n`;
+
+    for (const tag of remainingTags.sort()) {
+      const description = tagDescriptions[tag] || '';
+      const endpoints = tagEndpoints[tag];
+
+      mdx += `<details>\n`;
+      mdx += `<summary><strong>${tag}</strong> (${endpoints.length} endpoints) — ${description}</summary>\n\n`;
+      mdx += `| Method | Endpoint | Description |\n`;
+      mdx += `|--------|----------|-------------|\n`;
+
+      for (const ep of endpoints) {
+        mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;

Review Comment:
   Valid — fixed in 1c8a520. Same fix applied to all link templates: `./api/${ep.slug}` → `./${ep.slug}`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2733483995


##########
docs/yarn.lock:
##########
@@ -8250,16 +8669,24 @@ infima@0.2.0-alpha.45:
   resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.45.tgz#542aab5a249274d81679631b492973dd2c1e7466"
   integrity sha512-uyH0zfr1erU1OohLk0fT4Rrb94AOhguWNOcD9uGrSpRvNB+6gZXUoJX5J0NtvzBO10YZ9PgvA4NFgt+fYg8ojw==
 
-inherits@2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
-  integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"

Review Comment:
   This is a transitive dependency pulled in by the npm package ecosystem — not something we directly control. The `inflight` package is a deep transitive dep of `docusaurus-plugin-openapi-docs`. This would need to be addressed upstream.



##########
docs/yarn.lock:
##########
@@ -14089,6 +15026,14 @@ whatwg-fetch@^3.6.20:
   resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
   integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==
 
+whatwg-url@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+  integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
+  dependencies:
+    tr46 "~0.0.3"
+    webidl-conversions "^3.0.0"
+

Review Comment:
   The yarn.lock was not manually edited. It was regenerated by running `yarn install` after adding `docusaurus-plugin-openapi-docs` and `docusaurus-theme-openapi-docs` to `package.json`. The new entries are the expected transitive dependencies of these packages.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2733488511


##########
docs/yarn.lock:
##########
@@ -8250,16 +8669,24 @@ infima@0.2.0-alpha.45:
   resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.45.tgz#542aab5a249274d81679631b492973dd2c1e7466"
   integrity sha512-uyH0zfr1erU1OohLk0fT4Rrb94AOhguWNOcD9uGrSpRvNB+6gZXUoJX5J0NtvzBO10YZ9PgvA4NFgt+fYg8ojw==
 
-inherits@2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
-  integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"

Review Comment:
   <!-- Bito Reply -->
   This question isn’t related to the pull request. I can only help with questions about the PR’s code or comments.



##########
docs/yarn.lock:
##########
@@ -14089,6 +15026,14 @@ whatwg-fetch@^3.6.20:
   resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
   integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==
 
+whatwg-url@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+  integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
+  dependencies:
+    tr46 "~0.0.3"
+    webidl-conversions "^3.0.0"
+

Review Comment:
   <!-- Bito Reply -->
   Your explanation aligns with the PR changes: package.json was updated to include 'docusaurus-plugin-openapi-docs' and 'docusaurus-theme-openapi-docs', and yarn.lock was regenerated accordingly with their transitive dependencies.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on PR #37434:
URL: https://github.com/apache/superset/pull/37434#issuecomment-3808187501

   AI Code Review is in progress (usually takes 3 to 15 minutes unless it's a very large PR).
   
   <details>
   <summary>
   Bito Usage Guide
   </summary>
   
   **Commands**
         
   Type the following command in the pull request comment and save the comment.
         
   - `/review` - Manually triggers a full AI review.
   
   - `/pause` - Pauses automatic reviews on this pull request.
   - `/resume` - Resumes automatic reviews.
   - `/resolve` - Marks all Bito-posted review comments as resolved.
   - `/abort` - Cancels all in-progress reviews.
   
         
   Refer to the <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/available-commands" target="_blank" rel="noopener noreferrer">documentation</a> for additional commands.
         
   **Configuration**
   
   This repository uses `Superset` You can customize the agent settings <a href="https://alpha.bito.ai/home/ai-agents/code-review-agent" target="_blank" rel="noopener noreferrer">here</a> or contact your Bito workspace admin at evan@preset.io.
         
   **Documentation & Help**
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/getting-started/install-run-using-bito-cloud/create-or-customize-an-agent-instance" target="_blank" rel="noopener noreferrer">Customize agent settings</a>
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/implementing-custom-code-review-rules" target="_blank" rel="noopener noreferrer">Review rules</a>
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent" target="_blank" rel="noopener noreferrer">General documentation</a>
   - <a href="https://docs.bito.ai/bito-dev-agents/ai-code-review-agent/faqs" target="_blank" rel="noopener noreferrer">FAQ</a>
   
   </details>
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "codeant-ai-for-open-source[bot] (via GitHub)" <gi...@apache.org>.
codeant-ai-for-open-source[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2729749543


##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
+  }
+  style={{ marginBottom: '24px' }}
+/>
+
+---
+
+`;
+
+  // Track which tags we've rendered
+  const renderedTags = new Set();
+
+  // Render Authentication first (it's critical for using the API)
+  mdx += `### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+\`\`\`bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \\
+  -H "Content-Type: application/json" \\
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
+  http://localhost:8088/api/v1/dashboard/
+\`\`\`
+
+#### Security Endpoints
+
+`;
+
+  // Render Security tag endpoints
+  if (tagEndpoints['Security']) {
+    mdx += `| Method | Endpoint | Description |\n`;
+    mdx += `|--------|----------|-------------|\n`;
+    for (const ep of tagEndpoints['Security']) {
+      mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;
+    }
+    mdx += '\n';
+    renderedTags.add('Security');
+  }
+
+  mdx += `---\n\n### API Endpoints\n\n`;
+
+  // Render each category group
+  for (const [groupName, groupTags] of Object.entries(CATEGORY_GROUPS)) {
+    if (groupName === 'Authentication') continue; // Already rendered
+
+    const tagsInGroup = groupTags.filter(tag => tagEndpoints[tag] && !renderedTags.has(tag));
+    if (tagsInGroup.length === 0) continue;
+
+    mdx += `#### ${groupName}\n\n`;
+
+    for (const tag of tagsInGroup) {
+      const description = tagDescriptions[tag] || '';
+      const endpoints = tagEndpoints[tag];
+
+      mdx += `<details>\n`;
+      mdx += `<summary><strong>${tag}</strong> (${endpoints.length} endpoints) — ${description}</summary>\n\n`;
+      mdx += `| Method | Endpoint | Description |\n`;
+      mdx += `|--------|----------|-------------|\n`;
+
+      for (const ep of endpoints) {
+        mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;
+      }
+
+      mdx += `\n</details>\n\n`;
+      renderedTags.add(tag);
+    }
+  }
+
+  // Render any remaining tags not in a group
+  const remainingTags = Object.keys(tagEndpoints).filter(tag => !renderedTags.has(tag));
+  if (remainingTags.length > 0) {
+    mdx += `#### Other\n\n`;
+
+    for (const tag of remainingTags.sort()) {
+      const description = tagDescriptions[tag] || '';
+      const endpoints = tagEndpoints[tag];
+
+      mdx += `<details>\n`;
+      mdx += `<summary><strong>${tag}</strong> (${endpoints.length} endpoints) — ${description}</summary>\n\n`;
+      mdx += `| Method | Endpoint | Description |\n`;
+      mdx += `|--------|----------|-------------|\n`;
+
+      for (const ep of endpoints) {
+        mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;

Review Comment:
   **Suggestion:** In the "Other" tag section, endpoint links again use `./api/${ep.slug}` from the `/docs/api` page, which incorrectly resolves to `/docs/api/api/<slug>` and breaks all links for uncategorized tags. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ \"Other\" section links 404 on the API index page.
   - ⚠️ Unlabeled endpoints unreachable from index.
   - ⚠️ Search/navigation burden increased for users.
   ```
   </details>
   
   ```suggestion
           mdx += `| \`${ep.method}\` | [${ep.summary}](./${ep.slug}) | \`${ep.path}\` |\n`;
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Run docs/scripts/generate-api-index.mjs which produces the "Other" tag section using
   the loop at docs/scripts/generate-api-index.mjs:204-223; the per-endpoint link template is
   at lines 217-219.
   
   2. Serve the site (yarn start) and open /docs/api/; scroll to the "Other" section
   generated from the remaining tags.
   
   3. Click any endpoint link in that "Other" section. The link target uses "./api/<slug>"
   (from the generator at docs/scripts/generate-api-index.mjs:219) and resolves to
   /docs/api/api/<slug> instead of /docs/api/<slug>, leading to missing pages.
   
   4. Inspecting api.mdx confirms the duplicated "api" segment was produced by the template;
   switching to "./${ep.slug}" (improved code) produces correct links.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** docs/scripts/generate-api-index.mjs
   **Line:** 218:218
   **Comment:**
   	*Logic Error: In the "Other" tag section, endpoint links again use `./api/${ep.slug}` from the `/docs/api` page, which incorrectly resolves to `/docs/api/api/<slug>` and breaks all links for uncategorized tags.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
docs/src/styles/custom.css:
##########
@@ -187,3 +187,81 @@ ul.dropdown__menu svg {
 [data-theme='dark'] .ant-collapse-header {
   color: var(--ifm-font-base-color);
 }
+
+/* Hide the non-functional "Send API Request" button and Response block in API docs */
+/* The interactive API testing doesn't work due to CORS restrictions */
+.openapi-explorer__request-btn {
+  display: none !important;
+}
+
+.openapi-explorer__response-container {
+  display: none !important;

Review Comment:
   **Suggestion:** Hiding `.openapi-explorer__response-container` with `display: none !important` will completely remove the API "Response" block from all endpoint pages, which likely includes the documented response status codes and schemas that the new API reference is supposed to expose, so users won't see response information at all; keeping the button hidden is fine, but the response container itself should remain visible. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ API response schemas hidden on all endpoint pages.
   - ❌ Response status codes invisible to documentation readers.
   - ⚠️ Developer portal `/docs/api/` user experience degraded.
   - ⚠️ Documentation testers cannot see examples inline.
   ```
   </details>
   
   ```suggestion
     /* Keep the response container visible so response status codes and schemas remain documented.
        Interactive "Send request" behavior is disabled separately via the request button rule. */
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Build and run the docs site locally (as described in PR): run `cd docs && yarn install
   && yarn start`.
   
   2. Open the API reference landing page at `/docs/api/` in the running dev server.
   
   3. Navigate to any endpoint page (e.g., click an endpoint entry on the landing page).
   
   4. Inspect the endpoint page DOM in the browser devtools and find the element with class
   `openapi-explorer__response-container` (the docusaurus-openapi-docs response block).
   
   5. Observe that because `docs/src/styles/custom.css` contains the rule at lines 197-199,
   the response container element has `display: none !important` and is hidden — response
   status codes and example schemas are not visible.
   
   6. Confirm behavior is global by testing multiple endpoints: the same CSS rule in
   `docs/src/styles/custom.css:197-199` hides responses site-wide.
   
   Note: Hiding the request button is appropriate for CORS reasons
   (`.openapi-explorer__request-btn` at lines 193-195), but the separate response container
   rule at 197-199 removes documented response information entirely.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** docs/src/styles/custom.css
   **Line:** 198:198
   **Comment:**
   	*Logic Error: Hiding `.openapi-explorer__response-container` with `display: none !important` will completely remove the API "Response" block from all endpoint pages, which likely includes the documented response status codes and schemas that the new API reference is supposed to expose, so users won't see response information at all; keeping the button hidden is fine, but the response container itself should remain visible.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
+  }
+  style={{ marginBottom: '24px' }}
+/>
+
+---
+
+`;
+
+  // Track which tags we've rendered
+  const renderedTags = new Set();
+
+  // Render Authentication first (it's critical for using the API)
+  mdx += `### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+\`\`\`bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \\
+  -H "Content-Type: application/json" \\
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
+  http://localhost:8088/api/v1/dashboard/
+\`\`\`
+
+#### Security Endpoints
+
+`;
+
+  // Render Security tag endpoints
+  if (tagEndpoints['Security']) {
+    mdx += `| Method | Endpoint | Description |\n`;
+    mdx += `|--------|----------|-------------|\n`;
+    for (const ep of tagEndpoints['Security']) {
+      mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;
+    }
+    mdx += '\n';
+    renderedTags.add('Security');
+  }
+
+  mdx += `---\n\n### API Endpoints\n\n`;
+
+  // Render each category group
+  for (const [groupName, groupTags] of Object.entries(CATEGORY_GROUPS)) {
+    if (groupName === 'Authentication') continue; // Already rendered
+
+    const tagsInGroup = groupTags.filter(tag => tagEndpoints[tag] && !renderedTags.has(tag));
+    if (tagsInGroup.length === 0) continue;
+
+    mdx += `#### ${groupName}\n\n`;
+
+    for (const tag of tagsInGroup) {
+      const description = tagDescriptions[tag] || '';
+      const endpoints = tagEndpoints[tag];
+
+      mdx += `<details>\n`;
+      mdx += `<summary><strong>${tag}</strong> (${endpoints.length} endpoints) — ${description}</summary>\n\n`;
+      mdx += `| Method | Endpoint | Description |\n`;
+      mdx += `|--------|----------|-------------|\n`;
+
+      for (const ep of endpoints) {
+        mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;

Review Comment:
   **Suggestion:** In the grouped category sections, endpoint links are built as `./api/${ep.slug}` from the `/docs/api` page, which resolves to `/docs/api/api/<slug>` and thus does not match the actual OpenAPI-generated routes under `/docs/api/<slug>`. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Category endpoint links broken on API index page.
   - ⚠️ Users cannot open endpoint docs from categories.
   - ⚠️ Documentation navigation is confusing.
   ```
   </details>
   
   ```suggestion
           mdx += `| \`${ep.method}\` | [${ep.summary}](./${ep.slug}) | \`${ep.path}\` |\n`;
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Execute docs/scripts/generate-api-index.mjs to produce docs/docs/api.mdx (script writes
   output at docs/scripts/generate-api-index.mjs:234-235). The category sections use the loop
   at docs/scripts/generate-api-index.mjs:176-201 and produce per-endpoint links using the
   template at lines 194-196.
   
   2. Serve docs (yarn start) and navigate to /docs/api/ where the category tables are
   displayed.
   
   3. Click any endpoint link inside a grouped category. The anchor generated from the
   template is "./api/<slug>" (docs/scripts/generate-api-index.mjs:196) which resolves to
   /docs/api/api/<slug>, not /docs/api/<slug>, causing the link to fail to reach the
   OpenAPI-generated page.
   
   4. Verify by inspecting the generated MDX (api.mdx) or browser link target; fix by
   changing the template to "./${ep.slug}" as in the improved code.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** docs/scripts/generate-api-index.mjs
   **Line:** 195:195
   **Comment:**
   	*Logic Error: In the grouped category sections, endpoint links are built as `./api/${ep.slug}` from the `/docs/api` page, which resolves to `/docs/api/api/<slug>` and thus does not match the actual OpenAPI-generated routes under `/docs/api/<slug>`.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
docs/sidebars.js:
##########
@@ -107,9 +107,14 @@ const sidebars = {
       id: 'faq',
     },
     {
-      type: 'doc',
-      label: 'API',
-      id: 'api',
+      type: 'category',
+      label: 'API Reference',
+      link: {
+        type: 'doc',
+        id: 'api',
+      },
+      // eslint-disable-next-line @typescript-eslint/no-require-imports
+      items: require('./docs/api/sidebar.js'),

Review Comment:
   **Suggestion:** The sidebar now unconditionally requires a generated file `./docs/api/sidebar.js`; on a fresh clone or whenever `yarn generate:api-docs` hasn't been run yet, this file does not exist, so loading `sidebars.js` (and thus running Docusaurus commands directly) will throw a "Cannot find module './docs/api/sidebar.js'" error and break the docs build; wrapping the require with a try/catch and falling back to an empty array makes the configuration robust while still using the generated sidebar when available. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Local docs dev server fails to start.
   - ❌ CI docs build fails on fresh clones.
   - ⚠️ New contributors blocked running docs locally.
   - ⚠️ Release docs automation may break without generation.
   ```
   </details>
   
   ```suggestion
           items: (() => {
             try {
               // Generated by `yarn generate:api-docs`
               return require('./docs/api/sidebar.js');
             } catch (error) {
               // Fallback when API sidebar has not been generated yet
               return [];
             }
           })(),
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Clone the repository and do not run the API generation step (skip `yarn
   generate:api-docs`), so `docs/api/sidebar.js` is absent.
   
   2. From the repository root run the docs dev server in the docs directory: `cd docs &&
   yarn start`. Docusaurus loads `docs/sidebars.js` during startup.
   
   3. `docs/sidebars.js` (file path: `docs/sidebars.js`, lines 107-118) executes the line
   `items: require('./docs/api/sidebar.js')` and Node attempts to resolve
   `./docs/api/sidebar.js`.
   
   4. Because `./docs/api/sidebar.js` does not exist, Node throws "Cannot find module
   './docs/api/sidebar.js'" and the Docusaurus build/dev server fails to start — observable
   as a startup error in the terminal where `yarn start` was run.
   
   5. Repeating in CI: any CI job that runs docs build without first generating the API docs
   will reproduce the same failure during the docs build step (the exact failing location is
   `docs/sidebars.js:107-118` as shown above).
   
   Note: This is not hypothetical — the PR introduced an unconditional require for a
   generated file (`./docs/api/sidebar.js`) in `docs/sidebars.js` (lines 107-118), so a fresh
   clone or skipped generation step will trigger this error.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** docs/sidebars.js
   **Line:** 115:117
   **Comment:**
   	*Possible Bug: The sidebar now unconditionally requires a generated file `./docs/api/sidebar.js`; on a fresh clone or whenever `yarn generate:api-docs` hasn't been run yet, this file does not exist, so loading `sidebars.js` (and thus running Docusaurus commands directly) will throw a "Cannot find module './docs/api/sidebar.js'" error and break the docs build; wrapping the require with a try/catch and falling back to an empty array makes the configuration robust while still using the generated sidebar when available.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
docs/docusaurus.config.ts:
##########
@@ -189,6 +195,29 @@ const config: Config = {
       },
     ],
     ...dynamicPlugins,
+    [
+      'docusaurus-plugin-openapi-docs',
+      {
+        id: 'api',
+        docsPluginId: 'classic',

Review Comment:
   **Suggestion:** The OpenAPI docs plugin is configured to attach to a docs plugin with id `classic`, but in this configuration the main docs plugin created by the `@docusaurus/preset-classic` preset has no explicit `id` and therefore uses the default id (`default`), so the OpenAPI plugin will not find the expected docs instance and `docusaurus gen-api-docs superset`/builds can fail with "docs plugin not found" errors. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ API docs generation fails during docs build.
   - ⚠️ Contributor local docs workflow blocked.
   - ⚠️ CI docs build may fail for PRs touching docs.
   - ❌ /docs/api pages won't be produced.
   ```
   </details>
   
   ```suggestion
           docsPluginId: 'default',
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open the Docusaurus site config at docs/docusaurus.config.ts and locate the preset docs
   block starting at `presets` around `docs/docusaurus.config.ts:372` where the preset
   classic's docs options are defined (see `docs: { sidebarPath:
   require.resolve('./sidebars.js'), ... }` at ~line 374). This preset registers the docs
   plugin without an explicit id (so it uses the default id `default`).
   
   2. Inspect the OpenAPI plugin configuration at `docs/docusaurus.config.ts:199-219` where
   the plugin is registered. The plugin is configured with `docsPluginId: 'classic'` (exact
   line: `docs/docusaurus.config.ts:202`).
   
   3. Run the docs build or generation step (e.g., from repository root: `cd docs && yarn
   start` or `yarn build`). During startup Docusaurus initializes plugins; the openapi plugin
   will attempt to look up the docs plugin instance by id `'classic'`.
   
   4. Because the preset-registered docs plugin has no id (it is the default `default`), the
   openapi plugin cannot find a docs instance named `'classic'` and the generation step
   errors with messages such as "docs plugin not found" or "Cannot find docs plugin with id
   'classic'". This prevents API docs from being generated and the site build from
   completing.
   
   Note: I verified the two locations above in the final file: the preset docs block (no
   explicit id) at the presets section (~line 372-380) and the openapi plugin config
   containing `docsPluginId: 'classic'` at line 202 in `docs/docusaurus.config.ts`.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** docs/docusaurus.config.ts
   **Line:** 202:202
   **Comment:**
   	*Logic Error: The OpenAPI docs plugin is configured to attach to a docs plugin with id `classic`, but in this configuration the main docs plugin created by the `@docusaurus/preset-classic` preset has no explicit `id` and therefore uses the default id (`default`), so the OpenAPI plugin will not find the expected docs instance and `docusaurus gen-api-docs superset`/builds can fail with "docs plugin not found" errors.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
+  }
+  style={{ marginBottom: '24px' }}
+/>
+
+---
+
+`;
+
+  // Track which tags we've rendered
+  const renderedTags = new Set();
+
+  // Render Authentication first (it's critical for using the API)
+  mdx += `### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+\`\`\`bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \\
+  -H "Content-Type: application/json" \\
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
+  http://localhost:8088/api/v1/dashboard/
+\`\`\`
+
+#### Security Endpoints
+
+`;
+
+  // Render Security tag endpoints
+  if (tagEndpoints['Security']) {
+    mdx += `| Method | Endpoint | Description |\n`;
+    mdx += `|--------|----------|-------------|\n`;
+    for (const ep of tagEndpoints['Security']) {
+      mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;

Review Comment:
   **Suggestion:** In the "Security Endpoints" table, each endpoint link uses `./api/${ep.slug}` from the `/docs/api` page, which resolves to `/docs/api/api/<slug>` instead of `/docs/api/<slug>`, so all Security endpoint links will be broken. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Security endpoint links 404 on /docs/api.
   - ⚠️ Readers cannot access Security API docs easily.
   - ⚠️ Navigation inconsistency in generated API index.
   ```
   </details>
   
   ```suggestion
         mdx += `| \`${ep.method}\` | [${ep.summary}](./${ep.slug}) | \`${ep.path}\` |\n`;
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Run the generator: node docs/scripts/generate-api-index.mjs (entry at
   docs/scripts/generate-api-index.mjs:238-240). The generator builds the Security endpoints
   table using the loop at docs/scripts/generate-api-index.mjs:167-169.
   
   2. Start the docs site (yarn start) and open /docs/api/ in the browser (the generated MDX
   includes the table rendered from the code above).
   
   3. Click any Security endpoint link in the "Security Endpoints" table. The rendered anchor
   href is "./api/<slug>" (produced at docs/scripts/generate-api-index.mjs:169), which
   resolves from /docs/api/ to /docs/api/api/<slug>, producing a 404 because the actual
   endpoint pages are served at /docs/api/<slug>.
   
   4. Confirm the incorrect path is produced by the exact template string in the file at
   lines 167-169; updating the template to "./${ep.slug}" removes the duplicated "api"
   segment and fixes links.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** docs/scripts/generate-api-index.mjs
   **Line:** 168:168
   **Comment:**
   	*Logic Error: In the "Security Endpoints" table, each endpoint link uses `./api/${ep.slug}` from the `/docs/api` page, which resolves to `/docs/api/api/<slug>` instead of `/docs/api/<slug>`, so all Security endpoint links will be broken.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.

Review Comment:
   **Suggestion:** The schema documentation link inside the `<Alert>` component uses `./api/schemas` as a relative URL, which from the `/docs/api` page resolves to `/docs/api/api/schemas` instead of the intended `/docs/api/schemas`, causing the "Schema definitions" link to be broken. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Schema definitions link broken on /docs/api landing page.
   - ⚠️ Users cannot navigate to schema docs from API index.
   - ⚠️ Developer docs quality degraded for API consumers.
   ```
   </details>
   
   ```suggestion
         Browse the <a href="./schemas">Schema definitions</a> for detailed data model documentation.
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Run the generator and build docs: node docs/scripts/generate-api-index.mjs will write
   docs/docs/api.mdx (script file: docs/scripts/generate-api-index.mjs: lines 67-75, 234-236
   show entry and write). The file contains the Alert block at
   docs/scripts/generate-api-index.mjs:114-132 which produces the hyperlink <a
   href="./api/schemas">.
   
   2. Start Docusaurus dev server from the docs/ directory (yarn start). Open the generated
   API landing page served at path /docs/api/ (this is the page that corresponds to the
   generated api.mdx).
   
   3. From browser on URL /docs/api/ the anchor with href="./api/schemas" resolves to
   /docs/api/api/schemas (relative resolution: current path + ./api/schemas) instead of the
   intended /docs/api/schemas. Confirm the resulting URL returns 404 or does not load the
   schemas page.
   
   4. Observe broken link behavior tied directly to the literal href produced by the code in
   docs/scripts/generate-api-index.mjs at lines 114-132. Changing the href to "./schemas"
   (improved code) generates a link that resolves to /docs/api/schemas as intended.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** docs/scripts/generate-api-index.mjs
   **Line:** 121:128
   **Comment:**
   	*Logic Error: The schema documentation link inside the `<Alert>` component uses `./api/schemas` as a relative URL, which from the `/docs/api` page resolves to `/docs/api/api/schemas` instead of the intended `/docs/api/schemas`, causing the "Schema definitions" link to be broken.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734627201


##########
docs/docs/api.mdx:
##########
@@ -1,40 +1,590 @@
 ---
-title: API
+title: API Reference
 hide_title: true
 sidebar_position: 10
 ---
 
-import SwaggerUI from 'swagger-ui-react';
-import openapi from '/resources/openapi.json';
-import 'swagger-ui-react/swagger-ui.css';
 import { Alert } from 'antd';
 
-## API
+## REST API Reference
 
-Superset's public **REST API** follows the
-[OpenAPI specification](https://swagger.io/specification/), and is
-documented here. The docs below are generated using
-[Swagger React UI](https://www.npmjs.com/package/swagger-ui-react).
-
-:::resources
-- [Blog: The Superset REST API](https://preset.io/blog/2020-10-01-superset-api/)
-- [Blog: Accessing APIs with Superset](https://preset.io/blog/accessing-apis-with-superset/)
-:::
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
 
 <Alert
   type="info"
-  message={
-    <div>
-      <strong>NOTE! </strong>
-      You can find an interactive version of this documentation on your local Superset
-      instance at <strong>/swagger/v1</strong> (unless disabled)
-    </div>
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      The sidebar includes <strong>Schema definitions</strong> for detailed data model documentation.
+    </span>
   }
+  style={{ marginBottom: '24px' }}
 />
 
-<br />
-<br />
-<hr />
-<div className="swagger-container">
-  <SwaggerUI spec={openapi} />
-</div>
+---
+
+### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+```bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \
+  -H "Content-Type: application/json" \
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
+  http://localhost:8088/api/v1/dashboard/
+```
+
+#### Security Endpoints
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get the CSRF token](./api/get-the-csrf-token) | `/api/v1/security/csrf_token/` |
+| `POST` | [Get a guest token](./api/get-a-guest-token) | `/api/v1/security/guest_token/` |
+| `POST` | [Create security login](./api/create-security-login) | `/api/v1/security/login` |
+| `POST` | [Create security refresh](./api/create-security-refresh) | `/api/v1/security/refresh` |
+
+---
+
+### API Endpoints
+
+#### Core Resources
+
+<details>
+<summary><strong>Dashboards</strong> (26 endpoints) — Create, read, update, and delete dashboards.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete dashboards](./api/bulk-delete-dashboards) | `/api/v1/dashboard/` |
+| `GET` | [Get a list of dashboards](./api/get-a-list-of-dashboards) | `/api/v1/dashboard/` |
+| `POST` | [Create a new dashboard](./api/create-a-new-dashboard) | `/api/v1/dashboard/` |
+| `GET` | [Get metadata information about this API resource (dashboard--info)](./api/get-metadata-information-about-this-api-resource-dashboard-info) | `/api/v1/dashboard/_info` |
+| `GET` | [Get a dashboard detail information](./api/get-a-dashboard-detail-information) | `/api/v1/dashboard/{id_or_slug}` |
+| `GET` | [Get a dashboard's chart definitions.](./api/get-a-dashboards-chart-definitions) | `/api/v1/dashboard/{id_or_slug}/charts` |
+| `POST` | [Create a copy of an existing dashboard](./api/create-a-copy-of-an-existing-dashboard) | `/api/v1/dashboard/{id_or_slug}/copy/` |
+| `GET` | [Get dashboard's datasets](./api/get-dashboards-datasets) | `/api/v1/dashboard/{id_or_slug}/datasets` |
+| `DELETE` | [Delete a dashboard's embedded configuration](./api/delete-a-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `GET` | [Get the dashboard's embedded configuration](./api/get-the-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `POST` | [Set a dashboard's embedded configuration](./api/set-a-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `PUT` | [Update dashboard by id_or_slug embedded](./api/update-dashboard-by-id-or-slug-embedded) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `GET` | [Get dashboard's tabs](./api/get-dashboards-tabs) | `/api/v1/dashboard/{id_or_slug}/tabs` |
+| `DELETE` | [Delete a dashboard](./api/delete-a-dashboard) | `/api/v1/dashboard/{pk}` |
+| `PUT` | [Update a dashboard](./api/update-a-dashboard) | `/api/v1/dashboard/{pk}` |
+| `POST` | [Compute and cache a screenshot (dashboard-pk-cache-dashboard-screenshot)](./api/compute-and-cache-a-screenshot-dashboard-pk-cache-dashboard-screenshot) | `/api/v1/dashboard/{pk}/cache_dashboard_screenshot/` |
+| `PUT` | [Update colors configuration for a dashboard.](./api/update-colors-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/colors` |
+| `DELETE` | [Remove the dashboard from the user favorite list](./api/remove-the-dashboard-from-the-user-favorite-list) | `/api/v1/dashboard/{pk}/favorites/` |
+| `POST` | [Mark the dashboard as favorite for the current user](./api/mark-the-dashboard-as-favorite-for-the-current-user) | `/api/v1/dashboard/{pk}/favorites/` |
+| `PUT` | [Update native filters configuration for a dashboard.](./api/update-native-filters-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/filters` |
+| `GET` | [Get a computed screenshot from cache (dashboard-pk-screenshot-digest)](./api/get-a-computed-screenshot-from-cache-dashboard-pk-screenshot-digest) | `/api/v1/dashboard/{pk}/screenshot/{digest}/` |
+| `GET` | [Get dashboard's thumbnail](./api/get-dashboards-thumbnail) | `/api/v1/dashboard/{pk}/thumbnail/{digest}/` |
+| `GET` | [Download multiple dashboards as YAML files](./api/download-multiple-dashboards-as-yaml-files) | `/api/v1/dashboard/export/` |
+| `GET` | [Check favorited dashboards for current user](./api/check-favorited-dashboards-for-current-user) | `/api/v1/dashboard/favorite_status/` |
+| `POST` | [Import dashboard(s) with associated charts/datasets/databases](./api/import-dashboard-s-with-associated-charts-datasets-databases) | `/api/v1/dashboard/import/` |
+| `GET` | [Get related fields data (dashboard-related-column-name)](./api/get-related-fields-data-dashboard-related-column-name) | `/api/v1/dashboard/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>Charts</strong> (20 endpoints) — Create, read, update, and delete charts (slices).</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete charts](./api/bulk-delete-charts) | `/api/v1/chart/` |
+| `GET` | [Get a list of charts](./api/get-a-list-of-charts) | `/api/v1/chart/` |
+| `POST` | [Create a new chart](./api/create-a-new-chart) | `/api/v1/chart/` |
+| `GET` | [Get metadata information about this API resource (chart--info)](./api/get-metadata-information-about-this-api-resource-chart-info) | `/api/v1/chart/_info` |
+| `DELETE` | [Delete a chart](./api/delete-a-chart) | `/api/v1/chart/{pk}` |
+| `GET` | [Get a chart detail information](./api/get-a-chart-detail-information) | `/api/v1/chart/{pk}` |
+| `PUT` | [Update a chart](./api/update-a-chart) | `/api/v1/chart/{pk}` |
+| `GET` | [Compute and cache a screenshot (chart-pk-cache-screenshot)](./api/compute-and-cache-a-screenshot-chart-pk-cache-screenshot) | `/api/v1/chart/{pk}/cache_screenshot/` |
+| `GET` | [Return payload data response for a chart](./api/return-payload-data-response-for-a-chart) | `/api/v1/chart/{pk}/data/` |
+| `DELETE` | [Remove the chart from the user favorite list](./api/remove-the-chart-from-the-user-favorite-list) | `/api/v1/chart/{pk}/favorites/` |
+| `POST` | [Mark the chart as favorite for the current user](./api/mark-the-chart-as-favorite-for-the-current-user) | `/api/v1/chart/{pk}/favorites/` |
+| `GET` | [Get a computed screenshot from cache (chart-pk-screenshot-digest)](./api/get-a-computed-screenshot-from-cache-chart-pk-screenshot-digest) | `/api/v1/chart/{pk}/screenshot/{digest}/` |
+| `GET` | [Get chart thumbnail](./api/get-chart-thumbnail) | `/api/v1/chart/{pk}/thumbnail/{digest}/` |
+| `POST` | [Return payload data response for the given query (chart-data)](./api/return-payload-data-response-for-the-given-query-chart-data) | `/api/v1/chart/data` |
+| `GET` | [Return payload data response for the given query (chart-data-cache-key)](./api/return-payload-data-response-for-the-given-query-chart-data-cache-key) | `/api/v1/chart/data/{cache_key}` |
+| `GET` | [Download multiple charts as YAML files](./api/download-multiple-charts-as-yaml-files) | `/api/v1/chart/export/` |
+| `GET` | [Check favorited charts for current user](./api/check-favorited-charts-for-current-user) | `/api/v1/chart/favorite_status/` |
+| `POST` | [Import chart(s) with associated datasets and databases](./api/import-chart-s-with-associated-datasets-and-databases) | `/api/v1/chart/import/` |
+| `GET` | [Get related fields data (chart-related-column-name)](./api/get-related-fields-data-chart-related-column-name) | `/api/v1/chart/related/{column_name}` |
+| `PUT` | [Warm up the cache for the chart](./api/warm-up-the-cache-for-the-chart) | `/api/v1/chart/warm_up_cache` |
+
+</details>
+
+<details>
+<summary><strong>Datasets</strong> (18 endpoints) — Manage datasets (tables) used for building charts.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete datasets](./api/bulk-delete-datasets) | `/api/v1/dataset/` |
+| `GET` | [Get a list of datasets](./api/get-a-list-of-datasets) | `/api/v1/dataset/` |
+| `POST` | [Create a new dataset](./api/create-a-new-dataset) | `/api/v1/dataset/` |
+| `GET` | [Get metadata information about this API resource (dataset--info)](./api/get-metadata-information-about-this-api-resource-dataset-info) | `/api/v1/dataset/_info` |
+| `DELETE` | [Delete a dataset](./api/delete-a-dataset) | `/api/v1/dataset/{pk}` |
+| `GET` | [Get a dataset](./api/get-a-dataset) | `/api/v1/dataset/{pk}` |
+| `PUT` | [Update a dataset](./api/update-a-dataset) | `/api/v1/dataset/{pk}` |
+| `DELETE` | [Delete a dataset column](./api/delete-a-dataset-column) | `/api/v1/dataset/{pk}/column/{column_id}` |
+| `DELETE` | [Delete a dataset metric](./api/delete-a-dataset-metric) | `/api/v1/dataset/{pk}/metric/{metric_id}` |
+| `PUT` | [Refresh and update columns of a dataset](./api/refresh-and-update-columns-of-a-dataset) | `/api/v1/dataset/{pk}/refresh` |
+| `GET` | [Get charts and dashboards count associated to a dataset](./api/get-charts-and-dashboards-count-associated-to-a-dataset) | `/api/v1/dataset/{pk}/related_objects` |
+| `GET` | [Get distinct values from field data (dataset-distinct-column-name)](./api/get-distinct-values-from-field-data-dataset-distinct-column-name) | `/api/v1/dataset/distinct/{column_name}` |
+| `POST` | [Duplicate a dataset](./api/duplicate-a-dataset) | `/api/v1/dataset/duplicate` |
+| `GET` | [Download multiple datasets as YAML files](./api/download-multiple-datasets-as-yaml-files) | `/api/v1/dataset/export/` |
+| `POST` | [Retrieve a table by name, or create it if it does not exist](./api/retrieve-a-table-by-name-or-create-it-if-it-does-not-exist) | `/api/v1/dataset/get_or_create/` |
+| `POST` | [Import dataset(s) with associated databases](./api/import-dataset-s-with-associated-databases) | `/api/v1/dataset/import/` |
+| `GET` | [Get related fields data (dataset-related-column-name)](./api/get-related-fields-data-dataset-related-column-name) | `/api/v1/dataset/related/{column_name}` |
+| `PUT` | [Warm up the cache for each chart powered by the given table](./api/warm-up-the-cache-for-each-chart-powered-by-the-given-table) | `/api/v1/dataset/warm_up_cache` |
+
+</details>
+
+<details>
+<summary><strong>Database</strong> (31 endpoints) — Manage database connections and metadata.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get a list of databases](./api/get-a-list-of-databases) | `/api/v1/database/` |
+| `POST` | [Create a new database](./api/create-a-new-database) | `/api/v1/database/` |
+| `GET` | [Get metadata information about this API resource (database--info)](./api/get-metadata-information-about-this-api-resource-database-info) | `/api/v1/database/_info` |
+| `DELETE` | [Delete a database](./api/delete-a-database) | `/api/v1/database/{pk}` |
+| `GET` | [Get a database](./api/get-a-database) | `/api/v1/database/{pk}` |
+| `PUT` | [Change a database](./api/change-a-database) | `/api/v1/database/{pk}` |
+| `GET` | [Get all catalogs from a database](./api/get-all-catalogs-from-a-database) | `/api/v1/database/{pk}/catalogs/` |
+| `GET` | [Get a database connection info](./api/get-a-database-connection-info) | `/api/v1/database/{pk}/connection` |
+| `GET` | [Get function names supported by a database](./api/get-function-names-supported-by-a-database) | `/api/v1/database/{pk}/function_names/` |
+| `GET` | [Get charts and dashboards count associated to a database](./api/get-charts-and-dashboards-count-associated-to-a-database) | `/api/v1/database/{pk}/related_objects/` |
+| `GET` | [The list of the database schemas where to upload information](./api/the-list-of-the-database-schemas-where-to-upload-information) | `/api/v1/database/{pk}/schemas_access_for_file_upload/` |
+| `GET` | [Get all schemas from a database](./api/get-all-schemas-from-a-database) | `/api/v1/database/{pk}/schemas/` |
+| `GET` | [Get database select star for table (database-pk-select-star-table-name)](./api/get-database-select-star-for-table-database-pk-select-star-table-name) | `/api/v1/database/{pk}/select_star/{table_name}/` |
+| `GET` | [Get database select star for table (database-pk-select-star-table-name-schema-name)](./api/get-database-select-star-for-table-database-pk-select-star-table-name-schema-name) | `/api/v1/database/{pk}/select_star/{table_name}/{schema_name}/` |
+| `DELETE` | [Delete a SSH tunnel](./api/delete-a-ssh-tunnel) | `/api/v1/database/{pk}/ssh_tunnel/` |
+| `POST` | [Re-sync all permissions for a database connection](./api/re-sync-all-permissions-for-a-database-connection) | `/api/v1/database/{pk}/sync_permissions/` |
+| `GET` | [Get table extra metadata (database-pk-table-extra-table-name-schema-name)](./api/get-table-extra-metadata-database-pk-table-extra-table-name-schema-name) | `/api/v1/database/{pk}/table_extra/{table_name}/{schema_name}/` |
+| `GET` | [Get table metadata](./api/get-table-metadata) | `/api/v1/database/{pk}/table_metadata/` |
+| `GET` | [Get table extra metadata (database-pk-table-metadata-extra)](./api/get-table-extra-metadata-database-pk-table-metadata-extra) | `/api/v1/database/{pk}/table_metadata/extra/` |
+| `GET` | [Get database table metadata](./api/get-database-table-metadata) | `/api/v1/database/{pk}/table/{table_name}/{schema_name}/` |
+| `GET` | [Get a list of tables for given database](./api/get-a-list-of-tables-for-given-database) | `/api/v1/database/{pk}/tables/` |
+| `POST` | [Upload a file to a database table](./api/upload-a-file-to-a-database-table) | `/api/v1/database/{pk}/upload/` |
+| `POST` | [Validate arbitrary SQL](./api/validate-arbitrary-sql) | `/api/v1/database/{pk}/validate_sql/` |
+| `GET` | [Get names of databases currently available](./api/get-names-of-databases-currently-available) | `/api/v1/database/available/` |
+| `GET` | [Download database(s) and associated dataset(s) as a zip file](./api/download-database-s-and-associated-dataset-s-as-a-zip-file) | `/api/v1/database/export/` |
+| `POST` | [Import database(s) with associated datasets](./api/import-database-s-with-associated-datasets) | `/api/v1/database/import/` |
+| `GET` | [Receive personal access tokens from OAuth2](./api/receive-personal-access-tokens-from-o-auth-2) | `/api/v1/database/oauth2/` |
+| `GET` | [Get related fields data (database-related-column-name)](./api/get-related-fields-data-database-related-column-name) | `/api/v1/database/related/{column_name}` |
+| `POST` | [Test a database connection](./api/test-a-database-connection) | `/api/v1/database/test_connection/` |
+| `POST` | [Upload a file and returns file metadata](./api/upload-a-file-and-returns-file-metadata) | `/api/v1/database/upload_metadata/` |
+| `POST` | [Validate database connection parameters](./api/validate-database-connection-parameters) | `/api/v1/database/validate_parameters/` |
+
+</details>
+
+#### Data Exploration
+
+<details>
+<summary><strong>Explore</strong> (1 endpoints) — Chart exploration and data querying endpoints.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Assemble Explore related information in a single endpoint](./api/assemble-explore-related-information-in-a-single-endpoint) | `/api/v1/explore/` |
+
+</details>
+
+<details>
+<summary><strong>SQL Lab</strong> (6 endpoints) — Execute SQL queries and manage SQL Lab sessions.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get the bootstrap data for SqlLab page](./api/get-the-bootstrap-data-for-sql-lab-page) | `/api/v1/sqllab/` |
+| `POST` | [Estimate the SQL query execution cost](./api/estimate-the-sql-query-execution-cost) | `/api/v1/sqllab/estimate/` |
+| `POST` | [Execute a SQL query](./api/execute-a-sql-query) | `/api/v1/sqllab/execute/` |
+| `GET` | [Export the SQL query results to a CSV](./api/export-the-sql-query-results-to-a-csv) | `/api/v1/sqllab/export/{client_id}/` |
+| `POST` | [Format SQL code](./api/format-sql-code) | `/api/v1/sqllab/format_sql/` |
+| `GET` | [Get the result of a SQL query execution](./api/get-the-result-of-a-sql-query-execution) | `/api/v1/sqllab/results/` |
+
+</details>
+
+<details>
+<summary><strong>Queries</strong> (17 endpoints) — View and manage SQL Lab query history.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get a list of queries](./api/get-a-list-of-queries) | `/api/v1/query/` |
+| `GET` | [Get query detail information](./api/get-query-detail-information) | `/api/v1/query/{pk}` |
+| `GET` | [Get distinct values from field data (query-distinct-column-name)](./api/get-distinct-values-from-field-data-query-distinct-column-name) | `/api/v1/query/distinct/{column_name}` |
+| `GET` | [Get related fields data (query-related-column-name)](./api/get-related-fields-data-query-related-column-name) | `/api/v1/query/related/{column_name}` |
+| `POST` | [Manually stop a query with client_id](./api/manually-stop-a-query-with-client-id) | `/api/v1/query/stop` |
+| `GET` | [Get a list of queries that changed after last_updated_ms](./api/get-a-list-of-queries-that-changed-after-last-updated-ms) | `/api/v1/query/updated_since` |
+| `DELETE` | [Bulk delete saved queries](./api/bulk-delete-saved-queries) | `/api/v1/saved_query/` |
+| `GET` | [Get a list of saved queries](./api/get-a-list-of-saved-queries) | `/api/v1/saved_query/` |
+| `POST` | [Create a saved query](./api/create-a-saved-query) | `/api/v1/saved_query/` |
+| `GET` | [Get metadata information about this API resource (saved-query--info)](./api/get-metadata-information-about-this-api-resource-saved-query-info) | `/api/v1/saved_query/_info` |
+| `DELETE` | [Delete a saved query](./api/delete-a-saved-query) | `/api/v1/saved_query/{pk}` |
+| `GET` | [Get a saved query](./api/get-a-saved-query) | `/api/v1/saved_query/{pk}` |
+| `PUT` | [Update a saved query](./api/update-a-saved-query) | `/api/v1/saved_query/{pk}` |
+| `GET` | [Get distinct values from field data (saved-query-distinct-column-name)](./api/get-distinct-values-from-field-data-saved-query-distinct-column-name) | `/api/v1/saved_query/distinct/{column_name}` |
+| `GET` | [Download multiple saved queries as YAML files](./api/download-multiple-saved-queries-as-yaml-files) | `/api/v1/saved_query/export/` |
+| `POST` | [Import saved queries with associated databases](./api/import-saved-queries-with-associated-databases) | `/api/v1/saved_query/import/` |
+| `GET` | [Get related fields data (saved-query-related-column-name)](./api/get-related-fields-data-saved-query-related-column-name) | `/api/v1/saved_query/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>Datasources</strong> (1 endpoints) — Query datasource metadata and column values.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get possible values for a datasource column](./api/get-possible-values-for-a-datasource-column) | `/api/v1/datasource/{datasource_type}/{datasource_id}/column/{column_name}/values/` |
+
+</details>
+
+<details>
+<summary><strong>Advanced Data Type</strong> (2 endpoints) — Endpoints for advanced data type operations and conversions.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Return an AdvancedDataTypeResponse](./api/return-an-advanced-data-type-response) | `/api/v1/advanced_data_type/convert` |
+| `GET` | [Return a list of available advanced data types](./api/return-a-list-of-available-advanced-data-types) | `/api/v1/advanced_data_type/types` |
+
+</details>
+
+#### Organization & Customization
+
+<details>
+<summary><strong>Tags</strong> (15 endpoints) — Organize assets with tags.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete tags](./api/bulk-delete-tags) | `/api/v1/tag/` |
+| `GET` | [Get a list of tags](./api/get-a-list-of-tags) | `/api/v1/tag/` |
+| `POST` | [Create a tag](./api/create-a-tag) | `/api/v1/tag/` |
+| `GET` | [Get metadata information about tag API endpoints](./api/get-metadata-information-about-tag-api-endpoints) | `/api/v1/tag/_info` |
+| `POST` | [Add tags to an object](./api/add-tags-to-an-object) | `/api/v1/tag/{object_type}/{object_id}/` |
+| `DELETE` | [Delete a tagged object](./api/delete-a-tagged-object) | `/api/v1/tag/{object_type}/{object_id}/{tag}/` |
+| `DELETE` | [Delete a tag](./api/delete-a-tag) | `/api/v1/tag/{pk}` |
+| `GET` | [Get a tag detail information](./api/get-a-tag-detail-information) | `/api/v1/tag/{pk}` |
+| `PUT` | [Update a tag](./api/update-a-tag) | `/api/v1/tag/{pk}` |
+| `DELETE` | [Delete tag by pk favorites](./api/delete-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
+| `POST` | [Create tag by pk favorites](./api/create-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
+| `POST` | [Bulk create tags and tagged objects](./api/bulk-create-tags-and-tagged-objects) | `/api/v1/tag/bulk_create` |
+| `GET` | [Get tag favorite status](./api/get-tag-favorite-status) | `/api/v1/tag/favorite_status/` |
+| `GET` | [Get all objects associated with a tag](./api/get-all-objects-associated-with-a-tag) | `/api/v1/tag/get_objects/` |
+| `GET` | [Get related fields data (tag-related-column-name)](./api/get-related-fields-data-tag-related-column-name) | `/api/v1/tag/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>Annotation Layers</strong> (14 endpoints) — Manage annotation layers and annotations for charts.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Delete multiple annotation layers in a bulk operation](./api/delete-multiple-annotation-layers-in-a-bulk-operation) | `/api/v1/annotation_layer/` |
+| `GET` | [Get a list of annotation layers (annotation-layer)](./api/get-a-list-of-annotation-layers-annotation-layer) | `/api/v1/annotation_layer/` |
+| `POST` | [Create an annotation layer (annotation-layer)](./api/create-an-annotation-layer-annotation-layer) | `/api/v1/annotation_layer/` |
+| `GET` | [Get metadata information about this API resource (annotation-layer--info)](./api/get-metadata-information-about-this-api-resource-annotation-layer-info) | `/api/v1/annotation_layer/_info` |
+| `DELETE` | [Delete annotation layer (annotation-layer-pk)](./api/delete-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
+| `GET` | [Get an annotation layer (annotation-layer-pk)](./api/get-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
+| `PUT` | [Update an annotation layer (annotation-layer-pk)](./api/update-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
+| `DELETE` | [Bulk delete annotation layers](./api/bulk-delete-annotation-layers) | `/api/v1/annotation_layer/{pk}/annotation/` |
+| `GET` | [Get a list of annotation layers (annotation-layer-pk-annotation)](./api/get-a-list-of-annotation-layers-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
+| `POST` | [Create an annotation layer (annotation-layer-pk-annotation)](./api/create-an-annotation-layer-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
+| `DELETE` | [Delete annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/delete-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
+| `GET` | [Get an annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/get-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
+| `PUT` | [Update an annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/update-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
+| `GET` | [Get related fields data (annotation-layer-related-column-name)](./api/get-related-fields-data-annotation-layer-related-column-name) | `/api/v1/annotation_layer/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>CSS Templates</strong> (8 endpoints) — Manage CSS templates for custom dashboard styling.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete CSS templates](./api/bulk-delete-css-templates) | `/api/v1/css_template/` |
+| `GET` | [Get a list of CSS templates](./api/get-a-list-of-css-templates) | `/api/v1/css_template/` |
+| `POST` | [Create a CSS template](./api/create-a-css-template) | `/api/v1/css_template/` |
+| `GET` | [Get metadata information about this API resource (css-template--info)](./api/get-metadata-information-about-this-api-resource-css-template-info) | `/api/v1/css_template/_info` |
+| `DELETE` | [Delete a CSS template](./api/delete-a-css-template) | `/api/v1/css_template/{pk}` |
+| `GET` | [Get a CSS template](./api/get-a-css-template) | `/api/v1/css_template/{pk}` |
+| `PUT` | [Update a CSS template](./api/update-a-css-template) | `/api/v1/css_template/{pk}` |
+| `GET` | [Get related fields data (css-template-related-column-name)](./api/get-related-fields-data-css-template-related-column-name) | `/api/v1/css_template/related/{column_name}` |

Review Comment:
   False positive. The `docs/docs/api/` directory contains 240+ generated `.api.mdx` endpoint files (e.g., `docs/docs/api/bulk-delete-css-templates.api.mdx`). These are generated by `docusaurus gen-api-docs` from the OpenAPI spec.
   
   Docusaurus resolves markdown links relative to the **file system**, not the URL. From `docs/api.mdx`, the link `./api/bulk-delete-css-templates` correctly resolves to `docs/api/bulk-delete-css-templates.api.mdx`. A full build with `docusaurus build` confirms zero broken links from API pages.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2733491569


##########
docs/scripts/fix-openapi-spec.py:
##########
@@ -0,0 +1,828 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Fix missing schema references in the OpenAPI spec.
+
+This script patches the openapi.json file to add any missing schemas
+that are referenced but not defined.
+"""
+
+import json  # noqa: TID251 - standalone docs script
+import sys
+from pathlib import Path
+from typing import Any
+
+
+def add_missing_schemas(spec: dict[str, Any]) -> tuple[dict[str, Any], list[str]]:
+    """Add missing schema definitions to the OpenAPI spec."""
+    schemas = spec.get("components", {}).get("schemas", {})
+    fixed = []
+
+    # DashboardScreenshotPostSchema - based on superset/dashboards/schemas.py
+    if "DashboardScreenshotPostSchema" not in schemas:
+        schemas["DashboardScreenshotPostSchema"] = {
+            "type": "object",
+            "properties": {
+                "dataMask": {
+                    "type": "object",
+                    "description": "An object representing the data mask.",
+                    "additionalProperties": True,
+                },
+                "activeTabs": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "A list representing active tabs.",
+                },
+                "anchor": {
+                    "type": "string",
+                    "description": "A string representing the anchor.",
+                },
+                "urlParams": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {"type": "string"},
+                        "minItems": 2,
+                        "maxItems": 2,
+                    },
+                    "description": "A list of tuples, each containing two strings.",
+                },
+            },
+        }
+        fixed.append("DashboardScreenshotPostSchema")
+
+    # DashboardNativeFiltersConfigUpdateSchema - based on superset/dashboards/schemas.py
+    if "DashboardNativeFiltersConfigUpdateSchema" not in schemas:
+        schemas["DashboardNativeFiltersConfigUpdateSchema"] = {
+            "type": "object",
+            "properties": {
+                "deleted": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "List of deleted filter IDs.",
+                },
+                "modified": {
+                    "type": "array",
+                    "items": {"type": "object"},
+                    "description": "List of modified filter configurations.",
+                },
+                "reordered": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "List of filter IDs in new order.",
+                },
+            },
+        }
+        fixed.append("DashboardNativeFiltersConfigUpdateSchema")
+
+    # DashboardColorsConfigUpdateSchema - based on superset/dashboards/schemas.py
+    if "DashboardColorsConfigUpdateSchema" not in schemas:
+        schemas["DashboardColorsConfigUpdateSchema"] = {
+            "type": "object",
+            "properties": {
+                "color_namespace": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The color namespace.",
+                },
+                "color_scheme": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The color scheme name.",
+                },
+                "map_label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Mapping of labels to colors.",
+                },
+                "shared_label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Shared label colors across charts.",
+                },
+                "label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Label to color mapping.",
+                },
+                "color_scheme_domain": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "Color scheme domain values.",
+                },
+            },
+        }
+        fixed.append("DashboardColorsConfigUpdateSchema")
+
+    # FormatQueryPayloadSchema - based on superset/sqllab/schemas.py
+    if "FormatQueryPayloadSchema" not in schemas:
+        schemas["FormatQueryPayloadSchema"] = {
+            "type": "object",
+            "required": ["sql"],
+            "properties": {
+                "sql": {
+                    "type": "string",
+                    "description": "The SQL query to format.",
+                },
+                "engine": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The database engine.",
+                },
+                "database_id": {
+                    "type": "integer",
+                    "nullable": True,
+                    "description": "The database id.",
+                },
+                "template_params": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The SQL query template params as JSON string.",
+                },
+            },
+        }
+        fixed.append("FormatQueryPayloadSchema")
+
+    # get_slack_channels_schema - based on superset/reports/schemas.py
+    if "get_slack_channels_schema" not in schemas:
+        schemas["get_slack_channels_schema"] = {
+            "type": "object",
+            "properties": {
+                "search_string": {
+                    "type": "string",
+                    "description": "String to search for in channel names.",
+                },
+                "types": {
+                    "type": "array",
+                    "items": {
+                        "type": "string",
+                        "enum": ["public_channel", "private_channel"],
+                    },
+                    "description": "Types of channels to search.",
+                },
+                "exact_match": {
+                    "type": "boolean",
+                    "description": "Whether to match channel names exactly.",
+                },
+            },
+        }
+        fixed.append("get_slack_channels_schema")
+
+    if "components" not in spec:
+        spec["components"] = {}
+    spec["components"]["schemas"] = schemas
+
+    return spec, fixed
+
+
+def path_to_operation_id(path: str, method: str) -> str:
+    """Convert a path and method to an operationId."""
+    # Remove /api/v1/ prefix
+    clean_path = path.replace("/api/v1/", "").strip("/")
+
+    # Replace path parameters
+    clean_path = clean_path.replace("{", "by_").replace("}", "")
+
+    # Create operation name
+    method_prefix = {
+        "get": "get",
+        "post": "create",
+        "put": "update",
+        "delete": "delete",
+        "patch": "patch",
+    }.get(method.lower(), method.lower())
+
+    return f"{method_prefix}_{clean_path}".replace("/", "_").replace("-", "_")
+
+
+def path_to_summary(path: str, method: str) -> str:
+    """Generate a human-readable summary from path and method."""
+    # Remove /api/v1/ prefix
+    clean_path = path.replace("/api/v1/", "").strip("/")
+
+    # Handle path parameters
+    parts = []
+    for part in clean_path.split("/"):
+        if part.startswith("{") and part.endswith("}"):
+            param = part[1:-1]
+            parts.append(f"by {param}")
+        else:
+            parts.append(part.replace("_", " ").replace("-", " "))
+
+    resource = " ".join(parts)
+
+    method_verb = {
+        "get": "Get",
+        "post": "Create",
+        "put": "Update",
+        "delete": "Delete",
+        "patch": "Update",
+    }.get(method.lower(), method.capitalize())
+
+    return f"{method_verb} {resource}"
+
+
+def add_missing_operation_ids(spec: dict[str, Any]) -> int:
+    """Add operationId and summary to operations that are missing them."""
+    fixed_count = 0
+
+    for path, methods in spec.get("paths", {}).items():
+        for method, details in methods.items():
+            if method not in ["get", "post", "put", "delete", "patch"]:
+                continue
+
+            if not isinstance(details, dict):
+                continue
+
+            summary = details.get("summary")
+            operation_id = details.get("operationId")
+
+            if not summary and not operation_id:
+                details["operationId"] = path_to_operation_id(path, method)
+                details["summary"] = path_to_summary(path, method)
+                fixed_count += 1
+
+    return fixed_count
+
+
+TAG_DESCRIPTIONS = {
+    "Advanced Data Type": "Advanced data type operations and conversions.",
+    "Annotation Layers": "Manage annotation layers and annotations for charts.",
+    "AsyncEventsRestApi": "Real-time event streaming via Server-Sent Events (SSE).",
+    "Available Domains": "Get available domains for the Superset instance.",
+    "CSS Templates": "Manage CSS templates for custom dashboard styling.",
+    "CacheRestApi": "Cache management and invalidation operations.",
+    "Charts": "Create, read, update, and delete charts (slices).",
+    "Current User": "Get information about the authenticated user.",
+    "Dashboard Filter State": "Manage temporary filter state for dashboards.",
+    "Dashboard Permanent Link": "Permanent links to dashboard states.",
+    "Dashboards": "Create, read, update, and delete dashboards.",
+    "Database": "Manage database connections and metadata.",
+    "Datasets": "Manage datasets (tables) used for building charts.",
+    "Datasources": "Query datasource metadata and column values.",
+    "Embedded Dashboard": "Configure embedded dashboard settings.",
+    "Explore": "Chart exploration and data querying endpoints.",
+    "Explore Form Data": "Manage temporary form data for chart exploration.",
+    "Explore Permanent Link": "Permanent links to chart explore states.",
+    "Import/export": "Import and export Superset assets.",
+    "LogRestApi": "Access audit logs and activity history.",
+    "Menu": "Get the Superset menu structure.",
+    "OpenApi": "Access the OpenAPI specification.",
+    "Queries": "View and manage SQL Lab query history.",
+    "Report Schedules": "Configure scheduled reports and alerts.",
+    "Row Level Security": "Manage row-level security rules for data access.",
+    "SQL Lab": "Execute SQL queries and manage SQL Lab sessions.",
+    "SQL Lab Permanent Link": "Permanent links to SQL Lab states.",
+    "Security": "Authentication and token management.",
+    "Security Permissions": "View available permissions.",
+    "Security Permissions on Resources (View Menus)": "Permission-resource mappings.",
+    "Security Resources (View Menus)": "Manage security resources (view menus).",
+    "Security Roles": "Manage security roles and their permissions.",
+    "Security Users": "Manage user accounts.",
+    "Tags": "Organize assets with tags.",
+    "User": "User profile and preferences.",
+}
+
+
+def generate_code_sample(
+    method: str, path: str, has_body: bool = False
+) -> list[dict[str, str]]:
+    """Generate code samples for an endpoint in multiple languages."""
+    # Clean up path for display
+    example_path = path.replace("{pk}", "1").replace("{id_or_slug}", "1")
+
+    samples = []
+
+    # cURL sample
+    curl_cmd = f'curl -X {method.upper()} "http://localhost:8088{example_path}"'
+    curl_cmd += ' \\\n  -H "Authorization: Bearer $ACCESS_TOKEN"'
+    if has_body:
+        curl_cmd += ' \\\n  -H "Content-Type: application/json"'
+        curl_cmd += ' \\\n  -d \'{"key": "value"}\''
+
+    samples.append(
+        {
+            "lang": "cURL",
+            "label": "cURL",
+            "source": curl_cmd,
+        }
+    )
+
+    # Python sample
+    if method.lower() == "get":
+        python_code = f"""import requests
+
+response = requests.get(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.json())"""
+    elif method.lower() == "post":
+        python_code = f"""import requests
+
+response = requests.post(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}},
+    json={{"key": "value"}}
+)
+print(response.json())"""
+    elif method.lower() == "put":
+        python_code = f"""import requests
+
+response = requests.put(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}},
+    json={{"key": "value"}}
+)
+print(response.json())"""
+    elif method.lower() == "delete":
+        python_code = f"""import requests
+
+response = requests.delete(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.status_code)"""
+    else:
+        python_code = f"""import requests
+
+response = requests.{method.lower()}(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.json())"""
+
+    samples.append(
+        {
+            "lang": "Python",
+            "label": "Python",
+            "source": python_code,
+        }
+    )
+
+    # JavaScript sample
+    if method.lower() == "get":
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`
+    }}
+  }}
+);
+const data = await response.json();
+console.log(data);"""
+    elif method.lower() in ["post", "put", "patch"]:
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    method: "{method.upper()}",
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`,
+      "Content-Type": "application/json"
+    }},
+    body: JSON.stringify({{ key: "value" }})
+  }}
+);
+const data = await response.json();
+console.log(data);"""
+    else:
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    method: "{method.upper()}",
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`
+    }}
+  }}
+);
+console.log(response.status);"""
+
+    samples.append(
+        {
+            "lang": "JavaScript",
+            "label": "JavaScript",
+            "source": js_code,
+        }
+    )
+
+    return samples

Review Comment:
   <!-- Bito Reply -->
   That explanation aligns with the PR changes. The API documentation includes code samples with placeholders like YOUR_ACCESS_TOKEN in cURL examples, which is standard for docs to show usage patterns without real credentials.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734368937


##########
docs/yarn.lock:
##########
@@ -8782,6 +9219,13 @@ js-yaml-loader@^1.2.2:
     loader-utils "^1.2.3"
     un-eval "^1.2.0"
 
+js-yaml@4.1.0:

Review Comment:
   <!-- Bito Reply -->
   Your explanation aligns with the PR's changes: js-yaml@4.1.0 is added as a transitive dependency via @apidevtools/json-schema-ref-parser, and the yarn.lock was regenerated after adding the OpenAPI docs plugins. The package.json constraint ^4.1.1 allows this version, and yarn resolves it based on the dependency tree. As for CVE-2025-64718, since it's not verified in the NVD, it could be a scanner false positive—consider checking official sources or updating the transitive dependency if possible.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734731449


##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
+  }
+  style={{ marginBottom: '24px' }}
+/>
+
+---
+
+`;
+
+  // Track which tags we've rendered
+  const renderedTags = new Set();
+
+  // Render Authentication first (it's critical for using the API)
+  mdx += `### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+\`\`\`bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \\
+  -H "Content-Type: application/json" \\
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
+  http://localhost:8088/api/v1/dashboard/
+\`\`\`
+
+#### Security Endpoints
+
+`;
+
+  // Render Security tag endpoints
+  if (tagEndpoints['Security']) {
+    mdx += `| Method | Endpoint | Description |\n`;
+    mdx += `|--------|----------|-------------|\n`;
+    for (const ep of tagEndpoints['Security']) {
+      mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;

Review Comment:
   **Update (577ae18):** After further testing, we changed the links back to `./api/${slug}`. The bot's analysis assumes browser URL resolution, but Docusaurus resolves markdown links based on the **file system** at build time. From `docs/api.mdx`, `./api/create-security-login` resolves to `docs/api/create-security-login.api.mdx` — which is correct. A full `docusaurus build` confirms zero broken links. The scripts now also read the generated sidebar to use the plugin's exact slugs (avoiding apostrophe/camelCase mismatches).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "netlify[bot] (via GitHub)" <gi...@apache.org>.
netlify[bot] commented on PR #37434:
URL: https://github.com/apache/superset/pull/37434#issuecomment-3797917166

   ### <span aria-hidden="true">✅</span> Deploy Preview for *superset-docs-preview* ready!
   
   
   |  Name | Link |
   |:-:|------------------------|
   |<span aria-hidden="true">🔨</span> Latest commit | 712bdfc1917f6c81e81015068b47f16dbca113c0 |
   |<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/projects/superset-docs-preview/deploys/6976f32d837b2900083367b3 |
   |<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-37434--superset-docs-preview.netlify.app](https://deploy-preview-37434--superset-docs-preview.netlify.app) |
   |<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTM3NDM0LS1zdXBlcnNldC1kb2NzLXByZXZpZXcubmV0bGlmeS5hcHAifQ.j53FRdoan1x-zLQBDfSTdNRf-KJLOOR-6zakY03i_oY)<br /><br />_Use your smartphone camera to open QR code link._</details> |
   ---
   <!-- [superset-docs-preview Preview](https://deploy-preview-37434--superset-docs-preview.netlify.app) -->
   _To edit notification comments on pull requests, go to your [Netlify project configuration](https://app.netlify.com/projects/superset-docs-preview/configuration/notifications#deploy-notifications)._


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "netlify[bot] (via GitHub)" <gi...@apache.org>.
netlify[bot] commented on PR #37434:
URL: https://github.com/apache/superset/pull/37434#issuecomment-3797975914

   ### <span aria-hidden="true">✅</span> Deploy Preview for *superset-docs-preview* ready!
   
   
   |  Name | Link |
   |:-:|------------------------|
   |<span aria-hidden="true">🔨</span> Latest commit | 716777742f6cfc8e4a7e0613998bd657665b982f |
   |<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/projects/superset-docs-preview/deploys/6976f8973ba1e400084d76d9 |
   |<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-37434--superset-docs-preview.netlify.app](https://deploy-preview-37434--superset-docs-preview.netlify.app) |
   |<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTM3NDM0LS1zdXBlcnNldC1kb2NzLXByZXZpZXcubmV0bGlmeS5hcHAifQ.j53FRdoan1x-zLQBDfSTdNRf-KJLOOR-6zakY03i_oY)<br /><br />_Use your smartphone camera to open QR code link._</details> |
   ---
   <!-- [superset-docs-preview Preview](https://deploy-preview-37434--superset-docs-preview.netlify.app) -->
   _To edit notification comments on pull requests, go to your [Netlify project configuration](https://app.netlify.com/projects/superset-docs-preview/configuration/notifications#deploy-notifications)._


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2733480648


##########
docs/docusaurus.config.ts:
##########
@@ -189,6 +195,29 @@ const config: Config = {
       },
     ],
     ...dynamicPlugins,
+    [
+      'docusaurus-plugin-openapi-docs',
+      {
+        id: 'api',
+        docsPluginId: 'classic',

Review Comment:
   This is a false positive. The `docsPluginId: 'classic'` is correct — the plugin resolves preset names using `endsWith()` matching, so `'classic'` matches `@docusaurus/preset-classic`. The API docs generate and build successfully with this configuration. See `getDocsPluginConfig()` in `docusaurus-plugin-openapi-docs/lib/index.js`.



##########
docs/sidebars.js:
##########
@@ -107,9 +107,14 @@ const sidebars = {
       id: 'faq',
     },
     {
-      type: 'doc',
-      label: 'API',
-      id: 'api',
+      type: 'category',
+      label: 'API Reference',
+      link: {
+        type: 'doc',
+        id: 'api',
+      },
+      // eslint-disable-next-line @typescript-eslint/no-require-imports
+      items: require('./docs/api/sidebar.js'),

Review Comment:
   Valid point — fixed. The `require()` is now wrapped in a try/catch that falls back to an empty array when `yarn generate:api-docs` has not been run yet. See 1c8a520.



##########
docs/src/styles/custom.css:
##########
@@ -187,3 +187,81 @@ ul.dropdown__menu svg {
 [data-theme='dark'] .ant-collapse-header {
   color: var(--ifm-font-base-color);
 }
+
+/* Hide the non-functional "Send API Request" button and Response block in API docs */
+/* The interactive API testing doesn't work due to CORS restrictions */
+.openapi-explorer__request-btn {
+  display: none !important;
+}
+
+.openapi-explorer__response-container {
+  display: none !important;

Review Comment:
   False positive. The `.openapi-explorer__response-container` class is used exclusively by the **interactive** "Send API Request" response panel (in `ApiExplorer/Response/index.js`), not the documented response schemas. The documented response status codes and schemas use `openapi-tabs__response-container` (in `ApiTabs/index.js`) which is not hidden. Additionally, we set `hideSendButton: true` in the plugin config, which causes the Response component to `return null` anyway — the CSS is defense-in-depth.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734380348


##########
docs/docs/api.mdx:
##########
@@ -1,40 +1,590 @@
 ---
-title: API
+title: API Reference
 hide_title: true
 sidebar_position: 10
 ---
 
-import SwaggerUI from 'swagger-ui-react';
-import openapi from '/resources/openapi.json';
-import 'swagger-ui-react/swagger-ui.css';
 import { Alert } from 'antd';
 
-## API
+## REST API Reference
 
-Superset's public **REST API** follows the
-[OpenAPI specification](https://swagger.io/specification/), and is
-documented here. The docs below are generated using
-[Swagger React UI](https://www.npmjs.com/package/swagger-ui-react).
-
-:::resources
-- [Blog: The Superset REST API](https://preset.io/blog/2020-10-01-superset-api/)
-- [Blog: Accessing APIs with Superset](https://preset.io/blog/accessing-apis-with-superset/)
-:::
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
 
 <Alert
   type="info"
-  message={
-    <div>
-      <strong>NOTE! </strong>
-      You can find an interactive version of this documentation on your local Superset
-      instance at <strong>/swagger/v1</strong> (unless disabled)
-    </div>
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
   }
+  style={{ marginBottom: '24px' }}
 />
 
-<br />
-<br />
-<hr />
-<div className="swagger-container">
-  <SwaggerUI spec={openapi} />
-</div>
+---
+
+### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+```bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \
+  -H "Content-Type: application/json" \
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
+  http://localhost:8088/api/v1/dashboard/
+```
+
+#### Security Endpoints
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get the CSRF token](./get-the-csrf-token) | `/api/v1/security/csrf_token/` |

Review Comment:
   This was flagged on an older commit. The latest commit (577ae18) changed these links to `./api/${slug}` format. Docusaurus resolves markdown links file-relative at build time — from `docs/api.mdx`, `./api/get-the-csrf-token` correctly resolves to `docs/api/get-the-csrf-token.api.mdx`. The build confirms zero broken links from API pages.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2733484478


##########
docs/scripts/fix-openapi-spec.py:
##########
@@ -0,0 +1,828 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Fix missing schema references in the OpenAPI spec.
+
+This script patches the openapi.json file to add any missing schemas
+that are referenced but not defined.
+"""
+
+import json  # noqa: TID251 - standalone docs script
+import sys
+from pathlib import Path
+from typing import Any
+
+
+def add_missing_schemas(spec: dict[str, Any]) -> tuple[dict[str, Any], list[str]]:
+    """Add missing schema definitions to the OpenAPI spec."""
+    schemas = spec.get("components", {}).get("schemas", {})
+    fixed = []
+
+    # DashboardScreenshotPostSchema - based on superset/dashboards/schemas.py
+    if "DashboardScreenshotPostSchema" not in schemas:
+        schemas["DashboardScreenshotPostSchema"] = {
+            "type": "object",
+            "properties": {
+                "dataMask": {
+                    "type": "object",
+                    "description": "An object representing the data mask.",
+                    "additionalProperties": True,
+                },
+                "activeTabs": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "A list representing active tabs.",
+                },
+                "anchor": {
+                    "type": "string",
+                    "description": "A string representing the anchor.",
+                },
+                "urlParams": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {"type": "string"},
+                        "minItems": 2,
+                        "maxItems": 2,
+                    },
+                    "description": "A list of tuples, each containing two strings.",
+                },
+            },
+        }
+        fixed.append("DashboardScreenshotPostSchema")
+
+    # DashboardNativeFiltersConfigUpdateSchema - based on superset/dashboards/schemas.py
+    if "DashboardNativeFiltersConfigUpdateSchema" not in schemas:
+        schemas["DashboardNativeFiltersConfigUpdateSchema"] = {
+            "type": "object",
+            "properties": {
+                "deleted": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "List of deleted filter IDs.",
+                },
+                "modified": {
+                    "type": "array",
+                    "items": {"type": "object"},
+                    "description": "List of modified filter configurations.",
+                },
+                "reordered": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "List of filter IDs in new order.",
+                },
+            },
+        }
+        fixed.append("DashboardNativeFiltersConfigUpdateSchema")
+
+    # DashboardColorsConfigUpdateSchema - based on superset/dashboards/schemas.py
+    if "DashboardColorsConfigUpdateSchema" not in schemas:
+        schemas["DashboardColorsConfigUpdateSchema"] = {
+            "type": "object",
+            "properties": {
+                "color_namespace": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The color namespace.",
+                },
+                "color_scheme": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The color scheme name.",
+                },
+                "map_label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Mapping of labels to colors.",
+                },
+                "shared_label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Shared label colors across charts.",
+                },
+                "label_colors": {
+                    "type": "object",
+                    "additionalProperties": {"type": "string"},
+                    "description": "Label to color mapping.",
+                },
+                "color_scheme_domain": {
+                    "type": "array",
+                    "items": {"type": "string"},
+                    "description": "Color scheme domain values.",
+                },
+            },
+        }
+        fixed.append("DashboardColorsConfigUpdateSchema")
+
+    # FormatQueryPayloadSchema - based on superset/sqllab/schemas.py
+    if "FormatQueryPayloadSchema" not in schemas:
+        schemas["FormatQueryPayloadSchema"] = {
+            "type": "object",
+            "required": ["sql"],
+            "properties": {
+                "sql": {
+                    "type": "string",
+                    "description": "The SQL query to format.",
+                },
+                "engine": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The database engine.",
+                },
+                "database_id": {
+                    "type": "integer",
+                    "nullable": True,
+                    "description": "The database id.",
+                },
+                "template_params": {
+                    "type": "string",
+                    "nullable": True,
+                    "description": "The SQL query template params as JSON string.",
+                },
+            },
+        }
+        fixed.append("FormatQueryPayloadSchema")
+
+    # get_slack_channels_schema - based on superset/reports/schemas.py
+    if "get_slack_channels_schema" not in schemas:
+        schemas["get_slack_channels_schema"] = {
+            "type": "object",
+            "properties": {
+                "search_string": {
+                    "type": "string",
+                    "description": "String to search for in channel names.",
+                },
+                "types": {
+                    "type": "array",
+                    "items": {
+                        "type": "string",
+                        "enum": ["public_channel", "private_channel"],
+                    },
+                    "description": "Types of channels to search.",
+                },
+                "exact_match": {
+                    "type": "boolean",
+                    "description": "Whether to match channel names exactly.",
+                },
+            },
+        }
+        fixed.append("get_slack_channels_schema")
+
+    if "components" not in spec:
+        spec["components"] = {}
+    spec["components"]["schemas"] = schemas
+
+    return spec, fixed
+
+
+def path_to_operation_id(path: str, method: str) -> str:
+    """Convert a path and method to an operationId."""
+    # Remove /api/v1/ prefix
+    clean_path = path.replace("/api/v1/", "").strip("/")
+
+    # Replace path parameters
+    clean_path = clean_path.replace("{", "by_").replace("}", "")
+
+    # Create operation name
+    method_prefix = {
+        "get": "get",
+        "post": "create",
+        "put": "update",
+        "delete": "delete",
+        "patch": "patch",
+    }.get(method.lower(), method.lower())
+
+    return f"{method_prefix}_{clean_path}".replace("/", "_").replace("-", "_")
+
+
+def path_to_summary(path: str, method: str) -> str:
+    """Generate a human-readable summary from path and method."""
+    # Remove /api/v1/ prefix
+    clean_path = path.replace("/api/v1/", "").strip("/")
+
+    # Handle path parameters
+    parts = []
+    for part in clean_path.split("/"):
+        if part.startswith("{") and part.endswith("}"):
+            param = part[1:-1]
+            parts.append(f"by {param}")
+        else:
+            parts.append(part.replace("_", " ").replace("-", " "))
+
+    resource = " ".join(parts)
+
+    method_verb = {
+        "get": "Get",
+        "post": "Create",
+        "put": "Update",
+        "delete": "Delete",
+        "patch": "Update",
+    }.get(method.lower(), method.capitalize())
+
+    return f"{method_verb} {resource}"
+
+
+def add_missing_operation_ids(spec: dict[str, Any]) -> int:
+    """Add operationId and summary to operations that are missing them."""
+    fixed_count = 0
+
+    for path, methods in spec.get("paths", {}).items():
+        for method, details in methods.items():
+            if method not in ["get", "post", "put", "delete", "patch"]:
+                continue
+
+            if not isinstance(details, dict):
+                continue
+
+            summary = details.get("summary")
+            operation_id = details.get("operationId")
+
+            if not summary and not operation_id:
+                details["operationId"] = path_to_operation_id(path, method)
+                details["summary"] = path_to_summary(path, method)
+                fixed_count += 1
+
+    return fixed_count
+
+
+TAG_DESCRIPTIONS = {
+    "Advanced Data Type": "Advanced data type operations and conversions.",
+    "Annotation Layers": "Manage annotation layers and annotations for charts.",
+    "AsyncEventsRestApi": "Real-time event streaming via Server-Sent Events (SSE).",
+    "Available Domains": "Get available domains for the Superset instance.",
+    "CSS Templates": "Manage CSS templates for custom dashboard styling.",
+    "CacheRestApi": "Cache management and invalidation operations.",
+    "Charts": "Create, read, update, and delete charts (slices).",
+    "Current User": "Get information about the authenticated user.",
+    "Dashboard Filter State": "Manage temporary filter state for dashboards.",
+    "Dashboard Permanent Link": "Permanent links to dashboard states.",
+    "Dashboards": "Create, read, update, and delete dashboards.",
+    "Database": "Manage database connections and metadata.",
+    "Datasets": "Manage datasets (tables) used for building charts.",
+    "Datasources": "Query datasource metadata and column values.",
+    "Embedded Dashboard": "Configure embedded dashboard settings.",
+    "Explore": "Chart exploration and data querying endpoints.",
+    "Explore Form Data": "Manage temporary form data for chart exploration.",
+    "Explore Permanent Link": "Permanent links to chart explore states.",
+    "Import/export": "Import and export Superset assets.",
+    "LogRestApi": "Access audit logs and activity history.",
+    "Menu": "Get the Superset menu structure.",
+    "OpenApi": "Access the OpenAPI specification.",
+    "Queries": "View and manage SQL Lab query history.",
+    "Report Schedules": "Configure scheduled reports and alerts.",
+    "Row Level Security": "Manage row-level security rules for data access.",
+    "SQL Lab": "Execute SQL queries and manage SQL Lab sessions.",
+    "SQL Lab Permanent Link": "Permanent links to SQL Lab states.",
+    "Security": "Authentication and token management.",
+    "Security Permissions": "View available permissions.",
+    "Security Permissions on Resources (View Menus)": "Permission-resource mappings.",
+    "Security Resources (View Menus)": "Manage security resources (view menus).",
+    "Security Roles": "Manage security roles and their permissions.",
+    "Security Users": "Manage user accounts.",
+    "Tags": "Organize assets with tags.",
+    "User": "User profile and preferences.",
+}
+
+
+def generate_code_sample(
+    method: str, path: str, has_body: bool = False
+) -> list[dict[str, str]]:
+    """Generate code samples for an endpoint in multiple languages."""
+    # Clean up path for display
+    example_path = path.replace("{pk}", "1").replace("{id_or_slug}", "1")
+
+    samples = []
+
+    # cURL sample
+    curl_cmd = f'curl -X {method.upper()} "http://localhost:8088{example_path}"'
+    curl_cmd += ' \\\n  -H "Authorization: Bearer $ACCESS_TOKEN"'
+    if has_body:
+        curl_cmd += ' \\\n  -H "Content-Type: application/json"'
+        curl_cmd += ' \\\n  -d \'{"key": "value"}\''
+
+    samples.append(
+        {
+            "lang": "cURL",
+            "label": "cURL",
+            "source": curl_cmd,
+        }
+    )
+
+    # Python sample
+    if method.lower() == "get":
+        python_code = f"""import requests
+
+response = requests.get(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.json())"""
+    elif method.lower() == "post":
+        python_code = f"""import requests
+
+response = requests.post(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}},
+    json={{"key": "value"}}
+)
+print(response.json())"""
+    elif method.lower() == "put":
+        python_code = f"""import requests
+
+response = requests.put(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}},
+    json={{"key": "value"}}
+)
+print(response.json())"""
+    elif method.lower() == "delete":
+        python_code = f"""import requests
+
+response = requests.delete(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.status_code)"""
+    else:
+        python_code = f"""import requests
+
+response = requests.{method.lower()}(
+    "http://localhost:8088{example_path}",
+    headers={{"Authorization": "Bearer " + access_token}}
+)
+print(response.json())"""
+
+    samples.append(
+        {
+            "lang": "Python",
+            "label": "Python",
+            "source": python_code,
+        }
+    )
+
+    # JavaScript sample
+    if method.lower() == "get":
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`
+    }}
+  }}
+);
+const data = await response.json();
+console.log(data);"""
+    elif method.lower() in ["post", "put", "patch"]:
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    method: "{method.upper()}",
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`,
+      "Content-Type": "application/json"
+    }},
+    body: JSON.stringify({{ key: "value" }})
+  }}
+);
+const data = await response.json();
+console.log(data);"""
+    else:
+        js_code = f"""const response = await fetch(
+  "http://localhost:8088{example_path}",
+  {{
+    method: "{method.upper()}",
+    headers: {{
+      "Authorization": `Bearer ${{accessToken}}`
+    }}
+  }}
+);
+console.log(response.status);"""
+
+    samples.append(
+        {
+            "lang": "JavaScript",
+            "label": "JavaScript",
+            "source": js_code,
+        }
+    )
+
+    return samples

Review Comment:
   This is by design. The code samples are **documentation examples** showing the pattern for API usage — they use placeholder variables (`access_token` in Python, `accessToken` in JS) that users must replace with their own values. This is standard practice for API documentation (e.g., Stripe, GitHub, Twilio docs all use the same approach). The cURL examples use `$ACCESS_TOKEN` which is a shell variable users would set.



##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');

Review Comment:
   False positive. The path `path.join(__dirname, '..' , 'docs', 'api.mdx')` is correct. The script lives in `docs/scripts/`, so `..` goes to `docs/`, and then `docs/api.mdx` refers to `docs/docs/api.mdx` in the repo root. This is the Docusaurus content directory — the `docs/` project has its content in a `docs/` subdirectory (`docs/docs/`), which maps to the `/docs/` URL prefix.



##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {

Review Comment:
   This is a build-time script that runs as part of `yarn generate:api-docs`. If the OpenAPI spec is missing or invalid JSON, Node will throw a clear error with a stack trace, which is sufficient for a build script. Adding try/catch would just wrap the same error with less useful context.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2733481945


##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.

Review Comment:
   Valid — fixed in 1c8a520. Changed `./api/schemas` to `./schemas` so it resolves correctly from the `/docs/api/` URL with trailing slash.



##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
+  }
+  style={{ marginBottom: '24px' }}
+/>
+
+---
+
+`;
+
+  // Track which tags we've rendered
+  const renderedTags = new Set();
+
+  // Render Authentication first (it's critical for using the API)
+  mdx += `### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+\`\`\`bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \\
+  -H "Content-Type: application/json" \\
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
+  http://localhost:8088/api/v1/dashboard/
+\`\`\`
+
+#### Security Endpoints
+
+`;
+
+  // Render Security tag endpoints
+  if (tagEndpoints['Security']) {
+    mdx += `| Method | Endpoint | Description |\n`;
+    mdx += `|--------|----------|-------------|\n`;
+    for (const ep of tagEndpoints['Security']) {
+      mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;

Review Comment:
   Valid — fixed in 1c8a520. Changed all endpoint links from `./api/${ep.slug}` to `./${ep.slug}` so they resolve correctly with trailing-slash URLs.



##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {
+  console.log(`Reading OpenAPI spec from ${SPEC_PATH}`);
+  const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
+
+  // Build a map of tag -> endpoints
+  const tagEndpoints = {};
+  const tagDescriptions = {};
+
+  // Get tag descriptions
+  for (const tag of spec.tags || []) {
+    tagDescriptions[tag.name] = tag.description || '';
+  }
+
+  // Collect endpoints by tag
+  for (const [pathUrl, methods] of Object.entries(spec.paths || {})) {
+    for (const [method, details] of Object.entries(methods)) {
+      if (!['get', 'post', 'put', 'delete', 'patch'].includes(method)) continue;
+
+      const tags = details.tags || ['Untagged'];
+      const summary = details.summary || `${method.toUpperCase()} ${pathUrl}`;
+
+      for (const tag of tags) {
+        if (!tagEndpoints[tag]) {
+          tagEndpoints[tag] = [];
+        }
+        tagEndpoints[tag].push({
+          method: method.toUpperCase(),
+          path: pathUrl,
+          summary,
+          slug: generateEndpointLink(summary),
+        });
+      }
+    }
+  }
+
+  // Sort endpoints within each tag by path
+  for (const tag of Object.keys(tagEndpoints)) {
+    tagEndpoints[tag].sort((a, b) => a.path.localeCompare(b.path));
+  }
+
+  // Generate MDX content
+  let mdx = `---
+title: API Reference
+hide_title: true
+sidebar_position: 10
+---
+
+import { Alert } from 'antd';
+
+## REST API Reference
+
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
+
+<Alert
+  type="info"
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      Browse the <a href="./api/schemas">Schema definitions</a> for detailed data model documentation.
+    </span>
+  }
+  style={{ marginBottom: '24px' }}
+/>
+
+---
+
+`;
+
+  // Track which tags we've rendered
+  const renderedTags = new Set();
+
+  // Render Authentication first (it's critical for using the API)
+  mdx += `### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+\`\`\`bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \\
+  -H "Content-Type: application/json" \\
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
+  http://localhost:8088/api/v1/dashboard/
+\`\`\`
+
+#### Security Endpoints
+
+`;
+
+  // Render Security tag endpoints
+  if (tagEndpoints['Security']) {
+    mdx += `| Method | Endpoint | Description |\n`;
+    mdx += `|--------|----------|-------------|\n`;
+    for (const ep of tagEndpoints['Security']) {
+      mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;
+    }
+    mdx += '\n';
+    renderedTags.add('Security');
+  }
+
+  mdx += `---\n\n### API Endpoints\n\n`;
+
+  // Render each category group
+  for (const [groupName, groupTags] of Object.entries(CATEGORY_GROUPS)) {
+    if (groupName === 'Authentication') continue; // Already rendered
+
+    const tagsInGroup = groupTags.filter(tag => tagEndpoints[tag] && !renderedTags.has(tag));
+    if (tagsInGroup.length === 0) continue;
+
+    mdx += `#### ${groupName}\n\n`;
+
+    for (const tag of tagsInGroup) {
+      const description = tagDescriptions[tag] || '';
+      const endpoints = tagEndpoints[tag];
+
+      mdx += `<details>\n`;
+      mdx += `<summary><strong>${tag}</strong> (${endpoints.length} endpoints) — ${description}</summary>\n\n`;
+      mdx += `| Method | Endpoint | Description |\n`;
+      mdx += `|--------|----------|-------------|\n`;
+
+      for (const ep of endpoints) {
+        mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;

Review Comment:
   Valid — fixed in 1c8a520. Same fix as the security endpoints: `./api/${ep.slug}` → `./${ep.slug}`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2733489966


##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');

Review Comment:
   <!-- Bito Reply -->
   The suggestion to remove 'docs' from the OUTPUT_PATH is incorrect. The script in docs/scripts/ uses __dirname as docs/scripts/, so path.join(__dirname, '..', 'docs', 'api.mdx') correctly points to docs/docs/api.mdx, matching the file updated in the PR. Without 'docs', it would target docs/api.mdx, which doesn't align with the actual output location.



##########
docs/scripts/generate-api-index.mjs:
##########
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Generates a comprehensive API index MDX file from the OpenAPI spec.
+ * This creates the api.mdx landing page with all endpoints organized by category.
+ */
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SPEC_PATH = path.join(__dirname, '..', 'static', 'resources', 'openapi.json');
+const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'api.mdx');
+
+// Category groupings for better organization
+const CATEGORY_GROUPS = {
+  'Authentication': ['Security'],
+  'Core Resources': ['Dashboards', 'Charts', 'Datasets', 'Database'],
+  'Data Exploration': ['Explore', 'SQL Lab', 'Queries', 'Datasources', 'Advanced Data Type'],
+  'Organization & Customization': ['Tags', 'Annotation Layers', 'CSS Templates'],
+  'Sharing & Embedding': [
+    'Dashboard Permanent Link', 'Explore Permanent Link', 'SQL Lab Permanent Link',
+    'Embedded Dashboard', 'Dashboard Filter State', 'Explore Form Data'
+  ],
+  'Scheduling & Alerts': ['Report Schedules'],
+  'Security & Access Control': [
+    'Security Roles', 'Security Users', 'Security Permissions',
+    'Security Resources (View Menus)', 'Security Permissions on Resources (View Menus)',
+    'Row Level Security'
+  ],
+  'Import/Export & Administration': ['Import/export', 'CacheRestApi', 'LogRestApi'],
+  'User & System': ['Current User', 'User', 'Menu', 'Available Domains', 'AsyncEventsRestApi', 'OpenApi'],
+};
+
+function slugify(text) {
+  return text
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/(^-|-$)/g, '');
+}
+
+function generateEndpointLink(summary) {
+  // Convert summary to the slug format used by docusaurus-openapi-docs
+  return slugify(summary);
+}
+
+function main() {

Review Comment:
   <!-- Bito Reply -->
   Your reasoning makes sense for a build script. Letting Node throw the native error provides a clear stack trace directly pointing to the issue (missing file or invalid JSON), which is more helpful for debugging than a wrapped error. For build-time failures, explicit errors are preferable to silent failures or generic messages.
   
   **docs/scripts/generate-api-index.mjs**
   ```
   const spec = JSON.parse(fs.readFileSync(SPEC_PATH, 'utf-8'));
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734326763


##########
docs/docs/api.mdx:
##########
@@ -1,40 +1,590 @@
 ---
-title: API
+title: API Reference
 hide_title: true
 sidebar_position: 10
 ---
 
-import SwaggerUI from 'swagger-ui-react';
-import openapi from '/resources/openapi.json';
-import 'swagger-ui-react/swagger-ui.css';
 import { Alert } from 'antd';
 
-## API
+## REST API Reference
 
-Superset's public **REST API** follows the
-[OpenAPI specification](https://swagger.io/specification/), and is
-documented here. The docs below are generated using
-[Swagger React UI](https://www.npmjs.com/package/swagger-ui-react).
-
-:::resources
-- [Blog: The Superset REST API](https://preset.io/blog/2020-10-01-superset-api/)
-- [Blog: Accessing APIs with Superset](https://preset.io/blog/accessing-apis-with-superset/)
-:::
+Superset exposes a comprehensive **REST API** that follows the [OpenAPI specification](https://swagger.io/specification/).
+You can use this API to programmatically interact with Superset for automation, integrations, and custom applications.
 
 <Alert
   type="info"
-  message={
-    <div>
-      <strong>NOTE! </strong>
-      You can find an interactive version of this documentation on your local Superset
-      instance at <strong>/swagger/v1</strong> (unless disabled)
-    </div>
+  showIcon
+  message="Code Samples & Schema Documentation"
+  description={
+    <span>
+      Each endpoint includes ready-to-use code samples in <strong>cURL</strong>, <strong>Python</strong>, and <strong>JavaScript</strong>.
+      The sidebar includes <strong>Schema definitions</strong> for detailed data model documentation.
+    </span>
   }
+  style={{ marginBottom: '24px' }}
 />
 
-<br />
-<br />
-<hr />
-<div className="swagger-container">
-  <SwaggerUI spec={openapi} />
-</div>
+---
+
+### Authentication
+
+Most API endpoints require authentication via JWT tokens.
+
+#### Quick Start
+
+```bash
+# 1. Get a JWT token
+curl -X POST http://localhost:8088/api/v1/security/login \
+  -H "Content-Type: application/json" \
+  -d '{"username": "admin", "password": "admin", "provider": "db"}'
+
+# 2. Use the access_token from the response
+curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
+  http://localhost:8088/api/v1/dashboard/
+```
+
+#### Security Endpoints
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get the CSRF token](./api/get-the-csrf-token) | `/api/v1/security/csrf_token/` |
+| `POST` | [Get a guest token](./api/get-a-guest-token) | `/api/v1/security/guest_token/` |
+| `POST` | [Create security login](./api/create-security-login) | `/api/v1/security/login` |
+| `POST` | [Create security refresh](./api/create-security-refresh) | `/api/v1/security/refresh` |
+
+---
+
+### API Endpoints
+
+#### Core Resources
+
+<details>
+<summary><strong>Dashboards</strong> (26 endpoints) — Create, read, update, and delete dashboards.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete dashboards](./api/bulk-delete-dashboards) | `/api/v1/dashboard/` |
+| `GET` | [Get a list of dashboards](./api/get-a-list-of-dashboards) | `/api/v1/dashboard/` |
+| `POST` | [Create a new dashboard](./api/create-a-new-dashboard) | `/api/v1/dashboard/` |
+| `GET` | [Get metadata information about this API resource (dashboard--info)](./api/get-metadata-information-about-this-api-resource-dashboard-info) | `/api/v1/dashboard/_info` |
+| `GET` | [Get a dashboard detail information](./api/get-a-dashboard-detail-information) | `/api/v1/dashboard/{id_or_slug}` |
+| `GET` | [Get a dashboard's chart definitions.](./api/get-a-dashboards-chart-definitions) | `/api/v1/dashboard/{id_or_slug}/charts` |
+| `POST` | [Create a copy of an existing dashboard](./api/create-a-copy-of-an-existing-dashboard) | `/api/v1/dashboard/{id_or_slug}/copy/` |
+| `GET` | [Get dashboard's datasets](./api/get-dashboards-datasets) | `/api/v1/dashboard/{id_or_slug}/datasets` |
+| `DELETE` | [Delete a dashboard's embedded configuration](./api/delete-a-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `GET` | [Get the dashboard's embedded configuration](./api/get-the-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `POST` | [Set a dashboard's embedded configuration](./api/set-a-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `PUT` | [Update dashboard by id_or_slug embedded](./api/update-dashboard-by-id-or-slug-embedded) | `/api/v1/dashboard/{id_or_slug}/embedded` |
+| `GET` | [Get dashboard's tabs](./api/get-dashboards-tabs) | `/api/v1/dashboard/{id_or_slug}/tabs` |
+| `DELETE` | [Delete a dashboard](./api/delete-a-dashboard) | `/api/v1/dashboard/{pk}` |
+| `PUT` | [Update a dashboard](./api/update-a-dashboard) | `/api/v1/dashboard/{pk}` |
+| `POST` | [Compute and cache a screenshot (dashboard-pk-cache-dashboard-screenshot)](./api/compute-and-cache-a-screenshot-dashboard-pk-cache-dashboard-screenshot) | `/api/v1/dashboard/{pk}/cache_dashboard_screenshot/` |
+| `PUT` | [Update colors configuration for a dashboard.](./api/update-colors-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/colors` |
+| `DELETE` | [Remove the dashboard from the user favorite list](./api/remove-the-dashboard-from-the-user-favorite-list) | `/api/v1/dashboard/{pk}/favorites/` |
+| `POST` | [Mark the dashboard as favorite for the current user](./api/mark-the-dashboard-as-favorite-for-the-current-user) | `/api/v1/dashboard/{pk}/favorites/` |
+| `PUT` | [Update native filters configuration for a dashboard.](./api/update-native-filters-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/filters` |
+| `GET` | [Get a computed screenshot from cache (dashboard-pk-screenshot-digest)](./api/get-a-computed-screenshot-from-cache-dashboard-pk-screenshot-digest) | `/api/v1/dashboard/{pk}/screenshot/{digest}/` |
+| `GET` | [Get dashboard's thumbnail](./api/get-dashboards-thumbnail) | `/api/v1/dashboard/{pk}/thumbnail/{digest}/` |
+| `GET` | [Download multiple dashboards as YAML files](./api/download-multiple-dashboards-as-yaml-files) | `/api/v1/dashboard/export/` |
+| `GET` | [Check favorited dashboards for current user](./api/check-favorited-dashboards-for-current-user) | `/api/v1/dashboard/favorite_status/` |
+| `POST` | [Import dashboard(s) with associated charts/datasets/databases](./api/import-dashboard-s-with-associated-charts-datasets-databases) | `/api/v1/dashboard/import/` |
+| `GET` | [Get related fields data (dashboard-related-column-name)](./api/get-related-fields-data-dashboard-related-column-name) | `/api/v1/dashboard/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>Charts</strong> (20 endpoints) — Create, read, update, and delete charts (slices).</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete charts](./api/bulk-delete-charts) | `/api/v1/chart/` |
+| `GET` | [Get a list of charts](./api/get-a-list-of-charts) | `/api/v1/chart/` |
+| `POST` | [Create a new chart](./api/create-a-new-chart) | `/api/v1/chart/` |
+| `GET` | [Get metadata information about this API resource (chart--info)](./api/get-metadata-information-about-this-api-resource-chart-info) | `/api/v1/chart/_info` |
+| `DELETE` | [Delete a chart](./api/delete-a-chart) | `/api/v1/chart/{pk}` |
+| `GET` | [Get a chart detail information](./api/get-a-chart-detail-information) | `/api/v1/chart/{pk}` |
+| `PUT` | [Update a chart](./api/update-a-chart) | `/api/v1/chart/{pk}` |
+| `GET` | [Compute and cache a screenshot (chart-pk-cache-screenshot)](./api/compute-and-cache-a-screenshot-chart-pk-cache-screenshot) | `/api/v1/chart/{pk}/cache_screenshot/` |
+| `GET` | [Return payload data response for a chart](./api/return-payload-data-response-for-a-chart) | `/api/v1/chart/{pk}/data/` |
+| `DELETE` | [Remove the chart from the user favorite list](./api/remove-the-chart-from-the-user-favorite-list) | `/api/v1/chart/{pk}/favorites/` |
+| `POST` | [Mark the chart as favorite for the current user](./api/mark-the-chart-as-favorite-for-the-current-user) | `/api/v1/chart/{pk}/favorites/` |
+| `GET` | [Get a computed screenshot from cache (chart-pk-screenshot-digest)](./api/get-a-computed-screenshot-from-cache-chart-pk-screenshot-digest) | `/api/v1/chart/{pk}/screenshot/{digest}/` |
+| `GET` | [Get chart thumbnail](./api/get-chart-thumbnail) | `/api/v1/chart/{pk}/thumbnail/{digest}/` |
+| `POST` | [Return payload data response for the given query (chart-data)](./api/return-payload-data-response-for-the-given-query-chart-data) | `/api/v1/chart/data` |
+| `GET` | [Return payload data response for the given query (chart-data-cache-key)](./api/return-payload-data-response-for-the-given-query-chart-data-cache-key) | `/api/v1/chart/data/{cache_key}` |
+| `GET` | [Download multiple charts as YAML files](./api/download-multiple-charts-as-yaml-files) | `/api/v1/chart/export/` |
+| `GET` | [Check favorited charts for current user](./api/check-favorited-charts-for-current-user) | `/api/v1/chart/favorite_status/` |
+| `POST` | [Import chart(s) with associated datasets and databases](./api/import-chart-s-with-associated-datasets-and-databases) | `/api/v1/chart/import/` |
+| `GET` | [Get related fields data (chart-related-column-name)](./api/get-related-fields-data-chart-related-column-name) | `/api/v1/chart/related/{column_name}` |
+| `PUT` | [Warm up the cache for the chart](./api/warm-up-the-cache-for-the-chart) | `/api/v1/chart/warm_up_cache` |
+
+</details>
+
+<details>
+<summary><strong>Datasets</strong> (18 endpoints) — Manage datasets (tables) used for building charts.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete datasets](./api/bulk-delete-datasets) | `/api/v1/dataset/` |
+| `GET` | [Get a list of datasets](./api/get-a-list-of-datasets) | `/api/v1/dataset/` |
+| `POST` | [Create a new dataset](./api/create-a-new-dataset) | `/api/v1/dataset/` |
+| `GET` | [Get metadata information about this API resource (dataset--info)](./api/get-metadata-information-about-this-api-resource-dataset-info) | `/api/v1/dataset/_info` |
+| `DELETE` | [Delete a dataset](./api/delete-a-dataset) | `/api/v1/dataset/{pk}` |
+| `GET` | [Get a dataset](./api/get-a-dataset) | `/api/v1/dataset/{pk}` |
+| `PUT` | [Update a dataset](./api/update-a-dataset) | `/api/v1/dataset/{pk}` |
+| `DELETE` | [Delete a dataset column](./api/delete-a-dataset-column) | `/api/v1/dataset/{pk}/column/{column_id}` |
+| `DELETE` | [Delete a dataset metric](./api/delete-a-dataset-metric) | `/api/v1/dataset/{pk}/metric/{metric_id}` |
+| `PUT` | [Refresh and update columns of a dataset](./api/refresh-and-update-columns-of-a-dataset) | `/api/v1/dataset/{pk}/refresh` |
+| `GET` | [Get charts and dashboards count associated to a dataset](./api/get-charts-and-dashboards-count-associated-to-a-dataset) | `/api/v1/dataset/{pk}/related_objects` |
+| `GET` | [Get distinct values from field data (dataset-distinct-column-name)](./api/get-distinct-values-from-field-data-dataset-distinct-column-name) | `/api/v1/dataset/distinct/{column_name}` |
+| `POST` | [Duplicate a dataset](./api/duplicate-a-dataset) | `/api/v1/dataset/duplicate` |
+| `GET` | [Download multiple datasets as YAML files](./api/download-multiple-datasets-as-yaml-files) | `/api/v1/dataset/export/` |
+| `POST` | [Retrieve a table by name, or create it if it does not exist](./api/retrieve-a-table-by-name-or-create-it-if-it-does-not-exist) | `/api/v1/dataset/get_or_create/` |
+| `POST` | [Import dataset(s) with associated databases](./api/import-dataset-s-with-associated-databases) | `/api/v1/dataset/import/` |
+| `GET` | [Get related fields data (dataset-related-column-name)](./api/get-related-fields-data-dataset-related-column-name) | `/api/v1/dataset/related/{column_name}` |
+| `PUT` | [Warm up the cache for each chart powered by the given table](./api/warm-up-the-cache-for-each-chart-powered-by-the-given-table) | `/api/v1/dataset/warm_up_cache` |
+
+</details>
+
+<details>
+<summary><strong>Database</strong> (31 endpoints) — Manage database connections and metadata.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get a list of databases](./api/get-a-list-of-databases) | `/api/v1/database/` |
+| `POST` | [Create a new database](./api/create-a-new-database) | `/api/v1/database/` |
+| `GET` | [Get metadata information about this API resource (database--info)](./api/get-metadata-information-about-this-api-resource-database-info) | `/api/v1/database/_info` |
+| `DELETE` | [Delete a database](./api/delete-a-database) | `/api/v1/database/{pk}` |
+| `GET` | [Get a database](./api/get-a-database) | `/api/v1/database/{pk}` |
+| `PUT` | [Change a database](./api/change-a-database) | `/api/v1/database/{pk}` |
+| `GET` | [Get all catalogs from a database](./api/get-all-catalogs-from-a-database) | `/api/v1/database/{pk}/catalogs/` |
+| `GET` | [Get a database connection info](./api/get-a-database-connection-info) | `/api/v1/database/{pk}/connection` |
+| `GET` | [Get function names supported by a database](./api/get-function-names-supported-by-a-database) | `/api/v1/database/{pk}/function_names/` |
+| `GET` | [Get charts and dashboards count associated to a database](./api/get-charts-and-dashboards-count-associated-to-a-database) | `/api/v1/database/{pk}/related_objects/` |
+| `GET` | [The list of the database schemas where to upload information](./api/the-list-of-the-database-schemas-where-to-upload-information) | `/api/v1/database/{pk}/schemas_access_for_file_upload/` |
+| `GET` | [Get all schemas from a database](./api/get-all-schemas-from-a-database) | `/api/v1/database/{pk}/schemas/` |
+| `GET` | [Get database select star for table (database-pk-select-star-table-name)](./api/get-database-select-star-for-table-database-pk-select-star-table-name) | `/api/v1/database/{pk}/select_star/{table_name}/` |
+| `GET` | [Get database select star for table (database-pk-select-star-table-name-schema-name)](./api/get-database-select-star-for-table-database-pk-select-star-table-name-schema-name) | `/api/v1/database/{pk}/select_star/{table_name}/{schema_name}/` |
+| `DELETE` | [Delete a SSH tunnel](./api/delete-a-ssh-tunnel) | `/api/v1/database/{pk}/ssh_tunnel/` |
+| `POST` | [Re-sync all permissions for a database connection](./api/re-sync-all-permissions-for-a-database-connection) | `/api/v1/database/{pk}/sync_permissions/` |
+| `GET` | [Get table extra metadata (database-pk-table-extra-table-name-schema-name)](./api/get-table-extra-metadata-database-pk-table-extra-table-name-schema-name) | `/api/v1/database/{pk}/table_extra/{table_name}/{schema_name}/` |
+| `GET` | [Get table metadata](./api/get-table-metadata) | `/api/v1/database/{pk}/table_metadata/` |
+| `GET` | [Get table extra metadata (database-pk-table-metadata-extra)](./api/get-table-extra-metadata-database-pk-table-metadata-extra) | `/api/v1/database/{pk}/table_metadata/extra/` |
+| `GET` | [Get database table metadata](./api/get-database-table-metadata) | `/api/v1/database/{pk}/table/{table_name}/{schema_name}/` |
+| `GET` | [Get a list of tables for given database](./api/get-a-list-of-tables-for-given-database) | `/api/v1/database/{pk}/tables/` |
+| `POST` | [Upload a file to a database table](./api/upload-a-file-to-a-database-table) | `/api/v1/database/{pk}/upload/` |
+| `POST` | [Validate arbitrary SQL](./api/validate-arbitrary-sql) | `/api/v1/database/{pk}/validate_sql/` |
+| `GET` | [Get names of databases currently available](./api/get-names-of-databases-currently-available) | `/api/v1/database/available/` |
+| `GET` | [Download database(s) and associated dataset(s) as a zip file](./api/download-database-s-and-associated-dataset-s-as-a-zip-file) | `/api/v1/database/export/` |
+| `POST` | [Import database(s) with associated datasets](./api/import-database-s-with-associated-datasets) | `/api/v1/database/import/` |
+| `GET` | [Receive personal access tokens from OAuth2](./api/receive-personal-access-tokens-from-o-auth-2) | `/api/v1/database/oauth2/` |
+| `GET` | [Get related fields data (database-related-column-name)](./api/get-related-fields-data-database-related-column-name) | `/api/v1/database/related/{column_name}` |
+| `POST` | [Test a database connection](./api/test-a-database-connection) | `/api/v1/database/test_connection/` |
+| `POST` | [Upload a file and returns file metadata](./api/upload-a-file-and-returns-file-metadata) | `/api/v1/database/upload_metadata/` |
+| `POST` | [Validate database connection parameters](./api/validate-database-connection-parameters) | `/api/v1/database/validate_parameters/` |
+
+</details>
+
+#### Data Exploration
+
+<details>
+<summary><strong>Explore</strong> (1 endpoints) — Chart exploration and data querying endpoints.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Assemble Explore related information in a single endpoint](./api/assemble-explore-related-information-in-a-single-endpoint) | `/api/v1/explore/` |
+
+</details>
+
+<details>
+<summary><strong>SQL Lab</strong> (6 endpoints) — Execute SQL queries and manage SQL Lab sessions.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get the bootstrap data for SqlLab page](./api/get-the-bootstrap-data-for-sql-lab-page) | `/api/v1/sqllab/` |
+| `POST` | [Estimate the SQL query execution cost](./api/estimate-the-sql-query-execution-cost) | `/api/v1/sqllab/estimate/` |
+| `POST` | [Execute a SQL query](./api/execute-a-sql-query) | `/api/v1/sqllab/execute/` |
+| `GET` | [Export the SQL query results to a CSV](./api/export-the-sql-query-results-to-a-csv) | `/api/v1/sqllab/export/{client_id}/` |
+| `POST` | [Format SQL code](./api/format-sql-code) | `/api/v1/sqllab/format_sql/` |
+| `GET` | [Get the result of a SQL query execution](./api/get-the-result-of-a-sql-query-execution) | `/api/v1/sqllab/results/` |
+
+</details>
+
+<details>
+<summary><strong>Queries</strong> (17 endpoints) — View and manage SQL Lab query history.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get a list of queries](./api/get-a-list-of-queries) | `/api/v1/query/` |
+| `GET` | [Get query detail information](./api/get-query-detail-information) | `/api/v1/query/{pk}` |
+| `GET` | [Get distinct values from field data (query-distinct-column-name)](./api/get-distinct-values-from-field-data-query-distinct-column-name) | `/api/v1/query/distinct/{column_name}` |
+| `GET` | [Get related fields data (query-related-column-name)](./api/get-related-fields-data-query-related-column-name) | `/api/v1/query/related/{column_name}` |
+| `POST` | [Manually stop a query with client_id](./api/manually-stop-a-query-with-client-id) | `/api/v1/query/stop` |
+| `GET` | [Get a list of queries that changed after last_updated_ms](./api/get-a-list-of-queries-that-changed-after-last-updated-ms) | `/api/v1/query/updated_since` |
+| `DELETE` | [Bulk delete saved queries](./api/bulk-delete-saved-queries) | `/api/v1/saved_query/` |
+| `GET` | [Get a list of saved queries](./api/get-a-list-of-saved-queries) | `/api/v1/saved_query/` |
+| `POST` | [Create a saved query](./api/create-a-saved-query) | `/api/v1/saved_query/` |
+| `GET` | [Get metadata information about this API resource (saved-query--info)](./api/get-metadata-information-about-this-api-resource-saved-query-info) | `/api/v1/saved_query/_info` |
+| `DELETE` | [Delete a saved query](./api/delete-a-saved-query) | `/api/v1/saved_query/{pk}` |
+| `GET` | [Get a saved query](./api/get-a-saved-query) | `/api/v1/saved_query/{pk}` |
+| `PUT` | [Update a saved query](./api/update-a-saved-query) | `/api/v1/saved_query/{pk}` |
+| `GET` | [Get distinct values from field data (saved-query-distinct-column-name)](./api/get-distinct-values-from-field-data-saved-query-distinct-column-name) | `/api/v1/saved_query/distinct/{column_name}` |
+| `GET` | [Download multiple saved queries as YAML files](./api/download-multiple-saved-queries-as-yaml-files) | `/api/v1/saved_query/export/` |
+| `POST` | [Import saved queries with associated databases](./api/import-saved-queries-with-associated-databases) | `/api/v1/saved_query/import/` |
+| `GET` | [Get related fields data (saved-query-related-column-name)](./api/get-related-fields-data-saved-query-related-column-name) | `/api/v1/saved_query/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>Datasources</strong> (1 endpoints) — Query datasource metadata and column values.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Get possible values for a datasource column](./api/get-possible-values-for-a-datasource-column) | `/api/v1/datasource/{datasource_type}/{datasource_id}/column/{column_name}/values/` |
+
+</details>
+
+<details>
+<summary><strong>Advanced Data Type</strong> (2 endpoints) — Endpoints for advanced data type operations and conversions.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | [Return an AdvancedDataTypeResponse](./api/return-an-advanced-data-type-response) | `/api/v1/advanced_data_type/convert` |
+| `GET` | [Return a list of available advanced data types](./api/return-a-list-of-available-advanced-data-types) | `/api/v1/advanced_data_type/types` |
+
+</details>
+
+#### Organization & Customization
+
+<details>
+<summary><strong>Tags</strong> (15 endpoints) — Organize assets with tags.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete tags](./api/bulk-delete-tags) | `/api/v1/tag/` |
+| `GET` | [Get a list of tags](./api/get-a-list-of-tags) | `/api/v1/tag/` |
+| `POST` | [Create a tag](./api/create-a-tag) | `/api/v1/tag/` |
+| `GET` | [Get metadata information about tag API endpoints](./api/get-metadata-information-about-tag-api-endpoints) | `/api/v1/tag/_info` |
+| `POST` | [Add tags to an object](./api/add-tags-to-an-object) | `/api/v1/tag/{object_type}/{object_id}/` |
+| `DELETE` | [Delete a tagged object](./api/delete-a-tagged-object) | `/api/v1/tag/{object_type}/{object_id}/{tag}/` |
+| `DELETE` | [Delete a tag](./api/delete-a-tag) | `/api/v1/tag/{pk}` |
+| `GET` | [Get a tag detail information](./api/get-a-tag-detail-information) | `/api/v1/tag/{pk}` |
+| `PUT` | [Update a tag](./api/update-a-tag) | `/api/v1/tag/{pk}` |
+| `DELETE` | [Delete tag by pk favorites](./api/delete-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
+| `POST` | [Create tag by pk favorites](./api/create-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
+| `POST` | [Bulk create tags and tagged objects](./api/bulk-create-tags-and-tagged-objects) | `/api/v1/tag/bulk_create` |
+| `GET` | [Get tag favorite status](./api/get-tag-favorite-status) | `/api/v1/tag/favorite_status/` |
+| `GET` | [Get all objects associated with a tag](./api/get-all-objects-associated-with-a-tag) | `/api/v1/tag/get_objects/` |
+| `GET` | [Get related fields data (tag-related-column-name)](./api/get-related-fields-data-tag-related-column-name) | `/api/v1/tag/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>Annotation Layers</strong> (14 endpoints) — Manage annotation layers and annotations for charts.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Delete multiple annotation layers in a bulk operation](./api/delete-multiple-annotation-layers-in-a-bulk-operation) | `/api/v1/annotation_layer/` |
+| `GET` | [Get a list of annotation layers (annotation-layer)](./api/get-a-list-of-annotation-layers-annotation-layer) | `/api/v1/annotation_layer/` |
+| `POST` | [Create an annotation layer (annotation-layer)](./api/create-an-annotation-layer-annotation-layer) | `/api/v1/annotation_layer/` |
+| `GET` | [Get metadata information about this API resource (annotation-layer--info)](./api/get-metadata-information-about-this-api-resource-annotation-layer-info) | `/api/v1/annotation_layer/_info` |
+| `DELETE` | [Delete annotation layer (annotation-layer-pk)](./api/delete-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
+| `GET` | [Get an annotation layer (annotation-layer-pk)](./api/get-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
+| `PUT` | [Update an annotation layer (annotation-layer-pk)](./api/update-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
+| `DELETE` | [Bulk delete annotation layers](./api/bulk-delete-annotation-layers) | `/api/v1/annotation_layer/{pk}/annotation/` |
+| `GET` | [Get a list of annotation layers (annotation-layer-pk-annotation)](./api/get-a-list-of-annotation-layers-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
+| `POST` | [Create an annotation layer (annotation-layer-pk-annotation)](./api/create-an-annotation-layer-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
+| `DELETE` | [Delete annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/delete-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
+| `GET` | [Get an annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/get-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
+| `PUT` | [Update an annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/update-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
+| `GET` | [Get related fields data (annotation-layer-related-column-name)](./api/get-related-fields-data-annotation-layer-related-column-name) | `/api/v1/annotation_layer/related/{column_name}` |
+
+</details>
+
+<details>
+<summary><strong>CSS Templates</strong> (8 endpoints) — Manage CSS templates for custom dashboard styling.</summary>
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `DELETE` | [Bulk delete CSS templates](./api/bulk-delete-css-templates) | `/api/v1/css_template/` |
+| `GET` | [Get a list of CSS templates](./api/get-a-list-of-css-templates) | `/api/v1/css_template/` |
+| `POST` | [Create a CSS template](./api/create-a-css-template) | `/api/v1/css_template/` |
+| `GET` | [Get metadata information about this API resource (css-template--info)](./api/get-metadata-information-about-this-api-resource-css-template-info) | `/api/v1/css_template/_info` |
+| `DELETE` | [Delete a CSS template](./api/delete-a-css-template) | `/api/v1/css_template/{pk}` |
+| `GET` | [Get a CSS template](./api/get-a-css-template) | `/api/v1/css_template/{pk}` |
+| `PUT` | [Update a CSS template](./api/update-a-css-template) | `/api/v1/css_template/{pk}` |
+| `GET` | [Get related fields data (css-template-related-column-name)](./api/get-related-fields-data-css-template-related-column-name) | `/api/v1/css_template/related/{column_name}` |

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Broken Documentation Links</b></div>
   <div id="fix">
   
   The updated link paths (e.g., './api/bulk-delete-css-templates') point to non-existent files, as no 'api' subdirectory exists in docs/docs/. This breaks navigation for users reading the API reference. If these are intended as placeholders, consider removing the links or adding redirects until the detail pages are created.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #f4daa5</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org


Re: [PR] docs: add interactive API reference using docusaurus-openapi-docs [superset]

Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #37434:
URL: https://github.com/apache/superset/pull/37434#discussion_r2734373812


##########
docs/yarn.lock:
##########
@@ -14243,16 +15205,44 @@ xss@^1.0.14:
     commander "^2.20.3"
     cssfilter "0.0.10"
 
+y18n@^5.0.5:
+  version "5.0.8"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+  integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
 yallist@^3.0.2:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
   integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
 
-yaml@^1.10.0:
+yaml-ast-parser@0.0.43:
+  version "0.0.43"
+  resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb"
+  integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==
+
+yaml@1.10.2, yaml@^1.10.0:

Review Comment:
   Same as above — `yaml@1.10.2` is a transitive dependency, not directly controlled by this PR. It's pulled in by the dependency tree. Upgrading transitive dependencies requires upstream packages to update their ranges. This isn't something we can fix in this PR without potentially breaking compatibility.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org