GraphQL Content API (Beta Release)

Introduction

The GraphQL Content API provides a GraphQL interface to the content from Contentful. This API provides each space with a GraphQL schema based on its content model. The schema is generated at request time so it is always current.

You can use this API to consume both published and non published content. Read more about this on the previewing content section.

Basic API information

API Base URL https://graphql.contentful.com
This is a read-only API

Basic API Information

The Contentful GraphQL Content API is available at:

https://graphql.contentful.com/content/v1/spaces/{SPACE}

It is also available for specific environments at:

https://graphql.contentful.com/content/v1/spaces/{SPACE}/environments/{ENVIRONMENT}
Disclaimer: Please note that the new GraphQL API beta is initially being rolled out on Large and Performance space types, with future plans to make it available more broadly.

Authentication

Any client using the API needs to provide an access token in either:

  • The Authorization header, specifically, Authorization: Bearer MY_TOKEN.

  • The access_token URL query parameter.

The token must have an access to the space and environment you're targeting. For example, if you create an access token that only has access to the master environment of your space, you cannot use that token to access content from any other environment or space.

To learn more about authentication in Contentful and how to create your own access tokens take a look to the Authentication reference documentation.

Previewing content

Accessing non published content can be useful when you want to, for example, preview how a new article will look like before publishing it and therefore making it public to everybody. The GraphQL API gives you the control to choose if you want to access published or non published content in a very granular fashion.

To control whether you get published or non published content you have to use the preview argument, available to both the single resource fields and collection fields. This argument cascades, meaning that all the references resolved from a resource with preview: true are also showing preview content, unless explicitly overridden. So for example the root level could use non published content while a sub resource could use published content. This is explained in the example below:

query {
  houseCollection (preview: true) {
    items {
      // "house" fields will use non published content
      houseNumber
      numberOfRooms
      owner {
        ... // content for the "owner" will also be non published
      }
       architect (preview: false) {
        ... // content for the "architect" will be published
      }
    }
  }
}

Any query that accesses non published content requires a preview access token. Follow the authentication section to learn how to generate a token and how to use it to authenticate the requests. Fields in queries which require access to non published content but fail to provide a valid preview access token will be resolved with a ACCESS_TOKEN_INVALID error.

Reference

Locale handling

You can specify a locale via the locale argument on collections and single entities:

query {
  germanUser: friendlyUser(id: "hans", locale: "de-DE") {
    name
  }

  americanUser: friendlyUser(id: "joe", locale: "en-US")
}

If you don't specify a locale, the default locale of the space is used.

Unlike the CDA, the GraphQL Content API does not support the locale wildcard.

This argument cascades, meaning that all the references resolved from a resource with locale: "de-DE" are also showing German content, unless explicitly overridden. So for example the root level could use a different locale than a sub resource. When changing the locale on references, only the referenced entities are resolved with this locale. The reference field value itself is still resolved with the locale of the parent. This is explained in the example below:

query {
  germanUser: friendlyUser(id: "hans", locale: "de-DE") {
    name
    germanPetsInFrench: petsCollection(locale: "fr-FR") {
      items {
        name
      }
    }
  }
}

If requested locale does not exist, an UNKNOWN_LOCALE error is returned for this path.

Schema generation

The GraphQL schema is generated from the content model at request time so it is always current.

Types

The GraphQL schema is generated from the content types defined in the specified environment of the space (or master if no environment has been specified). For each content type in your environment the GraphQL Content API creates a corresponding GraphQL type.

Names

Type name is the pascalcase version of the content type ID, stripped of non-alphanumeric characters. For example:

Original value Transformed value
"my-2content-type" "My2ContentType"

If two or more content type IDs would be transformed to the same type name, a COLLIDING_TYPE_NAMES error is returned. For more information about errors see the errors section.

If the generated name starts with a number or collides with a reserved type name, it gets prefixed with 'ContentType'. For example:

Original content type id Transformed type name
Location ContentTypeLocation
5TbTQ4S6xqSeAU6WGQmQ2e ContentType5TbTQ4S6xqSeAU6WGQmQ2e

In order to keep the original name in query response, consider using aliases like:

query {
  location: contentTypeLocation(id: "some-id") {
    # ... location fields
  }
}

