Launch GraphOS Studio

Operation request format

How to send requests to Apollo Server over HTTP

Check out this post from the Apollo blog: Making GraphQL Requests using HTTP Methods.

By default, almost every IDE and client library takes care of sending in a format that supports. This article describes that format, which is also described on and in this preliminary spec.

accepts queries and sent as POST requests. It also accepts queries sent as GET requests.

POST requests

accepts POST requests with a JSON body. A valid request contains a query , along with optional variables, extensions, and an operationName (clarifying which query to run if the request contains multiple possible ). You must specify a Content-Type HTTP header with type application/json.

Let's say we want to execute the following :

query GetBestSellers($category: ProductCategory) {
bestSellers(category: $category) {

Here's an example of a valid POST request body for that :

"query": "query GetBestSellers($category: ProductCategory){bestSellers(category: $category){title}}",
"operationName": "GetBestSellers",
"variables": { "category": "BOOKS" }

Note that operationName isn't required for this particular request body, because query includes only one definition.

You can execute this against an Apollo-hosted example server right now with the following curl command:

curl --request POST \
-H 'Content-Type: application/json' \
--data '{"query":"query GetBestSellers($category: ProductCategory){bestSellers(category: $category){title}}", "operationName":"GetBestSellers", "variables":{"category":"BOOKS"}}' \

's default production landing page provides a curl command you can use to execute a test on your own server:


By default, 4 doesn't support batching HTTP requests. To enable HTTP batching, you must explicitly pass allowBatchedHttpRequests: true to the ApolloServer constructor.

If you have enabled HTTP batching, you can send a batch of queries in a single POST request by providing a JSON-encoded array of objects, like so:

"query": "query { testString }"
"query": "query AnotherQuery{ test(who: \"you\" ) }"

If you send a batched request, responds with a corresponding array of responses.

Note: If multiple in a request try to set the same HTTP response header (via error extensions or plugins), headers from later will take precedence on a per-header basis.

GET requests

also accepts GET requests for queries (but not ). With a GET request, details (query, operationName, variables) are provided as URL parameters. The variables option is a URL-escaped JSON object.

Sending queries as GET requests can help with CDN caching.

Here's the same from POST requests formatted for a curl GET request:

curl --request GET \

Unlike with POST requests, GET requests do not require a Content-Type header. However, if you have 4's default CSRF prevention feature enabled, GET requests that don't contain a Content-Type header must contain one of the following:

  • A non-empty X-Apollo-Operation-Name header
  • A non-empty Apollo-Require-Preflight header

For more details, see the CSRF prevention documentation.

Incremental delivery (experimental)

Incremental delivery is a Stage 2: Draft Proposal to the specification which adds @defer and @stream executable . These directives allow clients to specify that parts of an can be sent after an initial response, so that slower do not delay all other fields. As of September 2022, the graphql library (also known as graphql-js) upon which is built implements incremental delivery only in the unreleased major version 17. If a pre-release of graphql@17 is installed in your server, 4 can execute these incremental delivery and provide streaming multipart/mixed responses.

Support for incremental delivery in version 17 is opt-in, meaning the are not defined by default. In order to use @defer or @stream, you must provide the appropriate definition(s) in your . The definitions below can be pasted into your schema as-is:

directive @defer(if: Boolean, label: String) on FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @stream(if: Boolean, label: String, initialCount: Int = 0) on FIELD

If you are creating the schema object yourself, the appropriate (s) must be provided to the schema constructor like so:

import {
} from 'graphql';
const schema = new GraphQLSchema({
directives: [

Clients sending with incremental delivery need to explicitly indicate that they are expecting to receive multipart/mixed responses in an accept header. Moreover, because incremental delivery has not yet been finalized in the spec and may change before the final version, they need to specify that they expect the particular response format that produces today via a deferSpec parameter. Specifically, clients prepared to accept incremental delivery responses should send an accept header like multipart/mixed; deferSpec=20220824. Note that this header implies that only multipart responses should be accepted; typically, clients will send an accept header like multipart/mixed; deferSpec=20220824, application/json indicating that either multipart or single-part responses are acceptable.

You cannot combine batching with incremental delivery in the same request.

Build and run queries
Generating TS types
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy