Skip navigation

Delivery REST API

Download OpenAPI specification:Download


The Delivery API is a read-only REST API that serves published content from your projects.

Use the Delivery API to deliver large amounts of content to your website or app. Your content is cached in a CDN, which makes the content quickly available from wherever you are. The API provides content filtering that you can use to retrieve just the parts of content you need.

All requests to the API must be made securely over HTTPS with TLS 1.2.

Production vs. Preview

You can work with the Delivery REST API in two modes:

  • Production – Get the published versions of content items.
  • Preview – Get the latest versions of content items. The latest version can come from both published and unpublished content items.

In both cases, you use the same endpoints to request data but with a different base URL.

To retrieve published content items from your project, use the production URL:<YOUR_PROJECT_ID>/items

Protect your content

The Delivery API is public by default. To protect your published content, use the Delivery API with secure access enabled.

To preview latest version of your content items from your project, use the preview URL:<YOUR_PROJECT_ID>/items

If you want to preview the latest version of your content, you need to authorize your request.

  • JavaScript
// Tip: Find more about JS/TS SDKs at const KontentDelivery = require('@kontent-ai/delivery-sdk');   const deliveryClient = KontentDelivery.createDeliveryClient({ projectId: '<YOUR_PROJECT_ID>', previewApiKey: '<YOUR_PREVIEW_API_KEY>', defaultQueryConfig: { usePreviewMode: true, // Queries the Delivery Preview API. } });   const response = await deliveryClient.item('my_article') .toPromise();
  • TypeScript
// Tip: Find more about JS/TS SDKs at import { IContentItem, createDeliveryClient, Elements } from '@kontent-ai/delivery-sdk';   // Create strongly typed models according to export type Article = IContentItem<{ title: Elements.TextElement; summary: Elements.RichTextElement; post_date: Elements.DateTimeElement; teaser_image: Elements.AssetsElement; related_articles: Article[]; }>;   const deliveryClient = createDeliveryClient({ projectId: '<YOUR_PROJECT_ID>', previewApiKey: '<YOUR_PREVIEW_API_KEY>', defaultQueryConfig: { usePreviewMode: true, // Queries the Delivery Preview API. }, });   const response = await deliveryClient.item<Article>('my_article') .toPromise();
  • C#
// Tip: Find more about .NET SDKs at using Kontent.Ai.Delivery;   // Initializes a delivery client for previewing content IDeliveryClient client = DeliveryClientBuilder .WithOptions(builder => builder .WithProjectId("<YOUR_PROJECT_ID>") .UsePreviewApi("<YOUR_PREVIEW_API_KEY>") .Build()) .Build();   // Generate strongly typed models via IDeliveryItemResponse<Article> response = await client.GetItemAsync<Article>("my_article"); Article item = response.Item;
  • PHP
// Tip: Find more about PHP SDKs at // Defined by Composer to include required libraries require __DIR__ . '/vendor/autoload.php';   use Kontent\Ai\Delivery\DeliveryClient;   $client = new DeliveryClient('<YOUR_PROJECT_ID>', '<YOUR_PREVIEW_API_KEY>');   $item = $client->getItem('my_article');
  • Java
// Tip: Find more about Java SDK at import*;   // Initializes a Delivery client for preview DeliveryClient client = new DeliveryClient( DeliveryOptions.builder() .projectId("<YOUR_PROJECT_ID>") .previewApiKey("<YOUR_PREVIEW_API_KEY>") .usePreviewApi(true) .build() );   // Registers the model class for articles // Tip: Create strongly typed models according to client.registerType(Article.class);   // Gets an article CompletionStage<Article> article = client.getItem("my_article", Article.class);
  • Ruby
# Tip: Find more about Ruby SDKs at require 'delivery-sdk-ruby'   delivery_client = project_id: '<YOUR_PROJECT_ID>', preview_key: '<YOUR_PREVIEW_API_KEY>' delivery_client.item('my_article').execute do |response| puts response.to_s end
  • cURL
curl --request GET \ --url<YOUR_PROJECT_ID>/items/my_article \ --header 'authorization: Bearer <YOUR_PREVIEW_API_KEY>'

For the Delivery Preview API, you can use two concurrent API keys, Primary and Secondary. For more details on how to work with content preview, see configuring preview.


By default, the Delivery API does not require authentication. However, if you enable secure access for the Delivery API or use the Delivery Preview API, you need to authenticate your requests with valid API keys.

To get data from the Delivery API with secure access enabled or the Delivery Preview API, send your requests over HTTPS using the Authorization header in the following format: Authorization: Bearer <YOUR_API_KEY>. Requests with an incorrect or missing Authorization header will fail with an error.

To get your API key, go to > Project settings > API keys. The API keys provide access to a single project. You will need different API keys for each of your projects.

Try the API with Postman

Try out any of the APIs with Postman! 📫 The Postman collection is regularly updated and contains endpoints for all APIs, just like in the API references.


We offer the following SDKs to help you interact with Delivery API. However, you don't need an SDK to use the API.

If you want to create your own SDK, see our guidelines for SDK developers.

How the API caches your content

The Delivery API uses Fastly as its Content Delivery Network (CDN). The CDN stores responses to every successful API request in the CDN's cache.

Your first request to the Delivery API is uncached. Such request goes through the CDN directly to the Delivery API. The response from the Delivery API is then stored in the CDN. If you repeat the same request, you get a cached response from the CDN.

The response stays in the cache for as long as the requested content in your project stays the same. If the content changes, the cached response is removed from the cache.

For example, if you request a content item A from the API, you get a response with the contents of content item A and its linked items. That response with content item A is cached in the CDN. If you make changes to content item A, the cached response is removed from the cache. If the CDN had previously cached other responses that contained content of content item A, these responses are removed from the cache as well.

API limitations

API requests limit

Requests made to the Delivery API count towards the overall API Calls limit set in our Fair Use Policy.

Requests made to the Delivery Preview API, which lets you preview unpublished content, do NOT count towards the API Calls limit.

Change processing time

The Delivery API processes changes to your content items in sequential order, one after another. In high-volume scenarios, this can lead to delays between making a change and seeing the results of that change in the API. See the following example scenarios for details.

Example A: Editing and publishing content items

If you publish a content item, the API processes this change in a few seconds. When publishing larger amounts of content, there can be a delay in availability of that content in the API.

For example, if you publish 100 content items, the first item will be available a few minutes sooner than the last one.

Example B: Editing content types

When you change a content type, the API needs to process all content items based on that type. If your changes affect hundreds or thousands of content items, the API recalculates the content of each item. While this is happening, any new changes to content items need to wait before being processed by the API.

For example, imagine you have an Article content type with 100,000 content items based on that type. If you add an element to the content type, the API goes through the items and begins updating their content. Given the high number of items, this process can take up to a few hours.

Until the API finishes processing the Article items, any subsequent content changes need to wait. If you publish a content item right after modifying the Article content type, the published item appears in the API only after the type change was fully processed.

Example C: Changing project localization settings

We strongly recommend against changing language codenames on live projects with lots of content. This action might lead to temporary inconsistencies that might affect content in your web app.

If you change a project language's codename, the API needs to process all items that have content in that language. Until this change is fully processed, the API might return some items with the old language codename and some items with the new language codename.

Rate limitation

Rate limits specify the number of requests you can make to the Delivery API within a specific time window.

For cached requests served from our CDN, we don't enforce any rate limits. These are repeated requests for cached data. You can make an unlimited number of requests to the CDN.

For uncached requests that reach the Delivery API, we enforce a rate limitation of 100 requests per second and 2000 requests per minute. These are unique requests for uncached data.

When you reach the rate limit, 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.

Response size

When you request a single content item or list of items, the Delivery API limits the maximum number of items returned within a response to 2000 items. This number covers both the items that directly match the specified query and the linked items returned in the response's modular_content property.

You can find whether your requests are close to the limit by looking at the X-Request-Charge header.

If the X-Request-Charge value of your requests exceeds 1000, we recommend applying more specific filters and checking if a lower value for the depth parameter works for you. Fewer items returned per response means shorter response times and better performance for your app.


The 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 incorrect API key), and status codes in the 5xx range indicate an error on our side.

HTTP status codes summary

Status code


400 Bad Request

The request was not understood. Check your request for a missing required parameter or an invalid query parameter value.

401 Unauthorized

The provided API key is invalid or missing.

403 Forbidden

The provided API key is invalid for the requested project.

404 Not Found

The requested resource doesn't exist. Try checking the resource name for typos.

405 Method Not Allowed

The requested HTTP method is not supported for the specified resource.

429 Too Many Requests

The rate limit for the API has been exceeded. Try your request again after a few seconds as specified in the Retry-After header.

5xx Internal Error or Service Unavailable

Something went wrong on our side. Try your request again after a few seconds and use a retry policy.

Resolving errors

For troubleshooting failed requests, the API provides error messages defined in a consumable format to help you identify and fix the issue.


The error message explaining what caused the error.

string Nullable

The performed request's unique ID.

integer <int32> [ 1 .. 500 ]

The internal error code for the type of error. Used for finding patterns among error requests.

integer <int32>

Only useful for finding reasons behind failed requests in specific cases.

Expand all Collapse all
  • "message": "The continuation token specified in the 'X-Continuation' request header is malformed.",
  • "request_id": "d9b4b4e4750ee210",
  • "error_code": 107,
  • "specific_code": 0

If you cannot identify and resolve an issue with your API call, you can contact us with the response status and the request ID you get in the error response.

Secure access

By default, the Delivery API does not require authentication. This means your assets and published content items are publicly available.

You can enable secure access for your project to require authenticated requests. You'll then need to use an API key when getting content items.

Because the Delivery API is designed for continuous retrieval of published content, there is no expiration date for the Primary or Secondary API keys. The API keys are scoped per project. This means you need a separate API key for each project in All users within a single project share the same Delivery API keys.

If you have advanced asset management, you can also set up secure assets for your project. For more details, check how to restrict public access.

Revoking API keys

The Delivery API with secure access enabled and the Delivery Preview API both use two concurrent API keys, Primary and Secondary. In certain situations, you may need to revoke one of these keys and generate a new one. For example, when you suspect unauthorized key use or when a developer with access to the API key has left your company.

For situations like these, one or both of the API keys can be regenerated. Generating a new key will replace the old key. This process can take up to a couple of minutes. Requests made with a revoked API key will then receive a 401 Unauthorized HTTP status in the response.

Keep your API keys secure

There is no expiration date for the Primary or Secondary API key. However, we recommend that you regenerate the API keys periodically to prevent the keys from being compromised.

Learn more in Securing public access and Configuring content preview.

Filtering content

When getting content items, you can filter your items by building query parameters from content elements and system properties. Check our tutorial on filtering content items, which covers the basic use of common filtering parameters. Or read on for a deep dive.

Filtering does not apply to content items returned in the modular_content object property.

If you want to get only a specific set of elements from content items, use projection.

Filtering by system values

To filter by system property values, you need to use a query parameter in the system.<property_name> format. The system properties are id, collection, name, codename, language, type, last_modified, and workflow_step. For example, to retrieve only content items based on the Article content type, use system.type=article as a query parameter.

Filtering by element values

To filter by content element values, you need to use a query parameter in the elements.<element_codename>=<value> format. For example, to retrieve only content items whose number element named Price has a value of 16, use elements.price=16 as a query parameter.

Joining multiple query parameters

You can join multiple query parameters using the & character. Queries with two or more filtering parameters are more restrictive because the individual query parameters are merged with a logical conjunction (AND).

For example, the query system.type=article&elements.category[contains]=nature will return Article content items tagged with the term Nature.

Filtering operators

You can use the following filtering operators with both the system properties and element values.

All operators are case-sensitive.




Use with

[eq](same as =)

Property value equals the specified value.



Simple types


Property value does not equal the specified value.



Simple types


Property value is empty.


For rich text, use the equals operator, elements.content[eq]=<p><br></p>.

Simple types and arrays


Property value is not empty.


Simple types and arrays


Property value is less than the specified value.
More in Comparing values.


Simple types


Property value is less than or equal to the specified value.
More in Comparing values.


Simple types


Property value is greater than the specified value.
More in Comparing values.


Simple types


Property value is greater than or equal to the specified value.
More in Comparing values.


Simple types


Property value falls within the specified range of two values, both inclusive.
More in Comparing values.


Simple types


Property value is in the specified list of values.


Simple types


Property value is not in the specified list of values.


Simple types


Property with an array of values contains the specified value.
The [contains] operator cannot be used on strings.





Property with an array of values contains at least one value from the specified list of values.




Property with an array of values contains all of the specified values.



Arrays vs. simple types

You can use the [contains], [any], and [all] filtering operators only on arrays. The content elements that support these operators are custom elements (see limitations below), linked items, multiple choice, and taxonomy.

