HomeGuidesAPI Reference
Submit Documentation FeedbackJoin Developer CommunityOptimizely GitHubOptimizely NuGetLog In

Content Management API fundamentals

This topic describes 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/v3.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, you can use PUT to upsert objects, which will pave over existing content: /api/episerver/v3.0/contentmanagement/

PUT/api/episerver/v3.0/contentmanagement/{contentGuid}
curl --location --request PUT "http://<YOUR_DOMAIN>/api/episerver/v3.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']}}"

You can rely on PUT to control the incoming content, and specify Published status from the API to publish the content directly. Using the default Checkout status requires another manual or API action to publish changes. You can use the endpoint to create an existing content item in a new specific language.

A smarter content sync

Upserts are easy to work with but can be wasteful when an entire object is sent even when a single property is updated. You can build a more efficient integration with POST and PATCH (instead of PUT) to determine when an object is new or changed (and which properties were changed) in the source system.

You create a new content item by POSTing an object. Use this POST endpoint to create an existing content item in a specific language. See Translating content below for more details.

POST/api/episerver/v3.0/contentmanagement
curl --location --request POST "http://<YOUR_DOMAIN>/api/episerver/v3.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']}}"

Save changes to an existing object 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/v3.0/contentmanagement/{contentReference}
curl --location --request PATCH "http://<YOUR_DOMAIN>/api/episerver/v3.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'}}"

πŸ“˜

Notes

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

Translating content

When translating content to another language, you should first GET the object in the source language and use that as a template object for the translated content. To use this endpoint, clients must have at least one more privilege higher than Read privilege.

GET/api/episerver/v3.0/contentmanagement/{contentReference}
curl --location --request GET "http://<YOUR_DOMAIN>/api/episerver/v3.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/v3.0/contentmanagement
curl --location --request POST "http://<YOUR_DOMAIN>/api/episerver/v3.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

You can set values only for non-branch-specific properties in the master language. When translating content you should omit culture invariant properties.

Moving content

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

POST/api/episerver/v3.0/contentmanagement/{contentGuid}/move
curl --location --request POST "http://<YOUR_DOMAIN>/api/episerver/v3.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

The DELETE request places content in the trash. If you use a DELETE request on content already in the trash, the content is permanently deleted. You can skip the trash bin and permanently delete an object by setting the x-epi-permanent-delete header to true.

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

πŸ“˜

Note

You cannot delete system content such as RootPage and GlobalAssetsRoot.

Create a Media Content

To create a media object in Content Cloud, send a POST multi-part form-data request with required headers and parameters to the endpoint. The request body consists of two parts

  • One part must be named content. The body contains property values of media content and its metadata in JSON format. This is similar to the JSON value of a regular content object.
  • The other part contains the media filename and its binary data. This filename must be the same as the name given in the previous part.
  • If both the content part and binary part exist in the request, the filename and name property in the content part need to be the same or an exception is thrown.
Create/api/episerver/v3.0/contentmanagement
curl --location --request POST "https://<YOUR_DOMAIN>/api/episerver/v3.0/contentmanagement" ^
--header "Authorization: Bearer <AUTH_TOKEN>" ^
--form "content={'name': 'sample-image.jpg', 'contentType': ['ImageFile'], 'parentLink': {'id': 7}, 'status': 'published'}" ^
--form "[email protected]\"<PATH_TO_FILE>\""

Update a Media Content

To partially update media content, send a PATCH multi-part form-data request bundled with only updated data to the endpoint.

  • If both content part and binary part exist in the request, the filename and name property in the content part need to be the same. Otherwise, an exception is thrown.
  • To only patch the binary data, send a PATCH multi-part form-data request with the binary data as a single part. The file extension should match the existing one. Only binary data is updated and the filename is not impacted.
  • To only patch the media content's properties or metadata, send a PATCH multi-part form-data request with the updated data in the content part only without the binary part.
  • When a CMS content type can be of several extensions, such as ImageFile file extension that can be either .jpg or .png, you can update from one extension to the other.
curl --location --request PATCH "https://<YOUR_DOMAIN>/api/episerver/v3.0/contentmanagement/<EXISTING_CONTENT_ID_OR_GUID>" ^
--header "Authorization: Bearer <AUTH_TOKEN>" ^
--form "content={'name': 'another-image.jpg', 'status': 'published'}"

Create or Update a Media Content

The Media content can be created or updated by sending a Put request to the endpoint.

  • If the media content already exists, then this endpoint updates the content media object. In contrast to PATCH, in this case, full content media data is sent to the endpoint.
  • If it does not exist, a new media content object is created. This endpoint cannot be used to update the content hierarchy.
curl --location --request PUT "https://<YOUR_DOMAIN>/api/episerver/v3.0/contentmanagement/<CONTENT_GUID>" ^
--header "Authorization: Bearer <AUTH_TOKEN>" ^
--form "content={'name': 'sample-image.jpg', 'contentType': ['ImageFile'], 'parentLink': {'id': 44}, 'status': 'published'}" ^
--form "[email protected]\"<PATH_TO_FILE>\""