ScyllaDB University Live | Free Virtual Training Event
Learn more
ScyllaDB Documentation Logo Documentation
  • Deployments
    • Cloud
    • Server
  • Tools
    • ScyllaDB Manager
    • ScyllaDB Monitoring Stack
    • ScyllaDB Operator
  • Drivers
    • CQL Drivers
    • DynamoDB Drivers
    • Supported Driver Versions
  • Resources
    • ScyllaDB University
    • Community Forum
    • Tutorials
Install
Ask AI
ScyllaDB Docs ScyllaDB Sphinx Theme Examples API Documentation REST API (Redocly)

REST API (Redocly)¶

The ScyllaDB Cloud documentation uses Redocly to render OpenAPI/Swagger specifications as interactive API documentation.

Note

Currently, only ScyllaDB Cloud Docs uses REST API documentation with Redocly.

Interested in making this a reusable extension? Let us know in this issue #722.

How it works¶

The extension:

  1. Downloads the OpenAPI specification from the configured URL

  2. Generates code snippets (e.g., curl examples) using snippet-enricher-cli

  3. Saves the enriched spec to _static/swagger.json

  4. Renders the API documentation using Redocly at /api.html

Prerequisites¶

Install the required dependencies:

poetry add requests
npm install -g snippet-enricher-cli

Configuration¶

Add to conf.py¶

Configure the OpenAPI extension and specify the spec URL:

extensions = [
    # ... other extensions
    "scylladb_openapi"
]

# Additional pages
html_additional_pages = {'api': 'api.html'}

# Additional static paths
html_static_path = ['openapi']

# Custom CSS
html_css_files = [
    'custom.css',
]

# OpenAPI configuration
scylladb_openapi_url = 'https://api.cloud.scylladb.com/api-docs.json'
scylladb_openapi_server_url = 'https://api.cloud.scylladb.com'
scylladb_openapi_output_file = '/_static/swagger.json'

Create the extension¶

Create _ext/scylladb_openapi.py:

# -*- coding: utf-8 -*-
import json
import requests
import subprocess

def build_openapi_spec(app, exception) -> None:
    config = app.config
    output_file = app.outdir + config.scylladb_openapi_output_file
    spec_url = config.scylladb_openapi_url
    server_url = config.scylladb_openapi_server_url

    download_openapi_spec(output_file, spec_url, server_url)
    generate_code_snippets(output_file)

def download_openapi_spec(output_file, spec_url, server_url) -> None:
    print("Downloading OpenAPI spec from: " + spec_url)
    response = requests.get(spec_url, allow_redirects=True)
    content = json.loads(response.text)

    # Set the production URL
    content["servers"][0]["url"] = server_url

    with open(output_file, "w+") as file:
        json.dump(content, file)
        print("OpenAPI document downloaded to: " + output_file)

def generate_code_snippets(output_file) -> None:
    cmd = f"snippet-enricher-cli --targets='shell_curl' --input={output_file}"

    process = subprocess.Popen(cmd, shell=True,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)

    out, err = process.communicate()
    errcode = process.returncode

    if errcode != 0:
        raise Exception("Error generating code snippets: " + str(err))

    # Decode URL-encoded placeholders
    modified_content = out.decode().replace('%7B', '{').replace('%7D', '}')

    with open(output_file, "w+") as file:
        file.write(modified_content)
        print("Code snippets generated to: " + output_file)

def setup(app):
    app.connect('build-finished', build_openapi_spec)
    app.add_config_value(
        "scylladb_openapi_url",
        default="https://api.cloud.scylladb.com/api-docs.json",
        rebuild="html",
    )
    app.add_config_value(
        "scylladb_openapi_server_url",
        default="https://api.cloud.scylladb.com",
        rebuild="html",
    )
    app.add_config_value(
        "scylladb_openapi_output_file",
        default="/_static/swagger.json",
        rebuild="html",
    )

Create the template¶

Create _templates/api.html:

{% extends "!layout.html" %}

{% block title %} API Reference | Scylla Docs {% endblock %}

{% set openapi_path = pathto('_static/swagger.json', 1) %}

{% block scripts %}
<script type="text/javascript" src="{{ pathto('_static/js/runtime.bundle.js', 1) }}"></script>
<script type="text/javascript" src="{{ pathto('_static/js/main.bundle.js', 1) }}"></script>
{% include 'scylladb-scripts.html' %}
{% include 'local-scripts.html' %}
{% endblock %}

{% set hide_pre_content = "true" %}
{% set hide_post_content = "true" %}
{% set hide_sidebar = "true" %}
{% set hide_secondary_sidebar = "true" %}
{% set full_width = "true" %}

