GraphQL: Querying, Mutations, Schemas, and API Design
GraphQL Console: Explore Schemas, Run Queries, and Debug API Requests
Learn how to use a GraphQL console to connect to an endpoint, explore schemas, write queries and mutations, supply variables, inspect responses, and troubleshoot errors.
A GraphQL console is an interactive client for composing, sending, and inspecting GraphQL operations. It lets you explore an API's typed schema, prototype queries, test mutations, examine responses, and investigate failures without building a full application first.
GraphQL consoles are useful when learning an unfamiliar API, checking whether a field is available, testing authentication, reproducing a bug, or confirming the shape of data returned to a frontend. For background on the query language, see GraphQL.
What a GraphQL Console Does
A GraphQL console sends a GraphQL operation to a GraphQL endpoint: the HTTP or other transport address that receives operations. The console displays the server's response and usually provides tools for understanding the schema.
A console differs from a REST API browser or a general HTTP client in several ways:
- A REST browser usually navigates among resource URLs and HTTP methods, while GraphQL commonly uses one endpoint and describes the requested fields in the operation body.
- A general HTTP client can send arbitrary requests, but a GraphQL console understands GraphQL syntax, schema types, autocomplete, documentation, variables, fragments, and operation selections.
- A console can often use introspection to show the API's available operations, fields, arguments, and types.
A console does not replace automated tests or application code. It is best used for interactive exploration, quick experiments, request reproduction, and debugging.
Console Interface Overview
Tools such as GraphiQL, GraphQL Playground, Apollo Sandbox, and vendor-provided consoles use different layouts. Their controls and names vary, but many expose the following areas.
| Console area | Purpose | Typical user action |
|---|---|---|
| Operation editor | GraphQL document containing queries, mutations, or subscriptions | Write an operation and use formatting or autocomplete |
| Variables editor | JSON values supplied to declared variables | Enter IDs, filters, input objects, and flags |
| Response panel | Returned data, errors, and sometimes extensions | Expand fields, copy results, and inspect error paths |
| Documentation explorer | Descriptions of operations, fields, arguments, and types | Navigate from a root field to nested types |
| Schema explorer | Browsable view of query, mutation, subscription, and named types | Inspect objects, inputs, enums, interfaces, unions, and scalars |
| Request headers | Headers sent with the request | Configure authorization, tenant, or environment headers |
| Operation history | Previously run operations when supported | Reopen or compare an earlier request |
Connecting to a GraphQL Endpoint
The endpoint URL is where the GraphQL request is sent. It is different from the URL that displays the graphical console. A console may be hosted at one address while configured to send requests to another.
Use HTTPS for production traffic so credentials and data are encrypted in transit. HTTP may be acceptable for controlled local development, but it should not be used for sensitive production credentials.
In a browser-based console, the browser's same-origin and CORS rules apply. If the console is hosted on a different origin from the endpoint, the server must allow that console origin and permit the required methods and headers. An endpoint can be healthy while a browser console still fails because of CORS.
Endpoint access checklist
- Confirm the endpoint URL, environment, and tenant.
- Check whether the endpoint requires HTTPS, a specific HTTP method, or a particular content type.
- Configure authentication and tenant-selection headers in the request-headers area.
- Verify that the current user is allowed to call the endpoint and inspect its schema.
- If the browser cannot connect, compare the result with a server-side or command-line request.
Common request headers
| Authentication method | Example header format | Handling guidance |
|---|---|---|
| Bearer token | Authorization: Bearer <access-token> | Use a short-lived token when possible; never share the token in screenshots. |
| API key | X-API-Key: <api-key> | Use only when the API documents this header and protect the key. |
| Cookie | Browser-managed session cookie | Check whether credentials are permitted by the console and server CORS policy. |
| Custom header | X-Tenant-ID: tenant_a | Use the exact name and value required for tenant or environment selection. |
For direct JSON requests, the content type is commonly Content-Type: application/json. Browser consoles generally add it automatically.
Discovering the Schema
A schema is the typed contract describing available operations, fields, arguments, input values, and result shapes. Use the documentation or schema explorer before guessing field names.
- Open the root Query, Mutation, or Subscription type.
- Choose a root field and read its description, arguments, and return type.
- Follow the return type to an object or abstract type.
- Choose fields from that type until reaching scalar or enum values.
- Use autocomplete and type navigation to confirm spelling and nesting.
Introspection is the mechanism that allows a client to query schema metadata. Documentation panels and autocomplete commonly depend on it. An organization may disable or restrict introspection, especially in production. In that case, the explorer may be empty even though the endpoint works. Use approved published schema documentation or a development endpoint instead.
Types to recognize
- Scalar: a leaf value such as
String,ID,Int,Boolean, or a custom scalar. - Enum: one value from a fixed set of named values. Enum values are GraphQL names, not quoted strings.
- Object: a type with selectable fields.
- Input object: a structured argument value, frequently used by mutations.
- Interface: an abstract type containing fields shared by multiple object types.
- Union: an abstract type that can represent one of several object types.
- Connection: a common pagination pattern using fields such as
edges,nodes,cursor, andpageInfo.
Writing GraphQL Queries
A query is a read-oriented GraphQL operation. Clients request explicit fields, and the response follows the same selection structure. A selection set is the group of fields requested from a type. Object-valued fields need their own nested selection set; scalar fields do not.
query Viewer {
viewer {
id
name
}
}
This is a named operation. The name, Viewer, helps logs, tracing, and debugging. An operation name is optional when a document contains one operation, but explicit names are safer and clearer.
Build a query progressively
- Start with a root field suggested by the schema.
- Add one scalar field to verify that the field is reachable.
- Add arguments when the schema requires or supports them.
- Add nested object fields one level at a time.
- Request only the fields needed for the experiment.
query ProductById($id: ID!) {
product(id: $id) {
id
name
price
}
}
Arguments, aliases, fragments, and directives
An argument is a value supplied to a field to control its result. An alias changes the response key without changing the schema field name, which is useful when requesting the same field with different arguments.
query CompareProducts {
first: product(id: "prod_123") {
name
price
}
second: product(id: "prod_456") {
name
price
}
}
A fragment is a reusable named field selection for a type.
query ProductList {
products(first: 2) {
nodes {
...ProductSummary
}
}
}
fragment ProductSummary on Product {
id
name
price
}
A directive is an instruction attached to part of an operation. For example, @include conditionally includes a field.
query ProductDetails($id: ID!, $includeDescription: Boolean!) {
product(id: $id) {
id
name
description @include(if: $includeDescription)
}
}
Using Variables
A variable is a typed operation input whose value is supplied separately in the variables editor. The operation declares the variable using GraphQL syntax; the variables panel supplies JSON.
query ProductById($id: ID!) {
product(id: $id) {
id
name
}
}
{
"id": "prod_123"
}
ID! means the variable is required and cannot be null. Without !, a variable is optional. A variable can also have a default value.
query Products($first: Int = 10, $status: ProductStatus) {
products(first: $first, status: $status) {
nodes {
id
name
}
}
}
Input objects and lists are written as JSON in the variables editor:
{
"filter": {
"statuses": ["ACTIVE", "DRAFT"],
"search": "notebook"
},
"ids": ["prod_123", "prod_456"]
}
- Use JSON strings, numbers, booleans, arrays, objects, and
nullin the variables panel. - Match variable names exactly between the operation and JSON.
- Check the schema for required input fields and list element types.
- Enum values in GraphQL input syntax are normally unquoted names, while JSON variables represent values according to the API's expected JSON encoding. Follow the console and API's schema guidance for custom scalars and enums.
Running Mutations Safely
A mutation is an operation intended to change server-side state. Like queries, mutations require explicit response selections.
mutation CreateProduct($input: CreateProductInput!) {
createProduct(input: $input) {
product {
id
name
}
errors {
field
message
}
}
}
{
"input": {
"name": "Notebook",
"price": 12.5
}
}
The returned payload may contain the created resource and application-level validation errors. Request identifiers and updated fields so you can verify what changed. Also inspect top-level GraphQL errors; payload errors and top-level errors are separate mechanisms.
Subscriptions and Real-Time Operations
A subscription is a long-lived operation that receives events matching its selection and any filters. It is not equivalent to repeatedly sending a query.
subscription ProductCreated {
productCreated {
id
name
}
}
Subscriptions require API support and a compatible transport, commonly WebSocket or another streaming protocol. The console must support that transport and may need separate connection authentication. Start the subscription, generate or wait for a matching event, and stop it when finished. If no event arrives, verify the protocol, connection headers, filters, and whether an event was actually produced.
Understanding Responses
A typical GraphQL response can contain:
data: values matching the operation's selection structure.errors: one or more errors with messages and often locations, paths, or server-specific extensions.extensions: optional metadata such as tracing, request identifiers, rate-limit information, or error codes.
GraphQL supports partial responses: usable data can appear alongside errors. The error path identifies the field associated with a failure. A resolver is server-side logic that provides a field's value, so a resolver failure can affect only part of a response.
Nullability controls how failures spread. If a nullable field fails, that field may become null while other data remains available. If a non-null field cannot resolve, the null can propagate upward to the nearest nullable parent, potentially removing a larger portion of the response.
Use the response panel's formatting and expand/collapse controls to inspect nested data. Copy results when comparing runs, and inspect request metadata, status information, headers, and request identifiers when the console exposes them.
Authentication and Security
Authentication verifies who the caller is. Authorization verifies what that authenticated caller may access. A valid token can authenticate successfully while a requested field or resource remains unauthorized. Available fields and results may vary by user role, tenant, scopes, or environment.
- Bearer tokens are commonly sent in an
Authorizationheader. - API keys may use a documented custom header such as
X-API-Key. - Cookie-based sessions depend on browser credential settings and server CORS policy.
- Custom headers may select a tenant, region, or environment.
Do not expose credentials in shared screenshots, saved tabs, browser history, console recordings, or source control. Remove tokens before sharing an operation and use restricted, short-lived credentials for testing.
Safe Console Workflows
- Confirm the endpoint and environment.
- Inspect the schema and start with a small read-only query.
- Give every meaningful operation an explicit name.
- Use variables instead of embedding sensitive or frequently changing values in the operation.
- Request the minimum fields and smallest pagination size needed for the experiment.
- Check both top-level errors and application-level payload errors.
- Use staging for mutations, destructive operations, and invalid-input tests.
- Record the operation, variables shape, endpoint environment, and request identifier when reporting a problem, but exclude secrets.
Troubleshooting Console Requests
Classify the failure before changing the query. Syntax and validation failures happen before resolver execution; execution failures occur while fields are being resolved; transport, authentication, authorization, and schema-discovery failures can prevent a useful operation from running.
| Category | Typical symptom | Likely cause | First troubleshooting step |
|---|---|---|---|
| Syntax | Unexpected character or parsing error | Unbalanced braces, parentheses, quotes, or invalid GraphQL punctuation | Format the operation, check delimiters, and keep JSON out of the GraphQL editor |
| Validation | Unknown field or field cannot be selected | Wrong field, wrong type, missing selection set, or schema mismatch | Use current documentation and autocomplete; verify the endpoint |
| Variables | Invalid variable or missing required input | Name mismatch, malformed JSON, wrong type, or omitted non-null value | Validate the variables JSON and compare it with the declaration |
| Execution | Data contains null and an error path | A resolver failed, or a non-null failure propagated upward | Inspect the message, path, locations, and server extensions |
| Authentication | Unauthenticated or invalid-token error | Missing, expired, or malformed credential | Check headers, token validity, and environment |
| Authorization | Forbidden field or resource | User role or scope lacks permission | Confirm role, scopes, tenant, and field policy |
| Transport | Network, HTTP, or CORS failure | Incorrect URL, unavailable server, browser policy, or rejected headers | Inspect HTTP status and headers; compare with a command-line request |
| Schema discovery | Empty documentation explorer | Introspection disabled, restricted, or pointed at the wrong endpoint | Check permissions and use approved schema documentation |
Common mistakes
- Object fields such as
productneed nested selections; selecting only the object name is invalid. - GraphQL operations use GraphQL syntax, not JSON syntax. Do not add commas between fields just because JSON uses commas.
- The variables editor must contain valid JSON, including double-quoted property names.
- A required variable must be declared with the correct non-null type and supplied in the variables object.
- A field may exist in one environment or schema version but not another.
- A successful HTTP status does not guarantee a successful GraphQL operation; always inspect
errors.
Command-line comparison
A command-line request can distinguish endpoint or credential problems from browser-console problems:
curl -X POST https://api.example.com/graphql \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
--data '{"query":"query Viewer { viewer { id name } }"}'
Variables are sent as a separate JSON object:
curl -X POST https://api.example.com/graphql \
-H 'Content-Type: application/json' \
--data '{"query":"query ProductById($id: ID!) { product(id: $id) { id name } }","variables":{"id":"prod_123"}}'
If the command-line request works but the browser console fails, investigate the console endpoint configuration, CORS, browser credentials, and custom headers. If both fail, inspect the endpoint, schema, authentication, and server response.
GraphQL Operation Types at a Glance
| Operation type | Typical purpose | Execution behavior | Example use |
|---|---|---|---|
| Query | Read data | Requests selected fields without intending to change state | Fetch a viewer, product, or paginated list |
| Mutation | Change data | Invokes server-side state changes and returns selected payload fields | Create, update, or delete a resource |
| Subscription | Receive events | Keeps a supported streaming connection open | Watch for newly created resources |
Key Exam and Practice Notes
- The endpoint receives the operation; the console URL only provides the user interface.
- Introspection powers much of schema documentation and autocomplete, but it may be disabled.
- GraphQL responses are shaped by the client's selection set.
- Variables are declared in the operation and supplied separately as JSON.
- Mutations still require response selections and may report validation errors inside their payload.
- GraphQL can return data and errors together, so an HTTP success status is not enough to determine operation success.
- Authentication and authorization are different checks.
- For safe exploration, use named, minimal, read-only operations before testing mutations.