Integrate Open API (Swagger) — Confluence Cloud MacroNew
This Confluence user macro dynamically loads and renders an OpenAPI (Swagger) specification using Swagger UI.
The macro retrieves the specification URL from macro parameters, validates its availability and JSON structure, and initializes SwaggerUIBundle with deep linking and persistent authorization enabled. It includes loading states with AUI spinner feedback, graceful error handling for missing or invalid specifications, and custom dark-mode styling aligned with Atlassian design tokens to ensure seamless integration with Confluence themes.
User Parameters
URL
Enter a URL to fetch data from
Template
<script>
window.AP.theming.initializeTheming();
</script>
#set ($!swaggerUrl = $parameters["url"])
<link
rel="stylesheet"
href="https://unpkg.com/swagger-ui-dist/swagger-ui.css"
/>
<style>
html[data-color-mode="dark"] .swagger-ui .scheme-container,
html[data-color-mode="dark"] #servers {
background: #1c1c21;
}
html[data-color-mode="dark"] .swagger-ui .checkbox p,
html[data-color-mode="dark"] .swagger-ui .dialog-ux .modal-ux-content h4,
html[data-color-mode="dark"] .swagger-ui .dialog-ux .modal-ux-content p,
html[data-color-mode="dark"] .swagger-ui .dialog-ux .modal-ux-header h3,
html[data-color-mode="dark"] .swagger-ui .errors-wrapper .errors h4,
html[data-color-mode="dark"] .swagger-ui .errors-wrapper hgroup h4,
html[data-color-mode="dark"] .swagger-ui .info .base-url,
html[data-color-mode="dark"] .swagger-ui .info .title,
html[data-color-mode="dark"] .swagger-ui .info h1,
html[data-color-mode="dark"] .swagger-ui .info h2,
html[data-color-mode="dark"] .swagger-ui .info h3,
html[data-color-mode="dark"] .swagger-ui .info h4,
html[data-color-mode="dark"] .swagger-ui .info h5,
html[data-color-mode="dark"] .swagger-ui .info li,
html[data-color-mode="dark"] .swagger-ui .info p,
html[data-color-mode="dark"] .swagger-ui .info table,
html[data-color-mode="dark"] .swagger-ui .loading-container .loading::after,
html[data-color-mode="dark"] .swagger-ui .model,
html[data-color-mode="dark"] .swagger-ui .opblock .opblock-section-header h4,
html[data-color-mode="dark"] .swagger-ui .opblock .opblock-section-header > label,
html[data-color-mode="dark"] .swagger-ui .opblock .opblock-summary-description,
html[data-color-mode="dark"] .swagger-ui .opblock .opblock-summary-operation-id,
html[data-color-mode="dark"] .swagger-ui .opblock .opblock-summary-path,
html[data-color-mode="dark"]
.swagger-ui
.opblock
.opblock-summary-path__deprecated,
html[data-color-mode="dark"] .swagger-ui .opblock-description-wrapper,
html[data-color-mode="dark"] .swagger-ui .opblock-description-wrapper h4,
html[data-color-mode="dark"] .swagger-ui .opblock-description-wrapper p,
html[data-color-mode="dark"] .swagger-ui .opblock-external-docs-wrapper,
html[data-color-mode="dark"] .swagger-ui .opblock-external-docs-wrapper h4,
html[data-color-mode="dark"] .swagger-ui .opblock-external-docs-wrapper p,
html[data-color-mode="dark"] .swagger-ui .opblock-tag small,
html[data-color-mode="dark"] .swagger-ui .opblock-title_normal,
html[data-color-mode="dark"] .swagger-ui .opblock-title_normal h4,
html[data-color-mode="dark"] .swagger-ui .opblock-title_normal p,
html[data-color-mode="dark"] .swagger-ui .parameter__name,
html[data-color-mode="dark"] .swagger-ui .parameter__type,
html[data-color-mode="dark"] .swagger-ui .response-col_links,
html[data-color-mode="dark"] .swagger-ui .response-col_status,
html[data-color-mode="dark"] .swagger-ui .responses-inner h4,
html[data-color-mode="dark"] .swagger-ui .responses-inner h5,
html[data-color-mode="dark"] .swagger-ui .scheme-container .schemes > label,
html[data-color-mode="dark"] .swagger-ui .scopes h2,
html[data-color-mode="dark"] .swagger-ui .servers > label,
html[data-color-mode="dark"] .swagger-ui .tab li,
html[data-color-mode="dark"] .swagger-ui label,
html[data-color-mode="dark"] .swagger-ui select,
html[data-color-mode="dark"] .swagger-ui table.headers td {
color: var(--ds-text);
}
.swagger-status {
border: 1px solid #dfe1e6;
border-radius: 6px;
background: #f7f8f9;
padding: 10px;
display: flex;
align-items: center;
gap: 8px;
}
#swagger-ui-container {
display: none;
border: 1px solid #dfe1e6;
border-radius: 6px;
}
</style>
<div id="swagger-status">
<aui-spinner size="small"></aui-spinner>
<div class="aui-message aui-message-info">
<p class="title">
<strong>Loading OpenAPI specification…</strong>
</p>
</div>
</div>
<div id="swagger-ui-container"></div>
<div id="swagger-error-container"></div>
<div id="swagger-data" data-url="$swaggerUrl"></div>
<script src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"></script>
<script src="https://unpkg.com/swagger-ui-dist/swagger-ui-standalone-preset.js"></script>
<script>
(() => {
const ready = (fn) => {
if (document.readyState !== "loading") {
fn();
} else {
document.addEventListener("DOMContentLoaded", fn);
}
};
ready(async () => {
const status = document.getElementById("swagger-status");
const container = document.getElementById("swagger-ui-container");
const errorContainer = document.getElementById(
"swagger-error-container"
);
const swaggerUrl = document
.getElementById("swagger-data")
.dataset.url.trim();
const renderError = (message) => {
status.style.display = "none";
errorContainer.innerHTML = `
<div
role="note"
aria-labelledby="swagger-error-title"
class="aui-message aui-message-error"
>
<p id="swagger-error-title" aria-hidden="true" class="title">
<strong hidden>Error: </strong>
<strong>Could not reach URL</strong>
</p>
<p>
No OpenAPI / Swagger JSON found at this link.<br/>
Please verify that the URL points directly to a valid
OpenAPI / Swagger JSON file.
</p>
</div>
`;
};
try {
if (!swaggerUrl) {
renderError("Missing specification URL.");
return;
}
const res = await fetch(swaggerUrl);
if (!res.ok) {
renderError("HTTP " + res.status + " returned.");
return;
}
const text = await res.text();
try {
JSON.parse(text);
} catch {
renderError("Invalid JSON document.");
return;
}
status.style.display = "none";
container.style.display = "block";
SwaggerUIBundle({
url: swaggerUrl,
dom_id: "#swagger-ui-container",
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset,
],
layout: "BaseLayout",
persistAuthorization: true,
});
} catch (err) {
renderError();
}
});
})();
</script>Recommended Macros
Basic greeting for user
Convert a specified amount of cryptocurrency to fiat currency.
Read and display the fixed version of Confluence pages by checking page or ancestor labels
Shows page creation date
Get the latest cryptocurrency rates for major coins.
Show confetti bursts and a motivational message upon saving an edited page
The content of this macro will be printed and exported but not rendered on the page in view mode
Retrieve and display labels from a specified space.