Data model

The GraphCMS API is centered around the data model. The API is automatically generated based on the models you define within your project.

Every operation exposed via the API is associated with a model or relation from the data model you defined in your project.

Queries

Mutations

You are able to define the data model using the Dashboard or Management API and then perform any CRUD operations on the actual content of those models using the Content API.

Generated Schema

GraphCMS is built on the idea of the generated schema. Throught he schema builder, you define the basic type primitives you want your finished schema to support. Think "authors" or "articles". GraphCMS will take these primitives and generate the rest of the schema for you to support queries, mutations and some higher level content abstractions like filtering and internationalization.

Generated Queries

There are two top level generated content queries that are generated for you by GraphCMS.

  • Singular Query
  • Multiple Query

You can read more about querying singular nodes and multiple nodes in the Content API documentation.

Generated Mutations

Similar to generated queries, GraphCMS will generate mutations for you as well. These follow the basic operators of:

  • Create
  • Read
  • Update
  • Delete

Or "CRUD" for short.

You can read more about mutating singular nodes and multiple nodes in the Content API documentation.

Node selection

Many operations in the API only affect a subset of the existing nodes in the database, oftentimes even only a single node.

In these case, you need a way to ask for specific nodes in the API - most of the time this is done via a where argument.

Nodes can be selected via any field that's annotated with the @unique directive. That means every field that you selected as unique, as well as the ID of an entry, which is unique by default.

For the following examples, consider the following simple data model:

type Post {
  id: ID! @unique
  title: String!
}

Here are a few scenarios where node selection is required.

Retrieve a single node by its email:

query {
  post(where: { email: "user@graphcms.com" }) {
    id
  }
}

Update the title of a single node:

mutation {
  updatePost(
    where: { id: "ohco0iewee6eizidohwigheif" }
    data: { title: "GraphQL is awesome" }
  ) {
    id
  }
}

Update published of a many nodes at once:

mutation {
  updatePost(
    where: {
      id_in: [
        "ohco0iewee6eizidohwigheif"
        "phah4ooqueengij0kan4sahlo"
        "chae8keizohmiothuewuvahpa"
      ]
    }
    data: { status: PUBLISHED }
  ) {
    count
  }
}

Also see Batch operations.

Batch operations

It's recommended you use batch mutations when updating or deleting large chunks of nodes at once. GraphCMS will return a BatchPayload, containing the count of the affected nodes, instead of the full node data.

You can read more about batch updating and deleting within the Content API Mutations reference.

Connections

In contrast to the simpler object queries that directly return a list of nodes, connection queries are based on the Relay Connection model. In addition to pagination information, connections also offer advanced features like aggregation.

In the example below, we can use the automatically generated hotelsConnection type to return a HotelConnection type, which includes a aggregate type for getting the count of nodes in our connection query.

query {
  hotelsConnection(
    where: HotelWhereInput
    orderBy: HotelOrderByInput
    skip: Int
    after: String
    before: String
    first: Int
    last: Int
  ) {
    aggregate {
      count
    }
  }
}

We can also use the hotelsConnection type to get specific field data from each node.

In the example below, we can get the name field from the Post node.

query {
  hotelsConnection(
    where: HotelWhereInput
    orderBy: HotelOrderByInput
    skip: Int
    after: String
    before: String
    first: Int
    last: Int
  ) {
    edges {
      node {
        name
      }
    }
  }
}

hotelsConnection accepts multiple filter arguments, you can read more about those here.

Transactional Mutations

Single mutations that are executed against the GraphCMS API that are non batch operations are transactional, even if they consist of many actions that potentially spread across relations.

This is useful for nested mutations that perform several database writes on multiple types.

If you are creating a User node and multiple Post nodes that will be connected, while also connecting the new User node to two existing Post nodes in one mutation, and one fails, the entire mutation is rolled back.

Mutations are atomic and isolated, which means that between separate actions of the same nested mutation, no other mutations can alter the data. The result of a single action cannot be observed until the full mutation has been processed.

GraphQL Responses and Status Codes

When working with GraphQL, a traditional POST or GET request can be used, but in GraphCMS we only use POST. Apart from the communication with the server, that's where the similarities with REST end.

Success

A successful response from the server includes a data property in the body.

{
  "data": {
    /*...*/
  }
}

GraphCMS delivers a JSON response where the following GraphQL values map to the correlated JSON serialization values.

GraphQLJSON
MapObject
ListArray
Nullnull
StringString
Booleantrue or false
IntNumber
FloatNumber
Enum ValueString

Also of importance, according to the specification, the order of query is important. If content is queried as:

{
  last
  first
}

the response must be:

{
  "last": "value",
  "first": "value"
}

If the request was a query, the response will be of the query root type. If the operation was a mutation, the response will be of the mutation root type.

Errors

If an error occurred there's an error property in the response. If no error occurred, there is no error property.

A query will respond as "successful" in terms of the request, even if the query has caused an error.

{
  "errors": [
    /*...*/
  ]
}

Each error entry will include a message key and optionally, if it's possible to determine where the error occurred, a location key as well. Service providers like GraphCMS may include additional information to help assist the developer.

Error at Execution

It may be possible to have both an error property AND a data property if there was an error during the execution of the GraphQL query.

{
  "data": {
    /*...*/
  },
  "errors": [
    /*...*/
  ]
}

For more bedtime reading, check out the docs at the official spec.