Schema Generation
The GraphQL schema definition 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:
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 GraphQL Errors section.
If the generated name starts with a number or collides with a reserved type name, it gets prefixed with ContentType. For example:
To keep the original name in query responses, consider using aliases:
Reserved type names
Query, String, Int, Float, Boolean, Location, Circle, Rectangle, DateTime, RichText, Asset, AssetCollection, AssetLinkingCollections, AssetFilter, AssetOrder, Entry, EntryCollection, EntryOrder, Sys, SysFilter, ContentfulMetadata, ContentfulTag, ContentfulMetadataFilter, ContentfulMetadataTagsFilter, Dimension, HexColor, Quality, ImageResizeFocus, ImageResizeStrategy, ImageFormat, ImageTransformOptions, ResourceSys, ResourceLink, ResourceLinkCollection, and Never.
Example
For example, a single content type is defined as follows:
Using this content type definition, the API automatically generates the corresponding schema definition. 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 for fetching individual content (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 Collection fields section.
Fields
GraphQL type fields are generated from the corresponding content type fields. Each type has three additional fields: sys, contentfulMetadata and linkedFrom.
Names
Field name is the lower camelCase version of the field ID, stripped of non-alphanumeric characters. For example:
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, contentfulMetadata and linkedFrom.
For more information about errors see the errors section.
Types
Field type is determined based on the following mappings:
Fields of type Link and Array of Link are handled as explained in Modeling relationships.
Fields of type Location are handled as explained in Locations.
Fields of type RichText are handled as explained in Rich text.
Fields of type Never are handled as explained in Never.
Arguments
Fields on entries provide an optional locale argument, allowing the locale to be overridden for a single field. The current scope’s locale is used if a locale is not specified. If the requested locale does not exist, an UNKNOWN_LOCALE error is returned for this path.
Fields also support an optional useFallbackLocale argument. When set to false, the field returns null if no value exists in the requested locale, instead of the fallback locale. For more information, see the Disabling locale fallback section.
Example
Continuing with the previous example, extend the Friendly User content type with three fields: age, name and addresses:
The resulting GraphQL schema is:
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,contentfulMetadataorlinkedFrom.
You cannot change the content type ID without regenerating the content type, so be aware of these restrictions while creating your content models.
Colliding type names
In order to successfully generate the schema, the GraphQL type generated from a content type ID has to be unique.
Type uniqueness check will fail if a content type ID is transformed into a GraphQL type that already exists.
This can happen in two cases:
- when two or more content type IDs are transformed into the same GraphQL type name.
- when a content type ID is transformed into a GraphQL type name that collides with an existing GraphQL helper type.
While the first case is straightforward, let’s take a closer look at the second case.
GraphQL generates the following helper types for each content type:
CollectionLinkingCollectionsFilterOrder
For a content type Plants with id plants, GraphQL will generate type Plants and the following helper types:
PlantsCollectionPlantsLinkingCollectionsPlantsFilterPlantsOrder
If we happen to have a second content type called PlantsOrder with id plantsOrder, schema creation will fail. The GraphQL type PlantsOrder will collide with the PlantsOrder helper type generated for Plants content type.
To avoid type name collisions for a new content type, make sure that the GraphQL types and helper types generated for it won’t collide with any of the existing GraphQL types.
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.
ContentfulMetadata field
Each GraphQL type derived from a content type and the Asset type will also have a contentfulMetadata field. This field exposes information on the public tags that exist on the content.
To learn more about tags, see the tags section of the Content Management API reference.
Modeling relationships
One of the benefits of GraphQL is that it simplifies traversing the graph of relationships between different types.
In Contentful, relationships are modeled 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.
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.
One-to-one single-type relationships
One-to-one single-type relationships are modeled 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.
This results in the following schema:
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 modeled with the following content types:
This results in the following schema:
One-to-many single-type relationships
One-to-many relationships are modeled with arrays of links. For example, a FriendlyUser might have multiple friends.
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.
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.
This results in the following schema:
Links to a specific item (linkedFrom)
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:
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:
To retrieve names of all the cats and their owners:
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:
By default the current locale is used to search entry fields for links to the specific entry or asset. To override this behavior the linkedFrom field accepts an optional allowedLocales argument.
Note that this does not change the locale of the entries in the collection.
Due to the way GraphQL API treats arrays you can omit brackets if you only need a single locale.
Inline fragments
Since every GraphQL API type implements the Entry interface, the content type of the entries can be linked without validation:
Link to single entry (no validation)
The relationships are modeled 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.
This results in the following schema:
To query the manager field to be of type FriendlyUser:
Link to collection of entities (no validation)
The relationships are modeled by content type fields that link to a collection of entities. For example, each FriendlyUser entry has a managers field that links to a collection of entries.
This results in the following schema:
To only get the entries of type FriendlyUser:
Entries
In addition to collections for entries of a specific content type, querying for the generic Entry interface is supported on the root Query type.
The query above returns the following GraphQL types:
Example — retrieve entries across content types using the root collection type:
Assets
Assets in Contentful have a predefined schema function. This means that the type for any asset in the GraphQL schema follows the definition below:
Assets are also supported as root queries. At present, there are two root queries for it: single asset and collection of assets.
The queries above return the following GraphQL types:
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, pass a transform argument to its url field:
Transformation options translate to query string parameters that are appended to the url in the response. The resulting URL endpoints to the transformed version of the image.
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 the 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,BOTTOMTOP_RIGHT,TOP_LEFT,BOTTOM_RIGHT,BOTTOM_LEFTFACE— 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:ffffff 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:
JPGJPG_PROGRESSIVE— stores multiple passes of an image in progressively higher detail.PNGPNG8— supports up to 256 colors, weighs less than the standard 24-bit PNG.WEBPAVIF
If not defined, defaults to the original image format.
Asset keys
Asset keys are used when signing embargoed asset URLs.
Note: The Embargoed assets feature is only available on specific plans. Reach out to your Sales representative for more information about feature availability.
Secure asset URLs delivered by the CDA, CMA, CPA, or GraphQL API will have a host of (images,assets,videos,downloads).secure.ctfassets.net. They cannot be accessed without first signing the URL.
Signing an embargoed asset URL is accomplished by the following steps:
- Create an asset key for the space the asset URL belongs to. You must specify an
expiresAtvalue, a Unix epoch timestamp in seconds, and this can be no more than 48 hours in the future. - Create a JWT with the embargoed asset URL as the
sub(JWT subject). Sign the JWT with the asset key’ssecret. - Affix to the original embargoed asset URL the following query parameters:
policy— the asset key’s policytoken— the JWT created in step 2
- You may affix other query parameters as well, for example when using the Images API. These do not impact the validity of the signed URL.
By default, a signed asset URL will stop functioning after the expiresAt value that was specified when creating the asset key. When generating the JWT, you may optionally specify an exp (expiry) that will cause the signed URL to be unusable at the specified expiry time. If a per-URL expiry is greater than the expiresAt value specified when creating the asset key, the asset key’s expiresAt value will be used instead.
Note: You cannot create an Asset Key via the GraphQL API. Use the CMA, CDA, or CPA based on your access needs.
Locations
Locations are represented as types with the properties lat and lon:
Collections can be filtered on fields with Location type by applying supported location filters.
Rich Text
Rich text fields are represented as types with two properties:
json— exposes the actualRichTextfield value in a JSON formatlinks— allows you to deeply query various types of referenced entities
For example, if the content type Article has a RichText field text, the following types are generated:
Example query for a RichText field value and linked entities:
Never
The Never field type is used with the Functions feature. This type is assigned to the _data suffixed field when an error occurred during schema generation. For example, when the remote schema cannot be fetched, the _data fields depending on that schema will have the Never type. Field selections on a Never field will always return null, and the error information can be found in the errors array of the response.
Note that your Contentful schema can be fetched as it is and will not be impacted by any errors caused by external references.