Reserved type names are Query, String, Int, Float, Boolean, Location, Circle, Rectangle, DateTime, RichText, Asset, AssetCollection, AssetLinkingCollections, AssetFilter, AssetOrder, Entry, EntryCollection, Sys, SysFilter, ImageResizeFocus, ImageResizeStrategy, ImageFormat, and ImageTransformOptions.

Example

For example, a single content type is defined as following:

{
  sys: {
    id: "friendly-user"
  },
  fields: [
    ...
  ]
}

Using this content type definition, the API automatically generates the corresponding schema. Notice how the GraphQL type is named after the content type ID. The produced Query object exposes two fields that you can use to query content of that type: one to fetch individual content documents (friendlyUser in the example) and another to do queries over all the content of the type (friendlyUserCollection). Collections are explained in more detail in the Collections section.

type Sys {
  id: String
  spaceId: String
  environmentId: String
}

type FriendlyUser {
  sys: Sys
  # ... fields
}

input FriendlyUserFilter {
  # ... field based filters
}

type FriendlyUserCollection {
  skip: Int!
  limit: Int!
  total: Int!
  nodes: [FriendlyUser]!
}

type Query {
  friendlyUser(id: String!): FriendlyUser
  friendlyUserCollection(
    skip: Int
    limit: Int,
    where: FriendlyUserFilter
  ): FriendlyUserCollection
}

Fields

GraphQL type fields are generated from the corresponding content type fields. Each type also has two extra fields: sys and linkedFrom.

Names

Field name is the lower camelcased version of the field ID, stripped of non-alphanumeric characters. For example:

Original value Transformed value
"my-field8-name" "myField8Name"

If two or more field IDs on the same content type would be transformed to the same field name, a COLLIDING_FIELD_NAMES error is returned.

If the generated name collides with a reserved field name, a RESERVED_FIELD_NAME error is returned. Reserved field names are sys and linkedFrom.

For more information about errors see the errors section.

Types

Field type is determined based of the following mappings:

Contenful type GraphQL type
Symbol String
Text String
Number Float
Integer Int
Date DateTime
Boolean Boolean
Object JSON
Array of Symbol [String]

Fields of type Link and Array of Link are handled as explained in Modelling relationships.

Fields of type Location are handled as explained in Locations.

Fields of type RichText are handled as explained in Rich text.

Example

Next, continue with the previous example and extend the Friendly User content type with three fields: age, name and addresses.

{
  name: "Friendly User"
  sys: {
    id: "friendly-user",
    ...
  },
  fields: [
    {
      id: "age",
      type: "Integer"
    },
    {
      id: "name",
      type: "Symbol"
    },
    {
      id: "addresses",
      type: "Array",
      items: {
        type: "Symbol"
      }
    }
  ]
}

The resulting GraphQL schema is:

type FriendlyUser {
  sys: Sys
  linkedFrom: FriendlyUserLinkingCollections
  age: Int
  name: String
  addresses: [String]
}

Schema generation failure

Schema generation fails when:

  • Two or more content type IDs would be transformed to the same type name.

  • Two or more field IDs on the same content type would be transformed to the same field name.

  • Any field ID would be transformed to sys or linkedFrom field name.

You cannot change the content type ID without regenerating the content type, so be aware of these restrictions while creating your content models.

Sys field

Each graphql type derived from a content type and the Asset type will also have a system defined sys field. This field exposes meta information about the content.

type Sys {
  id: String!
  spaceId: String!
  environmentId: String!
}
type MyContentType {
  ... # content fields
  sys: Sys!
}
type Asset {
  ... # content fields
  sys: Sys!
}

The table below describes each of the fields in the graphql Sys type

Field Type Description
id String Unique identifier of the resource.
spaceId String Unique identifier of the resource's space.
environmentId String Unique identifier of the resource's environment.

Modelling relationships

One of the benefits of GraphQL is that it simplifies traversing the graph of relationships between different types.

In Contentful, relationships are modelled using links. An entry field can be a link to another entry or a list of links to other entries. The content type of the entries that can be linked from a given field can be restricted using the linkContentType validation. Although optional, it is recommended to define linkContentType for your link fields for a better experience. The GraphQL schema uses this validation to determine the type of a link field.

A field may also link to an asset by specifying linkType: "Asset". In this case there is no linkContentType validation, the GraphQL type of the field is always Asset.

Following sections explain in detail how different kinds of relationships are modelled and how the corresponding GraphQL schema looks.

One-to-one single-type relationships

One-to-one single-type relationships are modelled by content type fields that link to at most one entry of a fixed type. For example, each FriendlyUser entry has a manager field that links to one entry of content type FriendlyUser.

{
  name: "Friendly User"
  sys: {
    id: "friendly-user",
    ...
  },
  fields: [
    ...,
    {
      id: "manager",
      type: "Link",
      linkType: "Entry",
      validations: [{ linkContentType: ["friendlyUser"] }]
    }
  ]
}

This results in the following schema:

type FriendlyUser {
  sys: Sys
  manager: FriendlyUser
  # ... other fields
}

One-to-one multi-type relationships

It is possible for an entry field to link to entries of different content types. For example, each FriendlyUser may have a pet that is either a Dog or a Cat. This is modelled with the following content types.

{
  name: "Cat",
  sys: {
    id: "cat",
    ...
  }
}

{
  name: "Dog",
  sys: {
    id: "dog",
    ...
  }
}

{
  name: "Friendly User"
  sys: {
    id: "friendly-user",
    ...
  },
  fields: [
    ...,
    {
      id: "pet",
      type: "Link",
      linkType: "Entry",
      validations: [{ linkContentType: ["cat", "dog"] }]
    }
  ]
}

This results in the following schema:

type Dog {
  # ...
}

type Cat {
  # ...
}

union FriendlyUserPet = Cat | Dog

type FriendlyUser {
  sys: Sys
  age: Int
  name: String
  addresses: [String]
  petsCollection: FriendlyUserPetsCollection
  manager: FriendlyUser
  # ...
  pet: FriendlyUserPet
}

One-to-many single-type relationships

One-to-many relationships are modelled with arrays of links. For example, a FriendlyUser might have multiple friends.

{
  name: "Friendly User"
  sys: {
    id: "friendly-user",
    ...
  },
  fields: [
    ...,
    {
      id: "friends",
      type: "Array",
      items: {
        type: "Link",
        linkType: "Entry",
        validations: [{ linkContentType: ["friendlyUser"] }]
      }
    }
  ]
}

In the resulting GraphQL schema the friends field is renamed to friendsCollection and is of a collection type, the same type that is used for top-level collections for the FriendlyUser content type. The field has the same skip and limit arguments as the top-level collection field and the same limits apply.

type FriendlyUser {
  sys: Sys
  friendsCollection(skip: Int, limit: Int): FriendlyUserCollection
  # ...
}

type FriendlyUserCollection {
  skip: Int!
  limit: Int!
  total: Int!
  items: [FriendlyUser]!
}

One-to-many multi-type relationships

As with one-to-one relationships, a collection field can link to entries of different content types. For example, a FriendlyUser can have multiple pets, each of which is either a Dog or a Cat.

{
  name: "Cat",
  sys: {
    id: "cat",
    ...
  }
}

{
  name: "Dog",
  sys: {
    id: "dog",
    ...
  }
}

{
  name: "Friendly User"
  sys: {
    id: "friendly-user",
    ...
  },
  fields: [
    ...,
    {
      id: "pets",
      type: "Array",
      items: {
        type: "Link",
        linkType: "Entry",
        validations: [{ linkContentType: ["dog", "cat"] }]
      }
    }
  ]
}

This results in the following schema:

type Dog {
  # ...
}

type Cat {
  # ...
}

union FriendlyUserPetsItem = Cat | Dog

type FriendlyUserPetsCollection {
  skip: Int!
  limit: Int!
  total: Int!
  items: [FriendlyUserPetsItem]!
}

type FriendlyUser {
  sys: Sys
  petsCollection(skip: Int, limit: Int): FriendlyUserPetsCollection
  # ...
}

You can retrieve the collection of entries linking to a specific entry (or asset) by using the linkedFrom field in your query.

For example, consider a Friendly User content type defined as follows:

{
  name: "Friendly User"
  sys: {
    id: "friendly-user",
    ...
  },
  fields: [
    ...,
    {
      id: "photo",
      type: "Link",
      linkType: "Asset"
    },
    {
      id: "pets",
      type: "Array",
      items: {
        type: "Link",
        linkType: "Entry",
        validations: [{ linkContentType: ["dog", "cat"] }]
      }
    }
  ]
}

Friendly User links to the Asset type through the photo field, which is a link to an asset. It also links to the Dog and Cat types through the pets field, which is a list of links to entries, with content types restricted to Dog and Cat.

Based on those relationships, a friendlyUserCollection field is generated inside the linkedFrom fields of the Asset, Dog, and Cat types:

type Cat {
  sys: Sys
  linkedFrom: {
    friendlyUserCollection: FriendlyUserCollection
    entryCollection: EntryCollection
  }
  name: String
  # ...
}

type Dog {
  sys: Sys
  linkedFrom: {
    friendlyUserCollection: FriendlyUserCollection
    entryCollection: EntryCollection
  }
  name: String
  # ...
}

type Asset {
  sys: Sys
  linkedFrom: {
    friendlyUserCollection: FriendlyUserCollection
    entryCollection: EntryCollection
  }
  title: String
  # ...
}

To retrieve names of all the cats and their owners you can then use the following query:

query {
  catCollection {
    items {
      name
      linkedFrom {
        friendlyUserCollection {
          items {
            firstName
          }
        }
      }
    }
  }
}

Notice that each linkedFrom field also has a generic entryCollection field. This field is always present and allows you to query for linking entries of all types. If you don't have linkContentType validations defined for your fields, entryCollection is the only way to query for linking entries:

query {
  catCollection {
    items {
      name
      linkedFrom {
        entryCollection {
          items {
            ... on FriendlyUser {
              firstName
            }
          }
        }
      }
    }
  }
}

Inline fragments

Since every GraphQL type implements the Entry interface, the content type of the entries can be linked without validation.

  type Entry {
     sys: Sys
  }

Link to single entry

The relationships are modelled by content type fields that link to at most one entry. For example, each FriendlyUser entry has a manager field that links to one entry of content type FriendlyUser.

{
  name: "Friendly User"
  sys: {
    id: "friendly-user",
    ...
  },
  fields: [
    ...,
    {
      id: "manager",
      type: "Link",
      linkType: "Entry",
    }
  ]
}

This results in the following schema:

type FriendlyUser implements Entry {
  sys: Sys
  linkedFrom: FriendlyUserLinkingCollections
  manager: Entry
  # ... other fields
}

To query the manager field to be of type FriendlyUser do the following query:

query {
  friendlyUser(id: "hans") {
    manager {
      ... on FriendlyUser {
        # some user fields
      }
    }
  }
}

### Link to collection of entities [/schema-generation/inline-fragments]

The relationships are modelled by content type fields that
link to a collection of entities. For example, each `FriendlyUser` entry
has a `managers` field that links to collection of entries.