For custom elements, the [contains], [any], and [all] filters work only if the element's value is a stringified array of strings such as "[\"DE\",\"US\",\"UK\"]". The [contains], [any], and [all] operators can NOT be used on asset elements.

Comparing values

The [lt], [lte], [gt], [gte], and [range] filtering operators work best with numbers. For example, you can retrieve products with price larger or equal to 15 by using elements.price[gte]=15.

Filtering by date-time values

Properties that store dates are represented as strings. For example, this includes the last_modified system property and date & time content elements.

If you use filtering operators on properties with string values, the Delivery API tries to perform a string comparison. For instance, you can retrieve content items modified during February and March by using a query such as system.last_modified[range]=2020-02-01,2020-04-01, specifying the start date within the range and end date outside the range.


When getting content items or content types, you can specify which elements to return by using the elements query parameter.

  • For items, the parameter applies to content items returned within both the items array and modular_content object property.
  • For types, the parameter applies to content types returned within the types array.


By using elements=title as a query parameter, the elements property in each content item will contain only the element with the codename title, or, if the item doesn't have an element with such codename, the elements property will be empty.

For multiple elements, you can use a query parameter such as elements=title,summary,related_articles to retrieve only the elements with codenames title, summary, and related_articles.

Excluding the system properties

Projection does not apply to the system properties. This means that you cannot omit the system object from the response using any query.

Linked content and components

With the platform, you can compose and structure your content using rich text and linked items elements.

  • Linked items elements are used to reference other content items.
  • Rich text elements are used to compose your content with text, images, components, and content items. Components and content items are useful for inserting structured content into a specific point in the text.

Components 101

Rich text elements can contain components.

  • A component is a single-use content item.
  • It has the same structure as a content item.
  • Unlike a content item, a component only exists inside its rich text element.
  • It is based on a specific content type.

Retrieve linked content

When retrieving items using the Delivery API, the contents of all components and content items in the rich text and linked items elements are stored in the modular_content object property of the API response.

When enumerating the items in your project using the Delivery API, the modular_content object property will contain only components, not content items used in linked items elements.

The contents of modular_content, that is the individual components and content items, are not ordered. See linked items and rich text elements for details on how ordering is done within the elements.

For historical reasons, the property is called "modular_content" instead of "linked_content".

Linked content depth

Content items can reference other content items using linked items or rich text elements. These linked items can reference other items recursively. By default, the API returns only one level of linked items.

  • To include more than one level of linked items in response, set the depth query parameter to 2 or more.
  • To exclude all linked items, set the depth query parameter to 0.

When retrieving content, linked items cannot be filtered.

Components are not affected by the depth query parameter as they are an integral part of their rich text element. Components are always present in the API response. Components can be nested up to six levels deep.

Content items

Content items represent specific pieces of content based on a specific content type. To retrieve specific items from your project, either provide a codename for one item or filter all items using parameters. By default, the Delivery API returns content items in the default language.

Content item object


The content item's system properties.


The item's elements with values for the specific language.

The order of the element objects might not match the content element order in the UI.

Expand all Collapse all
  • "system":
    • "id": "335d17ac-b6ba-4c6a-ae31-23c1193215cb",
    • "collection": "default",
    • "name": "My article",
    • "codename": "my_article",
    • "language": "en-US",
    • "type": "article",
    • "sitemap_locations": [ ],
    • "last_modified": "2019-03-27T13:21:11.38Z",
    • "workflow_step": "published"
  • "elements":

List content items

See full URL

Delivery API{project_id}/items

Delivery Preview API{project_id}/items

Retrieve a list of content items from your project. By default, the API returns an unfiltered paginated list of content items ordered alphabetically by codename. The response size is limited to 2000 items.

The modular_content object property will contain both components and linked items in the API response. See Linked content and components for more details.

If you need to export all content items from your project, we recommend using the Enumerate content items endpoint.

You can change the order by specifying the order query parameter. You can customize pagination by specifying both the skip and limit query parameters. Note that the limit parameter affects only the items property, not modular_content.

Get only the items you need

To retrieve specific content items, use the filtering parameters in your requests. For example, you can request items tagged with a taxonomy term, items of a specific type, or items modified in the past three days.

path Parameters

Identifies your project.

If you're using environments, the project ID becomes environment ID and specifies one of the project's environments.

query Parameters

Determines which language variant of content items to return. By default, the API returns content in the default language.

If the requested content is not available in the specified language variant, the API follows the language fallbacks as configured in the Localization settings of your project.