Endpoints

Hot Chocolate provides a set of ASP.NET Core middleware for making the GraphQL server available via HTTP and WebSockets. There are also middleware for hosting the Nitro GraphQL IDE and an endpoint for downloading the schema in its SDL representation.

MapGraphQL

Call MapGraphQL() on the IEndpointRouteBuilder to register all of the middleware a standard GraphQL server requires.

C#
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGraphQL();
});

With .NET 6+ Minimal APIs, you can call MapGraphQL() on the app builder directly since it implements IEndpointRouteBuilder:

C#
var builder = WebApplication.CreateBuilder(args);
// Omitted code for brevity
var app = builder.Build();
app.MapGraphQL();
app.Run();

The middleware registered by MapGraphQL makes the GraphQL server available at /graphql by default.

You can customize the endpoint:

C#
endpoints.MapGraphQL("/my/graphql/endpoint");

Calling MapGraphQL() enables the following functionality on the specified endpoint:

  • HTTP GET and HTTP POST GraphQL requests are handled (Multipart included)
  • WebSocket GraphQL requests are handled (if the ASP.NET Core WebSocket middleware has been registered)
  • Including the query string ?sdl after the endpoint downloads the GraphQL schema
  • Accessing the endpoint from a browser loads the Nitro GraphQL IDE

You can customize the combined middleware using GraphQLServerOptions as shown below, or include only the parts of the middleware you need and configure them individually.

The following middleware are available:

GraphQLServerOptions

You can influence the behavior of the middleware registered by MapGraphQL using GraphQLServerOptions.

EnableSchemaRequests

C#
endpoints.MapGraphQL().WithOptions(o => o.EnableSchemaRequests = false);

This setting controls whether the schema of the GraphQL server can be downloaded by appending ?sdl to the endpoint.

EnableGetRequests

C#
endpoints.MapGraphQL().WithOptions(o => o.EnableGetRequests = false);

This setting controls whether the GraphQL server handles GraphQL operations sent via the query string in an HTTP GET request.

AllowedGetOperations

C#
endpoints.MapGraphQL().WithOptions(o => o.AllowedGetOperations = AllowedGetOperations.Query);

If EnableGetRequests is true, you can control the allowed operations for HTTP GET requests using the AllowedGetOperations setting.

By default, only queries are accepted via HTTP GET. You can also allow mutations by setting AllowedGetOperations to AllowedGetOperations.QueryAndMutation.

EnableMultipartRequests

C#
endpoints.MapGraphQL().WithOptions(o => o.EnableMultipartRequests = false);

This setting controls whether the GraphQL server handles HTTP multipart forms (file uploads).

Learn more about uploading files

Tool

You can specify options for Nitro using the Tool property.

For example, you could enable Nitro only during development:

C#
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGraphQL().WithOptions(o => o.Tool.Enable = env.IsDevelopment());
});

Learn more about possible NitroAppOptions

MapNitroApp

Call MapNitroApp() on the IEndpointRouteBuilder to serve Nitro on a different endpoint than the actual GraphQL endpoint.

C#
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapNitroApp("/graphql/ui");
});

This makes Nitro accessible via a web browser at the /graphql/ui endpoint.

NitroAppOptions

You can configure Nitro using NitroAppOptions.

Enable

C#
endpoints.MapNitroApp("/ui").WithOptions(o => o.Enable = false);

This setting controls whether Nitro is served.

GraphQLEndpoint

C#
endpoints.MapNitroApp("/ui").WithOptions(o => o.GraphQLEndpoint = "/my/graphql/endpoint");

This setting sets the GraphQL endpoint to use when creating new documents within Nitro.

UseBrowserUrlAsGraphQLEndpoint

C#
endpoints.MapNitroApp("/ui").WithOptions(o => o.UseBrowserUrlAsGraphQLEndpoint = true);

If set to true, the current browser URL is treated as the GraphQL endpoint when creating new documents within Nitro.

Warning: GraphQLEndpoint takes precedence over this setting.

Document

C#
endpoints.MapNitroApp("/ui").WithOptions(o => o.Document = "{ __typename }");

This setting lets you set a default GraphQL document that serves as a placeholder for each new document created using Nitro.

UseGet

C#
endpoints.MapNitroApp("/ui").WithOptions(o => o.UseGet = true);

This setting controls the default HTTP method used to execute GraphQL operations when creating new documents within Nitro. When set to true, HTTP GET is used instead of the default HTTP POST.

