• Cheat sheets
  • Documentation
  • API reference
  • Product updates
  • Sign in
Kontent.ai Learn
  • Try Kontent.ai
  • Plan
  • Set up
  • Model
  • Develop
  • Create
  • Docs
  • Accessibility in Kontent.ai
    • Overview
    • API keys
    • Custom elements JS API
    • Delivery GraphQL API
      • Introduction
      • Make POST or GET requests
      • Authentication
      • Preview content
      • Explore your GraphQL schema
      • API limitations
      • Errors
      • Query content
      • Filter content
      • Paging
      • Schemas
      • Content element schemas
    • Image transformation API
  • Collections
  • Custom apps
  • Custom elements
  • Environments
  • Keyboard shortcuts
  • Mission Control
  • Projects
  • Task management
  • Terminology

Delivery GraphQL API reference

Jan Cerman
37 minutes
Delivery API
GraphQL is a query language that prioritizes giving clients the data they request and no more. Compared to the Delivery REST API, the Delivery GraphQL API exposes only a single endpoint for making queries.
Explore your path to mastery
  • Say Hello World and learn the basics of getting and filtering content.
  • Build your first app that follows best practices.
  • Optimize the performance of your apps.
Each Kontent.ai environment has its own GraphQL schema generated from the environment's content model. The schema is generated dynamically at the request time and is always current.
Not familiar with GraphQL?If you're starting out with GraphQL, we recommend you first learn the fundamentals in How to GraphQL.

Introduction

The Delivery GraphQL API is a read-only API. The GraphQL API accepts GET and POST requests to the base URL https://graphql.kontent.ai/<YOUR_ENVIRONMENT_ID>. Use the API to deliver specific content to your website or app. The API responses are cached in a CDN. This makes the content quickly available from wherever you are.

Make POST or GET requests

You can make queries to the Delivery GraphQL API using either POST or GET requests. For both POST and GET requests, the base URL is the same. The difference is in how you specify your GraphQL query. The following examples show how to query for a specific article using POST and GET requests.
All requests to the API must be made securely over HTTPS. Learn more about our encryption security measures.

POST request

For POST requests, specify your GraphQL query in the body of your HTTP request. The maximum request body size is 8 kB.
cURL
curl --request POST \
  --url 'https://graphql.kontent.ai/<YOUR_ENVIRONMENT_ID>' \
  --header 'content-type: application/graphql'
  --data-raw '{article(codename:"my_article"){title}}'
Request body format depends on the content-type headerWith the content-type header set to application/graphql, you need to provide your GraphQL query directly in the request body. If you set the header to application/json, wrap your GraphQL query in valid JSON like this {"query":"{<YOUR_GRAPHQL_QUERY>}"}.

GET request

For GET requests, specify your GraphQL query using the query parameter named query. With query parameters, you’re limited by the maximum URL length of 2000 characters.
cURL
curl -g --request GET 'https://graphql.kontent.ai/<YOUR_ENVIRONMENT_ID>?query={article(codename:"on_roasts"){title}}'

Authentication

By default, Delivery GraphQL API doesn’t require authentication. If you enable secure access for your Kontent.ai environment or want to preview content, you need to authenticate your requests with a Delivery API key. To create Delivery API keys, you need to be a Project manager. When creating the API key, you can limit the API key scope to specific environments. To authenticate your API requests, add the Authorization header to your request in the following format: Authorization: Bearer <YOUR_API_KEY>. Requests with an incorrect or missing Authorization header will fail with an error.
cURL
curl --request POST \
  --url 'https://graphql.kontent.ai/<YOUR_ENVIRONMENT_ID>' \
  --header 'content-type: application/graphql'
  --header 'Authorization: Bearer <YOUR_DELIVERY_API_KEY>'
  --data-raw '{<YOUR_GRAPHQL_QUERY>}'

Preview content

To get the latest version of your content items from your project’s environment, you need to use the preview base URL and authenticate your requests with a valid Delivery API key. To create Delivery API keys, you need to be a Project manager. When making preview requests, use the following:
  • Preview base URL: https://preview-graphql.kontent.ai/<YOUR_ENVIRONMENT_ID>
  • Authorization: Add the Authorization header to your request in the following format: Authorization: Bearer <YOUR_PREVIEW_API_KEY>.
