We’re overhauling Dgraph’s docs to make them clearer and more approachable. If you notice any issues during this transition or have suggestions, please let us know.

POST request

Headers

HeaderOptionalityValue
Content-Typemandatoryapplication/graphql or application/json
Content-Encodingoptionalgzip to send compressed data
Accept-Encodingoptionalgzip to enabled data compression on response
X-Dgraph-AccessTokenif ACL is enabledpass the access token you got in the login response to access predicates protected by an ACL
X-Auth-Tokenif anonymous access is turned offadmin key or client key
header as set in Dgraph.Authorizationif GraphQL Dgraph.Authorization is setvalid JWT used by @auth directives

Refer to GraphQL security settings for explanations about anonymous access and Dgraph.Authorization.

Payload format

POST requests sent with the Content-Type header application/graphql must have a POST body content as a GraphQL query string. For example, the following is a valid POST body for a query:

query {
  getTask(id: "0x3") {
    id
    title
    completed
    user {
      username
      name
    }
  }
}

POST requests sent with the Content-Type header application/json must have a POST body in the following JSON format:

{
  "query": "...",
  "operationName": "...",
  "variables": { "var": "val", ... }
}

GraphQL requests can contain one or more operations. Operations include query, mutation, or subscription. If a request only has one operation, then it can be unnamed like the following:

Single operation

The most basic request contains a single anonymous (unnamed) operation. Each operation can have one or more queries within in. For example, the following query has query operation running the queries getTask and getUser:

query {
  getTask(id: "0x3") {
    id
    title
    completed
  }
  getUser(username: "dgraphlabs") {
    username
  }
}

Response:

{
  "data": {
    "getTask": {
      "id": "0x3",
      "title": "GraphQL docs example",
      "completed": true
    },
    "getUser": {
      "username": "dgraphlabs"
    }
  }
}

You can optionally name the operation as well, though it’s not required if the request only has one operation as it’s clear what needs to be executed.

Query shorthand

If a request only has a single query operation, then you can use the short-hand form of omitting the “query” keyword:

{
  getTask(id: "0x3") {
    id
    title
    completed
  }
  getUser(username: "dgraphlabs") {
    username
  }
}

This simplifies queries when a query doesn’t require an operation name or variables.

Multiple operations

If a request has two or more operations, then each operation must have a name. A request can only execute one operation, so you must also include the operation name to execute in the request. Every operation name in a request must be unique.

For example, in the following request has the operation names getTaskAndUser and completedTasks.

query getTaskAndUser {
  getTask(id: "0x3") {
    id
    title
    completed
  }
  queryUser(filter: { username: { eq: "dgraphlabs" } }) {
    username
    name
  }
}

query completedTasks {
  queryTask(filter: { completed: true }) {
    title
    completed
  }
}

When executing the following request (as an HTTP POST request in JSON format), specifying the “getTaskAndUser” operation executes the first query:

query getTaskAndUser {
  getTask(id: "0x3") {
    id
    title
    completed
  }
  queryUser(filter: { username: { eq: "dgraphlabs" } }) {
    username
    name
  }
}

query completedTasks {
  queryTask(filter: { completed: true }) {
    title
    completed
  }
}
{
  "data": {
    "getTask": {
      "id": "0x3",
      "title": "GraphQL docs example",
      "completed": true
    },
    "queryUser": [
      {
        "username": "dgraphlabs",
        "name": "Dgraph Labs"
      }
    ]
  }
}

And specifying the completedTasks operation executes the second query:

{
  "query": "query getTaskAndUser { getTask(id: \"0x3\") { id title completed } queryUser(filter: {username: {eq: \"dgraphlabs\"}}) { username name }\n}\n\nquery completedTasks { queryTask(filter: {completed: true}) { title completed }}",
  "operationName": "completedTasks"
}
{
  "data": {
    "queryTask": [
      {
        "title": "GraphQL docs example",
        "completed": true
      },
      {
        "title": "Show second operation",
        "completed": true
      }
    ]
  }
}

Multiple queries execution

When an operation contains multiple queries, they run concurrently and independently in a Dgraph read-only transaction per query.

When an operation contains multiple mutations, they run serially, in the order listed in the request, with a transaction per mutation. If a mutation fails, the following mutations aren’t executed and previous mutations aren’t rolled back.

Variables

Variables simplify GraphQL queries and mutations by letting you pass data separately. A GraphQL request can be split into two sections: one for the query or mutation, and another for variables.

Variables can be declared after the query or mutation and are passed like arguments to a function and begin with $.

Query example

query post($filter: PostFilter) {
  queryPost(filter: $filter) {
    title
    text
    author {
      name
    }
  }
}
{
  "filter": {
    "title": {
      "eq": "First Post"
    }
  }
}

Mutation example

mutation addAuthor($author: AddAuthorInput!) {
  addAuthor(input: [$author]) {
    author {
      name
      posts {
        title
        text
      }
    }
  }
}
{
  "author": {
    "name": "A.N. Author",
    "dob": "2000-01-01",
    "posts": [{
      "title": "First Post",
      "text": "Hello world!"
    }]
  }
}

Fragments

A GraphQL fragment is associated with a type and is a reusable subset of the fields from this type. Here, we declare a postData fragment that can be used with any Post object:

fragment postData on Post {
  id
  title
  text
  author {
    username
    displayName
  }
}
query allPosts {
  queryPost(order: { desc: title }) {
    ...postData
  }
}
mutation addPost($post: AddPostInput!) {
  addPost(input: [$post]) {
    post {
      ...postData
    }
  }
}

Using fragments with interfaces

It is possible to define fragments on interfaces. Here’s an example of a query that includes in-line fragments:

Schema

interface Employee {
  ename: String!
}
interface Character {
  id: ID!
  name: String! @search(by: [exact])
}
type Human implements Character & Employee {
  totalCredits: Float
}
type Droid implements Character {
  primaryFunction: String
}

Query

query allCharacters {
  queryCharacter {
    name
    __typename
    ... on Human {
      totalCredits
    }
    ... on Droid {
      primaryFunction
    }
  }
}

The allCharacters query returns a list of Character objects. Since Human and Droid implements the Character interface, the fields in the result would be returned according to the type of object.

Result

{
  "data": {
    "queryCharacter": [
      {
        "name": "Human1",
        "__typename": "Human",
        "totalCredits": 200.23
      },
      {
        "name": "Human2",
        "__typename": "Human",
        "totalCredits": 2.23
      },
      {
        "name": "Droid1",
        "__typename": "Droid",
        "primaryFunction": "Code"
      },
      {
        "name": "Droid2",
        "__typename": "Droid",
        "primaryFunction": "Automate"
      }
    ]
  }
}

GET request

GraphQL request may also be sent using an HTTP GET operation.

\GET requests must be sent in the following format. The query, variables, and operation are sent as URL-encoded query parameters in the URL.

http://localhost:8080/graphql?query={...}&variables={...}&operationName=...
  • query is mandatory
  • variables is only required if the query contains GraphQL variables.
  • operationName is only required if there are multiple operations in the query; in which case, operations must also be named.

Response

All responses, including errors, always return HTTP 200 OK status codes.

The response is a JSON map including the fields "data", "errors", or "extensions" following the GraphQL specification. They follow the following formats.

Successful queries are in the following format:

{
  "data": { ... },
  "extensions": { ... }
}

Queries that have errors are in the following format.

{
  "errors": [ ... ],
}

Data field

The “data” field contains the result of your GraphQL request. The response has exactly the same shape as the result. For example, notice that for the following query, the response includes the data in the exact shape as the query.

Query:

query {
  getTask(id: "0x3") {
    id
    title
    completed
    user {
      username
      name
    }
  }
}

Response:

{
  "data": {
    "getTask": {
      "id": "0x3",
      "title": "GraphQL docs example",
      "completed": true,
      "user": {
        "username": "dgraphlabs",
        "name": "Dgraph Labs"
      }
    }
  }
}

Errors field

The “errors” field is a JSON list where each entry has a "message" field that describes the error and optionally has a "locations" array to list the specific line and column number of the request that points to the error described. For example, here’s a possible error for the following query, where getTask needs to have an id specified as input:

Query:

query {
  getTask() {
    id
  }
}

Response:

{
  "errors": [
    {
      "message": "Field \"getTask\" argument \"id\" of type \"ID!\" is required but not provided.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ]
    }
  ]
}

Error propagation

Before returning query and mutation results, Dgraph uses the types in the schema to apply GraphQL value completion and error handling. As an example, null values for non-nullable fields (such as String!) cause error propagation to parent fields.

In short, the GraphQL value completion and error propagation mean the following.

  • Fields marked as nullable (without !) can return null in the JSON response.
  • For fields marked as non-nullable (with !) Dgraph never returns null for that field.
  • If an instance of type has a non-nullable field that has evaluated to null, the whole instance results in null.
  • Reducing an object to null might cause further error propagation. For example, querying for a post that has an author with a null name results in null: the null name (name: String!) causes the author to result in null, and a null author causes the post (author: Author!) to result in null.
  • Error propagation for lists with nullable elements (for example friends [Author]), can result in nulls inside the result list.
  • Error propagation for lists with non-nullable elements results in null for friends [Author!] and would cause further error propagation for friends [Author!]!.

Note that, a query that results in no values for a list always returns the empty list [], not null, regardless of whether it is nullable. For example, given a schema for an author with posts: [Post!]!, if an author hasn’t posted anything and we queried for that author, the result for the posts field would be posts: [].

A list can, however, result in null due to GraphQL error propagation. For example, if the definition is posts: [Post!], and we queried for an author who has a list of posts. If one of those posts happened to have a null title (title is non-nullable title: String!), then that post would evaluate to null, the posts list can’t contain nulls and so the list reduces to null.

Extensions field

The “extensions” field contains extra metadata for the request with metrics and trace information for the request.

  • "touched_uids": The number of nodes that were touched to satisfy the request. This is a good metric to gauge the complexity of the query.
  • "tracing": Displays performance tracing data in Apollo Tracing format. This includes the duration of the whole query and the duration of each operation.

Here’s an example of a query response with the extensions field:

{
  "data": {
    "getTask": {
      "id": "0x3",
      "title": "GraphQL docs example",
      "completed": true,
      "user": {
        "username": "dgraphlabs",
        "name": "Dgraph Labs"
      }
    }
  },
  "extensions": {
    "touched_uids": 9,
    "tracing": {
      "version": 1,
      "startTime": "2020-07-29T05:54:27.784837196Z",
      "endTime": "2020-07-29T05:54:27.787239465Z",
      "duration": 2402299,
      "execution": {
        "resolvers": [
          {
            "path": ["getTask"],
            "parentType": "Query",
            "fieldName": "getTask",
            "returnType": "Task",
            "startOffset": 122073,
            "duration": 2255955,
            "dgraph": [
              {
                "label": "query",
                "startOffset": 171684,
                "duration": 2154290
              }
            ]
          }
        ]
      }
    }
  }
}

Turn off extensions

To turn off extensions set the --graphql superflag’s extensions option to false (--graphql extensions=false) when running Dgraph Alpha.