Ocultar um endpoint significa deixá-lo fora do documento OpenAPI que a aplicação gera, para que ele nunca apareça no Swagger UI. O endpoint em si continua funcionando: todas as técnicas a seguir, exceto [NonAction], mantêm a rota acessível por HTTP.
Qual delas usar depende de quanto queremos ocultar e de quê. Atributos como [ApiExplorerSettings(IgnoreApi = true)] agem sobre o API Explorer do framework e ocultam uma ação de todos os geradores de uma vez. DocInclusionPredicate() e os filtros de documento agem dentro do Swashbuckle, e o gerador OpenAPI que vem com o .NET 9 e o .NET 10 tem equivalentes próprios para os dois.
Por que ocultar um endpoint no Swagger?
Ocultar um endpoint significa deixar a operação dele fora do documento OpenAPI que a aplicação gera. O Swagger UI exibe apenas o que esse documento contém, então uma operação que não está no documento também não está na página, e não há nenhum botão “Try it out” para clicar.
Nada muda na rota em si. O endpoint continua respondendo a requisições, continua aplicando a própria autorização e continua na tabela de roteamento. A única exceção é [NonAction], que diz ao MVC que o método nem sequer é uma ação, então a rota desaparece junto com a documentação e a URL passa a retornar 404.
Essa diferença resume toda a questão da segurança, e vale a pena ser direto sobre ela. Ocultar uma operação é uma decisão de documentação, e não um controle de segurança. Qualquer pessoa que conheça a URL ainda consegue chamar um endpoint oculto, então um endpoint sensível precisa primeiro de uma autorização de verdade, e a ocultação serve, no máximo, como segunda camada.
O Swagger é o conjunto de ferramentas construído em torno desse documento, e a configuração que este artigo pressupõe vem do artigo sobre como configurar o Swagger UI em uma Web API ASP.NET Core.
Pode haver vários motivos para não querermos expor um endpoint na documentação:
- Operações sensíveis
- Endpoints obsoletos
- Endpoints internos
- Endpoints não implementados por completo
Como ocultar um endpoint com o Swashbuckle?
Vamos ver cinco formas de ocultar um endpoint, e elas se dividem em dois grupos que se comportam de maneira diferente.
Três delas funcionam por meio do API Explorer, o inventário que o próprio framework mantém dos nossos endpoints. [NonAction], [ApiExplorerSettings(IgnoreApi = true)] e uma IActionModelConvention que define ApiExplorer.IsVisible como false removem a ação antes que qualquer gerador de documentos chegue a vê-la.
As outras duas funcionam dentro do próprio Swashbuckle. DocInclusionPredicate() decide, endpoint por endpoint, se uma ação pertence a um documento nomeado, e um IDocumentFilter edita o documento pronto e remove caminhos pelo nome.
Na prática, a diferença está no alcance. O grupo do API Explorer oculta um endpoint de todos os geradores que instalamos e de todos os documentos de uma vez. O grupo do Swashbuckle o oculta apenas do Swashbuckle, e apenas dos documentos que configuramos. É exatamente o que queremos quando um documento deve mostrar um endpoint e outro não.
Para começar, vamos criar um novo projeto de Web API ASP.NET Core. Podemos fazer isso com o modelo ASP.NET Core Web API no Visual Studio ou com a CLI do .NET.
Desde o .NET 9, esse modelo não inclui mais o Swashbuckle. Ele instala o pacote Microsoft.AspNetCore.OpenApi e chama AddOpenApi() e MapOpenApi(), que geram o documento OpenAPI, mas não disponibilizam nenhuma interface de usuário. Por isso, criamos o projeto com controladores e adicionamos o Swashbuckle nós mesmos:
dotnet new webapi --use-controllers dotnet add package Swashbuckle.AspNetCore
Depois, três linhas no Program.cs registram o gerador e a interface de usuário:
builder.Services.AddSwaggerGen(); app.UseSwagger(); app.UseSwaggerUI();
Para mostrar diferentes formas de ocultar um endpoint, vamos ampliar o controlador WeatherForecast padrão com alguns métodos nossos, substituindo a ação Get() que ele traz:
[HttpGet("GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return GetWeatherForecastData();
}
[HttpGet("GetMethodOne")]
public IEnumerable<WeatherForecast> GetMethodOne()
{
return GetWeatherForecastData();
}
[HttpGet("GetMethodTwo")]
public IEnumerable<WeatherForecast> GetMethodTwo()
{
return GetWeatherForecastData();
}
[HttpGet("GetMethodThree")]
public IEnumerable<WeatherForecast> GetMethodThree()
{
return GetWeatherForecastData();
}
[HttpGet("GetMethodFour")]
public IEnumerable<WeatherForecast> GetMethodFour()
{
return GetWeatherForecastData();
}
private IEnumerable<WeatherForecast> GetWeatherForecastData()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
Ampliamos o controlador WeatherForecast existente com mais quatro métodos, que podemos usar para experimentar a ocultação de endpoints. Para simplificar, mantivemos bem diretos os nomes dos métodos e as URIs dos endpoints; em situações reais, devemos seguir a formatação de URIs REST.
Observe que damos a cada método um segmento de rota, em vez do nome de rota que o modelo usa, para que cada endpoint tenha o próprio caminho.
Agora, se executarmos a aplicação e abrirmos http://localhost:<port>/swagger/index.html, veremos como todas as rotas estão documentadas no Swagger:

Agora que está tudo pronto, vamos tentar ocultar cada um desses métodos de uma forma diferente.
Uso de DocInclusionPredicate
A primeira forma de ocultar um endpoint no Swagger é usar DocInclusionPredicate().
DocInclusionPredicate() é um delegado invocado para cada ApiDescription que a aplicação expõe. Ele recebe dois parâmetros, docName e apiDesc. docName se refere ao nome do documento Swagger, o que pode ser útil para distinguir vários documentos Swagger.
Já o parâmetro apiDesc representa a descrição da API, que contém informações sobre o endpoint que está sendo processado.

E-book gratuito
Sua Web API está pronta para produção?
33 itens para verificar antes de implantá-la, com a correção de cada um. Um PDF gratuito de 76 páginas para .NET 10.
O e-book está em inglês.
Baixe o checklist gratuitoPDF gratuito. Um único e-mail para enviá-lo. Cancele a inscrição quando quiser.
Podemos definir DocInclusionPredicate() na configuração do Swagger e personalizá-lo para filtrar os endpoints e as operações incluídos na documentação gerada pelo Swagger.
Digamos que queremos ocultar o primeiro endpoint, chamado GetWeatherForecast:
builder.Services.AddSwaggerGen(c =>
{
c.DocInclusionPredicate((docName, apiDesc) =>
{
var routeTemplate = apiDesc.RelativePath;
if (routeTemplate == "WeatherForecast/GetWeatherForecast")
return false;
return true;
});
});
Primeiro, extraímos para a variável routeTemplate o caminho relativo do endpoint da API que está sendo avaliado. Depois, verificamos se o routeTemplate do endpoint corresponde a "WeatherForecast/GetWeatherForecast".
Se corresponder, retornamos false, o que significa que o endpoint da API será excluído da documentação do Swagger. Em qualquer outro caso, retornamos true, ou seja, o endpoint será incluído na documentação do Swagger.
Uso do atributo NonAction
Outra coisa que podemos fazer quando queremos ocultar um endpoint do Swagger é aplicar o atributo NonAction ao método do endpoint que queremos ocultar:
[HttpGet("GetMethodOne")]
[NonAction]
public IEnumerable<WeatherForecast> GetMethodOne()
{
return GetWeatherForecastData();
}
Com o atributo NonAction, indicamos que o método do controlador não é um método de ação. Como o Swagger depende das ações da API para gerar a documentação, ele ignora, durante a varredura, qualquer endpoint marcado com esse atributo e, por isso, o endpoint não aparece na documentação do Swagger. A ação também deixa de estar disponível publicamente.
Podemos aplicar esse atributo apenas aos endpoints do controlador, e não ao controlador inteiro.
Uso do atributo ApiExplorerSettings com o parâmetro IgnoreApi
Outra forma de ocultar um endpoint do Swagger é usar o atributo ApiExplorerSettings com o parâmetro IgnoreApi definido como true:
[HttpGet("GetMethodTwo")]
[ApiExplorerSettings(IgnoreApi = true)]
public IEnumerable<WeatherForecast> GetMethodTwo()
{
return GetWeatherForecastData();
}
Com o atributo [ApiExplorerSettings(IgnoreApi = true)], instruímos o API Explorer, que fornece os endpoints para a documentação do Swagger, a excluir um endpoint específico da documentação gerada.
Ao contrário do atributo NonAction, podemos usar este atributo no nível do controlador e ocultar todos os endpoints dele.
Uso de IActionModelConvention
Outro recurso que pode ser útil para ocultar um endpoint no Swagger é IActionModelConvention.
De modo geral, IActionModelConvention é uma interface que podemos usar para aplicar convenções a métodos de ação individuais. Para usá-la, precisamos implementar a interface e o método Apply(), que recebe um objeto ActionModel como parâmetro e aplica a ele as convenções desejadas:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
public class HideControllerConvention : IActionModelConvention
{
public void Apply(ActionModel action)
{
if (action.ActionName == "GetMethodThree")
{
action.ApiExplorer.IsVisible = false;
}
}
}
No nosso caso, queremos ocultar o endpoint GetMethodThree. Primeiro, verificamos a propriedade ActionName da ação para encontrar o nome de ação desejado e, quando o encontramos, definimos a visibilidade como false.
Agora que configuramos a convenção desejada, também precisamos registrá-la no Program.cs ao adicionar os controladores, para que tudo funcione como esperado:
builder.Services.AddControllers(s => s.Conventions.Add(new HideControllerConvention() ));
Uso de IDocumentFilter
A última abordagem que vamos adotar para ocultar um endpoint no Swagger é usar IDocumentFilter.
A interface IDocumentFilter faz parte do namespace Swashbuckle.AspNetCore.SwaggerGen e nos permite modificar o documento Swagger gerado antes que ele seja exibido. No nosso caso, criamos a classe SwaggerDocumentFilter, que implementa a interface IDocumentFilter:
using Microsoft.OpenApi;
using Swashbuckle.AspNetCore.SwaggerGen;
public class SwaggerDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
swaggerDoc.Paths.Remove("/WeatherForecast/GetMethodFour");
}
}
Dentro do método Apply(), temos acesso a OpenApiDocument e a DocumentFilterContext. OpenApiDocument representa o documento Swagger gerado, e DocumentFilterContext nos dá contexto adicional durante a geração do documento.
Ao chamar swaggerDoc.Paths.Remove("/WeatherForecast/GetMethodFour"), removemos a entrada desse endpoint específico da propriedade Paths do documento Swagger. Assim, garantimos que o método fique oculto na documentação gerada pelo Swagger.
Remover um caminho é só uma das tarefas de um filtro, e IOperationFilter, um ponto de extensão da mesma família, é o que usamos para adicionar um parâmetro de cabeçalho a todos os endpoints.
Por fim, precisamos adicionar o filtro de documento ao configurar o Swagger no Program.cs:
builder.Services.AddSwaggerGen(c =>
{
c.DocumentFilter<SwaggerDocumentFilter>();
c.DocInclusionPredicate((docName, apiDesc) =>
{
var routeTemplate = apiDesc.RelativePath;
if (routeTemplate == "WeatherForecast/GetWeatherForecast")
return false;
return true;
});
});
Agora, se executarmos a aplicação de novo, veremos que o arquivo de especificação gerado não apresenta nenhum dos endpoints:

O grupo WeatherForecast vazio e o esquema dele permanecem porque o filtro de documento remove apenas o caminho, e não a tag nem o esquema que o Swashbuckle gerou para ele.

E-book gratuito
Sua Web API está pronta para produção?
33 itens para verificar antes de implantá-la, com a correção de cada um. Um PDF gratuito de 76 páginas para .NET 10.
O e-book está em inglês.
Baixe o checklist gratuitoPDF gratuito. Um único e-mail para enviá-lo. Cancele a inscrição quando quiser.
Como ocultar um endpoint com o gerador OpenAPI nativo?
Microsoft.AspNetCore.OpenApi é o gerador que o modelo de Web API instala hoje, e todas as técnicas acima têm um equivalente nele. Ele já vem instalado em um projeto novo, e é por isso que a seção de configuração teve de adicionar o Swashbuckle manualmente.
As três técnicas do API Explorer não precisam de nenhuma mudança. [NonAction], [ApiExplorerSettings(IgnoreApi = true)] e uma IActionModelConvention ocultam uma ação aqui exatamente como fazem com o Swashbuckle, porque nenhuma delas mexe no gerador.
As duas específicas do Swashbuckle têm substitutos diretos. DocInclusionPredicate() vira o delegado ShouldInclude de OpenApiOptions, e IDocumentFilter vira IOpenApiDocumentTransformer, cujo método TransformAsync() recebe o mesmo OpenApiDocument e remove caminhos da mesma forma.
ShouldInclude traz uma armadilha em que é fácil cair. Atribuir algo a ele substitui o predicado padrão em vez de complementá-lo, e é o padrão que mantém os endpoints agrupados nos próprios documentos. Se você o sobrescrever sem repetir essa verificação, todos os endpoints agrupados vão aparecer em todos os documentos.
A configuração vai no Program.cs:
builder.Services.AddOpenApi(options =>
{
options.ShouldInclude = apiDesc => apiDesc.RelativePath != "WeatherForecast/GetWeatherForecast";
options.AddDocumentTransformer<HideEndpointDocumentTransformer>();
});
E o transformador substitui o filtro de documento:
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi;
public class HideEndpointDocumentTransformer : IOpenApiDocumentTransformer
{
public Task TransformAsync(OpenApiDocument document,
OpenApiDocumentTransformerContext context,
CancellationToken cancellationToken)
{
document.Paths.Remove("/WeatherForecast/GetMethodFour");
return Task.CompletedTask;
}
}
Com tudo lado a lado, temos uma única referência que mostra cada técnica nos dois geradores e se o endpoint ainda responde depois que o ocultamos:
| O que ocultar | Com o Swashbuckle | Com o gerador nativo | Continua acessível por HTTP? |
|---|---|---|---|
| Uma ação | [ApiExplorerSettings(IgnoreApi = true)] | O mesmo atributo | Sim |
| Uma ação, e também desativá-la | [NonAction] | O mesmo atributo | Não, a rota retorna 404 |
| Todas as ações de um controlador | [ApiExplorerSettings(IgnoreApi = true)] na classe | O mesmo atributo | Sim |
| Um endpoint de API mínima | .ExcludeFromDescription() | .ExcludeFromDescription() | Sim |
| Ações que atendem a uma regra que escrevemos | DocInclusionPredicate((docName, apiDesc) => …) | options.ShouldInclude = apiDesc => … | Sim |
| Ações que atendem a uma regra, antes de o gerador rodar | IActionModelConvention que define ApiExplorer.IsVisible como false | A mesma convenção | Sim |
| Um caminho que já está no documento pronto | IDocumentFilter que chama Paths.Remove(path) | IOpenApiDocumentTransformer que chama Paths.Remove(path) | Sim |
Os endpoints de APIs mínimas têm uma forma própria de fazer isso: app.MapGet("/internal", …).ExcludeFromDescription() mantém um endpoint fora do documento nos dois geradores. Também existe um atributo [ExcludeFromDescription], mas ele é um metadado de API mínima: colocá-lo em uma ação de controlador MVC não tem nenhum efeito, e a ação continua no documento.
Se a necessidade real é “documentação interna e pública a partir de uma única API”, e não “ocultar isto para sempre”, AddOpenApi("internal") junto com AddOpenApi("v1") nos dá dois documentos, e [ApiExplorerSettings(GroupName = "internal")] em um controlador decide em qual deles um endpoint vai parar. Um transformador de documento registrado em um documento não roda no outro.
O gerador nativo produz o documento e nada mais. app.MapOpenApi() o disponibiliza em /openapi/v1.json e não há nenhuma página para abrir, então, para ver o resultado, é preciso ler o JSON ou adicionar um pacote de interface de usuário, como o Swagger UI ou o Scalar. O próprio guia da Microsoft sobre como gerar documentos OpenAPI descreve a mesma separação entre gerar o documento e exibi-lo.
Manter uma operação inteira fora do documento é metade do trabalho, e a outra metade é ignorar propriedades do modelo com o Swagger, o que oculta um campo dentro do esquema, e não a operação em si.
Quando usar cada método?
Comece pelo atributo, porque ele é a solução mais enxuta que resolve o problema. [ApiExplorerSettings(IgnoreApi = true)] oculta uma ação, ou todas as ações de um controlador quando o colocamos na classe, e não exige configuração em nenhum outro lugar da aplicação.
Use [NonAction] apenas quando o objetivo for eliminar o endpoint, e não só ocultá-lo. É a única opção aqui que também remove a rota, então a URL responde com 404 em vez de retornar dados.
Use uma convenção quando a regra diz respeito às próprias ações: ocultar tudo o que está em um namespace, tudo o que tem um atributo marcador, tudo o que pertence a uma equipe interna. Ela roda uma única vez na inicialização, e nenhum gerador chega a ver essas ações.
Use ShouldInclude ou DocInclusionPredicate() quando o mesmo endpoint deve estar em um documento e não em outro, e um transformador ou filtro de documento quando a regra diz respeito ao documento pronto, e não ao endpoint.
Em casos simples, em que precisamos ocultar endpoints individuais, usar o parâmetro IgnoreApi do atributo ApiExplorerSettings ou o atributo NonAction pode ser suficiente. Eles são os mais simples de usar.
Vale notar que o atributo NonAction oculta o endpoint da documentação e também o desativa por completo, de modo que não conseguimos acessá-lo com chamadas HTTP, ao contrário das outras técnicas, em que o endpoint fica oculto na documentação, mas continua acessível para chamadas HTTP direcionadas a ele.
Para situações que exigem filtragem ou transformações mais avançadas, IActionModelConvention pode ser uma excelente escolha. Podemos ocultar um endpoint no Swagger com base em qualquer filtro personalizado, usando todas as propriedades disponíveis na classe ActionModel.
Os dois rodam em momentos diferentes. DocInclusionPredicate() é consultado sobre um endpoint de cada vez, antes de o documento existir, e responde sim ou não. Um IDocumentFilter roda uma única vez, no final, com o documento pronto, cada ApiDescription incluído e o nome do documento em mãos. Ele edita o que já existe, e é por isso que consegue remover um caminho que o predicado já deixou passar. Uma vantagem de DocInclusionPredicate() é que ele é definido diretamente na configuração do Swagger e não exige nenhuma implementação adicional de interface.
Conclusão
Neste artigo, vimos diferentes formas de ocultar endpoints de API na documentação do Swagger. Mostramos o uso de DocInclusionPredicate() para uma configuração direta, além de opções mais simples, como o parâmetro IgnoreApi e o atributo NonAction. Por fim, abordamos personalizações mais avançadas com as interfaces IDocumentFilter e IActionModelConvention, que nos dão várias opções para ocultar endpoints. Todas elas, ou os equivalentes no gerador nativo, continuam valendo no .NET 10, quer geremos o documento com o Swashbuckle, quer com o pacote Microsoft.AspNetCore.OpenApi que o modelo de Web API instala hoje.
Testado com .NET 10.0.10, Swashbuckle.AspNetCore 10.2.3 e Microsoft.AspNetCore.OpenApi 10.0.12.