Integration

The Scalar.AspNetCore NuGet package provides an easy way to render beautiful API References based on OpenAPI documents.

Basic Setup

  1. Install the package
dotnet add package Scalar.AspNetCore
  1. Add the using directive
using Scalar.AspNetCore;
  1. Configure your application

Add the following to Program.cs based on your OpenAPI generator:

For Microsoft.AspNetCore.OpenApi:

builder.Services.AddOpenApi();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.MapScalarApiReference();
}

For Swashbuckle.AspNetCore.SwaggerGen:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

if (app.Environment.IsDevelopment())
{
    app.MapSwagger("/openapi/{documentName}.json");
    app.MapScalarApiReference();
}

For NSwag:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenApiDocument();

if (app.Environment.IsDevelopment())
{
    app.UseOpenApi(options =>
    {
        options.Path = "/openapi/{documentName}.json";
    });
    app.MapScalarApiReference();
}

For FastEndpoints:

builder.Services.SwaggerDocument();

if (app.Environment.IsDevelopment())
{
    app.UseSwaggerGen(options =>
    {
        options.Path = "/openapi/{documentName}.json";
    });
    app.MapScalarApiReference();
}

You're all set! 🎉 Navigate to /scalar to view your API Reference.

For multiple OpenAPI documents, see Multiple OpenAPI Documents.

Migration Guide

If you are upgrading from 2.1.x to 2.2.x, please refer to the migration guide. If you are upgrading from 1.x.x to 2.x.x, please refer to the migration guide.

MapScalarApiReference Overloads

The MapScalarApiReference method provides several overloads to customize the route and configuration:

Basic Usage

// Accessible at /scalar (default route)
app.MapScalarApiReference();

Custom Route

app.MapScalarApiReference("/api-docs");
app.MapScalarApiReference("/docs");

With Configuration

app.MapScalarApiReference(options =>
{
    options.WithTitle("My API");
});

Custom Route + Configuration

app.MapScalarApiReference("/docs", options =>
{
    options.WithTitle("My API Documentation");
});

Dynamic Configuration

// Access HttpContext for dynamic configuration
app.MapScalarApiReference((options, httpContext) =>
{
    var isAdmin = httpContext.User.IsInRole("Admin");
    options.WithTitle(isAdmin ? "Admin API" : "Public API");
});

// Custom route with HttpContext access
app.MapScalarApiReference("/docs", (options, httpContext) =>
{
    options.WithTitle($"API for {httpContext.User.Identity?.Name}");
});

Configuration Options

The options parameter provides a fluent API to customize Scalar:

app.MapScalarApiReference(options =>
{
    options.WithTitle("My API")
           .WithSidebar(false)
           .WithDarkMode(true)
           .WithDefaultOpenAllTags(true);
});

OpenAPI Document Route

Customize where Scalar looks for your OpenAPI document:

app.MapScalarApiReference(options =>
{
    // Custom local path
    options.WithOpenApiRoutePattern("/api-spec/{documentName}.json");
    
    // External URL
    options.WithOpenApiRoutePattern("https://api.example.com/openapi/{documentName}.json");
    
    // Static external URL (no placeholder)
    options.WithOpenApiRoutePattern("https://registry.scalar.com/@scalar/apis/galaxy/latest?format=json");
});

Multiple OpenAPI Documents

Scalar allows you to configure multiple OpenAPI documents using the AddDocument or AddDocuments methods. By default, the document name v1 will be used. Each document can have its own custom route pattern for accessing the OpenAPI specification.

Add a Single Document

// Simple document name (uses default route pattern)
app.MapScalarApiReference(options => options.AddDocument("v1"));

// With custom title
app.MapScalarApiReference(options => options.AddDocument("v1", "Production API"));

// With custom route pattern
app.MapScalarApiReference(options => options.AddDocument("v1",
    routePattern: "api-specs/{documentName}/openapi.json"));

// Complete configuration
app.MapScalarApiReference(options => options.AddDocument("v1",
    "Production API", "api-specs/v1/openapi.json"));