cURL
curl --request POST \
  --url 'https://preview-graphql.kontent.ai/<YOUR_ENVIRONMENT_ID>' \
  --header 'content-type: application/graphql'
  --header 'Authorization: Bearer <YOUR_PREVIEW_API_KEY>'
  --data-raw '{<YOUR_GRAPHQL_QUERY>}'

Explore your GraphQL schema

You can explore your GraphQL schema in your web browser with GraphiQL online. 
  1. Open GraphiQL online in your browser.
  2. Enter the GraphQL base URL of your environment.
  3. Start sending queries.
GraphiQL supports specifying custom headers, which you can use to make API calls to environments with secure access enabled or to preview content.

API limitations

API requests limit

Requests made to the Delivery GraphQL API count towards the overall API Calls limit set in our Fair Use Policy. This includes requests for both published and unpublished content. There is no limit on the total number of API calls you can make.

Query complexity limit

Before processing your query, the GraphQL API calculates the following:
  • Query complexity – The maximum number of content items and components your query can return. The maximum complexity is 2000. See query complexity examples.
  • Query total depth level – The sum of maximum nesting levels of the queries in your API request. The maximum query depth is 124. See query depth examples.

Query complexity examples

If your query complexity exceeds 2000, the GraphQL API rejects your request and returns a QUERY_TOO_COMPLEX error. You can find whether your requests are close to the complexity limit by looking at the X-Complexity header. Example 1 The following query can return up to 1,000 Articles. Its complexity is 1,000.
GraphQL
query GetArticles {
  article_All(limit: 1000) {
    items {
      title
    }
  }
}
Example 2 The following query can return:
  • Up to 100 Articles – complexity is 100
  • Up to 20 linked content items for each Article – complexity is 100 Ă— 20
The total complexity of the query is 2100.
GraphQL
query GetArticlesWithRelatedArticles {
  article_All(limit: 100) {
    items {
      title
      relatedArticles(limit: 20) {
        items {
          _system_ {
            name
          }
        }
      }
    }
  }
}

Query total depth limit examples

The depth of each query starts at level zero. If your query exceeds the nesting limit of 124, the GraphQL API rejects your request and returns an error. Example 1 The total depth of the following query is 5. The root query in the API request goes five levels deep, with the first level counted as zero.
GraphQL
# Total query depth = 5
query GetImagesInArticle {
  article_All {     # level 0
    items {         # level 1
      bodyCopy {    # level 2
        assets {    # level 3
          items {   # level 4
            url     # level 5
          }
        }
      }
    }
  }
}
Example 2 The total depth of the following query is 4. The two root queries both go two levels deep. The sum of the maximum depth of the root queries is 4.
GraphQL
# Total query depth = 4
query GetPostsAndArticles {
  # Depth is 2 levels
  article_All { # level 0
    items {     # level 1
      title     # level 2
      url       # level 2
    }
  }
  # Depth is 2 levels
  post_All {  # level 0
    items {   # level 1
      title   # level 2
      url     # level 2
    }
  }
}

Rate limitation

The GraphQL API enforces a rate limitation based on resource consumption. For cached requests served from our CDN, we don't enforce any rate limits. You can make an unlimited number of repeated requests to the CDN. For uncached requests that reach the GraphQL API, we enforce a rate limitation of 2,000 resource units per second and 40,000 resource units per minute. To see how many resources your requests consumed, check the X-Request-Charge header. 
The scope of API rate limits is per environment. Requests made with multiple API keys to a single environment count against a single rate limit.
When you reach the resource limit for a given time period, the API rejects the request and responds with a 429 HTTP error. This error comes with the Retry-After header that tells you how many seconds you need to wait before retrying your request. Each failed request is perfectly safe to retry. If you begin to receive 429 errors, reduce the frequency of your requests.

CDN-level protection

In addition to the above, a CDN-level protective layer is in place by Fastly to filter out potentially disruptive traffic before it reaches the API. These limits are based on the number of uncached requests, regardless of their resource usage:
  • 1,000 requests per second
  • 5,000 requests per 10 seconds
  • 15,000 requests per minute
Cached responses are not subject to these limits and don’t affect normal usage.

Errors