HttpHeaders

C#
endpoints.MapNitroApp("/ui").WithOptions(o =>
{
o.HttpHeaders = new HeaderDictionary
{
{ "Content-Type", "application/json" }
};
});

This setting lets you specify default HTTP headers that are added to each new document created using Nitro.

IncludeCookies

C#
endpoints.MapNitroApp("/ui").WithOptions(o => o.IncludeCookies = true);

This setting specifies the default for including cookies in cross-origin requests when creating new documents within Nitro.

Title

C#
endpoints.MapNitroApp("/ui").WithOptions(o => o.Title = "My GraphQL explorer");

This setting controls the tab name when Nitro is opened inside a web browser.

DisableTelemetry

C#
endpoints.MapNitroApp("/ui").WithOptions(o => o.DisableTelemetry = true);

This setting lets you disable telemetry events.

GaTrackingId

C#
endpoints.MapNitroApp("/ui").WithOptions(o => o.GaTrackingId = "google-analytics-id");

This setting lets you set a custom Google Analytics ID, which allows you to gain insights into the usage of Nitro hosted as part of your GraphQL server.

The following information is collected:

NameDescription
deviceIdRandom string generated on a per-device basis
operatingSystemName of the operating system: Windows, macOS, Linux & Unknown
userAgentUser-Agent header
applicationTypeThe type of application: app (Electron) or middleware
applicationVersionVersion of Nitro

MapGraphQLHttp

Call MapGraphQLHttp() on the IEndpointRouteBuilder to make your GraphQL server available via HTTP at a specific endpoint.

C#
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGraphQLHttp("/graphql/http");
});

With the above configuration, you can issue HTTP GET/POST requests against the /graphql/http endpoint.

GraphQLServerOptions

The HTTP endpoint can also be configured with per-endpoint overrides using WithOptions:

C#
endpoints.MapGraphQLHttp("/graphql/http").WithOptions(o => o.EnableGetRequests = false);

The same GraphQLServerOptions properties available on MapGraphQL can be overridden here, except for Tool and EnableSchemaRequests which are not applicable to standalone HTTP endpoints.

Learn more about GraphQLServerOptions

MapGraphQLWebsocket

Call MapGraphQLWebSocket() on the IEndpointRouteBuilder to make your GraphQL server available via WebSockets at a specific endpoint.

C#
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGraphQLWebSocket("/graphql/ws");
});

With the above configuration, you can issue GraphQL subscription requests via WebSocket against the /graphql/ws endpoint.

MapGraphQLSchema

Call MapGraphQLSchema() on the IEndpointRouteBuilder to make your GraphQL schema available at a specific endpoint.

C#
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGraphQLSchema("/graphql/schema");
});

With the above configuration, you can download your schema.graphql file from the /graphql/schema endpoint.

MapGraphQLPersistedOperations

Call MapGraphQLPersistedOperations() on the IEndpointRouteBuilder to expose persisted operations via REST-like URLs. This enables clients to execute pre-registered GraphQL operations using a simple URL pattern instead of sending a full GraphQL request body.

C#
var builder = WebApplication.CreateBuilder(args);
builder
.AddGraphQL()
.AddQueryType<Query>()
.AddPersistedOperations(); // Register a persisted operation storage provider
var app = builder.Build();
app.MapGraphQL();
app.MapGraphQLPersistedOperations();
app.Run();

The default path is /graphql/persisted. The endpoint supports two URL patterns:

PatternExampleDescription
/{operationId}/graphql/persisted/abc123Execute a persisted operation by its ID
/{operationId}/{operationName}/graphql/persisted/abc123/GetUserExecute a specific named operation within a persisted document

Both GET and POST requests are supported. With POST requests, you can pass variables and extensions in the request body.

Custom Path

You can customize the path:

C#
app.MapGraphQLPersistedOperations("/api/operations");

Requiring an Operation Name

If you want to enforce that clients always specify an operation name in the URL, set requireOperationName to true:

C#
app.MapGraphQLPersistedOperations(requireOperationName: true);

When enabled, requests to /{operationId} without an operation name return a 400 Bad Request response.

For details on storing and managing persisted operations, see Trusted Documents.

AddGraphQL Parameters

The AddGraphQL() method on WebApplicationBuilder accepts parameters that control request parsing and default security behavior.

C#
builder.AddGraphQL(
maxAllowedRequestSize: 20 * 1000 * 1024, // ~20 MB (default)
disableDefaultSecurity: false); // default

