Documentation
Swagger UI, OpenAPI Docs & API Catalog for Confluence.
OpenAPI 3.1, OpenAPI 3.0 and Swagger 2.0, in YAML or JSON.
Add the macro
Type /Swagger UI on any Confluence page and pick Swagger UI & OpenAPI. The
configuration panel opens straight away, and the macro renders while you are
still editing — you do not have to publish the page to see whether it worked.
Several macros on one page work. Plan for roughly 20–30 on a single page; past that, Confluence's own 30-second page render budget becomes the limit.
Getting a specification in
Paste it
The simplest one, and the one to use when the document does not change often. What you paste is what readers see, up to 4 MB. Replacing it stores a new copy.
A public URL
Fetched once, in your browser, when you save — not on every page view. Readers see the stored copy. To pick up a change, re-open the configuration and press Refresh.
This is deliberate. A page that re-fetched on every view would make every reader's browser call your host, and would show the URL to every reader.
The URL is never written into the page, and is shown only to people who can edit it. A URL carrying a token in its query string is kept in encrypted storage.
The host must allow cross-origin requests from the app's frame. GitHub, GitLab and most documentation hosts do. An internal server behind a VPN does not — for those, paste the document or push it from CI.
A page attachment
Read once, when you save. Uploading a new version of the attachment does not update the macro; re-open the configuration and load it again. The attachment has to be on the same page as the macro.
A push from your CI pipeline
The answer for a private repository. Your pipeline sends the specification to an address this app gives you, with a token it also gives you. We never see your repository credential.
Open the macro configuration, choose CI push, and create an endpoint. The token is shown once — only a hash of it is stored, so a lost token is replaced, not recovered.
Then, in your pipeline:
# Export the token as OPENAPI_PUSH_TOKEN first.
curl -sS --fail-with-body -X POST "<WEB_TRIGGER_URL>" \
-H "Authorization: Bearer $OPENAPI_PUSH_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @openapi.json
A YAML file needs one extra step. The push endpoint receives request bodies without their line breaks — a platform behaviour, measured on the deployed trigger. JSON does not care; YAML cannot survive it. So send YAML base64-encoded through standard input, which the endpoint recognises and unwraps:
base64 < openapi.yaml | tr -d '\n' | \
curl -sS --fail-with-body -X POST "<WEB_TRIGGER_URL>" \
-H "Authorization: Bearer $OPENAPI_PUSH_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @-
Pipe it through standard input rather than passing "$(base64 …)" as an
argument: Linux caps a single argument at 128 KB, which most real
specifications exceed.
Ready-made snippets for GitHub Actions, GitLab CI and Bitbucket Pipelines are in the macro's configuration panel, with the endpoint URL already filled in. Copy them from there.
What the pipeline learns. A status code, and only a status code: 200
accepted, 400 malformed, 401 bad token, 404 unknown specification, 413
too large, 422 not a valid OpenAPI document. The endpoint cannot answer with
detail — that is a property of the platform feature it uses. When a push is
refused because the document is invalid, the reason is written into the macro
configuration, where you can read it.
Search
Once a specification is saved, its operations, paths and tags are published to Confluence's search index.
Use the catalog's Find by endpoint tab. Type a path, a tag or an operation id and it returns the pages that document it.
⚠️ The plain search box at the top of Confluence will not find these. The index lives in named fields, not in the page text that box reads. Measured: an operation id that CQL matches returns nothing when typed into the search field.
Everywhere CQL is accepted — the advanced search, the CQL query builder, the Page Properties Report macro, the REST search API — the fields are:
openapi_paths ~ "invoices"
openapi_operations ~ "createInvoice"
openapi_tags ~ "billing"
openapi_title ~ "Billing"
openapi_operation_count >= 50
⚠️ Search a path by its segments, not by the punctuated path. A ~ query
matches whole words and Confluence treats /, { and } as separators, so
openapi_paths ~ "invoices" finds /v2/invoices and
openapi_paths ~ "/v2/invoices" finds nothing. A camelCase name is one word.
There is a budget of 28,000 bytes of index per page. A page whose specifications exceed it is truncated deterministically, and the catalog says so.
The API catalog
Apps → API catalog. One row per specification, across every space: title, version, endpoint count, space, page, and how long since it changed. Filter as you type, sort by any column, and jump to the page.
The Find by endpoint tab searches the index directly, for when you know the path and not the page.
The catalog is one search request made as you, in your browser. It shows only pages you can already see, and it costs your instance nothing to open.
Export
PDF export carries the documentation. Each macro chooses between two branches in its configuration:
- Endpoint table — a compact, text-selectable table of operations. Fast and small.
- Native render — the full Swagger UI appearance, as the page looks.
On a four-macro page carrying one large specification, measured on a deployed site: the table branch was 13 s and 915 KB; the native branch was 46 s and 12.3 MB. The gap grows with the size of the specification.
Word export carries none of this, on either branch, and that is Confluence's Word pipeline rather than a setting you can change. See limitations.
Migrating from another app
Apps → API catalog → Migrate.
Choose a space and scan. You get a list of every page carrying another vendor's API specification macro, what would replace it, and what cannot be read. Nothing is written until you say so.
Then migrate the pages you picked, in one action. Afterwards, Undo this migration puts every page back to the version it had.
If a macro is holding a username, a password or a token in the page body — which several apps in this category do — you are told which page and which field, so you can rotate the credential. The value is never copied into the replacement and never shown back to you.
Macros whose specification cannot be read from the page are reported and left alone. That is the safe direction, and it is deliberate: replacing a macro with the wrong content is worse than not replacing it.
Limits worth knowing before you start
- A specification must be under 4 MB.
$refpointing at another file or a URL is never fetched — bundle the document first (redocly bundle,swagger-cli bundle). Internal#/references work normally.- Hiding tags or paths is a display filter, not access control. The whole document is retrievable by anyone who can read the page.
- A link to a single operation lands on the right page but cannot scroll to the operation. That is a platform limit, and it is explained in full on the limitations page.
The limitations page is the complete list. It is kept current.