{% set body ="<div id='redoc'></div>
<script src='https://cdn.redoc.ly/redoc/v2.1.3/bundles/redoc.standalone.js'></script>
<script>
    function getCssVariableValue(variable) {
        return getComputedStyle(document.documentElement)
            .getPropertyValue(variable).trim();
    }

    function calculateScrollOffset(element1Selector, element2Selector) {
        const element1 = document.querySelector(element1Selector);
        const element2 = document.querySelector(element2Selector);
        const element1Height = element1 ? element1.offsetHeight : 0;
        const element2Height = element2 ? element2.offsetHeight : 0;
        return element1Height + element2Height;
    }

    function initializeRedoc() {
        const textColor = getCssVariableValue('--text-color');
        const primaryColor = getCssVariableValue('--primary-color');
        const linkColor = getCssVariableValue('--link-color');
        const sidebarBackgroundColor = getCssVariableValue('--navigation-bg');
        const borderColor = getCssVariableValue('--border-color');
        const scrollOffset = calculateScrollOffset('.header', '.promo-banner');

        Redoc.init('" + openapi_path + "', {
            scrollYOffset: scrollOffset,
            hideDownloadButton: true,
            theme: {
                sidebar: {
                    backgroundColor: sidebarBackgroundColor,
                    width: '357px',
                    textColor: textColor,
                },
                colors: {
                    primary: { main: textColor },
                },
                typography: {
                    fontFamily: 'Roboto, sans-serif',
                    fontSize: '16px',
                },
            },
        }, document.getElementById('redoc'));
    }

    document.addEventListener('DOMContentLoaded', function() {
        document.documentElement.classList.add('openapi-page');
        initializeRedoc();
    });
</script>
" %}

Custom styling¶

Create _static/custom.css to style Redocly:

/* Reset scroll padding */
.openapi-page {
    scroll-padding-top: 0 !important;
}

.openapi-page .content-body {
    padding: 0;
}

/* Sidebar styling */
#redoc .menu-content .scrollbar-container > ul {
    padding: 30px 40px;
}

#redoc .menu-content ul ul {
    border-left: 1px solid var(--link-color);
    margin-left: 20px;
}

#redoc .menu-content label.active,
#redoc .menu-content label:hover {
    color: var(--link-color);
    background: transparent;
}

/* Right panel */
#redoc .http-verb {
    border-radius: 4px;
}

#redoc code {
    color: inherit;
    background: transparent;
}

Was this page helpful?

PREVIOUS
Doxygen
NEXT
Collapse
  • Create an issue
  • Edit this page

On this page

  • REST API (Redocly)
    • How it works
    • Prerequisites
    • Configuration
      • Add to conf.py
      • Create the extension
      • Create the template
      • Custom styling
ScyllaDB Sphinx Theme
  • 1.8
    • 1.8
    • 1.7
    • 1.6
    • 1.5
    • 1.4
    • 1.3
    • 1.2
    • 1.1
  • Getting started
    • Toolchain
    • Installation
    • Quickstart
  • Configuration
    • Template options
    • Page options
    • Multiversion options
    • Markdown support
    • Redirects support
    • AI chatbot support (beta)
    • Search support
    • Dependabot support
  • Commands
  • Deployment
    • Production deployment
    • Pull requests previews
    • Centralized publication
  • Examples
    • Admonitions
    • Alert
    • API Documentation
      • Python
      • Doxygen
      • REST API (Redocly)
    • Collapse
    • Code blocks
    • Diagrams
    • Grid
    • Glossary
    • Headings
    • Hero box
    • Icons
    • Images
    • Includes
    • Labels
    • Links
    • Lists
    • Mascots
    • Panel box
    • Substitutions
    • Tables
    • Tabs
    • Text
    • TOC
    • Tooltips
    • Topic box
    • Versions
    • Videos
  • Upgrade guides
    • Upgrading from 1.7 to 1.8
    • Upgrading from 1.6 to 1.7
    • Upgrading from 1.5 to 1.6
    • Upgrading from 1.4 to 1.5
    • Upgrading from 1.3 to 1.4
    • Upgrading from 1.2 to 1.3
    • Upgrading from 1.1 to 1.2
    • Upgrading from 1.0 to 1.1
    • Upgrading from 0.x to 1.0
    • Changelog
  • Contribute
    • Contribute to the documentation
    • Contribute to the theme
    • Source Code
Docs Tutorials University Contact Us About Us
© 2025 ScyllaDB | Terms of Service | Privacy Policy | ScyllaDB, and ScyllaDB Cloud, are registered trademarks of ScyllaDB, Inc.
Last updated on 24 Nov 2025.
Powered by Sphinx 7.4.7 & ScyllaDB Theme 1.8.9
Ask AI