The Delivery GraphQL API returns standard HTTP status codes to indicate the success or failure of a request. In general, status codes in the 2xx range indicate a successful request, status codes in the 4xx range indicate errors caused by an incorrect input (for example, providing an incorrect API key), and status codes in the 5xx range indicate an error on our side. If your query contains a mistake, the API might return a 200 with an error message in the response body.
Status codeDescription
200 OKThe request was successful. However, the API might return an error message. For example, if your query is too complex or fails to execute correctly.
400 Bad RequestThe request wasn't successful. Check your request for a missing required parameter or an invalid query parameter value.
403 ForbiddenThe API request was forbidden. Check if your subscription plan comes with GraphQL enabled.
404 Not FoundThe specified environment doesn't exist.
405 Method Not AllowedThe requested HTTP method is not supported for the specified resource.
429 Too Many RequestsThe rate limit for the API has been exceeded, triggering a 5-minute block for the originating IP address. Try your request again after waiting the number of seconds shown in the Retry-After header.
5xx Internal Error or Service UnavailableSomething went wrong on our side. Try your request again after a few seconds and use a retry policy.

Query content

For every content type in your project's environment, the API generates two GraphQL root queries. For example, for a content type named Article, you get the following queries:
  • article query for retrieving a single content item.
  • article_All collection query for retrieving multiple content items.
Both of these queries work with a GraphQL type named Article that is generated from the content type.

Get a content item

To get a single content item, you need to provide the item's type and the item's identifier. The identifier can be either a codename or an internal ID.
GraphQL
query GetArticleByCodename {
  article(codename: "my_article") {
    title
    slug
  }
}

query GetArticleById {
  article(id: "c706af79-2a4f-41e4-9bec-8c8383e00944") {
    title
    slug
  }
}

List content items

To get a list of content items, you need to use the <typeName>_All (as in article_All) query. By default, the items are ordered alphabetically by codename.
GraphQL
query GetArticles {
  article_All {
    items {
      title
      slug
    }
  }
}

Order content items

If you want to get your items in a specific order, use the order argument in your query. The order argument requires that you provide a field name and specify whether the order is ascending or descending.   
GraphQL
query GetOrderedItems {
  # Get articles ordered by their title from Z to A
  article_All(order: {title: desc}) {
    items {
      title
    }
  }
  # Blog posts ordered by codename from A to Z
  post_All(order: {_system_: {codename: asc}}) {
    items {
      title
    }
  }
}

Get localized content

By default, the GraphQL API returns content in the default language. To get content items in a specific language, use the languageFilter argument in your queries. If the requested content items don't have content in the specified language, the API follows language fallbacks as specified in your localization settings. To check the language of the returned content items, specify the language field of the content item's system_ object.
GraphQL
query GetSpanishArticles {
  # Requests articles in Spanish
  article_All(languageFilter: {languageCodename: "es-ES"}) {
    items {
      _system_ {
        language {
          _system_ {
            codename
          }
        }
      }
      title
      slug
    }
  }
}

Filter content

To retrieve content items based on specific criteria, you can filter the content items using the where argument. The where argument can be applied only to root collection queries, which are based on your content types such as article_All, navigationItem_All, and so on. In the where argument, you can specify a single condition with one filter or combine multiple filters using the AND and OR operators.
GraphQL
query GetNonArchivedArticles {
  article_All(where: {_system_: {workflowStep: {notEq: "archived"}}}) {
    items {
      title
    }
  }
}

Filterable fields

To filter by content item metadata, you can use the following _system_ fields:
  • id(string)
  • codename(string)
  • name (string)
  • lastModified (string)
  • collection (string)
  • workflow (string)
  • workflowStep (string)
  • language (LanguageFilter!)
To filter by the values of elements within content items, you can use fields that are based on the following content elements:
  • Date & time (value field only)
  • Linked items
  • Multiple choice
  • Number
  • Text
  • Taxonomy

Filters

