Writing Queries
A query starts with the query keyword (optional for read operations) and specifies exactly which fields to return:
query GetPost($id: ID!) {
post(id: $id) {
id
title
publishedAt
author {
name
email
}
tags
}
}Variables are passed separately as JSON — never concatenated into the query string:
{ "id": "post_42" }Aliases
Fetch the same field twice with different arguments using aliases:
query ComparePosts {
firstPost: post(id: "1") { title publishedAt }
secondPost: post(id: "2") { title publishedAt }
}The response uses the alias names as keys.
Fragments
Reuse field selections with fragments:
fragment PostFields on Post {
id
title
publishedAt
}
query {
featuredPost { ...PostFields author { name } }
latestPost { ...PostFields }
}Mutations
Mutations follow the same syntax but use the mutation keyword:
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
title
publishedAt
}
}Variables:
{
"input": {
"title": "My First Post",
"body": "Hello, GraphQL!",
"authorId": "user_1"
}
}Common mutation patterns:
# Update
mutation UpdatePost($id: ID!, $title: String!) {
updatePost(id: $id, title: $title) { id title }
}
# Delete
mutation DeletePost($id: ID!) {
deletePost(id: $id) # returns Boolean or deleted object
}Query in JavaScript
Ctrl+Enter
HTML
CSS
JS
Preview
Input Types
For mutations with many arguments, group them into an input type:
input CreatePostInput {
title: String!
body: String!
authorId: ID!
tags: [String!]
}
type Mutation {
createPost(input: CreatePostInput!): Post!
}This keeps mutations clean and makes them easier to extend.
Error Handling
GraphQL always returns HTTP 200. Errors go inside the response body:
{
"data": { "post": null },
"errors": [
{
"message": "Post not found",
"locations": [{ "line": 2, "column": 3 }],
"path": ["post"]
}
]
}Always check for errors in your response, even on a 200 status.