Skip navigation

Securing public access

When using the public Delivery API, you cannot use it to manage the user roles and their access to particular content in your application. With secure access enabled, you can protect your content by requiring an API key with each request and configuring content authorization in your app.

Premium feature

Secure access to the Delivery API requires a Business plan or higherOpens in a new window.

Table of contents

    Secure access to the Delivery API allows you to use two concurrent API keys, Primary and Secondary.

    Primary vs. Secondary key

    The following instructions work equally for both the Primary key and the Secondary key. Both API keys are generated per project and have no expiration date. For continuous use, we recommend using the Primary key. Use the Secondary key only when revoking the Primary key to prevent downtime.

    Enabling secure access

    Secure access to the Delivery API is disabled by default for new projects and you need to activate it. By activating the secure access, the system will also generate new API keys, Primary and Secondary.

    1. In Kentico Kontent, choose a project.
    2. From the app menu, choose .
    3. Under Development, choose API keys.
    4. In the Secure access box, toggle the Inactive switch to activate secure access.
    A screenshot of secure access enabled in a project.

    You will mainly use the Primary key to authenticate your requests. Both API keys are generated per project and have no expiration date. For more information, see secure access in our API reference.

    Getting your API key

    Every request to the Delivery API with secure access enabled must be authenticated with an API key. This key is unique to each project in Kentico Kontent.

    To get the key:

    1. In Kentico Kontent, choose a project.
    2. From the app menu, choose .
    3. Under Development, choose API keys.
    4. In the Secure access box, click .

    You can now use the key to authenticate your requests to the API.

    Authenticating requests

    Every request you make must come with an API key in the Authorization header. The Authorization header uses the following format: Authorization: Bearer <YOUR_API_KEY>

    Retrieving secured content

    Security tips

    Here are some quick tips to help you while using the secure access to the Delivery API:

    • Only regenerate one key at a time to prevent downtime.
    • Do not store API Keys in the source code.
    • Encrypt the key when storing it.
    • Regenerate your API keys periodically.
    • The older a key is, the higher the probability it could have been compromised.

    To retrieve a specific content item from Kentico Kontent via API, you need to use the project ID and the content item's codename in your request. See Getting content to find out how you can get these two values.

    The Delivery API uses the following URI to retrieve the published content:

    https://deliver.kontent.ai/<YOUR_PROJECT_ID>/

    Once you have the project ID and content item codename, you can retrieve the published content item.

    For example, to retrieve the content of an article named "My article", you can use the following request.

    • Java
    // Tip: Find more about Java/JavaRx SDKs at https://docs.kontent.ai/javaandroid import com.github.kentico.kontent_delivery_core.*; import com.github.kentico.kontent_delivery_rx.*; import io.reactivex.Observer; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Function; // Prepares the DeliveryService configuration object String projectId = "<YOUR_PROJECT_ID>"; String secureApiKey = "<YOUR_API_KEY>"; IDeliveryConfig config = DeliveryConfig.newConfig(projectId) .withSecuredApiKey(secureApiKey); // Gets the latest version of a content item using a simple request ContentItem item = deliveryService.<ContentItem>item("my_article") .get() .getItem(); // Gets the latest version of a content item using RxJava2 deliveryService.<ContentItem>item("my_article") .getObservable() .subscribe(new Observer<DeliveryItemResponse<ContentItem>>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(DeliveryItemResponse<ContentItem> response) { // Gets the content item ContentItem item = response.getItem(); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } });
    // Tip: Find more about Java/JavaRx SDKs at https://docs.kontent.ai/javaandroid import com.github.kentico.kontent_delivery_core.*; import com.github.kentico.kontent_delivery_rx.*; import io.reactivex.Observer; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Function; // Prepares the DeliveryService configuration object String projectId = "<YOUR_PROJECT_ID>"; String secureApiKey = "<YOUR_API_KEY>"; IDeliveryConfig config = DeliveryConfig.newConfig(projectId) .withSecuredApiKey(secureApiKey); // Gets the latest version of a content item using a simple request ContentItem item = deliveryService.<ContentItem>item("my_article") .get() .getItem(); // Gets the latest version of a content item using RxJava2 deliveryService.<ContentItem>item("my_article") .getObservable() .subscribe(new Observer<DeliveryItemResponse<ContentItem>>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(DeliveryItemResponse<ContentItem> response) { // Gets the content item ContentItem item = response.getItem(); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } });
    • Swift
    // Tip: Find more about Swift SDK at https://docs.kontent.ai/ios import KenticoKontentDelivery let client = DeliveryClient.init(projectId: "<YOUR_PROJECT_ID>", secureApiKey: "<YOUR_API_KEY>") // Create strongly typed models according to https://docs.kontent.ai/strongly-typed-models client.getItem(modelType: Article.self, itemName: "my_article") { (isSuccess, deliveryItem, error) in if isSuccess { if let article = deliveryItem.item { // Use your item here } } else { if let error = error { print(error) } }
    // Tip: Find more about Swift SDK at https://docs.kontent.ai/ios import KenticoKontentDelivery let client = DeliveryClient.init(projectId: "<YOUR_PROJECT_ID>", secureApiKey: "<YOUR_API_KEY>") // Create strongly typed models according to https://docs.kontent.ai/strongly-typed-models client.getItem(modelType: Article.self, itemName: "my_article") { (isSuccess, deliveryItem, error) in if isSuccess { if let article = deliveryItem.item { // Use your item here } } else { if let error = error { print(error) } }
    • Java
    // Tip: Find more about Java/JavaRx SDKs at https://docs.kontent.ai/java import com.github.kentico.kontent.delivery; DeliveryOptions options = new DeliveryOptions(); options.setProjectId("<YOUR_PROJECT_ID>"); options.setProductionApiKey("<YOUR_API_KEY>"); DeliveryClient client = new DeliveryClient(options); ContentItemResponse item = client.getItem("my_article");
    // Tip: Find more about Java/JavaRx SDKs at https://docs.kontent.ai/java import com.github.kentico.kontent.delivery; DeliveryOptions options = new DeliveryOptions(); options.setProjectId("<YOUR_PROJECT_ID>"); options.setProductionApiKey("<YOUR_API_KEY>"); DeliveryClient client = new DeliveryClient(options); ContentItemResponse item = client.getItem("my_article");
    • JavaScript
    // Tip: Find more about JS/TS SDKs at https://docs.kontent.ai/javascript const KontentDelivery = require('@kentico/kontent-delivery'); // Create strongly typed models according to https://docs.kontent.ai/strongly-typed-models class Article extends KontentDelivery.ContentItem { constructor() { super(); } } const deliveryClient = new KontentDelivery.DeliveryClient({ projectId: '<YOUR_PROJECT_ID>', globalQueryConfig: { useSecuredMode: true, // Queries the Delivery API using secure access. }, secureApiKey: '<YOUR_API_KEY>', typeResolvers: [ new KontentDelivery.TypeResolver('article', (rawData) => new Article) ] }); deliveryClient.item('my_article') .toObservable() .subscribe(response => console.log(response));
    // Tip: Find more about JS/TS SDKs at https://docs.kontent.ai/javascript const KontentDelivery = require('@kentico/kontent-delivery'); // Create strongly typed models according to https://docs.kontent.ai/strongly-typed-models class Article extends KontentDelivery.ContentItem { constructor() { super(); } } const deliveryClient = new KontentDelivery.DeliveryClient({ projectId: '<YOUR_PROJECT_ID>', globalQueryConfig: { useSecuredMode: true, // Queries the Delivery API using secure access. }, secureApiKey: '<YOUR_API_KEY>', typeResolvers: [ new KontentDelivery.TypeResolver('article', (rawData) => new Article) ] }); deliveryClient.item('my_article') .toObservable() .subscribe(response => console.log(response));
    • C#
    // Tip: Find more about .NET SDKs at https://docs.kontent.ai/net using Kentico.Kontent.Delivery; // Initializes a secured content delivery client IDeliveryClient client = DeliveryClientBuilder .WithOptions(builder => builder .WithProjectId("<YOUR_PROJECT_ID>") .UseProductionApi("<YOUR_API_KEY>") .Build()) .Build(); // Gets a specific content item // Create strongly typed models according to https://docs.kontent.ai/strongly-typed-models DeliveryItemResponse response = await client.GetItemAsync("my_article"); IReadOnlyList<ContentItem> items = response.Items;
    // Tip: Find more about .NET SDKs at https://docs.kontent.ai/net using Kentico.Kontent.Delivery; // Initializes a secured content delivery client IDeliveryClient client = DeliveryClientBuilder .WithOptions(builder => builder .WithProjectId("<YOUR_PROJECT_ID>") .UseProductionApi("<YOUR_API_KEY>") .Build()) .Build(); // Gets a specific content item // Create strongly typed models according to https://docs.kontent.ai/strongly-typed-models DeliveryItemResponse response = await client.GetItemAsync("my_article"); IReadOnlyList<ContentItem> items = response.Items;
    • PHP
    <?php // Tip: Find more about PHP SDKs at https://docs.kontent.ai/php // Defined by Composer to include required libraries require __DIR__ . '/vendor/autoload.php'; use Kentico\Kontent\Delivery\DeliveryClient; $client = new DeliveryClient('<YOUR_PROJECT_ID>', '<YOUR_API_KEY>'); $item = $client->getItem('my_article');
    <?php // Tip: Find more about PHP SDKs at https://docs.kontent.ai/php // Defined by Composer to include required libraries require __DIR__ . '/vendor/autoload.php'; use Kentico\Kontent\Delivery\DeliveryClient; $client = new DeliveryClient('<YOUR_PROJECT_ID>', '<YOUR_API_KEY>'); $item = $client->getItem('my_article');
    • cURL
    curl --request GET \ --url https://deliver.kontent.ai/<YOUR_PROJECT_ID>/items/my_article \ --header 'authorization: Bearer <YOUR_API_KEY>'
    curl --request GET \ --url https://deliver.kontent.ai/<YOUR_PROJECT_ID>/items/my_article \ --header 'authorization: Bearer <YOUR_API_KEY>'
    • Ruby
    # Tip: Find more about Ruby SDKs at https://docs.kontent.ai/ruby require 'delivery-sdk-ruby' delivery_client = Kentico::Kontent::Delivery::DeliveryClient.new project_id: '<YOUR_PROJECT_ID>', secure_key: '<YOUR_API_KEY>' delivery_client.item('my_article').execute do |response| item = response.item end
    # Tip: Find more about Ruby SDKs at https://docs.kontent.ai/ruby require 'delivery-sdk-ruby' delivery_client = Kentico::Kontent::Delivery::DeliveryClient.new project_id: '<YOUR_PROJECT_ID>', secure_key: '<YOUR_API_KEY>' delivery_client.item('my_article').execute do |response| item = response.item end
    • TypeScript
    // Tip: Find more about JS/TS SDKs at https://docs.kontent.ai/javascript import { ContentItem, DeliveryClient, Elements, TypeResolver } from '@kentico/kontent-delivery'; // Create strongly typed models according to https://docs.kontent.ai/strongly-typed-models export class Article extends ContentItem { public title: Elements.TextElement; public summary: Elements.TextElement; public post_date: Elements.DateTimeElement; public teaser_image: Elements.AssetsElement; public related_articles: Article[]; } const deliveryClient = new DeliveryClient({ projectId: '<YOUR_PROJECT_ID>', globalQueryConfig: { useSecuredMode: true // Queries the Delivery API using secure access. }, secureApiKey: '<YOUR_API_KEY>', typeResolvers: [new TypeResolver('article', (rawData) => new Article())] }); deliveryClient .item<Article>('my_article') .toObservable() .subscribe(response => console.log(response));
    // Tip: Find more about JS/TS SDKs at https://docs.kontent.ai/javascript import { ContentItem, DeliveryClient, Elements, TypeResolver } from '@kentico/kontent-delivery'; // Create strongly typed models according to https://docs.kontent.ai/strongly-typed-models export class Article extends ContentItem { public title: Elements.TextElement; public summary: Elements.TextElement; public post_date: Elements.DateTimeElement; public teaser_image: Elements.AssetsElement; public related_articles: Article[]; } const deliveryClient = new DeliveryClient({ projectId: '<YOUR_PROJECT_ID>', globalQueryConfig: { useSecuredMode: true // Queries the Delivery API using secure access. }, secureApiKey: '<YOUR_API_KEY>', typeResolvers: [new TypeResolver('article', (rawData) => new Article())] }); deliveryClient .item<Article>('my_article') .toObservable() .subscribe(response => console.log(response));

    After performing the request, you receive a single content item in the JSON format.

    • JSON
    { "item": { "system": { "id": "29b82988-fb9e-4327-a34b-b568cfaa39e9", "name": "My article", "codename": "my_article", "language": "en-US", "type": "article", "sitemap_locations": [], "last_modified": "2020-02-03T13:58:21.5779868Z" }, "elements": { "title": { "type": "text", "name": "Title", "value": "My article" }, "body_copy": { "type": "rich_text", "name": "Body", "images": {}, "links": {}, "modular_content": [], "value": "<p>Lorem ipsum dolor sit amet, aeque homero duo an, quo natum delectus an. Est vidit feugiat impedit id, quo ei elit antiopam, id tantas consetetur voluptatum ius. Iisque liberavisse ut vel, ornatus sensibus an nam, ne sonet tollit quo.</p>\n<p>Quo zril mediocrem ad, pro corpora petentium id, tale labore imperdiet id sed.</p>" }, "teaser_image": { "type": "asset", "name": "Teaser image", "value": [] }, "related_articles": { "type": "modular_content", "name": "Related articles", "value": [ "about_us" ] }, "author": { "type": "modular_content", "name": "Author", "value": [ "jane_doe" ] }, "...": "...more elements omitted for brevity" } }, "modular_content": { "...": "...more items omitted for brevity" } }
    { "item": { "system": { "id": "29b82988-fb9e-4327-a34b-b568cfaa39e9", "name": "My article", "codename": "my_article", "language": "en-US", "type": "article", "sitemap_locations": [], "last_modified": "2020-02-03T13:58:21.5779868Z" }, "elements": { "title": { "type": "text", "name": "Title", "value": "My article" }, "body_copy": { "type": "rich_text", "name": "Body", "images": {}, "links": {}, "modular_content": [], "value": "<p>Lorem ipsum dolor sit amet, aeque homero duo an, quo natum delectus an. Est vidit feugiat impedit id, quo ei elit antiopam, id tantas consetetur voluptatum ius. Iisque liberavisse ut vel, ornatus sensibus an nam, ne sonet tollit quo.</p>\n<p>Quo zril mediocrem ad, pro corpora petentium id, tale labore imperdiet id sed.</p>" }, "teaser_image": { "type": "asset", "name": "Teaser image", "value": [] }, "related_articles": { "type": "modular_content", "name": "Related articles", "value": [ "about_us" ] }, "author": { "type": "modular_content", "name": "Author", "value": [ "jane_doe" ] }, "...": "...more elements omitted for brevity" } }, "modular_content": { "...": "...more items omitted for brevity" } }

    You can limit the retrieved data, for example, retrieve only specific elements, by using optional query parameters. See the Delivery API reference to learn more about the available options and methods.

    Revoking the API keys

    In certain situations, you may need to revoke one of the API keys and generate a new one. For example, when you suspect unauthorized key usage or when a developer with access to the API key has left your company.

    For the reasons above, 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 code in the response.

    1. In Kentico Kontent, choose a project.
    2. From the app menu, choose .
    3. Under Development, choose API keys.
    4. Regenerate the Secondary key as this ensures it's new and secure.
    5. Change all applications using the secured Delivery API to use the newly regenerated Secondary key.
    6. Validate all applications using the Secondary key are functioning correctly.
    7. Regenerate the Primary key to make sure any unauthorized users cannot use this key to access the application.
    8. (Optional) Switch back to using the regenerated Primary key in all of your applications.

    The last step is optional as switching back to the regenerated Primary key might seem unnecessarily complicated. The reason behind this is simple – you can easily keep track of the API key you are currently using for your application. If you only use the Secondary key to prevent downtime when revoking the Primary key, it can keep things simple in the long run.