Sync API is a secure REST API that provides read-only access to your Kontent.ai environment.
Use Sync API to keep content in your apps up to date. Sync API lets you know if your content changed in Delivery API or Delivery Preview API.
Use Sync API to update content in your apps. Sync API can be especially useful if you need to:
Both webhooks and Sync API are tools to react to changes in your live and preview content. You can use them together or separately.
Webhooks give you real-time notifications about changes in your content items. Webhooks are great if you need immediate updates. For example, when reporting the latest news or advancements in a sports match. However, immediate updates also mean your app must always be available to process those updates quickly and respond to them. This might be an issue if your app receives a lot of webhook notifications at once.
With Sync API, you get a list of recently changed content. These can be changes to content items, content types, languages, or taxonomy groups. You call Sync API in intervals that fit your use case and process the content changes as necessary.
Sync API is built on top of Delivery REST API. If you enable secure access for Delivery REST API or want to sync changes in preview content, you need to authenticate your synchronization requests with a valid Delivery API key.
If your use case requires authentication, send your sync requests over HTTPS and use the Authorization
header in the following format: Authorization: Bearer <YOUR_API_KEY>
. To create and manage your API keys, go to Kontent.ai > Project settings > API keys. Requests with an incorrect or missing Authorization
header will fail with an error.
Try the Kontent.ai APIs in Postman collection! Our Postman collection is regularly updated and contains endpoints for all Kontent.ai APIs.
We recommend that you fork the Kontent.ai APIs collection. Forking lets you stay up to date by pulling updates when needed.
Once you import the collection, you can start sending requests. Make sure to use environment variables for API keys.
Postman environments are sets of variables with specific values. You can use these variables everywhere in your requests in Postman.
For instance, the Kontent.ai APIs collection comes with an environment called Kontent.ai APIs sample values. The environment specifies a variable named environment_id
, which is used in all requests. To get started quickly, we recommend you change the environment_id
value to the ID of your own environment.
You can synchronize your changes via the JavaScript Delivery SDK or .NET Delivery SDK. 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.
Sync API works on top of Delivery API. Sync requests for changes in published and unpublished content, i.e., Delivery API and Delivery Preview API, count towards the overall API Calls limit set in our Fair Use Policy or your subscription plan.
There is no limit on the total number of API calls you can make.
Rate limits specify the number of requests you can make to Sync 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.
For uncached requests that reach Sync 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.
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.
Status code | Description |
---|---|
400 Bad Request |
The request was not understood. Check if your request is missing a required parameter or contains an invalid query parameter value. |
401 Unauthorized |
The provided API key is doesn't provide access to the requested resource. The error can also occur if the API key is malformed or missing. Try copying and pasting your current API key to avoid typos. |
403 Forbidden |
The provided API key is valid but doesn't provide permission for the specified resource. |
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. |
For troubleshooting failed requests, the API provides error messages defined in a consumable format to help you identify and fix the issue.
Error object in Delivery API.
message required | string The error message explaining what caused the error. |
request_id | string or null The performed request's unique ID. |
error_code | integer <int32> [ 1 .. 500 ] The internal error code for the type of error. Used for finding patterns among error requests. |
specific_code | integer <int32> Only useful for finding reasons behind failed requests in specific cases. |
{- "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.
The state of the Sync API may change in the future. However, the majority of the changes won't be breaking changes.
To create more robust scripts and integrations, we recommend you get familiar with the list of general changes to the API that aren't considered breaking. Make sure your app doesn't rely on a state that might change in the future. In general, the non-breaking changes include adding functionality or changes in the order of the returned data.
The following are NOT breaking changes:
When you synchronize changes, you get a list of delta updates for each entity that has been changed or deleted since the last synchronization. A delta update is similar to a webhook notification, it provides metadata about the changed entity.
When you receive updates from the Sync API, the response contains only the system
property for each entity, and you can use further Delivery API calls to get more information.
Sync API sends only the last change type
For example, when a content item has been changed and then deleted, you only get change_type: "deleted"
in the Sync API response, not the previous changes.
Synchronize recent changes in your content items by following these steps:
X-Continuation
token from the initialization response. This token identifies your content synchronization.X-Continuation
token.X-Continuation
token from the sync response.When there aren’t any more changes to synchronize, you should wait a while before synchronizing again (step 3). The wait time depends on your use case. It can be five minutes, an hour, or a day.
Metadata specifying a content item in a specific language and the time of the item's last change.
change_type required | string Determines whether the content item was modified or deleted since the last synchronization.
| ||||||
timestamp required | string ISO-8601 formatted date and time in UTC of the last change to the content item. The timestamp identifies when the change occurred in Delivery API. | ||||||
required | object The affected content item's metadata. |
{- "change_type": "changed",
- "timestamp": "2025-06-20T13:03:06.1310204Z",
- "data": {
- "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": "default",
- "workflow_step": "published"
}
}
}
Metadata specifying a content type and the time of the type's last change.
change_type required | string Determines whether the content type was modified or deleted since the last synchronization.
| ||||||
timestamp required | string <date-time> ISO-8601 formatted date and time in UTC of the last change to the content type. The timestamp identifies when the change occurred in Delivery API. | ||||||
required | object The affected content type's metadata. |
{- "change_type": "changed",
- "timestamp": "2025-06-20T13:03:06.1310204Z",
- "data": {
- "system": {
- "id": "b2c14f2c-6467-460b-a70b-bca17972a33a",
- "name": "Article",
- "codename": "article",
- "last_modified": "2019-10-20T12:03:17.4685693Z"
}
}
}
Metadata specifying a language and the time of its last change.
change_type required | string Determines whether the language was modified or deactivated since the last synchronization.
| ||||||
timestamp required | string <date-time> ISO-8601 formatted date and time in UTC of the last change to the language. The timestamp identifies when the change occurred in Delivery API. | ||||||
required | object The metadata of the affected language. |
{- "change_type": "changed",
- "timestamp": "2025-06-20T13:03:06.1310204Z",
- "data": {
- "system": {
- "id": "00000000-0000-0000-0000-000000000000",
- "name": "Default language",
- "codename": "default"
}
}
}
Metadata specifying a taxonomy group and the time of its last change.
change_type required | string Determines whether the taxonomy group was modified or deleted since the last synchronization.
| ||||||
timestamp required | string <date-time> ISO-8601 formatted date and time in UTC of the last change to the taxonomy group. The timestamp identifies when the change occurred in Delivery API. | ||||||
required | object The affected taxonomy group's metadata. |
{- "change_type": "changed",
- "timestamp": "2025-06-20T13:03:06.1310204Z",
- "data": {
- "system": {
- "id": "f30c7f72-e9ab-8832-2a57-62944a038809",
- "name": "Programming language",
- "codename": "programming_language",
- "last_modified": "2019-08-31T09:41:06.520241Z"
}
}
}
Initializes synchronization of changes in all of the supported entities. After the initialization, you’ll get the X-Continuation
token found in the HTTP headers. Use the token to synchronize changes in the entities.
You can follow the rest of the steps on how to sync changes.
Content synchronization was initialized.
// Tip: Find more about .NET SDKs at https://kontent.ai/learn/net using Kontent.Ai.Delivery; // Tip: Use DI to create Delivery client https://kontent.ai/learn/net-register-client IDeliveryClient client = DeliveryClientBuilder .WithEnvironmentId("KONTENT_AI_ENVIRONMENT_ID") .Build(); // Gets the continuation token based on the given parameters IDeliverySyncV2Response response = await client.PostSyncV2InitAsync() string continuationToken = response.ApiResponse.ContinuationToken;
{- "items": [ ],
- "types": [ ],
- "languages": [ ],
- "taxonomies": [ ]
}
Retrieve a list of delta updates to recently changed entities.
You can follow the rest of the steps on how to sync changes.
X-Continuation required | string Determines which content changes to synchronize next. You get a new Example: G3sAAMTSTeVP97uW0ag9FMER8iRdLEnvTPtQG9jumJHh9Twl6xfy6zqQVMbSKJdIKWhrxjCOc5Jg8IWRoaV2JB3pWEiXjckqcCODtSqVYFiP+10eZIBhMTdkaC7xAw== |
Delta updates of entities that changed since previous sync.
The provided continuation token is invalid.
// Tip: Find more about .NET SDKs at https://kontent.ai/learn/net using Kontent.Ai.Delivery; // Tip: Use DI to create Delivery client https://kontent.ai/learn/net-register-client IDeliveryClient client = DeliveryClientBuilder .WithEnvironmentId("KONTENT_AI_ENVIRONMENT_ID") .Build(); // Gets a list of recently changed content items IDeliverySyncResponse response = await client.GetSyncV2Async("KONTENT_AI_CONTINUATION_TOKEN"); IList<ISyncV2Item> syncItems = response.SyncItems; IList<ISyncV2ContentType> syncTypes = response.SyncTypes; IList<ISyncV2Taxonomy> syncTaxonomies = response.SyncTaxonomies; IList<ISyncV2Language> syncLanguages = response.SyncLanguages;
{- "items": [
- {
- "change_type": "changed",
- "timestamp": "2025-05-28T05:33:58.6348403Z",
- "data": {
- "system": {
- "id": "79eab20c-f4b6-4a93-bf01-17096cbfa765",
- "name": "Test content item",
- "codename": "content_item",
- "language": "default",
- "type": "child",
- "collection": "default",
- "last_modified": "2025-05-27T10:20:07.0340165Z",
- "workflow": "default",
- "workflow_step": "published"
}
}
}, - {
- "change_type": "deleted",
- "timestamp": "2025-05-28T09:11:42.3361261Z",
- "data": {
- "system": {
- "id": "79807741-234f-47c4-aec0-102a97c9779b",
- "name": "Child",
- "codename": "child",
- "language": "default",
- "type": "child",
- "collection": "default",
- "last_modified": "2025-03-04T10:17:19.8445811Z",
- "workflow": "default",
- "workflow_step": "published"
}
}
}
], - "types": [
- {
- "change_type": "changed",
- "timestamp": "2025-05-28T09:10:46.2792473Z",
- "data": {
- "system": {
- "id": "ebf65f57-a572-4586-9c85-03022db35bcc",
- "name": "Type",
- "codename": "type",
- "last_modified": "2025-05-28T09:10:43.9856679Z"
}
}
}
], - "taxonomies": [
- {
- "change_type": "changed",
- "timestamp": "2025-05-28T09:10:58.9337234Z",
- "data": {
- "system": {
- "id": "b34b9c8c-c80f-4516-9077-b17b69d9e381",
- "name": "Taxonomy",
- "codename": "taxonomy",
- "last_modified": "2025-05-28T09:10:58.0433607Z"
}
}
}
], - "languages": [
- {
- "change_type": "deleted",
- "timestamp": "2025-05-28T09:11:28.7212524Z",
- "data": {
- "system": {
- "id": "bf6678d8-b856-4a33-8b52-36401ed7ac59",
- "name": "English",
- "codename": "english"
}
}
}
]
}