Loading...
Area: Optimizely Content Management API
Applies to versions: 2 and higher

API fundamentals

Recommended reading 

Below are common examples of how the Content Management API might be used. To keep the examples short, they generally favor using the integer-based content references instead of GUIDs. 

get/api/episerver/v2.0/contentGet content by given content url or by list of GUID/Reference with given language

Be aware:

  • The API implicitly uses the primary draft when changing and publishing content.
  • Manipulating personalization in content areas is not currently supported. For example, you cannot change or add a specific visitor group on a specific item in a content area via the Content Management API.
  • ContentReference in all endpoints should not include workID (for example, 5_5). An exception is thrown if workID is included.

A simple content sync

The simplest way to push content to the CMS is to assume the integration process always has right of way, and that no one else is making significant changes to the same part of the content tree. With these limitations in mind, objects can be upserted using PUT, which will pave over any existing content:/api/episerver/v2.0/contentmanagement/

put/api/episerver/v2.0/contentmanagement/{contentGuid}
curl --location --request PUT "http://<YOUR_DOMAIN>/api/episerver/v2.0/contentmanagement/7fa446db-6e02-41c5-9d3a-06e1b4d75cdf" ^ 
--header "Content-Type: application/json" ^
--header "Authorization: Bearer <AUTH_TOKEN>" ^
--data-raw "{'name': 'Alloy Track','language': {'name': 'sv'},'contentType':['ProductPage'],'parentLink': {'id': 5},'status': 'CheckedOut','metaTitle': {'value': 'Alloy Track Updated'},'uniqueSellingPoints': {'value': ['Shared timeline','Project emails','To-do lists','Workflows','Status reports']}}"

Relying on PUT makes sense since we assume free rein over all the content coming in. We can even publish straight from the API by specifying 'status' as Published if the external content is fit for publishing directly. Alternatively, leaving 'status' as CheckedOut will require manual action in the CMS or an additional API call to publish any changes. This endpoint can also be used to create an existing content item in a new specific language.

A smarter content sync

While upserts are nice and simple to work with, they are also a bit wasteful, since the entire object is sent even if just a single property was updated. If the integration client "knows" when an object in the source system is new or changed, and which properties were affected by a change, it is feasible to build a more efficient integration using POST and PATCH, instead of PUT.

A new content item is created by POSTing an object. This Post endpoint can be used to create an existing content item in a specific language (see Translating content below for more details).

post/api/episerver/v2.0/contentmanagement
curl --location --request POST "http://<YOUR_DOMAIN>/api/episerver/v2.0/contentmanagement" ^ 
--header "Content-Type: application/json" ^ 
--header "Authorization: Bearer <AUTH_TOKEN>" ^ 
--data-raw "{'name': 'Alloy Track','language': {'name': 'sv'},'contentType': ['ProductPage'],'parentLink': {'id': 5},'status': 'CheckedOut','metaTitle': {'value': 'Alloy Track SV'},'uniqueSellingPoints': {'value': ['Shared timeline','Project emails','To-do lists','Workflows','Status reports']}}" 

Changes to an existing object can be saved by PATCHing an object, which accepts a partial object, and only applies changes to the properties included in the payload. For example, if the title of a content object was changed, PATCH can specify just that one property in its payload. 

patch/api/episerver/v2.0/contentmanagement/{contentReference}
curl --location --request PATCH "http://<YOUR_DOMAIN>/api/episerver/v2.0/contentmanagement/116" ^
--header "Content-Type: application/json" ^
--header "Authorization: Bearer <AUTH_TOKEN>" ^
--data-raw "{'name': 'Alloy Track','language': {'name': 'en'},'metaTitle': {'value': 'Alloy Track Patched'}}"

Note:

  • It is only possible to PATCH values for culture invariant properties in the master language. That means if you want to update a content in a specific language other than master language, then you must ommit culture invariant properties.
  • Should only pass Language in the request body if the content type is localizable.
  • Route segment can only be set for the content that is IRoutable.
  • StartPublish, StopPublish, or Status can only be set for content that is versionable.
  • StartPublish must be set when content item is set for scheduled publishing.
  • Ignore validation of content by setting the the header x-epi-validation-mode to minimal.

Translating content

When translating content to another language it might be useful to first GET the object in the source language and use that as a template object for the translated content. In addition to Read privilege, clients need to have at least one more privilege higher than Read to be able to use this endpoint. 

get/api/episerver/v2.0/contentmanagement/{contentReference}
curl --location --request GET "http://<YOUR_DOMAIN>/api/episerver/v2.0/contentmanagement/116" ^
--header "Authorization: Bearer <AUTH_TOKEN>" ^

Language variations of content are treated as separate content objects with shared culture invariant properties. That means a newly translated object is POSTed and should specify the correct target language.

post/api/episerver/v2.0/contentmanagement
curl --location --request POST "http://<YOUR_DOMAIN>/api/episerver/v2.0/contentmanagement/116" ^
--header "Content-Type: application/json" ^
--header "Authorization: Bearer <AUTH_TOKEN>" ^
--data-raw "{'name': 'Alloy Track','language': {'name': 'sv'},'contentType': ['ProductPage'],'parentLink': {'id': 5},'status': 'CheckedOut','metaTitle': {'value': 'Alloy Track SV'},'uniqueSellingPoints': {'value': ['Shared timeline','Project emails','To-do lists','Workflows','Status reports']}}"

Note:

  • It is only possible to set values for non-branch specific properties in the master language. When translating content you should ommit culture invariant properties.

Moving content

The location of content in the content tree is not a mutable property of the content object. Instead of PUTting or PATCHing the object location, a separate endpoint lets you move content to another location in the hierarchy. 

post/api/episerver/v2.0/contentmanagement/{contentGuid}/move
curl --location --request POST "http://<YOUR_DOMAIN>/api/episerver/v2.0/contentmanagement/116/move" ^
--header "Content-Type: application/json" ^
--header "Authorization: Bearer <AUTH_TOKEN>" ^
--data-raw "{'parentLink': {'id': 6},'routeSegment': 'new-segment'"}

Note:

  • System content items such as RootPage and GlobalAssetsRoot cannot be moved.

Deleting content

Content can be trashed or permanently deleted from the API by issuing a DELETE request. Which moves content to the content trash bin. Requesting a DELETE for an object already in the trash will permanently delete it with set the param X-Epi-Permanent-Delete on the header request is true. For simplicity, you can skip the trash bin and permanently delete an object by including the x-epi-permanent-delete header.

delete/api/episerver/v2.0/contentmanagement/{contentReference}
curl --location --request DELETE "http://<YOUR_DOMAIN>/api/episerver/v2.0/contentmanagement/115" ^
--header "Authorization: Bearer <AUTH_TOKEN>"

Note:

  • System content such as RootPage and GlobalAssetsRoot cannot be deleted.
      Do you find this information helpful? Please log in to provide feedback.

      Last updated: Apr 20, 2021

      Recommended reading