// External OpenAPI document
app.MapScalarApiReference(options => options.AddDocument("galaxy",
    "Galaxy API", "https://registry.scalar.com/@scalar/apis/galaxy/latest?format=json"));

Add Multiple Documents

// Chain multiple documents
app.MapScalarApiReference(options =>
{
    options.AddDocument("v1", "Production API", "api/v1/openapi.json")
           .AddDocument("v2-beta", "Beta API", "api/v2-beta/openapi.json")
           .AddDocument("internal", "Internal API", "internal/openapi.json");
});

// From string array
string[] versions = ["v1", "v2", "v3"];
app.MapScalarApiReference(options => options.AddDocuments(versions));

// From ScalarDocument objects
var documents = new[]
{
    new ScalarDocument("v1", "Production API", "api/v1/openapi.json"),
    new ScalarDocument("v2-beta", "Beta API", "api/v2-beta/openapi.json"),
    new ScalarDocument("galaxy", "Galaxy API", "https://registry.scalar.com/@scalar/apis/galaxy/latest?format=json")
};
app.MapScalarApiReference(options => options.AddDocuments(documents));

The routePattern parameter in AddDocument allows you to customize the URL path where the OpenAPI document is served. If not specified, it uses the global OpenApiRoutePattern from the options. The pattern can include the {documentName} placeholder which will be replaced with the document name.

Authentication

Scalar allows you to pre-configure authentication details for your API, making it easier for developers to test your endpoints. Scalar supports API Key, OAuth2, and HTTP authentication schemes.

Before you start: Your OpenAPI document must already include authentication security schemes for Scalar to work with them. Scalar can only pre-fill authentication details for schemes that are already defined in your OpenAPI specification.

The security schemes are added by your OpenAPI generator (NSwag, Swashbuckle.AspNetCore.SwaggerGen, or Microsoft.AspNetCore.OpenApi). If you don't see authentication options in Scalar, check your OpenAPI generator's documentation to learn how to properly define security schemes.

Security Notice: Pre-filled authentication details are visible in the browser and should never be used in production environments. Only use this feature for development and testing.

API Key Authentication

app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("ApiKey")
    .AddApiKeyAuthentication("ApiKey", apiKey =>
    {
        apiKey.Value = "sk-demo-key-12345";
    }));

Bearer Token Authentication

app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("BearerAuth")
    .AddHttpAuthentication("BearerAuth", auth =>
    {
        auth.Token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
    }));

Basic Authentication

app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("BasicAuth")
    .AddHttpAuthentication("BasicAuth", auth =>
    {
        auth.Username = "demo-user";
        auth.Password = "demo-password";
    }));

OAuth2 Authentication

Scalar provides convenience methods for each OAuth2 flow type to pre-fill authentication details in the API reference interface:

Authorization Code Flow
app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("OAuth2")
    .AddAuthorizationCodeFlow("OAuth2", flow =>
    {
        flow.ClientId = "scalar-demo-client";
        flow.ClientSecret = "scalar-demo-secret";
        flow.Pkce = Pkce.Sha256;
        flow.SelectedScopes = ["read", "write", "admin"];
    }));
Client Credentials Flow
app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("OAuth2")
    .AddClientCredentialsFlow("OAuth2", flow =>
    {
        flow.ClientId = "service-client-12345";
        flow.ClientSecret = "service-secret-67890";
        flow.SelectedScopes = ["api.read", "api.write"];
    }));
Password Flow
app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("OAuth2")
    .AddPasswordFlow("OAuth2", flow =>
    {
        flow.ClientId = "password-client";
        flow.Username = "demo@example.com";
        flow.Password = "demo-password-123";
        flow.SelectedScopes = ["profile", "email"];
    }));
Implicit Flow
app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("OAuth2")
    .AddImplicitFlow("OAuth2", flow =>
    {
        flow.ClientId = "spa-client-abc123";
        flow.SelectedScopes = ["openid", "profile", "email"];
    }));
