OpenAPI
Binde eine OpenAPI-Spezifikation ein und erhalte eine native API-Referenz – eine echte Seite pro Operation, in deiner Sidebar und in der Suche.
Richte Blume auf eine OpenAPI-Spezifikation aus, und es generiert eine native API-Referenz: eine echte Seite pro Operation, nach Tag gruppiert in einer tab-bezogenen Sidebar, mit Schematabellen, Request-/Response-Beispielen, generierten Codebeispielen und einem interaktiven Try it-Panel. Da jede Operation eine echte Blume-Seite ist, bekommt sie ihre eigene URL, taucht in der Website-Suche und in llms.txt auf und erhält ein Open-Graph-Bild – genau wie jede handgeschriebene Doku-Seite.
Jede Referenz ist ein Adapter, den du aus blume/reference importierst und unter reference auflistest: openapi() für ein OpenAPI-Dokument, asyncapi() für ein AsyncAPI-Dokument und graphql() für ein GraphQL-Schema. Jeder Adapter verwaltet seine eigenen Spec-Quellen, seine Mount-Route und seine Anzeigeoptionen, sodass die Liste beliebig viele Adapter jeder Art enthalten kann. Die folgende Konfiguration richtet Blume als Beispiel auf die öffentliche Petstore-Spezifikation aus.
import { defineConfig } from "blume";
import { openapi } from "blume/reference";
export default defineConfig({
reference: [
openapi({ spec: "https://petstore3.swagger.io/api/v3/openapi.json" }),
],
});
Damit wird die Referenz unter /reference (einer Übersichtsseite) eingebunden, jede Operation unter /reference/<tag>/<operation>. spec ist entweder eine http(s)-URL oder ein Pfad zu einer lokalen Datei in deinem Projekt. Blume parst sie mit dem OpenAPI-Parser von Scalar – Swagger-2.0- und OpenAPI-3.0-Spezifikationen werden automatisch auf 3.1 aktualisiert, und Spezifikationen in 3.1 und 3.2 werden so gelesen, wie sie geschrieben sind. Ein Adapter ist eine einfache Beschreibung der Referenz – keine geparste Spezifikation –, sodass Blume ihn vorab validieren und in die generierte Website einbetten kann; lässt du reference weg (oder leer), wird überhaupt keine Referenz gerendert. Du dokumentierst stattdessen eine eventgesteuerte API oder eine GraphQL-API? Sieh dir AsyncAPI und GraphQL an.
Um von der Spezifikation, die dein Framework generiert, zu einer deployten Referenz zu kommen, folge der Anleitung für FastAPI, Django REST Framework, NestJS, Spring Boot, ASP.NET Core, Laravel, Rails, Hono, Fastify, Elysia oder oRPC. Wenn du die API in TypeSpec definierst, veröffentliche sie aus der TypeSpec-Definition. API-Doku aus einer OpenAPI-Spezifikation generieren geht von einer beliebigen Spezifikationsdatei aus.
Die Referenz fügt von sich aus keinen Header-Tab hinzu. Um sie sichtbar zu machen, richte einen Navigations-Tab auf ihre Route aus – dadurch wird beim nativen Renderer auch die Sidebar mit den Operationen auf diesen Tab beschränkt:
navigation: {
tabs: [{ label: "API", path: "/reference" }],
}
Die Tag-Gruppen der Sidebar und die Abschnitte der Übersichtsseite folgen derselben Reihenfolge: der Reihenfolge der tags-Liste auf oberster Ebene der Spezifikation, danach alle Tags, die sie nicht deklariert, in der Reihenfolge, in der Operationen sie zum ersten Mal verwenden. Innerhalb eines Tags folgen auch die Operationen der Spezifikation: Pfade in der Reihenfolge, in der sie aufgelistet sind, und die Methoden jedes Pfads in der Reihenfolge, in der sie geschrieben sind. Eine meta.ts im Ordner eines Tags mit eigener pages-Liste überschreibt diese Reihenfolge.
Das x-displayName eines Tags, die Extension von Redocly, beschriftet seine Gruppe in der Sidebar und seinen Abschnitt in der Übersicht anstelle seines Namens. Seine URL leitet sich weiterhin aus seinem Namen ab, sodass das Hinzufügen keine Seite verschiebt. Eine Operation wird so beschriftet, wie ihre Seite betitelt ist: mit ihrem summary oder, wenn sie keins hat, mit ihrer Methode und ihrem Pfad (GET /pets).
Die info.description der Spezifikation steht am Anfang der Übersichtsseite, und die description jedes Tags steht dort am Anfang seines Abschnitts. Ihre Überschriften rücken eine Ebene tiefer, sodass der Titel der Seite ihre einzige Überschrift der obersten Ebene bleibt: Ein # Authentication in info.description oder in der description einer Operation wird als Überschrift zweiter Ebene gerendert, in der Beschreibung eines Tags als Überschrift dritter Ebene, unterhalb der Überschrift des Tags selbst.
Eine lokale Spezifikation
Ein relativer Pfad wird von deinem Projektstammverzeichnis aus aufgelöst und zur Build-Zeit gelesen. Sowohl JSON als auch YAML funktionieren, und blume dev überwacht die Datei – zusammen mit allen lokalen Overlays –, sodass die Referenz aktualisiert wird, wenn du die Spezifikation speicherst:
reference: [openapi({ spec: "./openapi.yaml" })],
OpenAPI 3.2
OpenAPI-3.2-Spezifikationen werden so gerendert, wie sie geschrieben sind. Eine query-Operation für die HTTP-Methode QUERY (ein sicherer Request, der einen Body mitführt) bekommt wie jede andere Methode eine Seite, Try it und Codebeispiele. Felder, die 3.2 hinzufügt und die Blume nicht anzeigt, etwa das summary eines Tags oder einer Response, werden ignoriert statt abgelehnt. Einige Neuerungen aus 3.2 werden noch nicht gerendert:
additionalOperationsfür Methoden, die ein Path Item nicht direkt benennt (etwaCOPY): Diese Operationen werden weggelassen, mit einerBLUME_OPENAPI_UNSUPPORTED-Warnung.in: querystring-Parameter: Sie bekommen keine Zeile in der Parametertabelle, kein Eingabefeld in Try it und keinen Platz in den Codebeispielen, mit derselben Warnung.itemSchema, das Schema jedes Elements in einem gestreamten Body (text/event-stream,application/jsonl): Die Seite zeigt für diesen Body kein Schema, es sei denn, daneben istschemagesetzt.- Beispiele, die mit
dataValueoderserializedValuestattvaluegeschrieben sind: Die Seite zeigt sie nicht an. - Verschachtelte Tags (
parent) und daskindvon Tags: Tags bleiben in der Sidebar und in der Übersicht eine flache Liste.
Route
route legt fest, wo die Referenz eingebunden wird – also die Übersichtsseite und das Präfix für jede Operationsroute (und die Route, auf die du einen Navigations-Tab ausrichtest):
reference: [
openapi({
route: "/api", // overview at /api, operations at /api/<tag>/<operation>
spec: "./openapi.yaml",
}),
],
Das <tag> einer Operation ist ihr erster Tag (operations, wenn sie keinen hat), und ihre <operation> ist ihre operationId, sonst ihre Methode und ihr Pfad. Beides wird kleingeschrieben, wobei die Wörter durch Bindestriche getrennt werden, auch bei camelCase und PascalCase: Aus dem Tag InboxesThreads wird inboxes-threads, und aus der operationId listThreads wird list-threads. Der Slug einer Operation muss nur innerhalb ihres Tags eindeutig sein, sodass zwei Tags jeweils ein list haben können; ein zweites list im selben Tag bekommt seine Methode angehängt (list-post), mit einer BLUME_OPENAPI_DUPLICATE_OPERATION_ID-Warnung, wenn sich die beiden eine operationId teilen.
Frühere Versionen von Blume haben die Wörter eines Tags zusammengeschrieben (inboxesthreads) und den Slug einer Operation über die gesamte Spezifikation hinweg eindeutig gemacht (list-get für das zweite list). Blume leitet jede dieser URLs samt ihrer Markdown-Fassung auf die aktuelle URL der Seite weiter, es sei denn, unter dieser URL liegt bereits eine Seite oder einer deiner redirects.
Codebeispiele und Schemas
codeSamples legt fest, welche Sprachen pro Operation gerendert werden, und zwar in der Reihenfolge, in der du sie auflistest. Standardmäßig ist das ["curl", "js", "python"], und mit false oder einer leeren Liste werden keine angezeigt. Mit expandSchemas starten verschachtelte Schemazeilen ausgeklappt statt eingeklappt:
reference: [
openapi({
spec: "./openapi.yaml",
codeSamples: ["curl", "python", "go", "java", "csharp"],
expandSchemas: true,
}),
],
Jedes Beispiel ist schlichter Code für den Request, den du direkt kopieren und einfügen kannst – geschrieben mit dem Standard- oder dem gängigsten HTTP-Client der jeweiligen Sprache:
| Id | Sprache | Client | Akzeptiert auch |
|---|---|---|---|
curl |
cURL | curl |
bash, sh, shell |
python |
Python | requests |
py |
js |
JavaScript | fetch |
javascript |
node |
Node.js | axios |
nodejs, node.js |
typescript |
TypeScript | fetch |
ts |
php |
PHP | die curl-Extension | |
go |
Go | net/http |
golang |
java |
Java | java.net.http |
|
ruby |
Ruby | net/http |
rb |
powershell |
PowerShell | Invoke-RestMethod |
ps1 |
swift |
Swift | URLSession |
|
csharp |
C# | HttpClient |
c#, cs |
dotnet |
.NET | RestSharp | .net, dot-net |
c |
C | libcurl | |
cpp |
C++ | cpr | c++, cplusplus |
kotlin |
Kotlin | OkHttp | kt |
rust |
Rust | reqwest | rs |
dart |
Dart | package:http |
flutter |
Jeder Wert wird nach den Regeln der jeweiligen Sprache maskiert, sodass ein Header wie If-Match: "33a64df5" oder ein Body mit einem $ darin genau so bei der API ankommt, wie er geschrieben wurde.
Eine Id, für die Blume kein Beispiel generiert, etwa objectivec von ReadMe, wird auf jeder Seite weggelassen, mit einer BLUME_OPENAPI_UNKNOWN_CODE_SAMPLE-Warnung, die die obigen Ids auflistet. Um ein Beispiel in einer anderen Sprache zu zeigen, schreibe es als eigenes Beispiel in die Spezifikation.
Schematabellen folgen – wie die Beispiele – der Richtung, in der die Daten fließen: Ein Request-Body lässt readOnly-Properties weg, die der Server setzt, und eine Response lässt writeOnly-Properties weg, die er nie zurückgibt. Der Body eines Webhooks oder Callbacks ist ein Request, den deine API sendet, daher wird er wie eine Response dargestellt. Dasselbe gilt für die Request-Beispiele, das Try it-Formular und seine Vorbelegung sowie die Response-Beispiele, einschließlich der Beispiele, die in der Spezifikation stehen, etwa ein example auf Modellebene, das die id des Modells enthält.
Enthält die examples-Map eines Bodys oder einer Response zwei oder mehr benannte Beispiele, wird jedes davon angezeigt, beschriftet mit seinem summary oder, wenn es keins hat, mit seinem Schlüssel. Eine Response bekommt pro Beispiel einen Tab hinter ihrem Status (200 · A cat), ein Webhook-Payload einen pro Beispiel hinter seinem Medientyp und ein Request-Body einen Examples-Block unter seinem Schema. Die Codebeispiele und Try it starten mit dem ersten.
Bei einer Property, die als $ref mit Keywords daneben geschrieben ist – was OpenAPI 3.1 erlaubt –, haben diese Keywords Vorrang vor denen des referenzierten Schemas. Ihre Zeile zeigt ihre eigene description, und die Beispiele verwenden ihr eigenes example oder ihren eigenen default.
Eigene Beispiele
Um statt eines rohen HTTP-Aufrufs dein SDK zu zeigen, füge einer Operation in der Spezifikation x-codeSamples hinzu. Das ist die von Redocly definierte Extension, und Speakeasy und Stainless können sie für dich schreiben. Jeder Eintrag nimmt ein lang, den source und ein optionales label:
paths:
/plants:
get:
x-codeSamples:
- lang: typescript
label: SDK
source: |
const plants = await planter.plants.list();
- lang: bash
label: CLI
source: |
planter list
Diese Beispiele werden als eigene Tabs vor den generierten gerendert und bleiben unverändert, wenn Lesende das Try it-Formular ändern. Die ältere Schreibweise x-code-samples funktioniert ebenfalls. Um nur deine eigenen Beispiele zu zeigen, setze codeSamples: false. Anders als die generierten Beispiele sind sie auch in der Markdown-Fassung der Operationsseite enthalten, sodass llms-full.txt, der MCP-Server und der Assistent deine SDK-Aufrufe sehen. Diese Fassung listet außerdem den Medientyp und die Properties der obersten Ebene des Request-Bodys samt seinem Beispiel (jedem benannten) auf sowie Status und Beschreibung jeder Response, mit den Beispielen, die die Spezifikation enthält, und einem generierten Beispiel für die erste Erfolgs-Response, die keins enthält.
Ein source kann auch ein $ref auf eine Datei sein, die den Code des Beispiels enthält – so, wie Redocly es beschreibt, Beispiele in eigenen Dateien abzulegen. Blume liest die Datei relativ zur Spezifikation und lädt sie herunter, wenn die Spezifikation eine URL ist. Bei einem $ref, den Blume nicht lesen kann, oder einem, der in ein Dokument hinein zeigt (#/…), wird dieses Beispiel mit einer BLUME_OPENAPI_CODE_SAMPLE_REF-Warnung weggelassen:
paths:
/plants:
get:
x-codeSamples:
- lang: go
source:
$ref: ./code_samples/go/list_plants.go
SDK-Beispiele zu generierter API-Dokumentation hinzufügen führt durch Beispiele für ein TypeScript- und ein Python-SDK, mit einer Prüfung, die Beispiele erkennt, die ein SDK-Release kaputt gemacht hat.
Try-it-Playground
Nativ gerenderte Operationsseiten bringen standardmäßig ein interaktives Try it-Panel mit. Blume generiert das Formular aus der Operation selbst: ein Eingabefeld pro Pfad-, Query- und Header-Parameter, einen Body-Editor, der aus dem Request-Body-Schema erstellt wird, und alles ist mit den Beispielen aus der Spezifikation vorausgefüllt. Werte werden so übertragen, wie die Spezifikation sie beschreibt: Array- und Objektparameter folgen ihrem style und explode (tags=dog&tags=cat in einer Query, 1,2 in einem Pfad, filter[color]=red bei deepObject), und ein application/x-www-form-urlencoded- oder multipart/form-data-Body wird als Formularfelder statt als JSON gesendet. Eine Serverauswahl listet die Server der Operation auf (ihre eigenen servers, sonst die ihres Pfads, sonst die der Spezifikation, wobei jede {variable} auf ihrem default steht), mit einem Freitextfeld für jede andere Basis-URL, und die Auth-Eingaben entsprechen der aufgelösten Security der Operation – Bearer-Token, API-Key und Basic-Credentials, wobei OAuth2 als Feld zum Einfügen eines Tokens umgesetzt ist (bring einen Access-Token mit; Blume führt den Flow nicht aus).
Wenn eine der Responses der Operation JSON ist, fordern Requests JSON an: Send und die Codebeispiele senden einen Accept-Header mit dem ersten JSON-Medientyp, den die Responses auflisten, wobei der einer Erfolgs-Response Vorrang vor den anderen hat. Frameworks wie Laravel beantworten einen Request ohne diesen Header so, als hätte ein Browser ihn gesendet, und leiten einen nicht authentifizierten Aufruf auf eine Login-Seite weiter, statt den 401 zurückzugeben, den die API dokumentiert. Ein Accept-Header-Parameter, den die Operation deklariert, tritt an seine Stelle.
Panel und Codebeispiele bleiben synchron: Werte, die du ins Formular eingibst, aktualisieren die generierten Codebeispiele live, sodass ein kopierter curl-Befehl immer genau dem entspricht, was Send tun würde. Und das Panel steht nicht im Weg – es wird serverseitig eingeklappt gerendert, und sein JavaScript lädt erst, wenn es jemand zum ersten Mal öffnet. Wer es nie anfasst, lädt nichts davon herunter.
Die einzige Methode, die ein Browser nicht senden kann, ist TRACE: fetch verweigert sie, daher weist Send bei einer trace-Operation darauf hin, statt den Request zu senden, und das JavaScript-Beispiel (das auf fetch basiert) ist ein Hinweis statt Code. Die cURL- und Python-Beispiele senden sie problemlos.
Mit playground: false schaltest du es komplett ab:
reference: [openapi({ spec: "./openapi.yaml", playground: false })],
Zugangsdaten
Zugangsdaten, die in die Auth-Eingaben eingegeben werden, bleiben im Arbeitsspeicher und verschwinden beim Neuladen. Wird Remember on this device aktiviert, werden sie in localStorage gespeichert, beschränkt auf den Origin der Doku – sie werden nirgendwohin gesendet außer an die aufgerufene API. Codebeispiele zeigen weiterhin Platzhalter (YOUR_TOKEN und Co.), egal was eingegeben wurde, es sei denn, die lesende Person aktiviert Include my values in samples.
CORS und der Proxy
Wie bei einem Scalar-Embed gehen Requests direkt vom Browser an die Ziel-API, daher muss die API Cross-Origin-Requests von der Doku-Website erlauben (Access-Control-Allow-Origin). Für APIs, die das nicht können, setze playground.proxy: Eine URL leitet Requests über einen Proxy, den du selbst hostest, und true aktiviert die eingebaute Route /_api-proxy (unter {basePath}/_api-proxy, wenn du einen basePath setzt) – die Server-Output benötigt, also einen Host-Adapter wie deployment: vercel() aus blume/deploy:
reference: [
openapi({
spec: "./openapi.yaml",
playground: {
proxy: true, // or a URL of your own
},
}),
],
Der eingebaute Proxy leitet Requests nur an die Origins weiter, die deine Spezifikationen in servers deklarieren (auf Dokument-, Pfad- oder Operationsebene, mit Variablen auf ihren Standardwerten) – auch über Redirects hinweg –, sodass ein öffentliches Doku-Deployment nicht auf andere Hosts in seinem Netzwerk gerichtet werden kann. Eine im Panel eingegebene Custom base URL ist kein dokumentierter Server: Bei aktiviertem Proxy werden Requests an sie mit einem 403 abgelehnt. Er leitet nur die Header weiter, die das Panel selbst setzt – die eingegebenen Zugangsdaten und Header-Parameter, den Accept-Header und den Content-Type des Bodys –, sodass Cookies, Zugangsdaten, die der Browser für die Doku-Website mitschickt (etwa HTTP-Basic-Auth bei einer passwortgeschützten Preview), und Header, die dein Host hinzufügt (X-Forwarded-For, CF-*, X-Vercel-*), nie bei der API ankommen. Er liest einen Request-Body nur bis zu 4 MB (alles Größere erhält einen 413), und jede Response, die er weiterleitet, enthält Content-Security-Policy: sandbox, X-Content-Type-Options: nosniff und Cross-Origin-Resource-Policy: same-origin – plus Content-Disposition: attachment bei HTML oder SVG –, sodass eine API-Fehlerseite, die ihre Eingabe zurückgibt, kein Skript auf dem Origin der Doku ausführen kann. Der Proxy ist außerdem pro lesender Person rate-limitiert, wie jede Server-Route, die Lesende aufrufen können.
Wenn ein Try-it-Request blockiert wird, reproduziert CORS-Fehler in einem Playground für API-Dokumentation beheben das Problem, liest den Preflight aus, den der Browser sendet, und behebt es mit einer CORS-Policy auf deiner API oder mit dem eingebauten Proxy.
Mehrere Spezifikationen
Verwende sources, um mehr als eine Spezifikation aus einem Adapter zu veröffentlichen. Jede Quelle bekommt ihre eigene Übersichtsroute und eigene Operationsseiten und teilt sich die Anzeigeoptionen des Adapters. Gib jeder Quelle ein label, das unverändert ihre Gruppe in der Sidebar benennt und aus dem ihre Route abgeleitet wird, oder setze eine explizite route:
reference: [
openapi({
sources: [
{ label: "Public API", spec: "./public.json" }, // → /reference/public-api
{ label: "Admin API", route: "/admin", spec: "./admin.json" },
],
}),
],
Die Gruppe einer Quelle liegt an ihrer Route, und jeder Ordner der Route darüber ist ebenfalls eine Gruppe in der Sidebar. Richte eine Spezifikation also auf den Ordner aus, den sie beschreibt: Mit route: "/apis/messaging" wird die Gruppe der Quelle zur eigenen Gruppe des Ordners messaging, benannt nach ihrem label, während "/apis/messaging/openapi" diese Gruppe in eine Messaging-Gruppe verschachtelt, die sonst nichts enthält.
spec ist eine Kurzform für ein sources mit einem einzigen Eintrag, du greifst also nur dann zu sources, wenn du mehr als eine Spezifikation hast. Wenn zwei Spezifikationen unterschiedliche Anzeigeoptionen brauchen – zum Beispiel eine andere Auswahl an Codebeispielen –, liste stattdessen zwei openapi()-Adapter auf, jeden mit eigener route. Eine eingebettete Scalar-Referenz neben nativen Seiten ist ein eigener scalar()-Adapter in der Liste. Quellen werden in Listenreihenfolge aufgelöst, und wenn zwei auf dieselbe Route aufgelöst werden, gewinnt die erste (der Build warnt vor der verworfenen).
Mehrere OpenAPI-Spezifikationen auf einer Doku-Website kombinieren baut auf diese Weise ein API-Portal auf, in dem die Spezifikation jedes Services auf einer eigenen Route und in einem eigenen Tab liegt.
Indexierung pro Quelle
Generierte Seiten sind standardmäßig Teil der Suche, von llms.txt und der Crawler-Indexierung. Eine sekundäre oder überlappende Spezifikation kann sich von jedem dieser Bereiche abmelden, ohne ihre Seiten zu verstecken oder aus der Navigation zu entfernen:
reference: [
openapi({
sources: [
{ label: "Public API", route: "/api", spec: "./public.json" },
{
label: "Platform API",
route: "/platform",
spec: "./platform.json",
includeInSearch: false,
includeInLlms: false,
noindex: true,
},
],
}),
],
includeInSearch: falsehält die Übersicht und die Operationen der Quelle aus der Website-Suche heraus.includeInLlms: falsehält sie aus beidenllms.txt-Dateien heraus.noindex: truefügt Noindex-Metadaten für Crawler hinzu und entfernt die Seiten aus der Sitemap.
Die Meta-Description jeder Operationsseite ist die eigene description (oder summary) der Operation, gefolgt von einem generierten Satz, der den Endpoint benennt – „Reference for the GET /pets endpoint in the Petstore API.“ –, sodass auch eine Spezifikation mit knappen einzeiligen Zusammenfassungen für jede Seite eine eigenständige Description in Snippet-Länge liefert. Dieser Satz ist auf Englisch. Auf einer Website, deren Spezifikationstexte in einer anderen Sprache verfasst sind, setze seoDescriptionSuffix: false an der Quelle, um ihn wegzulassen und jede Seite nur mit dem selbst verfassten Text zu beschreiben; eine Operation ohne description und ohne summary greift auf ihren Titel (GET /pets) zurück, sodass keine Seite mit leerer Description ausgeliefert wird:
reference: [
openapi({
sources: [{ spec: "./openapi.de.json", seoDescriptionSuffix: false }],
}),
],
Ein scalar()-Embed unterstützt davon nur noindex – es liegt ohnehin außerhalb von Blumes Suche und llms.txt, daher haben die beiden include*-Einstellungen dort keine Wirkung.
Overlays
Wenn die Spezifikation von einem anderen Tool generiert wird oder einem anderen Team gehört, halte deine Doku-Änderungen mit einem OpenAPI Overlay aus ihr heraus: einer separaten Datei, die Änderungen an der Spezifikation auflistet, etwa klarere Beschreibungen, eine öffentliche Server-URL oder entfernte interne Operationen. Liste Overlays neben spec auf. Jedes ist ein lokaler Pfad oder eine http(s)-URL, und sie werden der Reihe nach angewendet:
reference: [
openapi({
spec: "./openapi.json",
overlays: ["./overlays/public.yaml"],
}),
],
overlay: 1.1.0
info:
title: Public docs
version: 1.0.0
actions:
- target: $.paths.*[?@['x-internal'] == true]
remove: true
- target: $.info
update:
description: The public Acme API.
Das target jeder Action ist ein JSONPath-Ausdruck. update wird mit jedem ausgewählten Knoten zusammengeführt: Objekte werden Schlüssel für Schlüssel zusammengeführt, Arrays erhalten die neuen Einträge, und andere Werte werden ersetzt. copy führt einen Knoten von einer anderen Stelle der Spezifikation hinein (Overlay 1.1), und remove: true löscht die Ziele. Sowohl Overlay Specification 1.0 als auch 1.1 werden unterstützt.
Overlays werden auf die Spezifikation in ihrer geschriebenen Form angewendet, bevor Blume sie auf OpenAPI 3.1 aktualisiert – ein Overlay zielt also auf die Version, in der du die Spezifikation geschrieben hast. Alles, was aus der Spezifikation gebaut wird, sieht das Ergebnis: die Operationsseiten, die Sidebar, die Suche, llms.txt und der MCP-Server. Mit sources gibst du jeder Quelle ihre eigenen overlays. Ein Overlay, das sich nicht anwenden lässt, lässt die Referenz genauso fehlschlagen wie eine unlesbare Spezifikation, sodass ein kaputtes Overlay nicht veröffentlichen kann, was es verbergen sollte.
Interne Endpoints aus öffentlicher API-Doku entfernen führt durch ein Overlay, das bei jedem Build interne Operationen aus einer generierten Spezifikation entfernt.
Autorisierung
Operationen, die Security-Anforderungen deklarieren, rendern oberhalb ihrer Parameter einen Authorization-Abschnitt, und die generierten Codebeispiele senden Platzhalter-Zugangsdaten (Authorization: Bearer YOUR_TOKEN, einen API-Key-Header oder einen Query-Key – je nachdem, was das Security-Scheme verlangt). Es gibt nichts zu konfigurieren: Blume liest security aus der Spezifikation, sodass die Referenz immer dem entspricht, was die API tatsächlich durchsetzt.
Die OpenAPI-Semantik wird unverändert übernommen:
- Die eigene
securityeiner Operation überschreibt den Standardwert auf Root-Ebene des Dokuments;security: []kennzeichnet sie als öffentlich, und es wird kein Authorization-Abschnitt gerendert. - Mehrere Anforderungseinträge sind Alternativen – gerendert als „oder“-Gruppen; alle Schemes innerhalb eines Eintrags sind gemeinsam erforderlich. Die erste Alternative fließt in die Codebeispiele ein.
- Ein leerer
{}-Eintrag bedeutet, dass Auth für diese Operation optional ist, und der Abschnitt weist darauf hin. - OAuth2-Scopes werden pro Scheme aufgelistet; die
descriptions von Schemes auscomponents.securitySchemeswerden inline gerendert.
Webhooks und Callbacks
Auch die ausgehenden Requests deiner API werden dokumentiert. Jeder Webhook im webhooks-Feld auf oberster Ebene der Spezifikation bekommt wie eine Operation seine eigene Seite: einsortiert unter seinem ersten Tag oder in einer Webhooks-Gruppe, wenn er keinen hat. Die Seite zeigt das Schema des Payloads und die Responses, die dein Endpoint zurücksenden sollte. Anstelle des Try-it-Panels und der Codebeispiele zeigt die rechte Spalte einen Beispiel-Payload, da deine API diesen Request sendet, statt ihn zu beantworten. Eine Webhook-Seite listet nur die security auf, die der Webhook selbst deklariert: Die security auf Root-Ebene der Spezifikation schützt Aufrufe an deine API und gilt daher nicht für Requests, die die API sendet. Ein Webhook, der ein $ref auf ein gemeinsam genutztes Path Item ist, wird weggelassen, mit einer BLUME_OPENAPI_REF_PATH_ITEM-Warnung.
webhooks:
newPet:
post:
summary: New pet added
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
responses:
"200":
description: Return a 200 to acknowledge the event.
Die Webhooks einer 3.0-Spezifikation unter der Extension x-webhooks werden zu webhooks, wenn Blume die Spezifikation auf 3.1 aktualisiert. Eine Spezifikation, die bereits in 3.1 oder neuer vorliegt, wird nicht aktualisiert, daher wird für Webhooks, die sie noch unter x-webhooks führt, nichts gerendert, und es erscheint eine BLUME_OPENAPI_X_WEBHOOKS-Warnung: Benenne das Feld in webhooks um.
Die callbacks einer Operation – die Requests, die deine API zurück an eine vom Aufrufer angegebene URL sendet – werden in einem Callbacks-Abschnitt auf der Seite dieser Operation gerendert. Jeder zeigt den URL-Ausdruck ({$request.body#/callbackUrl}), seine Methode, seine Parameter (etwa einen Signatur-Header), seinen Request-Body und seine erwarteten Responses. Callbacks, die unter components.callbacks deklariert und mit $ref referenziert werden, funktionieren genauso.
Webhook-Seiten sind echte Seiten: Sie tauchen in der Suche, in llms.txt und im MCP-Server auf, und ihr Markdown teilt Agents mit, dass es sich um einen Request handelt, den die API sendet – so versucht ein Agent nicht, ihn aufzurufen.
Webhook-Dokumentation mit OpenAPI 3.1 schreiben ergänzt die Webhook-Seiten um Signatur-Header und Empfangsbestätigungen und fügt eine Anleitung zum Empfangen mit einem funktionierenden Receiver in Node.js hinzu.
Spezifikationswarnungen
Blume validiert eine Spezifikation nicht gegen das OpenAPI-Schema – nutze dafür einen Linter wie Spectral oder oasdiff in deiner CI. Blume warnt aber in blume dev, blume build und blume check vor Fehlern, die sonst ohne jeden Hinweis falsch gerendert würden, und vor Teilen einer Spezifikation, die es weglässt. Jede Warnung nennt die Spezifikation, und der Rest der Referenz wird trotzdem gebaut:
| Code | Was falsch ist |
|---|---|
BLUME_OPENAPI_PATH_PARAMETER_MISSING |
Zu einem {name} im Pfad einer Operation gibt es keinen in: path-Parameter dieses Namens, daher hat die Seite kein Eingabefeld dafür, und Try it sowie die Codebeispiele senden den Platzhalter als wörtlichen Text. |
BLUME_OPENAPI_PATH_PARAMETER_UNUSED |
Zu einem in: path-Parameter gibt es kein {name} im Pfad, daher landet der Wert, nach dem Try it fragt, nie in der URL. |
BLUME_OPENAPI_UNKNOWN_SECURITY_SCHEME |
Eine security-Anforderung nennt ein Scheme, das components.securitySchemes nicht definiert, daher kann der Authorization-Abschnitt es nicht beschreiben, und Requests senden keine Zugangsdaten dafür. |
BLUME_OPENAPI_UNSUPPORTED |
Die Spezifikation verwendet ein Feature aus OpenAPI 3.2, das Blume noch nicht rendert: additionalOperations, wodurch diese Operationen weggelassen werden, oder einen in: querystring-Parameter, wodurch der Query-String auf der Seite, in Try it und in den Codebeispielen fehlt. |
BLUME_OPENAPI_CODE_SAMPLE_REF |
Das source eines x-codeSamples-Eintrags ist ein $ref, den Blume nicht lesen kann oder der in ein Dokument hinein zeigt, daher wird dieses Beispiel weggelassen. |
BLUME_OPENAPI_X_WEBHOOKS |
Eine Spezifikation in 3.1 oder neuer führt ihre Webhooks unter x-webhooks, der Extension, die 3.0-Tools lesen, und hat kein webhooks, daher wird keiner davon gerendert. Benenne das Feld in webhooks um. |
BLUME_OPENAPI_REF_PATH_ITEM |
Ein Pfad oder Webhook ist ein $ref auf ein gemeinsam genutztes Path Item, etwa eines unter components.pathItems. Blume löst diese nicht auf, daher fehlen seine Operationen in der Referenz. Schreibe das Path Item direkt unter paths oder webhooks; seine Schemas, Parameter und Responses können $refs bleiben. |
BLUME_OPENAPI_DUPLICATE_OPERATION_ID |
Zwei Operationen teilen sich eine operationId, die in einer Spezifikation eindeutig sein muss. Die Warnung nennt beide. Blume hängt die Methode an die Id der zweiten in <Operation id> an und, wenn die beiden denselben Tag haben, auch an ihre URL. Gib jeder Operation ihre eigene operationId. |
BLUME_OPENAPI_LOCAL_SERVER |
Ein Server, den die Spezifikation, ein Pfad oder eine Operation deklariert, ist eine lokale Adresse (localhost, 127.0.0.1, 0.0.0.0, [::1]), oft von einem Framework eingetragen, das die Spezifikation auf einem Entwicklungsrechner exportiert hat. Try it und die Codebeispiele würden Requests an diese Adresse senden, die für Lesende nicht erreichbar ist. Trag die öffentliche URL in servers ein oder setze sie mit einem Overlay. |
BLUME_OPENAPI_NULLABLE |
Eine Spezifikation, die OpenAPI 3.1 oder neuer deklariert, verwendet nullable, das in 3.1 entfernt wurde. Blume zeigt diese Werte weiterhin als nullable an, aber Validatoren und SDK-Generatoren, die sich an 3.1 halten, lesen sie als niemals null. Die Warnung nennt die Stellen als JSON Pointer in die Spezifikation. Füge stattdessen "null" zum type des Schemas hinzu (type: [string, "null"]). |
API-Dokumentation in der CI mit Backend-Änderungen synchron halten führt diese Prüfungen in GitHub Actions aus: Die Spezifikation wird aus dem Backend exportiert, der Build schlägt fehl, wenn die Spezifikation veraltet oder ungültig ist oder Breaking Changes enthält, und die Referenz wird daraus neu gebaut.
Operationen auf deinen eigenen Seiten
Jede MDX-Seite kann mit <Operation> eine Operation aus einer Referenz anzeigen: ihre Autorisierung, ihre Parameter, ihren Request-Body und ihre Responses, neben dem Try-it-Panel und den Codebeispielen, so wie die eigene Seite der Operation sie zeigt. Ein Quickstart kann so den einen Aufruf durchgehen, um den es geht, ohne Lesende auf eine andere Seite zu schicken:
---
title: Quickstart
mode: wide
---
Create your first pet:
<Operation source="reference" id="add-pet" />
source benennt die Referenz über ihre Route, ohne Schrägstriche, kleingeschrieben und mit Bindestrichen (/reference wird zu reference, /api/v2 zu api-v2). id benennt die Operation: ihre operationId, kleingeschrieben mit durch Bindestriche getrennten Wörtern (addPet wird zu add-pet), oder, wenn sie keine hat, ihre Methode und ihr Pfad (post-pets). Am sichersten bekommst du beides über die rohe MDX-Fassung einer Operationsseite unter ihrer URL plus .mdx, deren Body genau das Tag ist, das du kopierst. Die Operation wird zweispaltig dargestellt, gib der Seite also mode: wide: Neben dem Inhaltsverzeichnis ist die linke Spalte schmal. In der Markdown-Fassung der Seite wird das Tag zum Endpoint, zum Request-Body und zu den Responses, wie auf der eigenen Seite der Operation.
Scalar stattdessen einbetten
openapi() rendert immer Blumes eigene Seiten. Um stattdessen die eigenständige API-Referenz-UI von Scalar auf einer einzelnen Route einzubetten – mit eigener Sidebar, eigener Suche, eigenem Theme und eigenem Request-Client –, liste anstelle dieses Adapters (oder daneben) einen scalar()-Adapter aus blume/reference auf. Die Seite Scalar erklärt, was das Embed kann und was nicht und wie du Scalars eigene Optionen durchreichst.