maxAllowedRequestSize

Controls the maximum allowed size (in bytes) of an incoming GraphQL request body. The default is 20 * 1000 * 1024 (approximately 20 MB). If a request exceeds this limit, it is rejected before parsing.

Reduce this value if you expect only small queries and want to protect against excessively large payloads:

C#
builder.AddGraphQL(
maxAllowedRequestSize: 1 * 1000 * 1024); // ~1 MB

disableDefaultSecurity

When false (the default), AddGraphQL() automatically enables these security features:

  • Cost analysis: Protects against expensive queries by analyzing the computational cost of each operation.
  • Introspection disabled in production: Introspection is automatically turned off when IHostEnvironment.IsDevelopment() returns false.
  • MaxAllowedFieldCycleDepthRule: Prevents deeply cyclic field selections in production.

If you need full control over which security features are enabled, set disableDefaultSecurity to true and configure each feature individually:

C#
builder
.AddGraphQL(disableDefaultSecurity: true)
.AddCostAnalyzer(); // Opt in to specific features manually

Warning: Disabling default security removes important protections. Only do this if you are configuring equivalent protections manually.

GraphQLServerOptions Reference

The full set of properties available on GraphQLServerOptions is listed below. You can set these via ModifyServerOptions (schema-level) or WithOptions (per-endpoint).

PropertyTypeDefaultDescription
EnableGetRequestsbooltrueControls whether HTTP GET requests are accepted.
AllowedGetOperationsAllowedGetOperationsQueryWhich operation types are allowed via HTTP GET. Values: None, Query, Mutation, Subscription, QueryAndMutation, All.
EnableMultipartRequestsbooltrueControls whether multipart form requests (file uploads) are accepted.
EnableSchemaRequestsbooltrueControls whether the schema SDL can be downloaded via ?sdl.
EnableSchemaFileSupportbooltrueControls whether the schema SDL is served as a downloadable file.
EnforceGetRequestsPreflightHeaderboolfalseWhen true, GET requests must include a CSRF preflight header.
EnforceMultipartRequestsPreflightHeaderbooltrueWhen true, multipart requests must include a CSRF preflight header.
BatchingAllowedBatchingNoneWhich batching modes are allowed.
MaxBatchSizeint1024Maximum number of operations in a single batch. 0 means unlimited.
SocketsGraphQLSocketOptions(see below)WebSocket-specific options.
ToolNitroAppOptions(see below)Nitro IDE options.

The Sockets property contains a GraphQLSocketOptions object with these properties:

PropertyTypeDefaultDescription
ConnectionInitializationTimeoutTimeSpanTimeSpan.FromSeconds(10)Time the client has to send connection_init after opening a WebSocket.
KeepAliveIntervalTimeSpan?TimeSpan.FromSeconds(5)Interval for server keep-alive pings. null disables keep-alive.

Per-Endpoint Configuration with WithOptions

Hot Chocolate uses a delegate-based WithOptions pattern to configure options per-endpoint. The delegate receives the options object, and you modify it in place. These overrides are applied on top of the schema-level defaults set via ModifyServerOptions.

MapGraphQL

C#
app.MapGraphQL().WithOptions(o =>
{
o.EnableGetRequests = false;
o.AllowedGetOperations = AllowedGetOperations.Query;
o.Tool.Enable = false;
});

MapGraphQLHttp

C#
app.MapGraphQLHttp("/graphql/http").WithOptions(o =>
{
o.EnableMultipartRequests = false;
o.EnforceGetRequestsPreflightHeader = true;
});

MapGraphQLWebSocket

The WebSocket endpoint accepts a delegate over GraphQLSocketOptions directly:

C#
app.MapGraphQLWebSocket("/graphql/ws").WithOptions(o =>
{
o.ConnectionInitializationTimeout = TimeSpan.FromSeconds(30);
o.KeepAliveInterval = TimeSpan.FromSeconds(12);
});

Schema-Level Defaults

To set defaults that apply to all endpoints, use ModifyServerOptions on the request executor builder:

C#
builder
.AddGraphQL()
.ModifyServerOptions(o =>
{
o.EnableGetRequests = false;
o.Sockets.KeepAliveInterval = TimeSpan.FromSeconds(15);
o.Tool.Enable = false;
});

Per-endpoint WithOptions overrides take precedence over schema-level defaults.

Next Steps

Last updated on April 13, 2026 by Michael Staib