Advanced OAuth2 Configuration
app.MapScalarApiReference(options => options
    .AddAuthorizationCodeFlow("OAuth2", flow =>
    {
        flow.ClientId = "advanced-client-id";
        
        // Custom query parameters for authorization request
        flow.AddQueryParameter("audience", "https://api.example.com")
            .AddQueryParameter("resource", "https://graph.microsoft.com");

        // Custom body parameters for token request
        flow.AddBodyParameter("custom_param", "custom_value");

        // Specify credentials location
        flow.WithCredentialsLocation(CredentialsLocation.Header);
    }));
Multiple OAuth2 Flows
app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("OAuth2")
    .AddOAuth2Flows("OAuth2", flows =>
    {
        flows.AuthorizationCode = new AuthorizationCodeFlow
        {
            ClientId = "web-client-12345",
            AuthorizationUrl = "https://auth.example.com/oauth2/authorize",
            TokenUrl = "https://auth.example.com/oauth2/token"
        };

        flows.ClientCredentials = new ClientCredentialsFlow
        {
            ClientId = "service-client-67890",
            ClientSecret = "service-secret",
            TokenUrl = "https://auth.example.com/oauth2/token"
        };
    })
    .AddDefaultScopes("OAuth2", ["read", "write"]));

Multiple Security Schemes

app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("OAuth2", "ApiKey")
    
    // Configure OAuth2
    .AddAuthorizationCodeFlow("OAuth2", flow =>
    {
        flow.ClientId = "multi-auth-client";
        flow.SelectedScopes = ["read", "write"];
    })
    
    // Configure API Key
    .AddApiKeyAuthentication("ApiKey", apiKey =>
    {
        apiKey.Value = "sk-demo-key-12345";
    })
    
    // Configure Basic Auth
    .AddHttpAuthentication("BasicAuth", auth =>
    {
        auth.Username = "demo-user";
        auth.Password = "demo-password";
    }));

Persisting Authentication

app.MapScalarApiReference(options => options
    .AddPreferredSecuritySchemes("OAuth2")
    .AddAuthorizationCodeFlow("OAuth2", flow =>
    {
        flow.ClientId = "persistent-client-id";
    })
    .WithPersistentAuthentication());

Persisting authentication information in the browser's local storage may present security risks. Use with caution.

Custom HTTP Client

Set a default HTTP client for code samples:

app.MapScalarApiReference(options =>
{
    options.WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);
});

Assets

Scalar uses local assets by default. To load assets from a different location:

app.MapScalarApiReference(options =>
{
    options.WithCdnUrl("https://cdn.jsdelivr.net/npm/@scalar/api-reference");
});

Fonts are loaded from a CDN by default. To disable this, set DefaultFonts to false.

Custom JavaScript Configuration

Extend Scalar's functionality with a custom JavaScript configuration module:

app.MapScalarApiReference(options =>
{
    options.WithJavaScriptConfiguration("/scalar/config.js");
});

Create a JavaScript module in your static files directory (e.g. wwwroot/scalar/config.js) that exports a default object with your custom configuration:

// wwwroot/scalar/config.js
export default {
  // Custom slug generation for operations
  generateOperationSlug: (operation) => `custom-${operation.method.toLowerCase()}${operation.path}`,

  // Hook into document selection events
  onDocumentSelect: () => console.log('Document changed'),

  // Add any other custom configuration options supported by Scalar
  // Checkout https://guides.scalar.com/scalar/scalar-api-references/configuration
}

Make sure to expose the directory that contains your JavaScript module through static file middleware using app.MapStaticAssets() or app.UseStaticFiles().

Dependency Injection

Configuration options can also be set via dependency injection:

builder.Services.Configure<ScalarOptions>(options => options.Title = "My API");
// or
builder.Services.AddOptions<ScalarOptions>().BindConfiguration("Scalar");

Options set via MapScalarApiReference override those set through dependency injection.

Additional Information

The MapScalarApiReference method returns an IEndpointConventionBuilder, allowing you to use minimal API features:

app.MapScalarApiReference().AllowAnonymous();

For all available configuration properties and their default values, check out the ScalarOptions and ScalarOptionsExtensions.