```javascript
{
  name: "Friendly User"
  sys: {
    id: "friendly-user",
    ...
  },
  fields: [
    ...,
    {
      id: "managers",
      type: "Array",
      items: {
        type: 'Link',
        linkType: 'Entry'
      }
    }
  ]
}

This results in the following schema:

type FriendlyUser implements Entry {
  sys: Sys
  linkedFrom: FriendlyUserLinkingCollections
  managersCollection: FriendlyUserManagersCollection
  # ... other fields
}

To only get the entries of type FriendlyUser, you can do the following query:

query {
  friendlyUser(id: "hans") {
    managersCollection {
      items {
        ... on FriendlyUser {
          # some user fields
        }
      }
    }
  }
}

Assets

Assets in Contentful have a predefined schema. This means that the type for any asset in the GraphQL schema follows the definition below:

type Asset {
  sys: Sys
  linkedFrom: AssetLinkingCollections
  title: String
  description: String
  contentType: String
  fileName: String
  url: String
  size: Int
  width: Int?
  height: Int?
}

Assets are also supported as root queries. At present, there are two root queries for it: single asset and collection of assets.

type Query {
  # ...
  asset (id: String!): Asset
  assetCollection(skip: Int, limit: Int): AssetCollection
}

The queries above return following GraphQL types:

type Asset {
  sys: Sys
  linkedFrom: AssetLinkingCollections
  title: String
  description: String
  contentType: String
  fileName: String
  url: String
  size: Int
  width: Int?
  height: Int?
}

type AssetCollection {
  skip: Int!
  limit: Int!
  total: Int!
  items: [Asset]!
}

Unlike the CDA, the GraphQL Content API always serves asset URLs with a protocol, defaulting to HTTPS.

Image transformations

The GraphQL Content API exposes a set of image transformation options, such as cropping or resizing. To request image transformations for an asset, you have to pass a transform argument to its url field.

For example:

{
  asset(id: "KTsF62Q4gg60q6WCsWJw8") {
    title
    url(transform: {
      width: 500,
      height: 300,
      resizeStrategy: FILL,
      resizeFocus: BOTTOM,
      backgroundColor: "rgb:321032",
      cornerRadius: 100,
      format: JPG,
      quality: 90
    })
   }
}

Transformation options translate to query string parameters that are appended to the url in the response. The resulting URL points to the transformed version of the image.

{
  data: {
    asset: {
      title: "contentful-team",
      url: "https://images.ctfassets.net/f8bqpb154z8p/4dgP2U7BeMuk0icguS4qGw/bc9431adf0b4a798b1aee97b2c56aa60/Contentful_team.png?w=500&h=300&q=90&fit=fill&f=bottom&r=100&bg=rgb%3A321032&fm=jpg"
    }
  }
}

Transformation options take no effect when the asset is not an image.

width and height

Desired width and height of the image in pixels. Accept values between 1 and 4000. If not defined, default to the original image width and height.

quality

Desired quality of the image. Used for PNG8, JPG, JPG_PROGRESSIVE and WEBP formats. Accepts percentage values, between 1 and 100.

cornerRadius

Desired corner radius in pixels. Results in an image with rounded corners (pass -1 for a full circle/ellipse). If not defined, defaults to 0. Uses desired background color as padding color, unless the format is JPG or JPG_PROGRESSIVE and resize strategy is PAD, then defaults to white.

resizeStrategy

Desired resize strategy. Accepts the following enum type values:

  • FIT (default) resizes the image to fit into the specified dimensions.

  • PAD resizes the image to the specified dimensions, padding the image if needed. Uses desired background color as padding color.

  • FILL resizes the image to the specified dimensions, cropping the image if needed.

  • SCALE resizes the image to the specified dimensions, changing the original aspect ratio if needed.

  • CROP crops a part of the original image to fit into the specified dimensions.

  • THUMB creates a thumbnail from the image focusing on the focus area

resizeFocus

Desired resize focus area. Accepts the following enum type values:

  • CENTER (default)

  • TOP, RIGHT, LEFT, BOTTOM.

  • TOP_RIGHT, TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT.

  • FACE - focuses on the largest face.

  • FACES - focuses on the area containing all the faces.

It has no effect when used with FIT or SCALE resize strategy.

backgroundColor

Desired background color, used with corner radius or PAD resize strategy. Accepts RGB values in rgb:ffffffT} format. If not defined, defaults to transparent (for PNG, PNG8 and WEBP) or white (for JPG and JPG_PROGRESSIVE).

format

Desired image format. Accepts the following enum values:

  • JPG

  • JPG_PROGRESSIVE Progressive JPG format stores multiple passes of an image in progressively higher detail. While a progressive image is loading, the viewer will first see a lower quality pixelated version, which will gradually improve in detail, until the image is fully downloaded. This displays the image as early as possible in order to maintain the layout as designed.

  • PNG

  • PNG8 8-bit PNG images support up to 256 colors and weigh less than the standard 24-bit PNG equivalent. The 8-bit PNG format is mostly used for simple images, such as icons or logos.

  • WEBP

If not defined, defaults to the original image format.

Locations

Locations are represented as types with the properties lat and lon. The GraphQL type looks like:

type Location {
  lat: Float
  lon: Float
}

Rich text

Rich text fields are represented as types with the property json. The GraphQL type looks like:

type RichText {
  json: JSON
}

Collections can be filtered on fields with Location type by applying supported filters.

Collection fields

Collections of entries and assets are exposed through collection fields in the root query object and in one-to-many relationship fields. For example:

type FriendlyUserCollection {
  skip: Int!
  limit: Int!
  total: Int!
  items: [FriendlyUser]!
}

input FriendlyUserFilter {
  # ... field based filters
}

type Query {
  # ...
  friendlyUserCollection(
    skip: Int
    limit: Int,
    where: FriendlyUserFilter
  ): FriendlyUserCollection
}

Arguments

The following optional arguments are available when querying a collection:

Argument Type Description
skip Number zero-indexed offset in the collection from which items are fetched. The default is 0
limit Number maximum number of items to fetch. The default is 100 and the maximum is 100
where InputType filter specifications to apply on the collection query. For more information see the Collection Filters section
order InputType order specifications to apply on the collection query. For more information see the Collection Order section.
preview Boolean when set to true the field will be resolved with non published content. The default is false
locale String locale for the collection items. If not set the default locale is used.

Return value

The value returned from a collection field contains the meta fields skip, limit and, total and the requested items in the items field. The skip and limit fields corresponds to respective input arguments. The total fields contains the total number of items in that collection.

Collection Filters

The GraphQL Content API allows users to specify filters on root collection queries.

Collections could be filtered by different fields or combination of fields that contain collection items. There are general and type specific filters:

Filter Postfix Field type
equal <any>
not equal _not <any>
exists _exists <any>
contains _contains String
does not contain _not_contains String
greater than _gt Number, Date
greater or equals _gte Number, Date
less than _lt Number, Date
less or equals _lte Number, Date
in given list _in String, Number, Date
not in given list _not_in String, Number, Date
within circle _withinCircle Location
within rectangle _withinRectangle Location

For each content type the schema defines an input type to filter entries of that content type. For example, for the type FriendlyUser structured in the following way:

type FriendlyUser {
  sys: Sys
  name: String
  age: Integer
}

The schema defines the following filter input type:

input FriendlyUserFilter {
  sys: SysFilter
  name: String
  name_not: String
  name_exists: Boolean
  name_contains: String
  # ... more name filters
  age: Number
  age_gt: Number
  age_lt: Number
  # ... more age filters
  AND: [FriendlyUserFilter]
  OR: [FriendlyUserFilter]
}

Filter inputs can be passed to collection queries of their corresponding type to filter the result set.

For example, to find all FriendlyUsers whose name is "Frank" or "Francine" and who are older than 30 years, write the following query:

query {
  friendlyUserCollection(where: {
    AND: [
      {
        OR: [
          { name: "Frank" },
          { name: "Francine" }
        ]
      },
      { age_gt: 30 }
    ],
  }) {
    name
    age
  }
}

Limitations

It is not possible to filter on fields of Type Link, Array, Object, or RichText.

_contains filter is case insensitive and must be at least 2 characters long to work.

Filter generation

Filter input types are derived from the content model, just like the output types. For each content type, one filter input type is derived. The user can pass it to the corresponding root collection query.

Each filter input type has the sys, AND, and OR fields as well as additional field type specific filters for every field.

Name of the filter input type is derived from the output type by appending Filter to it.

Logical connectives

Each filter input type has two special fields AND and OR. These fields are used to logically combine filters.

If multiple fields are specified on a filter, they get connected with an implicit AND:

query {
  friendlyUserCollection(where: {
    OR: [
      { name: "Hans" },
      { name: "Joe" }
    ]
    age_gte: 30,
    age_lte: 40
  }) { name }
}

And result in the following equivalent query:

query {
  friendlyUserCollection(where: {
    AND: [
      OR: [
        { name: "Hans" },
        { name: "Joe" }
      ],
      { age_gte: 30 },
      { age_lte: 40 }
    ]
  }) { name }
}

Both queries return all the friendly users between the age of 30 to 40 and are named either Hans or Joe.

Filters by field type

For each field in a content type a set of filter fields is added to the content type’s filter input type. The type of filters is determined by the [field type][/developers/docs/concepts/data-model/#fields].

Symbol and Text

GraphQL Content API does not distinguish between Symbol and Text types and generates the same filters for both.

For example, if the content type FriendlyUser has a Symbol field name, the following types are generated:

type FriendlyUser {
  # ... other fields
  name: String
}

input FriendlyUserFilter {
  # ... other field filters

  # Matches if the field is equal to the given value
  name: String
  # Matches if the field is not equal to the given value
  name_not: String
  # Matches if the field exists
  name_exists: Boolean
  # Matches if the field value equal one of the given values
  name_in: [String]
  # Matches if the field value does not equal any of the given values
  name_not_in: [String]
  # Matches if given value is a substring of the the field value
  name_contains: String
  # Matches if given value is not a substring of the the field value
  name_not_contains: String
}

Number and Integer

Filter names for Integer and Number types are same. They only differ in the input types for values. For Integer fields the value type is Int, whereas for Number fields the type is Float.

For example, if the content type FriendlyUser has an Integer field age, the following types are generated:

type FriendlyUser {
  # ... other fields
  age: Int
}

input FriendlyUserFilter {
  # ... other field filters

  # Matches if the field is equal to the given value
  age: Int
  # Matches if the field is not equal to the given value
  age_not: Int
  # Matches if the field exists
  age_exists: Boolean
  # Matches if the field value equal one of the given values
  age_in: [Int]
  # Matches if the field value does not equal any of the given values
  age_not_in: [Int]
  # Matches if the field value is strictly smaller than the given value
  age_lt: Int
  # Matches if the field value is smaller than or equal to the given value
  age_lte: Int
  # Matches if the field value is strictly greater than the given value
  age_gt: Int
  # Matches if the field value is greater than or equal to the given value
  age_gte: Int
}

Boolean

Boolean filter accepts values of type Boolean and could be used only on fields with type Boolean.

For example, if the content type FriendlyUser has an Boolean field employed, the following types are generated:

type FriendlyUser {
  # ... other fields
  employed: Boolean
}

input FriendlyUserFilter {
  # ... other field filters

  # Matches if the field is equal to the given value
  employed: Boolean
  # Matches if the field is not equal to the given value
  employed_not: Boolean
  # Matches if the field exists
  employed_exists: Boolean
}

Date

For the fields with type Date the value types are DateTime. The value for filter should be provided full DateTime value in ISO-8601 format eg yyyy-mm-ddThh:mm:ss:sssZ.

For example, if the content type FriendlyUser has an DateTime field birthday, the following types are generated:

type FriendlyUser {
  # ... other fields
  birthday: DateTime
}

input FriendlyUserFilter {
  # ... other field filters

  # Matches if the field is equal to the given value
  birthday: DateTime
  # Matches if the field is not equal to the given value
  birthday_not: DateTime
  # Matches if the field exists
  birthday_exists: Boolean
  # Matches if the field value equal one of the given values
  birthday_in: [DateTime]
  # Matches if the field value does not equal any of the given values
  birthday_not_in: [DateTime]
  # Matches if the field value is strictly smaller than the given value
  birthday_lt: DateTime
  # Matches if the field value is smaller than or equal to the given value
  birthday_lte: DateTime
  # Matches if the field value is strictly greater than the given value
  birthday_gt: DateTime
  # Matches if the field value is greater than or equal to the given value
  birthday_gte: DateTime
}

Location

For fields with type Location the value types are either Circle or Rectangle.

The Circle scalar type has the following format:

{
  lat: 10.11,
  lon: 10.11,
  radius: 10,
}

where lat and lon are coordinates of the center of the circle and radius its radius in kilometers.

The Rectangle scalar type has the following format:

{
  topLeftLat: 40,
  topLeftLon: 13.35,
  bottomRightLat: 41,
  bottomRightLon: 14.36
}

where topLeftLat with topLeftLon are the coordinates of the top left corner of the rectangle, and bottomRightLat with bottomRightLon are the coordinates of the bottom right corner of the rectangle.

For example, if the content type FriendlyUser has an Location field place, the following types are generated:

type FriendlyUser {
  # ... other fields
  place: Location
}

input FriendlyUserFilter {
  # ... other field filters

  # Matches if the position is inside the given circle
  place_withinCircle: Circle
  # Matches if the position is inside the given rectangle
  place_withinRectangle: Rectangle
}

sys filters

Every filter input type has a sys property. The type of the sys filter property is the statically defined SysFilter type.

type FriendlyUser {
  sys: SysFilter
  # ... other fields
}

input SysFilter {
  id: String
  id_not: String
  id_in: [String]
  id_not_in: [String]
  id_contains: String
  id_not_contains: String
}

Similar to other field filters the SysFilter input type is generated from the Sys output type. For each field in the Sys type, a set of corresponding filters are added to SysFilter.

Following is an example of a query for a list of entries by IDs:

query {
  friendlyUserCollection(where: {
    sys: {
      id_in: ["id1", "id2"]
    }
  }) { sys { id } }
}

Collection Order

The GraphQL Content API allows users to specify the fields and direction to sort on root collection queries.

For example, for the type FriendlyUser structured in the following way:

type FriendlyUser {
  sys: Sys
  name: String
  age: Integer
}

The schema defines the following order input enum type:

enum FriendlyUserOrder {
  name_ASC
  name_DESC
  age_ASC
  age_DESC
  sys_id_ASC
  sys_id_DESC
}

Order enum values can be passed to collection queries of their corresponding type to sort the result set.

For example, to find the oldest FriendlyUser, write the following query:

query {
  friendlyUserCollection(order: [age_DESC], limit: 1) {
    items {
      name
    }
  }
}

Collections can be sorted by multiple fields, each of them with a direction information.

For example, to order FriendlyUsers by their age (descending) first and for items with same age it should sort by name (ascending), write the following query:

query {
  friendlyUserCollection(order: [age_DESC, name_ASC]) {
    items {
      name
      age
    }
  }
}

Limitations

It is not possible to order on fields of Type Link, Array, Text, Location, Object, or RichText.

Single resource fields

When you want to fetch just one resource of a given type you can use the single resource fields. As explained in the types section, the name of this fields is the camelcased version of the content type from which they derive or asset.

type Query {
  contentModule (id: "introduction") {
    ...
  }
  asset (id: "my-picture") {
    ...
  }
}

Arguments

The following arguments are available when querying a single resource:

Argument Type Required Description
id String true The id of the resource you want to fetch
preview Boolean false when set to true the field will be resolved with non published content. The default is false
locale String false locale for the resource. If not set, the default locale is used.

Exploring the schema with GraphiQL

You can explore and inspect the schema of a space using the GraphiQL, an in-browser GraphQL IDE.

To open GraphiQL visit the https://graphql.contentful.com/content/v1/spaces/{SPACE}/explore?access_token={CDA_TOKEN} URL in your browser. You must provide the CDA_TOKEN as a query parameter.

GraphQL Errors

The GraphQL Content API responses contains errors that occur during the different phases of a request (authentication, validation, schema generation and execution). Among these errors there can also be other internal system errors.

The errors returned by the GraphQL API follow the GraphQL error spec. There is an additional contentful object in the extensions error property with information relevant to the failed request to facilitate debugging and fixing problems. The contentful object contains the following properties:

  • code: unique error identifier.

  • requestId: unique request identifier.

  • details: optional object with details about a specific kind of error.

Following is an example of such a response from the API:

{
  data: { // query data: optional, might be presented in case of partial response queries
    ...
  },
  errors: [{
    message: 'Query execution error. Query too complex to be executed in allocated resources', // Human readable error message
    locations: [{line: 4, column: 17}],
    path: ['too', 'many', 'db_ops'],
    extensions: {
      contentful: {
        code: 'TOO_COMPLEX_QUERY', // text error code
        requestId: 'xxx' // id of current request
      }
    }
  }]
}

List of known errors:

Category Message Is partial*
Authentication ACCESS_TOKEN_MISSING no
Authentication ACCESS_TOKEN_INVALID no
Schema generation COLLIDING_TYPE_NAMES no
Schema generation RESERVED_FIELD_NAME no
Schema generation COLLIDING_FIELD_NAMES no
Schema generation LINKED_CONTENT_TYPES_DO_NOT_EXIST no
Validation UNKNOWN_ENVIRONMENT no
Validation UNKNOWN_LOCALE yes
Validation MISSING_QUERY no
Validation INVALID_QUERY_FORMAT no
Validation INVALID_VARIABLES_FORMAT no
Query execution TOO_COMPLEX_QUERY yes
Query execution UNRESOLVABLE_LINK yes
Query execution LINK_WITHOUT_TYPE_VALIDATIONS no
System errors INTERNAL_SERVER_ERROR no
System errors UPGRADE_PLAN_REQUIRED no

Is partial indicates whether for given error partial data response is possible.