You can use the following filters on specific system fields and element fields.
FilterDescriptionExample conditionUse with types
eqChecks whether the field value matches exactly to the specified filter value.where: {title: {eq: "My article"}} where: {_system_: {id: {eq: "<item-id>"}}} DateTime, Number, String
notEqChecks if the field value is different than the specified value.where: {_system_: {workflowStep: {notEq: "archived"}}}DateTime,  Number, String
ltChecks if the field's value is less than the specified value.where: {postDate_with_timezone: {value: {lt: "2021-01-01T00:00:00Z"}}}DateTime, Number
lteChecks if the field's datetime value is less than or equal to the specified value.where: {_system_: {lastModified: {lte: "2021-01-01T00:00:00Z"}}}DateTime, Number
gtChecks if the field's datetime value is greater than the specified value.where: {postDate_with_timezone: {value: {gt: "2021-01-01T00:00:00Z"}}}DateTime, Number
gteChecks if the field's datetime value is greater than or equal to the specified value.where: {price: {gte: 10.5}}DateTime, Number
inChecks if the field value matches at least one of the specified array values.where: {_system_: {collection: {in: ["hr", "marketing"]}}}DateTime, Number, String
notInChecks if the field value is different than the specified array values.where: {_system_: {collection: {notIn: ["default"]}}}DateTime, Number, String
isEmptyChecks if the field value is null or empty.where: {relatedArticles: { isEmpty: true }}DateTime, Number, String, Array
containsAllChecks if the array field value matches all of the specified array values.where: {topic: { containsAll: ["gadget", "security"] }}Array
containsAnyChecks if the field value matches at least one of the specified array values.where: {topic: { containsAny: ["nature"] }}Array

Combine filters with AND and OR

To combine multiple filters in your where arguments, you can use the AND and OR operators. Both operators take an array of at least two values and can be nested in one another.
GraphQL
query GetArticlesByComplexCondition {
  article_All(where: {AND: [
    {OR: [
      {title: {eq: "On Roasts"}},
      {title: {eq: "Donate with us"}},
    ]},
    {summary: {isEmpty: false}}
  ]}) {
    items {
      title
    }
  }
}

Paging

To paginate through collection fields, use the limit and offset arguments combined with the predefined totalCount field.
  • limit (Int) – Specifies the number of objects to retrieve. If not specified, the API returns up to 10 objects. The maximum limit value is 1,000.
  • offset (Int) – Specifies the number of objects to skip. If not specified, the offset is 0, and the API returns the first page of results.
GraphQL
# Paginating articles
query GetPaginatedArticles {
  article_All(limit: 10, offset: 10) {
    items {
      title
    }
    offset      # Returns the specified offset
    limit       # Returns the specified limit
    totalCount  # Returns the total number of content items that match the query
  }
}

# Paginating linked content in rich text
query GetPaginatedLinkedItems {
  article_All {
    items {
      bodyCopy {
        html
        linkedItems(offset: 10, limit: 10) {
          items {
            _system_ {
              codename
            }
          }
          offset      # Returns the specified offset
          limit       # Returns the specified limit
          totalCount  # Returns the total number of content items that match the query
        }
      }
    }
  }
}

Schemas

The GraphQL schema for your Kontent.ai environment is dynamically generated based on your content model. The schema is generated at request time and is always current. This also means that any changes to your content model will affect your GraphQL schemas.

How schema names are generated

The names of fields and types in your GraphQL schema are generated from the codenames of your content types, content type snippets, and the elements that define them. The original codename is stripped of underscores (_), converted to PascalCase, and used as a GraphQL name. For content type snippets, the converted codename is prefixed with an underscore. For date & time elements, the converted codename is suffixed with string _with_timezone. The GraphQL type names and field names must be unique. If two codenames lead to an identical GraphQL name, the GraphQL schema fails to build correctly. For example, the codenames button and button_ would lead to the same GraphQL name. In such case, adjust your codenames to avoid collisions.
Reserved field namesThe codenames of your types, snippets, or elements must not be one of the following: Array, Boolean, DateTime, Float, Guid, Int, String.
Examples of codename conversion to GraphQL names:
Original codenameGraphQL object type nameGraphQL query name
Content type articleArticle for single item Article_All for multiple items article for single item  article_All for multiple items
Content type fact_about_usFactAboutUs for single item FactAboutUs_All for multiple items factAboutUs for single item factAboutUs_All for multiple items
Content type snippet metadata_metadata for the GraphQL fieldNone. Elements under the content type snippet are available as subfields of the _metadata field.
Date & time element postDatepostDate_with_timezone for the GraphQL fieldNone. Data of the date & time element are available as subfields of the postDate_with_timezone field.

Collection fields

