Wiki — API Reference (endpoints · params)
A Stripe-style REST API reference page for the fictional Aurora DB service, with a persistent left nav of resources and endpoints, a readable main column, and a sticky dark code panel. Each endpoint block pairs an HTTP method badge and path with a parameters table and a responses section of status badges. The panel offers cURL, JavaScript and Python tabs, copy buttons, and a collapsible JSON response tree. JS adds an endpoint filter, a required-only param toggle, deep-link anchors and TOC scrollspy.
MCP
Código
:root {
--bg: #ffffff;
--bg-2: #f7f8fa;
--panel: #ffffff;
--ink: #1a1a1f;
--ink-2: #3a3a42;
--muted: #6b7280;
--line: rgba(20, 20, 30, 0.10);
--line-2: rgba(20, 20, 30, 0.18);
--link: #2563eb;
--link-hover: #1d4ed8;
--accent: #2563eb;
--note: #2563eb;
--tip: #16a34a;
--warn: #d97706;
--danger: #dc2626;
--code-bg: #f4f4f6;
--kbd-bg: #eceef2;
--r-sm: 6px;
--r-md: 10px;
--r-lg: 14px;
--sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
--serif: "Source Serif 4", Georgia, "Times New Roman", serif;
--mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
--topbar-h: 56px;
--sidebar-w: 244px;
--panel-w: 380px;
--m-get: #047857;
--m-get-bg: #ecfdf5;
--m-post: #1d4ed8;
--m-post-bg: #eff6ff;
--m-del: #b91c1c;
--m-del-bg: #fef2f2;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: calc(var(--topbar-h) + 18px); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
margin: 0;
background: var(--bg);
color: var(--ink);
font-family: var(--sans);
font-size: 15px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
a { color: var(--link); text-decoration: none; }
a:hover { color: var(--link-hover); text-decoration: underline; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.skip-link {
position: fixed; left: 12px; top: -60px; z-index: 200;
background: var(--ink); color: #fff; padding: 8px 14px;
border-radius: var(--r-sm); transition: top .15s ease;
}
.skip-link:focus { top: 12px; text-decoration: none; }
code {
font-family: var(--mono);
font-size: 0.86em;
background: var(--code-bg);
border: 1px solid var(--line);
border-radius: 5px;
padding: 0.08em 0.4em;
color: var(--ink-2);
}
/* ---------- TOPBAR ---------- */
.topbar {
position: sticky; top: 0; z-index: 60;
height: var(--topbar-h);
background: rgba(255, 255, 255, 0.86);
backdrop-filter: saturate(1.6) blur(10px);
border-bottom: 1px solid var(--line);
}
.topbar-inner {
height: 100%; display: flex; align-items: center; gap: 14px;
padding: 0 18px; max-width: 1480px; margin: 0 auto;
}
.brand { display: flex; align-items: center; gap: 8px; color: var(--ink); }
.brand:hover { text-decoration: none; }
.brand-mark { font-size: 19px; color: var(--accent); }
.brand-name { font-weight: 800; letter-spacing: -0.01em; }
.brand-tag {
font-size: 11px; font-weight: 600; color: var(--accent);
background: var(--m-post-bg); border: 1px solid var(--line);
padding: 1px 7px; border-radius: 999px;
}
.topbar-search { flex: 1; max-width: 360px; margin-left: 8px; }
.topbar-search input {
width: 100%; height: 34px; padding: 0 12px;
font-family: var(--sans); font-size: 13px; color: var(--ink);
background: var(--bg-2); border: 1px solid var(--line);
border-radius: var(--r-sm);
}
.topbar-search input:focus { background: #fff; border-color: var(--line-2); outline: 2px solid var(--accent); outline-offset: 1px; }
.topbar-actions { display: flex; align-items: center; gap: 12px; margin-left: auto; }
.env-pill {
display: inline-flex; align-items: center; gap: 6px;
font-family: var(--mono); font-size: 12px; color: var(--muted);
background: var(--bg-2); border: 1px solid var(--line);
padding: 4px 10px; border-radius: 999px;
}
.env-pill .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--tip); box-shadow: 0 0 0 3px rgba(22,163,74,.16); }
.btn {
display: inline-flex; align-items: center; height: 32px; padding: 0 14px;
font-size: 13px; font-weight: 600; border-radius: var(--r-sm);
border: 1px solid var(--line-2); cursor: pointer; background: #fff; color: var(--ink);
}
.btn.ghost:hover { background: var(--bg-2); text-decoration: none; border-color: var(--accent); color: var(--accent); }
.icon-btn {
display: none; align-items: center; justify-content: center;
width: 36px; height: 36px; border-radius: var(--r-sm);
background: transparent; border: 1px solid var(--line); cursor: pointer;
}
.burger { display: block; width: 16px; height: 2px; background: var(--ink); position: relative; }
.burger::before, .burger::after { content: ""; position: absolute; left: 0; width: 16px; height: 2px; background: var(--ink); }
.burger::before { top: -5px; } .burger::after { top: 5px; }
/* ---------- LAYOUT ---------- */
.layout {
display: grid;
grid-template-columns: var(--sidebar-w) 1fr;
max-width: 1480px; margin: 0 auto;
}
/* ---------- SIDEBAR ---------- */
.sidebar {
position: sticky; top: var(--topbar-h);
height: calc(100vh - var(--topbar-h));
border-right: 1px solid var(--line);
background: var(--bg);
}
.sidebar-scroll { height: 100%; overflow-y: auto; padding: 20px 14px 40px; }
.nav-group { margin-bottom: 20px; }
.nav-title {
margin: 0 0 6px; padding: 0 8px;
font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
text-transform: uppercase; color: var(--muted);
}
.nav-link {
display: flex; align-items: center; gap: 8px;
padding: 5px 8px; margin-bottom: 1px; border-radius: var(--r-sm);
font-size: 13.5px; color: var(--ink-2); line-height: 1.35;
}
.nav-link:hover { background: var(--bg-2); color: var(--ink); text-decoration: none; }
.nav-link.is-active { background: var(--m-post-bg); color: var(--accent); font-weight: 600; }
.nav-link[hidden] { display: none; }
.m {
flex: none; font-family: var(--mono); font-size: 9.5px; font-weight: 700;
letter-spacing: 0.03em; padding: 1px 4px; border-radius: 4px; line-height: 1.4;
}
.m-get { color: var(--m-get); background: var(--m-get-bg); }
.m-post { color: var(--m-post); background: var(--m-post-bg); }
.m-del { color: var(--m-del); background: var(--m-del-bg); }
.scrim {
position: fixed; inset: 0; z-index: 55;
background: rgba(15, 15, 25, 0.4); border: 0;
}
/* ---------- MAIN ---------- */
.main {
display: grid;
grid-template-columns: minmax(0, 1fr) var(--panel-w);
align-items: start;
gap: 0;
min-width: 0;
}
.doc-col {
max-width: 760px;
padding: 36px 40px 80px;
min-width: 0;
}
.crumbs { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 12.5px; color: var(--muted); margin-bottom: 20px; }
.crumbs span[aria-hidden] { color: var(--line-2); }
.crumbs span[aria-current] { color: var(--ink-2); font-weight: 600; }
.block { scroll-margin-top: calc(var(--topbar-h) + 18px); margin-bottom: 44px; }
.block:focus { outline: none; }
h1 { font-size: 30px; font-weight: 800; letter-spacing: -0.02em; margin: 0 0 14px; line-height: 1.15; }
h2 { font-size: 21px; font-weight: 700; letter-spacing: -0.01em; margin: 0 0 12px; }
h3 { font-size: 14px; font-weight: 700; margin: 24px 0 10px; }
.doc-col p { font-family: var(--serif); font-size: 16px; line-height: 1.65; color: var(--ink-2); margin: 0 0 14px; }
.lead { font-size: 17.5px !important; color: var(--ink) !important; }
.doc-col p code, td code { font-family: var(--mono); }
.foot-note { font-style: italic; color: var(--muted); font-size: 13.5px !important; margin-top: 22px !important; }
/* ---------- ENDPOINT HEAD ---------- */
.ep-head {
display: flex; align-items: center; gap: 10px;
padding: 10px 12px; margin-bottom: 14px;
background: var(--bg-2); border: 1px solid var(--line);
border-radius: var(--r-md); position: relative;
}
.method {
flex: none; font-family: var(--sans); font-size: 11px; font-weight: 800;
letter-spacing: 0.04em; padding: 3px 8px; border-radius: var(--r-sm);
}
.method.m-get { color: var(--m-get); background: var(--m-get-bg); border: 1px solid rgba(4,120,87,.2); }
.method.m-post { color: var(--m-post); background: var(--m-post-bg); border: 1px solid rgba(29,78,216,.2); }
.method.m-del { color: var(--m-del); background: var(--m-del-bg); border: 1px solid rgba(185,28,28,.2); }
.path { font-family: var(--mono); font-size: 13.5px; background: transparent; border: 0; padding: 0; color: var(--ink); font-weight: 500; }
.path-var { color: var(--accent); }
.anchor {
margin-left: auto; color: var(--muted); font-weight: 700; font-size: 16px;
opacity: 0; transition: opacity .12s ease; padding: 0 4px;
}
.ep-head:hover .anchor, .anchor:focus { opacity: 1; text-decoration: none; }
.ep-title { font-size: 22px; margin-bottom: 10px; }
/* ---------- PARAMS ---------- */
.params-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 22px; }
.params-title, .resp-title { margin: 0; }
.resp-title { margin-top: 24px; }
.filter-toggle {
display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
font-size: 12.5px; font-weight: 500; color: var(--ink-2);
user-select: none;
}
.filter-toggle input { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.table-wrap { overflow-x: auto; margin-top: 10px; border: 1px solid var(--line); border-radius: var(--r-md); }
table.params { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.params th {
text-align: left; font-weight: 700; font-size: 11px; letter-spacing: 0.04em;
text-transform: uppercase; color: var(--muted);
padding: 9px 14px; background: var(--bg-2); border-bottom: 1px solid var(--line);
}
table.params td { padding: 11px 14px; border-bottom: 1px solid var(--line); color: var(--ink-2); vertical-align: top; font-family: var(--sans); }
table.params tr:last-child td { border-bottom: 0; }
table.params td:first-child { white-space: nowrap; }
.ty { font-family: var(--mono) !important; font-size: 12px; color: var(--muted); }
.req-yes { color: var(--m-del); font-weight: 700; font-size: 11px; }
.req-no { color: var(--muted); font-size: 11px; }
tr[hidden] { display: none; }
/* ---------- RESPONSES ---------- */
.resp-list { list-style: none; margin: 12px 0 0; padding: 0; }
.resp-list li {
display: flex; align-items: baseline; gap: 12px;
padding: 9px 0; border-bottom: 1px dashed var(--line);
font-size: 14px; color: var(--ink-2);
}
.resp-list li:last-child { border-bottom: 0; }
.status {
flex: none; font-family: var(--mono); font-size: 12px; font-weight: 600;
padding: 2px 8px; border-radius: var(--r-sm);
}
.status.inline { font-size: 10px; padding: 1px 6px; }
.s-2xx { color: var(--tip); background: #ecfdf5; border: 1px solid rgba(22,163,74,.22); }
.s-4xx { color: var(--warn); background: #fffbeb; border: 1px solid rgba(217,119,6,.22); }
.s-5xx { color: var(--danger); background: #fef2f2; border: 1px solid rgba(220,38,38,.22); }
/* ---------- CALLOUTS ---------- */
.callout {
display: flex; gap: 12px; padding: 13px 15px; margin: 18px 0;
border: 1px solid var(--line); border-left-width: 3px; border-radius: var(--r-md);
background: var(--bg-2); font-size: 14px;
}
.callout div { font-family: var(--sans); line-height: 1.55; color: var(--ink-2); }
.callout-ic {
flex: none; width: 20px; height: 20px; border-radius: 50%;
display: grid; place-items: center; font-weight: 800; font-size: 12px; color: #fff;
}
.callout.note { border-left-color: var(--note); background: #eff6ff; }
.callout.note .callout-ic { background: var(--note); }
.callout.warn { border-left-color: var(--warn); background: #fffbeb; }
.callout.warn .callout-ic { background: var(--warn); }
/* ---------- CODE BLOCK (light) ---------- */
pre.code {
font-family: var(--mono); font-size: 13px; line-height: 1.6;
background: var(--code-bg); border: 1px solid var(--line);
border-radius: var(--r-md); padding: 12px 14px; overflow-x: auto; margin: 0;
}
pre.code code { background: none; border: 0; padding: 0; color: var(--ink); }
/* ---------- CODE PANEL (right, sticky) ---------- */
.code-panel {
position: sticky; top: var(--topbar-h);
align-self: start;
height: calc(100vh - var(--topbar-h));
padding: 24px 24px 24px 0;
overflow: hidden;
}
.cp-card {
height: 100%;
display: flex; flex-direction: column;
background: #0f1117; border: 1px solid #1f2330;
border-radius: var(--r-lg); overflow: hidden;
box-shadow: 0 12px 30px rgba(15,17,23,.18);
}
.cp-head { padding: 8px 8px 0; border-bottom: 1px solid #1f2330; background: #0c0e14; }
.lang-tabs { display: flex; gap: 2px; }
.lang-tab {
font-family: var(--sans); font-size: 12.5px; font-weight: 600;
color: #8b93a7; background: transparent; border: 0;
padding: 9px 14px; cursor: pointer; border-bottom: 2px solid transparent;
}
.lang-tab:hover { color: #c9d1e0; }
.lang-tab.is-active { color: #fff; border-bottom-color: #4f86f7; }
.cp-section { display: flex; flex-direction: column; min-height: 0; }
.cp-section:first-of-type { border-bottom: 1px solid #1f2330; }
.cp-section:last-of-type { flex: 1; min-height: 0; }
.cp-label {
display: flex; align-items: center; justify-content: space-between;
padding: 10px 14px 6px; font-size: 11px; font-weight: 700;
letter-spacing: 0.06em; text-transform: uppercase; color: #6b7488;
}
.cp-label .status.inline { letter-spacing: 0; }
.s-2xx.inline { color: #34d399; background: rgba(16,185,129,.12); border-color: rgba(16,185,129,.3); }
.copy-btn {
font-family: var(--sans); font-size: 11px; font-weight: 600;
color: #aeb6c8; background: #1a1e2b; border: 1px solid #2a2f40;
padding: 3px 9px; border-radius: var(--r-sm); cursor: pointer;
letter-spacing: 0; text-transform: none;
}
.copy-btn:hover { background: #242938; color: #fff; }
.copy-btn.copied { color: #34d399; border-color: rgba(16,185,129,.4); }
pre.code.dark {
background: transparent; border: 0; border-radius: 0;
padding: 4px 14px 14px; color: #e3e8f2; flex: 1; min-height: 0;
overflow: auto; font-size: 12.5px;
}
pre.code.dark code { color: #e3e8f2; }
pre.code.dark[hidden] { display: none; }
/* JSON tree */
.json-tree {
font-family: var(--mono); font-size: 12.5px; line-height: 1.6;
color: #e3e8f2; padding: 4px 14px 16px; overflow: auto;
flex: 1; min-height: 0;
}
.jt-row { white-space: pre; }
.jt-toggle {
display: inline-flex; align-items: center; justify-content: center;
width: 14px; height: 14px; margin-right: 2px; cursor: pointer;
color: #6b7488; background: none; border: 0; font-family: var(--mono);
font-size: 11px; vertical-align: baseline; transition: transform .12s ease;
}
.jt-toggle:hover { color: #fff; }
.jt-toggle.collapsed { transform: rotate(-90deg); }
.jt-key { color: #7fb2ff; }
.jt-str { color: #8ee2a8; }
.jt-num { color: #f0b27a; }
.jt-bool { color: #c792ea; }
.jt-null { color: #8b93a7; }
.jt-punc { color: #6b7488; }
.jt-collapsed-hint { color: #6b7488; font-style: italic; }
.jt-children.hidden { display: none; }
/* ---------- TOAST ---------- */
.toast {
position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 14px);
background: var(--ink); color: #fff; font-size: 13px; font-weight: 500;
padding: 9px 16px; border-radius: 999px; z-index: 120;
opacity: 0; pointer-events: none; transition: opacity .18s ease, transform .18s ease;
box-shadow: 0 8px 24px rgba(0,0,0,.25);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
/* ---------- RESPONSIVE ---------- */
@media (max-width: 1180px) {
:root { --panel-w: 330px; }
.doc-col { padding: 32px 28px 70px; }
}
@media (max-width: 980px) {
.main { grid-template-columns: minmax(0, 1fr); }
.code-panel {
position: static; height: auto; padding: 0 28px 40px;
}
.cp-card { height: auto; max-height: 560px; }
.doc-col { max-width: none; }
}
@media (max-width: 820px) {
.layout { grid-template-columns: 1fr; }
.icon-btn { display: inline-flex; }
.sidebar {
position: fixed; top: var(--topbar-h); left: 0; z-index: 56;
width: 280px; max-width: 84vw; height: calc(100vh - var(--topbar-h));
background: #fff; transform: translateX(-102%);
transition: transform .2s ease; box-shadow: 4px 0 24px rgba(0,0,0,.12);
}
.sidebar.open { transform: translateX(0); }
.env-pill { display: none; }
}
@media (prefers-reduced-motion: reduce) {
.sidebar { transition: none; }
}
@media (max-width: 520px) {
body { font-size: 14.5px; }
.topbar-inner { padding: 0 12px; gap: 10px; }
.topbar-search { display: none; }
.doc-col { padding: 24px 16px 60px; }
.code-panel { padding: 0 16px 32px; }
h1 { font-size: 25px; }
.ep-title { font-size: 19px; }
.doc-col p { font-size: 15.5px; }
.params-bar { flex-direction: column; align-items: flex-start; gap: 8px; }
.btn.ghost { display: none; }
}(function () {
"use strict";
const $ = (sel, ctx) => (ctx || document).querySelector(sel);
const $$ = (sel, ctx) => Array.from((ctx || document).querySelectorAll(sel));
/* ---------------- Toast ---------------- */
const toastEl = $("#toast");
let toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(() => toastEl.classList.remove("show"), 1800);
}
/* ---------------- Mobile nav drawer ---------------- */
const sidebar = $("#sidebar");
const navToggle = $("#navToggle");
const scrim = $("#scrim");
function setNav(open) {
sidebar.classList.toggle("open", open);
navToggle.setAttribute("aria-expanded", String(open));
navToggle.setAttribute("aria-label", open ? "Close navigation" : "Open navigation");
scrim.hidden = !open;
}
navToggle.addEventListener("click", () => setNav(!sidebar.classList.contains("open")));
scrim.addEventListener("click", () => setNav(false));
/* ---------------- Endpoint filter (left nav search) ---------------- */
const navSearch = $("#navSearch");
navSearch.addEventListener("input", () => {
const q = navSearch.value.trim().toLowerCase();
$$(".nav-group").forEach((group) => {
let visible = 0;
$$(".nav-link", group).forEach((link) => {
const match = link.textContent.toLowerCase().includes(q);
link.hidden = q && !match;
if (!link.hidden) visible++;
});
group.style.display = q && visible === 0 ? "none" : "";
});
});
/* ---------------- Smooth anchor + close drawer ---------------- */
$$('a[href^="#"]').forEach((a) => {
a.addEventListener("click", (e) => {
const id = a.getAttribute("href").slice(1);
const target = document.getElementById(id);
if (!target) return;
e.preventDefault();
target.scrollIntoView({ behavior: "smooth", block: "start" });
history.replaceState(null, "", "#" + id);
target.focus({ preventScroll: true });
if (window.innerWidth <= 820) setNav(false);
});
});
/* Anchor links inside endpoint heads -> copy deep link */
$$(".anchor").forEach((a) => {
a.addEventListener("click", () => {
const url = location.href.split("#")[0] + a.getAttribute("href");
if (navigator.clipboard) {
navigator.clipboard.writeText(url).then(() => toast("Link copied"), () => {});
}
});
});
/* ---------------- TOC scrollspy ---------------- */
const sections = $$("section.block");
const navLinks = $$(".nav-link");
const linkById = new Map();
navLinks.forEach((l) => {
const id = (l.getAttribute("href") || "").slice(1);
if (id) linkById.set(id, l);
});
function setActive(id) {
navLinks.forEach((l) => l.classList.remove("is-active"));
const link = linkById.get(id);
if (link) {
link.classList.add("is-active");
const scroll = $(".sidebar-scroll");
if (scroll) {
const lr = link.getBoundingClientRect();
const sr = scroll.getBoundingClientRect();
if (lr.top < sr.top + 40 || lr.bottom > sr.bottom - 40) {
link.scrollIntoView({ block: "nearest" });
}
}
}
}
if ("IntersectionObserver" in window) {
const seen = new Map();
const obs = new IntersectionObserver(
(entries) => {
entries.forEach((en) => seen.set(en.target.id, en.intersectionRatio));
let bestId = null;
let best = -1;
sections.forEach((s) => {
const r = seen.get(s.id) || 0;
const top = s.getBoundingClientRect().top;
if (top < 200 && r >= 0 && (r > best || (bestId === null))) {
// prefer the last section whose top is above the trigger line
}
});
// choose the section closest to (but above) the trigger line
let chosen = null;
sections.forEach((s) => {
const top = s.getBoundingClientRect().top;
if (top - 120 <= 0) chosen = s.id;
});
if (chosen) setActive(chosen);
},
{ rootMargin: "-110px 0px -65% 0px", threshold: [0, 0.25, 0.5, 1] }
);
sections.forEach((s) => obs.observe(s));
}
// also update on scroll for snappy highlight
let raf;
window.addEventListener(
"scroll",
() => {
if (raf) return;
raf = requestAnimationFrame(() => {
raf = null;
let chosen = sections[0] ? sections[0].id : null;
sections.forEach((s) => {
if (s.getBoundingClientRect().top - 120 <= 0) chosen = s.id;
});
if (chosen) setActive(chosen);
});
},
{ passive: true }
);
/* ---------------- Language tabs ---------------- */
const langTabs = $$(".lang-tab");
function selectLang(lang) {
langTabs.forEach((t) => {
const on = t.dataset.lang === lang;
t.classList.toggle("is-active", on);
t.setAttribute("aria-selected", String(on));
});
$$("[data-lang-pane]").forEach((p) => {
p.hidden = p.getAttribute("data-lang-pane") !== lang;
});
}
langTabs.forEach((t) => t.addEventListener("click", () => selectLang(t.dataset.lang)));
/* ---------------- Copy buttons ---------------- */
$$(".copy-btn").forEach((btn) => {
btn.addEventListener("click", () => {
let text = "";
if (btn.dataset.copy === "req") {
const active = $('[data-lang-pane]:not([hidden])');
text = active ? active.innerText : "";
} else if (btn.dataset.copy === "res") {
text = JSON.stringify(SAMPLE, null, 2);
}
const done = () => {
const old = btn.textContent;
btn.textContent = "Copied";
btn.classList.add("copied");
toast("Copied to clipboard");
setTimeout(() => {
btn.textContent = old;
btn.classList.remove("copied");
}, 1400);
};
if (navigator.clipboard) {
navigator.clipboard.writeText(text).then(done, () => toast("Copy failed"));
} else {
toast("Clipboard unavailable");
}
});
});
/* ---------------- Required-only param filters ---------------- */
$$(".req-filter").forEach((cb) => {
cb.addEventListener("change", () => {
const wrap = cb.closest(".endpoint") || cb.closest(".block");
const table = wrap ? $("table.params", wrap) : null;
if (!table) return;
let shown = 0;
$$("tbody tr", table).forEach((row) => {
const required = row.dataset.required === "true";
row.hidden = cb.checked && !required;
if (!row.hidden) shown++;
});
toast(cb.checked ? `Showing ${shown} required param${shown === 1 ? "" : "s"}` : "Showing all params");
});
});
/* ---------------- Collapsible JSON tree ---------------- */
const SAMPLE = {
id: "clu_8Kdb20fA",
object: "cluster",
name: "prod-eu",
region: "eu-west-3",
tier: "verdant",
status: "provisioning",
encryption: true,
replicas: [
{ id: "rep_01", role: "primary", healthy: true, lag_ms: 0 },
{ id: "rep_02", role: "read", healthy: true, lag_ms: 12 },
{ id: "rep_03", role: "read", healthy: true, lag_ms: 9 }
],
latest_snapshot: null,
created_at: "2026-06-08T14:22:05Z"
};
const treeEl = $("#jsonTree");
function tokenFor(val) {
if (val === null) return { cls: "jt-null", text: "null" };
const t = typeof val;
if (t === "string") return { cls: "jt-str", text: JSON.stringify(val) };
if (t === "number") return { cls: "jt-num", text: String(val) };
if (t === "boolean") return { cls: "jt-bool", text: String(val) };
return null;
}
function makeRow(indent) {
const row = document.createElement("div");
row.className = "jt-row";
row.style.paddingLeft = indent * 14 + "px";
return row;
}
function punc(text) {
const s = document.createElement("span");
s.className = "jt-punc";
s.textContent = text;
return s;
}
function renderValue(container, value, indent, keyName, trailingComma) {
const isArr = Array.isArray(value);
const isObj = value && typeof value === "object";
if (!isObj) {
// leaf
const row = makeRow(indent);
if (keyName !== null) {
const k = document.createElement("span");
k.className = "jt-key";
k.textContent = JSON.stringify(keyName);
row.appendChild(k);
row.appendChild(punc(": "));
}
const tok = tokenFor(value);
const v = document.createElement("span");
v.className = tok.cls;
v.textContent = tok.text;
row.appendChild(v);
if (trailingComma) row.appendChild(punc(","));
container.appendChild(row);
return;
}
// object / array with a toggle
const open = isArr ? "[" : "{";
const close = isArr ? "]" : "}";
const entries = isArr ? value.map((v, i) => [i, v]) : Object.entries(value);
const headRow = makeRow(indent);
const toggle = document.createElement("button");
toggle.className = "jt-toggle";
toggle.type = "button";
toggle.setAttribute("aria-label", "Toggle node");
toggle.textContent = "▾";
headRow.appendChild(toggle);
if (keyName !== null) {
const k = document.createElement("span");
k.className = "jt-key";
k.textContent = JSON.stringify(keyName);
headRow.appendChild(k);
headRow.appendChild(punc(": "));
}
headRow.appendChild(punc(open));
const hint = document.createElement("span");
hint.className = "jt-collapsed-hint";
hint.textContent = " " + entries.length + (isArr ? " items " : " keys ") + close;
hint.style.display = "none";
headRow.appendChild(hint);
container.appendChild(headRow);
const children = document.createElement("div");
children.className = "jt-children";
container.appendChild(children);
entries.forEach(([k, v], i) => {
renderValue(children, v, indent + 1, isArr ? null : k, i < entries.length - 1);
});
const closeRow = makeRow(indent);
closeRow.appendChild(punc(close));
if (trailingComma) closeRow.appendChild(punc(","));
container.appendChild(closeRow);
toggle.addEventListener("click", () => {
const collapsed = children.classList.toggle("hidden");
toggle.classList.toggle("collapsed", collapsed);
closeRow.style.display = collapsed ? "none" : "";
hint.style.display = collapsed ? "" : "none";
});
}
if (treeEl) {
treeEl.innerHTML = "";
renderValue(treeEl, SAMPLE, 0, null, false);
}
/* ---------------- Keyboard shortcut: "/" focuses filter ---------------- */
document.addEventListener("keydown", (e) => {
if (e.key === "/" && document.activeElement !== navSearch) {
const tag = (document.activeElement.tagName || "").toLowerCase();
if (tag === "input" || tag === "textarea") return;
e.preventDefault();
navSearch.focus();
}
if (e.key === "Escape" && sidebar.classList.contains("open")) setNav(false);
});
// Open from initial hash
if (location.hash) {
const el = document.getElementById(location.hash.slice(1));
if (el) setTimeout(() => el.scrollIntoView({ block: "start" }), 60);
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Aurora DB API Reference — Stealthis Docs</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Source+Serif+4:opsz,[email protected],400;8..60,600&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="topbar">
<div class="topbar-inner">
<button class="icon-btn nav-toggle" id="navToggle" aria-label="Open navigation" aria-expanded="false" aria-controls="sidebar">
<span class="burger"></span>
</button>
<a class="brand" href="#overview">
<span class="brand-mark" aria-hidden="true">⛁</span>
<span class="brand-name">Aurora DB</span>
<span class="brand-tag">API v3</span>
</a>
<div class="topbar-search">
<input id="navSearch" type="search" placeholder="Filter endpoints… /" aria-label="Filter endpoints" />
</div>
<div class="topbar-actions">
<span class="env-pill"><span class="dot"></span> api.auroradb.dev</span>
<a class="btn ghost" href="#authentication">Get keys</a>
</div>
</div>
</header>
<div class="layout">
<!-- LEFT NAV -->
<nav class="sidebar" id="sidebar" aria-label="API resources">
<div class="sidebar-scroll">
<div class="nav-group">
<p class="nav-title">Getting started</p>
<a class="nav-link" href="#overview">Overview</a>
<a class="nav-link" href="#authentication">Authentication</a>
<a class="nav-link" href="#errors">Errors & status codes</a>
</div>
<div class="nav-group">
<p class="nav-title">Clusters</p>
<a class="nav-link" href="#list-clusters"><span class="m m-get">GET</span> List clusters</a>
<a class="nav-link" href="#create-cluster"><span class="m m-post">POST</span> Create cluster</a>
<a class="nav-link" href="#get-cluster"><span class="m m-get">GET</span> Retrieve cluster</a>
<a class="nav-link" href="#delete-cluster"><span class="m m-del">DEL</span> Delete cluster</a>
</div>
<div class="nav-group">
<p class="nav-title">Snapshots</p>
<a class="nav-link" href="#create-snapshot"><span class="m m-post">POST</span> Create snapshot</a>
<a class="nav-link" href="#list-snapshots"><span class="m m-get">GET</span> List snapshots</a>
</div>
<div class="nav-group">
<p class="nav-title">Reference</p>
<a class="nav-link" href="#pagination">Pagination</a>
<a class="nav-link" href="#rate-limits">Rate limits</a>
</div>
</div>
</nav>
<div class="scrim" id="scrim" hidden></div>
<!-- MAIN -->
<main class="main" id="main">
<div class="doc-col">
<nav class="crumbs" aria-label="Breadcrumb">
<a href="#overview">Docs</a><span aria-hidden="true">/</span>
<a href="#overview">API Reference</a><span aria-hidden="true">/</span>
<span aria-current="page">Clusters</span>
</nav>
<section id="overview" class="block" tabindex="-1">
<h1>Aurora DB REST API</h1>
<p class="lead">The Aurora DB API lets you provision distributed clusters, manage point-in-time
snapshots, and inspect replica health over plain HTTPS. Every response is JSON, every request is
authenticated with a secret key, and all timestamps are RFC 3339 UTC.</p>
<p>The API is organized around resources. Predictable, resource-oriented URLs accept
form-encoded request bodies, return JSON-encoded responses, and use standard HTTP verbs,
authentication, and status codes. The current stable version is <code>v3</code>; the base URL is:</p>
<div class="callout note">
<span class="callout-ic" aria-hidden="true">i</span>
<div><strong>Base URL.</strong> <code>https://api.auroradb.dev/v3</code> — all requests must
be made over HTTPS. Calls over plain HTTP will fail.</div>
</div>
</section>
<section id="authentication" class="block" tabindex="-1">
<h2>Authentication</h2>
<p>Authenticate by passing your secret key in the <code>Authorization</code> header as a bearer
token. Keys are scoped to a single project and carry the <code>live</code> or <code>test</code>
prefix. Never embed a secret key in client-side code.</p>
<pre class="code"><code>Authorization: Bearer ak_live_7Qm3…f2Vd</code></pre>
</section>
<!-- ENDPOINT: list clusters -->
<section id="list-clusters" class="block endpoint" tabindex="-1">
<div class="ep-head">
<span class="method m-get">GET</span>
<code class="path">/v3/clusters</code>
<a class="anchor" href="#list-clusters" aria-label="Link to this endpoint">#</a>
</div>
<h2 class="ep-title">List clusters</h2>
<p>Returns a paginated list of clusters owned by the authenticated project, most recently created
first. Use the <code>region</code> and <code>status</code> query parameters to narrow results.</p>
<div class="params-bar">
<h3 class="params-title">Query parameters</h3>
<label class="filter-toggle">
<input type="checkbox" class="req-filter" />
<span>Required only</span>
</label>
</div>
<div class="table-wrap">
<table class="params">
<thead><tr><th>Name</th><th>Type</th><th>Req.</th><th>Description</th></tr></thead>
<tbody>
<tr><td><code>region</code></td><td class="ty">string</td><td><span class="req-no">optional</span></td><td>Filter by deployment region, e.g. <code>us-east-1</code> or <code>eu-west-3</code>.</td></tr>
<tr><td><code>status</code></td><td class="ty">enum</td><td><span class="req-no">optional</span></td><td>One of <code>provisioning</code>, <code>active</code>, <code>degraded</code>, <code>archived</code>.</td></tr>
<tr data-required="true"><td><code>limit</code></td><td class="ty">integer</td><td><span class="req-yes">required</span></td><td>Page size between 1 and 100. Defaults to 20 when omitted on the first page.</td></tr>
<tr><td><code>starting_after</code></td><td class="ty">string</td><td><span class="req-no">optional</span></td><td>Cursor for pagination — the object ID that defines your place in the list.</td></tr>
</tbody>
</table>
</div>
<h3 class="resp-title">Responses</h3>
<ul class="resp-list">
<li><span class="status s-2xx">200</span> A paged list object with a <code>data</code> array of clusters.</li>
<li><span class="status s-4xx">401</span> Missing or invalid API key.</li>
<li><span class="status s-4xx">422</span> The <code>limit</code> parameter is out of range.</li>
</ul>
</section>
<!-- ENDPOINT: create cluster -->
<section id="create-cluster" class="block endpoint" tabindex="-1">
<div class="ep-head">
<span class="method m-post">POST</span>
<code class="path">/v3/clusters</code>
<a class="anchor" href="#create-cluster" aria-label="Link to this endpoint">#</a>
</div>
<h2 class="ep-title">Create cluster</h2>
<p>Provisions a new Aurora DB cluster in the requested region. The call returns immediately with a
cluster in the <code>provisioning</code> state; poll <a href="#get-cluster">Retrieve cluster</a>
until <code>status</code> becomes <code>active</code>.</p>
<div class="params-bar">
<h3 class="params-title">Body parameters</h3>
<label class="filter-toggle">
<input type="checkbox" class="req-filter" />
<span>Required only</span>
</label>
</div>
<div class="table-wrap">
<table class="params">
<thead><tr><th>Name</th><th>Type</th><th>Req.</th><th>Description</th></tr></thead>
<tbody>
<tr data-required="true"><td><code>name</code></td><td class="ty">string</td><td><span class="req-yes">required</span></td><td>Human-readable name, 1–48 characters. Must be unique within the project.</td></tr>
<tr data-required="true"><td><code>region</code></td><td class="ty">string</td><td><span class="req-yes">required</span></td><td>Target region. See <a href="#overview">supported regions</a>.</td></tr>
<tr><td><code>tier</code></td><td class="ty">enum</td><td><span class="req-no">optional</span></td><td>Compute tier: <code>nimbus</code>, <code>verdant</code>, or <code>aurora</code>. Defaults to <code>nimbus</code>.</td></tr>
<tr><td><code>replicas</code></td><td class="ty">integer</td><td><span class="req-no">optional</span></td><td>Number of read replicas, 0–8. Defaults to <code>2</code>.</td></tr>
<tr><td><code>encryption</code></td><td class="ty">boolean</td><td><span class="req-no">optional</span></td><td>Enable at-rest encryption with a managed key. Defaults to <code>true</code>.</td></tr>
</tbody>
</table>
</div>
<h3 class="resp-title">Responses</h3>
<ul class="resp-list">
<li><span class="status s-2xx">201</span> The newly created <code>cluster</code> object.</li>
<li><span class="status s-4xx">409</span> A cluster with that <code>name</code> already exists.</li>
<li><span class="status s-4xx">422</span> Validation failed on one or more fields.</li>
<li><span class="status s-5xx">503</span> The region is at capacity; retry with backoff.</li>
</ul>
</section>
<!-- ENDPOINT: get cluster -->
<section id="get-cluster" class="block endpoint" tabindex="-1">
<div class="ep-head">
<span class="method m-get">GET</span>
<code class="path">/v3/clusters/<span class="path-var">{id}</span></code>
<a class="anchor" href="#get-cluster" aria-label="Link to this endpoint">#</a>
</div>
<h2 class="ep-title">Retrieve cluster</h2>
<p>Fetches the details of an existing cluster, including live replica health and the most recent
snapshot. You only need to supply the unique cluster ID returned on creation.</p>
<div class="params-bar">
<h3 class="params-title">Path parameters</h3>
<label class="filter-toggle">
<input type="checkbox" class="req-filter" />
<span>Required only</span>
</label>
</div>
<div class="table-wrap">
<table class="params">
<thead><tr><th>Name</th><th>Type</th><th>Req.</th><th>Description</th></tr></thead>
<tbody>
<tr data-required="true"><td><code>id</code></td><td class="ty">string</td><td><span class="req-yes">required</span></td><td>The cluster ID, e.g. <code>clu_8Kdb20fA</code>.</td></tr>
<tr><td><code>expand</code></td><td class="ty">array</td><td><span class="req-no">optional</span></td><td>Expand nested objects, e.g. <code>replicas</code>, <code>latest_snapshot</code>.</td></tr>
</tbody>
</table>
</div>
<h3 class="resp-title">Responses</h3>
<ul class="resp-list">
<li><span class="status s-2xx">200</span> The requested <code>cluster</code> object.</li>
<li><span class="status s-4xx">404</span> No cluster matches that ID for this project.</li>
</ul>
</section>
<!-- ENDPOINT: delete cluster -->
<section id="delete-cluster" class="block endpoint" tabindex="-1">
<div class="ep-head">
<span class="method m-del">DELETE</span>
<code class="path">/v3/clusters/<span class="path-var">{id}</span></code>
<a class="anchor" href="#delete-cluster" aria-label="Link to this endpoint">#</a>
</div>
<h2 class="ep-title">Delete cluster</h2>
<p>Permanently deletes a cluster and all of its read replicas. Snapshots are retained according to
your project's retention policy. This action cannot be undone.</p>
<div class="callout warn">
<span class="callout-ic" aria-hidden="true">!</span>
<div><strong>Destructive.</strong> Deletion is irreversible. Take a final snapshot first if you
may need the data later.</div>
</div>
<div class="params-bar">
<h3 class="params-title">Path parameters</h3>
<label class="filter-toggle">
<input type="checkbox" class="req-filter" />
<span>Required only</span>
</label>
</div>
<div class="table-wrap">
<table class="params">
<thead><tr><th>Name</th><th>Type</th><th>Req.</th><th>Description</th></tr></thead>
<tbody>
<tr data-required="true"><td><code>id</code></td><td class="ty">string</td><td><span class="req-yes">required</span></td><td>The ID of the cluster to delete.</td></tr>
</tbody>
</table>
</div>
<h3 class="resp-title">Responses</h3>
<ul class="resp-list">
<li><span class="status s-2xx">200</span> A <code>deleted</code> confirmation object.</li>
<li><span class="status s-4xx">404</span> The cluster does not exist.</li>
<li><span class="status s-4xx">409</span> The cluster has an in-flight snapshot; retry shortly.</li>
</ul>
</section>
<section id="errors" class="block" tabindex="-1">
<h2>Errors & status codes</h2>
<p>Aurora DB uses conventional HTTP response codes. Codes in the <code>2xx</code> range indicate
success; <code>4xx</code> codes indicate a problem with the supplied information; and
<code>5xx</code> codes indicate a server-side error.</p>
<div class="table-wrap">
<table class="params">
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
<tbody>
<tr><td><span class="status s-4xx">400</span></td><td>Bad request — often a malformed body.</td></tr>
<tr><td><span class="status s-4xx">401</span></td><td>Unauthorized — no valid API key provided.</td></tr>
<tr><td><span class="status s-4xx">429</span></td><td>Too many requests — see <a href="#rate-limits">rate limits</a>.</td></tr>
<tr><td><span class="status s-5xx">500</span></td><td>Something went wrong on Aurora DB's end.</td></tr>
</tbody>
</table>
</div>
</section>
<section id="pagination" class="block" tabindex="-1">
<h2>Pagination</h2>
<p>All list endpoints support cursor-based pagination via <code>limit</code> and
<code>starting_after</code>. Each list response includes a <code>has_more</code> boolean and the
ID of the last object, which you pass back as the next cursor.</p>
</section>
<section id="rate-limits" class="block" tabindex="-1">
<h2>Rate limits</h2>
<p>The API allows up to <strong>100 requests per second</strong> per project in live mode. Responses
include <code>X-RateLimit-Remaining</code> and <code>X-RateLimit-Reset</code> headers. Exceeding
the limit returns <span class="status s-4xx">429</span>; back off using the reset header.</p>
<p class="foot-note">Illustrative UI only — fictional articles, products, and data.</p>
</section>
</div>
<!-- RIGHT: sticky code panel -->
<aside class="code-panel" aria-label="Code examples">
<div class="cp-card">
<div class="cp-head">
<div class="lang-tabs" role="tablist" aria-label="Language">
<button class="lang-tab is-active" role="tab" aria-selected="true" data-lang="curl">cURL</button>
<button class="lang-tab" role="tab" aria-selected="false" data-lang="js">JavaScript</button>
<button class="lang-tab" role="tab" aria-selected="false" data-lang="py">Python</button>
</div>
</div>
<div class="cp-section">
<div class="cp-label">
<span>Request</span>
<button class="copy-btn" data-copy="req" aria-label="Copy request">Copy</button>
</div>
<pre class="code dark" data-lang-pane="curl"><code>curl https://api.auroradb.dev/v3/clusters \
-H "Authorization: Bearer ak_live_7Qm3…f2Vd" \
-d name="prod-eu" \
-d region="eu-west-3" \
-d tier="verdant" \
-d replicas=3</code></pre>
<pre class="code dark" data-lang-pane="js" hidden><code>const res = await fetch(
"https://api.auroradb.dev/v3/clusters",
{
method: "POST",
headers: {
Authorization: "Bearer ak_live_7Qm3…f2Vd",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "prod-eu",
region: "eu-west-3",
tier: "verdant",
replicas: 3,
}),
}
);
const cluster = await res.json();</code></pre>
<pre class="code dark" data-lang-pane="py" hidden><code>import requests
res = requests.post(
"https://api.auroradb.dev/v3/clusters",
headers={"Authorization": "Bearer ak_live_7Qm3…f2Vd"},
json={
"name": "prod-eu",
"region": "eu-west-3",
"tier": "verdant",
"replicas": 3,
},
)
cluster = res.json()</code></pre>
</div>
<div class="cp-section">
<div class="cp-label">
<span>Response <span class="status s-2xx inline">201</span></span>
<button class="copy-btn" data-copy="res" aria-label="Copy response">Copy</button>
</div>
<div class="json-tree" id="jsonTree" aria-label="Sample JSON response"></div>
</div>
</div>
</aside>
</main>
</div>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>API Reference (endpoints · params)
A complete REST API reference view for Aurora DB, a fictional distributed database, built in the
clean white knowledge-base palette. A persistent left sidebar groups resources and endpoints —
Clusters, Snapshots and reference topics — each entry carrying a coloured GET / POST / DELETE
method chip. The centered main column documents real-feeling endpoints: an HTTP method badge and
path, a description, a parameters table (name, type, required, description) and a responses section
of 2xx / 4xx / 5xx status badges, alongside callouts and code blocks.
A sticky dark code panel rides the right rail. Language tabs switch the request example between cURL, JavaScript and Python, copy buttons lift either the request or the response to the clipboard, and the sample JSON response renders as a fully collapsible tree — every object and array node can be folded to a one-line summary. Each parameters table has a required-only toggle that filters the rows, and every endpoint head exposes a deep-link anchor you can copy.
Navigation is wired throughout: the left nav doubles as an endpoint filter (press / to
jump to it), clicks smooth-scroll and move focus, and an IntersectionObserver scrollspy highlights
the endpoint you are reading while keeping its nav entry in view. The sidebar collapses into a drawer
below 820px, the code panel drops beneath the prose on tablets, and everything runs on vanilla JS
with no frameworks or build step.
Illustrative UI only — fictional articles, products, and data.