OpenAPI
Adicione uma especificação OpenAPI e ganhe uma referência de API nativa, com uma página real por operação, na sua barra lateral e na busca.
Aponte o Blume para uma especificação OpenAPI e ele gera uma referência de API nativa: uma página real por operação, agrupada por tag em uma barra lateral com escopo de aba, com tabelas de schema, exemplos de requisição/resposta, exemplos de código gerados e um painel interativo Try it. Como cada operação é uma página genuína do Blume, ela ganha sua própria URL, aparece na busca do site e no llms.txt e ganha uma imagem Open Graph, igual a qualquer documento escrito à mão.
Toda referência é um adaptador importado de blume/reference e listado em reference: openapi() para um documento OpenAPI, asyncapi() para um documento AsyncAPI e graphql() para um schema GraphQL. Cada adaptador cuida das próprias fontes de especificação, da própria rota de montagem e das próprias opções de exibição, então a lista pode ter quantos adaptadores de cada tipo você precisar. Como exemplo, a configuração abaixo aponta o Blume para a especificação pública do Petstore.
import { defineConfig } from "blume";
import { openapi } from "blume/reference";
export default defineConfig({
reference: [
openapi({ spec: "https://petstore3.swagger.io/api/v3/openapi.json" }),
],
});
Isso monta a referência em /reference (uma página de visão geral), com cada operação em /reference/<tag>/<operation>. O spec pode ser uma URL http(s) ou o caminho de um arquivo local no seu projeto. O Blume faz o parse dele com o parser de OpenAPI do Scalar. Especificações Swagger 2.0 e OpenAPI 3.0 são convertidas para 3.1 automaticamente, e especificações 3.1 e 3.2 são lidas do jeito que foram escritas. Um adaptador é uma descrição simples da referência, e não uma especificação já processada. Por isso o Blume consegue validá-lo de antemão e embuti-lo no site gerado. Se você deixar reference de fora (ou vazio), nenhuma referência é renderizada. Está documentando uma API orientada a eventos ou uma API GraphQL? Veja AsyncAPI e GraphQL.
Para ir da especificação gerada pelo seu framework até uma referência publicada, siga o guia de FastAPI, Django REST Framework, NestJS, Spring Boot, ASP.NET Core, Laravel, Rails, Hono, Fastify, Elysia ou oRPC. Se você define a API em TypeSpec, publique a referência a partir da definição em TypeSpec. O guia Gerar a documentação da API a partir de uma especificação OpenAPI parte de qualquer arquivo de especificação.
A referência não adiciona uma aba ao cabeçalho sozinha. Para exibi-la, aponte uma aba de navegação para a rota dela. Isso também define o escopo da barra lateral de operações no renderizador nativo:
navigation: {
tabs: [{ label: "API", path: "/reference" }],
}
Os grupos de tags da barra lateral e as seções da página de visão geral seguem a mesma ordem: a ordem da lista tags na raiz da especificação e, depois, qualquer tag que ela não declare, na ordem em que as operações a usam pela primeira vez. Dentro de uma tag, as operações também seguem a especificação: os caminhos na ordem em que são listados e os métodos de cada caminho na ordem em que foram escritos. Um meta.ts na pasta de uma tag, com a própria lista pages, substitui essa ordem.
O x-displayName de uma tag, a extensão da Redocly, nomeia o grupo dela na barra lateral e a seção dela na visão geral no lugar do nome. A URL dela continua vindo do nome, então adicionar um não muda nenhuma página de lugar. Uma operação aparece com o seu summary ou, quando não tem um, com o método e o caminho (GET /pets), do mesmo jeito que a página dela recebe o título.
O info.description da especificação abre a página de visão geral, e a description de cada tag abre a seção dela ali. Os títulos desses textos descem um nível em relação a onde estão, então o título da página continua sendo o único título de primeiro nível: um # Authentication no info.description ou na description de uma operação é renderizado como título de segundo nível e, na descrição de uma tag, como título de terceiro nível, abaixo do título da própria tag.
Uma especificação local
Um caminho relativo é resolvido a partir da raiz do seu projeto e lido durante o build. Funciona tanto com JSON quanto com YAML, e o blume dev observa o arquivo, junto com quaisquer overlays locais, então a referência é atualizada quando você salva a especificação:
reference: [openapi({ spec: "./openapi.yaml" })],
OpenAPI 3.2
Especificações OpenAPI 3.2 são renderizadas do jeito que foram escritas. Uma operação query, para o método HTTP QUERY (uma requisição segura que carrega um corpo), ganha uma página, o Try it e exemplos de código, como qualquer outro método. Campos adicionados na 3.2 que o Blume não exibe, como o summary de uma tag ou de uma resposta, são ignorados em vez de rejeitados. Algumas novidades da 3.2 ainda não são renderizadas:
additionalOperations, para métodos que um path item não nomeia diretamente (comoCOPY): essas operações ficam de fora, com um avisoBLUME_OPENAPI_UNSUPPORTED.- Parâmetros
in: querystring: eles não ganham linha na tabela de parâmetros, nem campo no Try it, nem lugar nos exemplos de código, e geram o mesmo aviso. itemSchema, o schema de cada item em um corpo transmitido em streaming (text/event-stream,application/jsonl): a página não mostra nenhum schema para esse corpo, a menos queschemaesteja definido ao lado dele.- Exemplos escritos com
dataValueouserializedValueno lugar devalue: a página não os mostra. - Tags aninhadas (
parent) e okinddas tags: as tags continuam em uma única lista plana na barra lateral e na visão geral.
Rota
route define onde a referência é montada. Isso vale para a página de visão geral, para o prefixo de todas as rotas de operação e para a rota à qual você aponta uma aba de navegação:
reference: [
openapi({
route: "/api", // overview at /api, operations at /api/<tag>/<operation>
spec: "./openapi.yaml",
}),
],
O <tag> de uma operação é a primeira tag dela (operations quando ela não tem nenhuma), e o <operation> é o operationId dela ou, na falta dele, o método e o caminho. Os dois ficam em minúsculas, com as palavras separadas por hífens, inclusive em camelCase e PascalCase: a tag InboxesThreads vira inboxes-threads, e o operationId listThreads vira list-threads. O slug de uma operação só precisa ser único dentro da tag dela, então duas tags podem ter cada uma um list. Um segundo list na mesma tag ganha o método no final (list-post), com um aviso BLUME_OPENAPI_DUPLICATE_OPERATION_ID quando os dois compartilham um operationId.
Versões anteriores do Blume mantinham as palavras de uma tag juntas (inboxesthreads) e faziam o slug de uma operação ser único na especificação inteira (list-get para o segundo list). O Blume redireciona cada uma dessas URLs, e a cópia em Markdown delas, para a URL atual da página, a menos que uma página ou um dos seus redirects já esteja nessa URL.
Exemplos de código e schemas
codeSamples escolhe quais linguagens são renderizadas em cada operação, na ordem em que você as lista. O padrão é ["curl", "js", "python"], e false ou uma lista vazia não mostra nenhum. Com expandSchemas, as linhas de schemas aninhados começam expandidas em vez de recolhidas:
reference: [
openapi({
spec: "./openapi.yaml",
codeSamples: ["curl", "python", "go", "java", "csharp"],
expandSchemas: true,
}),
],
Cada exemplo é um código simples, pronto para copiar e colar, que faz a requisição com o cliente HTTP padrão ou mais comum da linguagem:
| Id | Linguagem | Cliente | Também aceita |
|---|---|---|---|
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 | a extensão curl | |
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 |
Cada valor é colocado entre aspas de acordo com as regras da própria linguagem. Assim, um header como If-Match: "33a64df5" ou um corpo com um $ chega à API exatamente como foi escrito.
Um id para o qual o Blume não gera exemplo, como o objectivec do ReadMe, fica de fora de todas as páginas, com um aviso BLUME_OPENAPI_UNKNOWN_CODE_SAMPLE que lista os ids acima. Para mostrar um exemplo em outra linguagem, escreva-o na especificação como um exemplo seu.
As tabelas de schema seguem o caminho que os dados percorrem, assim como os exemplos: o corpo de uma requisição deixa de fora as propriedades readOnly, que o servidor define, e uma resposta deixa de fora as writeOnly, que ele nunca devolve. O corpo de um webhook ou callback é uma requisição que a sua API envia, então ele é tratado como uma resposta. O mesmo vale para os exemplos de requisição, para o formulário do Try it e o pré-preenchimento dele e para os exemplos de resposta, inclusive os exemplos escritos na especificação, como um example no nível do modelo que traz o id do modelo.
Um corpo ou uma resposta cujo mapa examples nomeia dois ou mais exemplos mostra cada um deles, identificado pelo seu summary ou, quando não tem um, pela sua chave. Uma resposta ganha uma aba por exemplo depois do status (200 · A cat), o payload de um webhook ganha uma por exemplo depois do media type, e o corpo de uma requisição ganha um bloco Examples abaixo do schema. Os exemplos de código e o Try it partem do primeiro.
Uma propriedade escrita como um $ref com palavras-chave ao lado, algo que o OpenAPI 3.1 permite, usa essas palavras-chave no lugar das do schema referenciado. A linha dela mostra a própria description, e os exemplos usam o próprio example ou default dela.
Seus próprios exemplos
Para mostrar o seu SDK em vez de uma chamada HTTP crua, adicione x-codeSamples a uma operação na especificação. Essa é a extensão definida pela Redocly, e o Speakeasy e o Stainless conseguem gerá-la para você. Cada entrada recebe um lang, o source e um label opcional:
paths:
/plants:
get:
x-codeSamples:
- lang: typescript
label: SDK
source: |
const plants = await planter.plants.list();
- lang: bash
label: CLI
source: |
planter list
Esses exemplos aparecem em abas próprias, antes dos gerados, e continuam exatamente como foram escritos quando o leitor altera o formulário do Try it. A grafia antiga x-code-samples também funciona. Para mostrar só os seus próprios exemplos, defina codeSamples: false. Diferente dos exemplos gerados, eles também entram na cópia em Markdown da página da operação, então o llms-full.txt, o servidor MCP e o assistente veem as chamadas do seu SDK. Essa cópia também lista o media type e as propriedades de primeiro nível do corpo da requisição, com o exemplo dele (todos os nomeados), e o status e a descrição de cada resposta, com os exemplos que a especificação registra e um exemplo gerado para a primeira resposta de sucesso que não registra nenhum.
O source também pode ser um $ref para um arquivo com o código do exemplo, do jeito que a Redocly descreve para manter os exemplos em arquivos próprios. O Blume lê o arquivo de forma relativa à especificação e o baixa quando a especificação é uma URL. Um $ref que ele não consegue ler, ou que aponta para dentro de um documento (#/…), deixa esse exemplo de fora com um aviso BLUME_OPENAPI_CODE_SAMPLE_REF:
paths:
/plants:
get:
x-codeSamples:
- lang: go
source:
$ref: ./code_samples/go/list_plants.go
O guia Adicionar exemplos de SDK à documentação de API gerada mostra, passo a passo, exemplos para um SDK em TypeScript e outro em Python, com uma verificação que detecta exemplos quebrados por uma nova versão do SDK.
Playground Try it
As páginas de operação renderizadas nativamente já vêm com um painel interativo Try it. O Blume gera o formulário a partir da própria operação. Cada parâmetro de caminho, de query e de header ganha um campo, o editor de corpo é montado a partir do schema do corpo da requisição e tudo vem pré-preenchido com os exemplos da especificação. Os valores são enviados do jeito que a especificação descreve: parâmetros de array e de objeto seguem o style e o explode deles (tags=dog&tags=cat em uma query, 1,2 em um caminho, filter[color]=red para deepObject), e um corpo application/x-www-form-urlencoded ou multipart/form-data é enviado como campos de formulário, e não como JSON. Um seletor de servidor lista os servidores da operação (os servers dela, senão os do caminho dela, senão os da especificação, com cada {variable} no seu default) e inclui um campo de texto livre para qualquer outra URL base. Os campos de autenticação seguem a segurança resolvida da operação: token bearer, chave de API e credenciais basic. Para OAuth2, há um campo onde você cola o token. Você precisa trazer um access token, porque o Blume não executa o fluxo.
Quando alguma das respostas da operação é JSON, as requisições pedem JSON: o Send e os exemplos de código enviam um header Accept com o primeiro media type JSON listado nas respostas, dando preferência ao de uma resposta de sucesso. Frameworks como o Laravel respondem a uma requisição sem esse header como se ela viesse de um navegador e redirecionam uma chamada sem autenticação para uma página de login em vez de devolver o 401 que a API documenta. Se a operação declara um parâmetro de header Accept, ele é usado no lugar.
O painel e os exemplos de código andam juntos. Os valores digitados no formulário atualizam os exemplos gerados em tempo real, então um comando curl copiado sempre corresponde exatamente ao que o Send faria. E o painel não atrapalha: ele é renderizado no servidor já recolhido, e o JavaScript dele só carrega quando um leitor o abre pela primeira vez. Quem nunca mexe no painel não baixa nada disso.
O único método que um navegador não consegue enviar é o TRACE, porque o fetch se recusa a enviá-lo. Por isso, em uma operação trace, o Send avisa isso em vez de enviar a requisição, e o exemplo em JavaScript (feito com fetch) vira uma nota em vez de código. Os exemplos em cURL e Python enviam normalmente.
Para desligar tudo, basta usar playground: false:
reference: [openapi({ spec: "./openapi.yaml", playground: false })],
Credenciais
As credenciais digitadas nos campos de autenticação ficam só na memória e somem quando a página é recarregada. Se você marcar Remember on this device, elas ficam salvas no localStorage, restritas à origem da documentação. Elas nunca são enviadas a nenhum lugar além da API chamada. Os exemplos de código continuam mostrando placeholders (YOUR_TOKEN e afins), não importa o que for digitado, a menos que o leitor ative Include my values in samples.
CORS e o proxy
Assim como em um embed do Scalar, as requisições vão direto do navegador para a API de destino. Por isso, a API precisa permitir requisições cross-origin vindas do site de documentação (Access-Control-Allow-Origin). Se a API não permitir, defina playground.proxy. Com uma URL, as requisições passam por um proxy hospedado por você. Com true, você ativa a rota nativa /_api-proxy (em {basePath}/_api-proxy quando você define um basePath), que exige saída de servidor, ou seja, um adaptador de hospedagem como deployment: vercel() de blume/deploy:
reference: [
openapi({
spec: "./openapi.yaml",
playground: {
proxy: true, // or a URL of your own
},
}),
],
O proxy nativo só encaminha requisições para as origens declaradas em servers nas suas especificações (no nível do documento, do caminho ou da operação, com as variáveis nos seus valores padrão), inclusive quando segue redirecionamentos. Assim, uma documentação publicada não pode ser usada para acessar outros hosts da rede onde ela roda. Uma Custom base URL digitada no painel não conta como servidor documentado: com o proxy ativado, as requisições para ela são recusadas com um 403. O proxy só encaminha os headers que o próprio painel define (as credenciais e os parâmetros de header preenchidos, o header Accept e o Content-Type do corpo). Assim, cookies, credenciais que o navegador anexa para o site de documentação (como a autenticação HTTP Basic de um preview protegido por senha) e headers adicionados pela sua hospedagem (X-Forwarded-For, CF-*, X-Vercel-*) nunca chegam à API. O proxy lê o corpo da requisição só até 4 MB, e qualquer coisa maior recebe um 413. Toda resposta repassada por ele carrega Content-Security-Policy: sandbox, X-Content-Type-Options: nosniff e Cross-Origin-Resource-Policy: same-origin, além de Content-Disposition: attachment para HTML ou SVG. Assim, uma página de erro da API que ecoa a entrada não consegue executar scripts na origem da documentação. O proxy também tem limite de requisições por leitor, assim como toda rota de servidor que um leitor pode chamar.
Quando uma requisição do Try it é bloqueada, o guia Corrigir erros de CORS em um playground de documentação de API reproduz o problema, analisa o preflight que o navegador envia e o corrige com uma política de CORS na sua API ou com o proxy nativo.
Várias especificações
Use sources para publicar mais de uma especificação com um único adaptador. Cada fonte ganha sua própria rota de visão geral e suas próprias páginas de operação, e todas compartilham as opções de exibição do adaptador. Dê um label a cada uma (ele nomeia o grupo dela na barra lateral exatamente como está escrito e serve para derivar a rota) ou defina uma route explícita:
reference: [
openapi({
sources: [
{ label: "Public API", spec: "./public.json" }, // → /reference/public-api
{ label: "Admin API", route: "/admin", spec: "./admin.json" },
],
}),
],
O grupo de uma fonte fica na rota dela, e cada pasta da rota acima dele também vira um grupo na barra lateral. Então, monte a especificação na pasta que ela descreve: route: "/apis/messaging" faz do grupo da fonte o próprio grupo da pasta messaging, com o nome do label dela, enquanto "/apis/messaging/openapi" aninha esse grupo dentro de um grupo Messaging que não contém mais nada.
spec é um atalho para um sources com uma única entrada, então você só precisa de sources quando tiver mais de uma especificação. Se duas especificações precisarem de opções de exibição diferentes, como conjuntos diferentes de exemplos de código, liste dois adaptadores openapi(), cada um com sua própria route. Para incorporar uma referência do Scalar ao lado das páginas nativas, adicione um adaptador scalar() separado na lista. As fontes são resolvidas na ordem da lista. Quando duas resolvem para a mesma rota, a primeira vence, e o build emite um aviso sobre a que foi descartada.
O guia Combinar várias especificações OpenAPI em um único site de documentação monta um portal de APIs desse jeito, com a especificação de cada serviço em sua própria rota e aba.
Indexação por fonte
Por padrão, as páginas geradas entram na busca, no llms.txt e na indexação por crawlers. Uma especificação secundária ou sobreposta pode ficar de fora de qualquer um desses lugares sem esconder suas páginas nem sair da navegação:
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: falsetira a visão geral e as operações da fonte da busca do site.includeInLlms: falsetira essas páginas dos dois arquivosllms.txt.noindex: trueadiciona metadados de noindex para crawlers e remove as páginas do sitemap.
A meta description de cada página de operação é a description (ou o summary) da própria operação, seguida de uma frase gerada que cita o endpoint, como “Reference for the GET /pets endpoint in the Petstore API.”. Assim, mesmo uma especificação com resumos curtos de uma linha gera uma descrição única, do tamanho de um snippet, para cada página. Essa frase é em inglês. Se a prosa da sua especificação estiver em outro idioma, defina seoDescriptionSuffix: false na fonte para removê-la. Aí cada página é descrita só com o texto que você escreveu. Uma operação sem description e sem summary usa o título como fallback (GET /pets), então nenhuma página fica com a descrição vazia:
reference: [
openapi({
sources: [{ spec: "./openapi.de.json", seoDescriptionSuffix: false }],
}),
],
Um embed scalar() aceita só a opção noindex dentre essas. Ele já fica fora da busca e do llms.txt do Blume, então as duas opções include* não teriam efeito nele.
Overlays
Quando a especificação é gerada por outra ferramenta ou pertence a outro time, mantenha as alterações da sua documentação fora dela com um OpenAPI Overlay: um arquivo separado que lista as alterações a serem feitas na especificação, como descrições mais claras, uma URL de servidor pública ou a remoção de operações internas. Liste os overlays ao lado de spec. Cada um é um caminho local ou uma URL http(s), e eles são aplicados em ordem:
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.
O target de cada ação é uma expressão JSONPath. update mescla seu conteúdo em cada nó selecionado: objetos são mesclados chave por chave, arrays ganham os novos itens e os demais valores são substituídos. copy mescla um nó vindo de outra parte da especificação (Overlay 1.1), e remove: true apaga os alvos. As versões 1.0 e 1.1 da Overlay Specification são suportadas.
Os overlays são aplicados à especificação do jeito que ela foi escrita, antes de o Blume convertê-la para OpenAPI 3.1. Por isso, um overlay tem como alvo a versão em que você escreveu a especificação. Tudo o que é gerado a partir da especificação reflete o resultado: as páginas de operação, a barra lateral, a busca, o llms.txt e o servidor MCP. Com sources, dê a cada fonte seus próprios overlays. Um overlay que não pode ser aplicado faz a referência falhar, assim como acontece com uma especificação ilegível. Assim, um overlay quebrado não consegue publicar o que deveria esconder.
O guia Remover endpoints internos da documentação pública da API mostra, passo a passo, um overlay que remove as operações internas de uma especificação gerada a cada build.
Autorização
Operações que declaram requisitos de segurança renderizam uma seção Authorization acima dos parâmetros. Os exemplos de código gerados enviam uma credencial placeholder de acordo com o esquema: Authorization: Bearer YOUR_TOKEN, um header de chave de API ou uma chave na query. Não há nada para configurar. O Blume lê security da especificação, então a referência sempre corresponde ao que a API realmente exige.
A semântica do OpenAPI é mantida exatamente como está escrita:
- O
securityda própria operação substitui o padrão definido na raiz do documento.security: []marca a operação como pública, e nenhuma seção Authorization é renderizada. - Várias entradas de requisito são alternativas e aparecem como grupos “ou”. Todos os esquemas de uma mesma entrada são exigidos juntos. Os exemplos de código usam a primeira alternativa.
- Uma entrada vazia
{}significa que a autenticação é opcional naquela operação, e a seção avisa isso. - Os escopos OAuth2 são listados por esquema, e as
descriptions dos esquemas emcomponents.securitySchemesaparecem inline.
Webhooks e callbacks
As requisições que a sua API envia também são documentadas. Cada webhook no webhooks da raiz da especificação ganha sua própria página, assim como uma operação: ele fica na sua primeira tag ou, quando não tem nenhuma, em um grupo Webhooks. A página mostra o schema do payload e as respostas que o seu endpoint deve devolver. No lugar do painel Try it e dos exemplos de código, a coluna lateral mostra um payload de exemplo, já que a sua API envia essa requisição em vez de recebê-la. A página de um webhook lista só o security que o próprio webhook declara: o security da raiz da especificação protege as chamadas feitas à sua API, então ele não se aplica às requisições que a API envia. Um webhook que é um $ref para um path item compartilhado fica de fora, com um aviso BLUME_OPENAPI_REF_PATH_ITEM.
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.
Os webhooks de uma especificação 3.0 que ficam na extensão x-webhooks viram webhooks quando o Blume converte a especificação para 3.1. Uma especificação que já está na 3.1 ou em uma versão posterior não é convertida, então os webhooks que ela ainda mantém em x-webhooks não renderizam nada e geram um aviso BLUME_OPENAPI_X_WEBHOOKS: renomeie o campo para webhooks.
Os callbacks de uma operação, ou seja, as requisições que a sua API faz de volta para uma URL informada por quem a chamou, são renderizados em uma seção Callbacks na página dessa operação. Cada um mostra a expressão de URL ({$request.body#/callbackUrl}), o método, os parâmetros (um header de assinatura, por exemplo), o corpo da requisição e as respostas esperadas. Callbacks declarados em components.callbacks e referenciados com $ref funcionam do mesmo jeito.
As páginas de webhook são páginas reais: elas aparecem na busca, no llms.txt e no servidor MCP, e o Markdown delas avisa aos agentes que se trata de uma requisição enviada pela API. Assim, um agente não vai tentar chamá-la.
O guia Escrever documentação de webhooks com OpenAPI 3.1 adiciona headers de assinatura e confirmações de recebimento às páginas de webhook, além de um guia de recebimento com um receptor funcional em Node.js.
Avisos da especificação
O Blume não valida a especificação contra o schema do OpenAPI. Para isso, rode um linter como o Spectral ou o oasdiff no CI. Mas ele avisa, no blume dev, no blume build e no blume check, sobre erros que, de outra forma, seriam renderizados errado sem nenhum sinal, e sobre partes da especificação que ele deixa de fora. Cada aviso cita a especificação, e o resto da referência continua sendo gerado:
| Código | O que está errado |
|---|---|
BLUME_OPENAPI_PATH_PARAMETER_MISSING |
Um {name} no caminho de uma operação não tem um parâmetro in: path com esse nome. Assim, a página não tem campo para ele, e o Try it e os exemplos de código enviam o placeholder como texto literal. |
BLUME_OPENAPI_PATH_PARAMETER_UNUSED |
Um parâmetro in: path não tem um {name} correspondente no caminho, então o valor que o Try it pede nunca chega à URL. |
BLUME_OPENAPI_UNKNOWN_SECURITY_SCHEME |
Um requisito de security cita um esquema que components.securitySchemes não define. Assim, a seção Authorization não consegue descrevê-lo, e as requisições não enviam nenhuma credencial para ele. |
BLUME_OPENAPI_UNSUPPORTED |
A especificação usa um recurso do OpenAPI 3.2 que o Blume ainda não renderiza: additionalOperations, que deixa essas operações de fora, ou um parâmetro in: querystring, que deixa a query string de fora da página, do Try it e dos exemplos de código. |
BLUME_OPENAPI_CODE_SAMPLE_REF |
O source de uma entrada de x-codeSamples é um $ref que o Blume não consegue ler, ou que aponta para dentro de um documento, então esse exemplo fica de fora. |
BLUME_OPENAPI_X_WEBHOOKS |
Uma especificação 3.1 ou posterior mantém os webhooks em x-webhooks, a extensão que as ferramentas de 3.0 leem, e não tem webhooks, então nenhum deles é renderizado. Renomeie o campo para webhooks. |
BLUME_OPENAPI_REF_PATH_ITEM |
Um caminho ou webhook é um $ref para um path item compartilhado, como um que fica em components.pathItems. O Blume não resolve esses casos, então as operações dele ficam de fora da referência. Coloque o path item inline em paths ou webhooks. Os schemas, parâmetros e respostas dele podem continuar como $refs. |
BLUME_OPENAPI_DUPLICATE_OPERATION_ID |
Duas operações compartilham um operationId, que precisa ser único em uma especificação. O aviso cita as duas. O Blume adiciona o método ao id da segunda no <Operation id> e à URL dela quando as duas compartilham uma tag. Dê a cada operação o próprio operationId. |
BLUME_OPENAPI_LOCAL_SERVER |
Um servidor declarado pela especificação, por um caminho ou por uma operação é um endereço local (localhost, 127.0.0.1, 0.0.0.0, [::1]), muitas vezes escrito por um framework que exportou a especificação em uma máquina de desenvolvimento. O Try it e os exemplos de código enviariam as requisições para lá, onde os leitores não conseguem chegar. Liste a URL pública em servers ou defina-a com um overlay. |
BLUME_OPENAPI_NULLABLE |
Uma especificação que declara OpenAPI 3.1 ou posterior usa nullable, que a 3.1 removeu. O Blume continua mostrando esses valores como anuláveis, mas validadores e geradores de SDK que seguem a 3.1 os leem como nunca nulos. O aviso indica onde, como JSON Pointers dentro da especificação. Em vez disso, adicione "null" ao type do schema (type: [string, "null"]). |
O guia Manter a documentação da API sincronizada com as mudanças do backend no CI roda essas verificações no GitHub Actions: ele exporta a especificação do backend, falha quando a especificação está desatualizada, inválida ou traz mudanças incompatíveis, e regenera a referência a partir dela.
Operações nas suas próprias páginas
Qualquer página MDX pode mostrar uma operação de uma referência com <Operation>: a autorização, os parâmetros, o corpo da requisição e as respostas dela, ao lado do painel Try it e dos exemplos de código, do jeito que a página da própria operação mostra. Um quickstart pode explicar, passo a passo, a chamada de que trata sem mandar os leitores para outra página:
---
title: Quickstart
mode: wide
---
Create your first pet:
<Operation source="reference" id="add-pet" />
source identifica a referência pela rota dela, sem as barras, em minúsculas e com hífens (/reference vira reference, /api/v2 vira api-v2). id identifica a operação: o operationId dela, em minúsculas e com as palavras separadas por hífens (addPet vira add-pet), ou, quando ela não tem um, o método e o caminho (post-pets). O jeito mais seguro de obter os dois é a cópia em MDX bruto da página de uma operação, na URL dela seguida de .mdx, cujo corpo é a tag que você deve copiar. A operação é exibida em duas colunas, então defina mode: wide na página: ao lado do índice, a coluna da esquerda fica estreita. Na cópia em Markdown da página, a tag vira o endpoint, o corpo da requisição e as respostas, assim como na página da própria operação.
Incorporando o Scalar
openapi() sempre renderiza as páginas do próprio Blume. Se você preferir incorporar a UI de referência de API independente do Scalar em uma única rota, com barra lateral, busca, tema e cliente de requisições próprios, liste um adaptador scalar() de blume/reference no lugar deste ou ao lado dele. A página do Scalar explica o que o embed faz e o que ele não faz, além de mostrar como repassar as opções do próprio Scalar.