The collection fields in the GraphQL schema can hold objects such as content items, assets, taxonomy terms, linked items, and more. You can use filters and paging on the collection fields to specify what kind of objects you want.
GraphQL
type Article implements _Item {
  ...
  teaserImage(          # Asset element
    offset: Int!
    limit: Int!
    totalCount: Int!
  ): _AssetCollection!
  relatedArticles(      # Linked items element
    offset: Int!
    limit: Int!
    totalCount: Int!
  ): _ItemCollection!
  personas(             # Taxonomy element
    offset: Int!
    limit: Int!
    totalCount: Int!
  ): _TaxonomyTermCollection!
}
When retrieving lists of objects using collection fields, you need to specify the items field and at least one of its subfields. You can also specify the predefined totalCount field to find how many items the collection contains.
GraphQL
query HowToQueryCollectionFields {
  article_All {
    items {
      teaserImage {
        items {
          name
        }
        totalCount # Returns the total number of assets inserted in the asset element
      }
      personas {
        items {
          _system_ {
            codename
          }
        }
        totalCount # Returns the total number of selected taxonomy terms
      }
      relatedArticles {
        items {
          ... on Article {
            title
          }
        }
        totalCount # Returns the total number of items linked in the element
      }
    }
    totalCount # Returns the total number of articles matching the query
  }
}

Content items

Every GraphQL type for retrieving content items consists of the following fields:
  • The predefined _system_ field with the content item's metadata.
  • The individual fields for every content element as defined by the item's content type.
For example, the following is a GraphQL type for the content type named Article.
GraphQL
type Article implements _Item {
  _system_: _Sys!                         # The content item's metadata.
  title: String!                          # Text element
  teaserImage(                            # Asset element
    offset: Int = 0
    limit: Int = 10
  ): _AssetCollection!
  postDate_with_timezone: _DateAndTime    # Date & time element
  bodyCopy: _RichText!                    # Rich text element
  relatedArticles(                        # Linked items element
    offset: Int = 0
    limit: Int = 10
  ): _ItemCollection!
  personas(                               # Taxonomy element
    offset: Int = 0
    limit: Int = 10
  ): _TaxonomyTermCollection!
  urlPattern: String!                     # URL slug element
}

System metadata in the _system_ fields

Some of the GraphQL types come with the _system_ field. The _system_ field is defined by the _Sys type, which contains your content items' metadata. For example, the content item's last modification date, codename, and so on. The _Sys type is used in the GraphQL types generated from your content types.
GraphQL
type _Sys {
  name: String!     # The content item's display name.
  codename: String! # The content item's codename.
  language: _Language!  # Metadata of the content item's language.
  type: _ContentType!   # Metadata of the content item's content type.
  lastModified: DateTime! # ISO-8601 formatted date and time of the last change to user-content of the content item. The value is not affected when moving content items through workflow steps.
  collection: _Collection!      # Metadata of the content item's collection.
  workflow: _Workflow!  # Metadata of the content item's current workflow.
  workflowStep: _WorkflowStep!  # Metadata of the content item's current workflow step.
  id: Guid! # The content item's internal ID.
}

Partial system metadata

You'll also find the _system_ field in the predefined system GraphQL types such as _Language, _ContentType, _Collection, _Workflow, and _WorkflowStep. In these types, the _system_ field contains partial metadata such as the object's name or codename.
GraphQL
type _Collection {
  _system_: _CollectionSys! # The collection's predefined system fields.
}

type _CollectionSys {
  codename: String! # The collection's codename.
}

type _ContentType {
  _system_: _ContentTypeSys! # The content type's predefined system fields.
}

type _ContentTypeSys {
  name: String!     # The content type's display name.
  codename: String! # The content type's codename.
}

type _Language {
  _system_: _LanguageSys! # The language's predefined system fields.
}

type _LanguageSys {
  name: String!     # The language's display name.
  codename: String! # The language's codename.
}

type _Workflow {
  _system_: _WorkflowSys! # The workflow's predefined system fields.
}

type _WorkflowSys {
  codename: String! # The workflow's codename.
}

type _WorkflowStep {
  _system_: _WorkflowStepSys! # The workflow step's predefined system fields.
}

type _WorkflowStepSys {
  codename: String! # The workflow step's codename.
}

Content element schemas

Assets

Assets in asset elements

Copyright © 2026 Kontent.ai. All rights reserved.
  • Web
  • Privacy policy
  • Cookies policy
  • Consent settings
  • Security
  • GDPR