Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

Dev GuideAPI ReferenceChangelog
Dev GuideAPI ReferenceUser GuideLegal TermsDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Content type versions

Every piece of content created in Optimizely Content Marketing Platform (CMP) relates to the latest version of the content type. Content type versions track and manage changes made to the structure of a content type. Each content type (like a blog post, product, or recipe) has a history of modifications, letting you see a history of changes and restore previous versions.

If the following changes occur to a content type, you can update a field definition version instead of creating another version. Changes outside of these conditions must create another content type.

  • Change the name of a field.
  • Change the description of a field.
  • Order the field.
  • Change a currently required field to an optional (non-required) field.
  • Change an internationalization requirement to optional.
  • Add an optional field to the content type.

You can also merge field definition versions in the following advanced cases:

  • Merge string fields.
  • Relax boundary validations for date, choice, and number fields.
  • Relax list boundaries (lower a minimum or raise a maximum).
  • Relax string length boundaries (increase max length, decrease min length; applies for rich text field also).
  • Remove validation patterns.
  • Allow additional types of assets for the library field.
  • Allow new content types for the content type relation field.

Migrate content from an earlier version to the latest version

This section explains how to create and modify omnichannel content (also called structured content) by using the Optimizely CMP Public API.

The following are APIs for migrating a content's content type version:

  • Supervised Content Migration API – This API accepts a new version for the content with the target content type version. The content type version has to belong to the original content type.

  • Managed Content Migration API – This API facilitates bulk content migration, specifically targeting the migration of content type versions to the latest version of the respective content type. However, successful migration depends on the automatic migration capability of the new versions of the content types. The following factors contribute to managed migration:

    • Add a required field with a default value.
    • Add a non-required field (it does not matter whether there is a default value).
    • Mark a non-required field as required, which has a default value.
    • Expand the referenceable content types associated with a reference field.
    • Change a field from singular to list.
    • Remove a field.

When managed migration does not work, use supervised migration to migrate the content's content type version.

To make requests to the API, create an application in CMP and get a token. You can follow the authentication steps to do so. To get an API token without an OAuth 2.0 flow, click Generate Temporary Token in your application's Test App section in CMP.

When you have the token, copy and paste the POST and GET requests below. You should change the Authorization header value with the token you generated and the "created_by" value, which should be your user SSO ID.

Use the following APIs to create content for the library:

Content Types

To create content types, use the POST /structured-content/content-types.

The following example creates Books for the first version with the fields title, authorName, and publishYear.

curl --location 'https://api.cmp.optimizely.com/v3/structured-content/content-types' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee' \
--data '{
    "created_by": "6409c3ac8070ad1d1d8762b3",
    "details": {
        "name": "Books",
        "component": false
    },
    "field_definitions": [
        {
            "core": {
                "key": "title",
                "name": "Title",
                "field_type": "text-field",
                "is_list": false,
                "is_required": true,
                "need_internationalization": false
            },
            "min_length": 1,
            "validation_pattern": ""
        },
        {
            "core": {
                "key": "authorName",
                "name": "Author Name",
                "field_type": "text-field",
                "is_list": false,
                "is_required": true,
                "need_internationalization": false
            },
            "min_length": 1,
            "validation_pattern": ""
        },
        {
            "core": {
                "key": "publishYear",
                "name": "Publish Year",
                "field_type": "number",
                "is_list": false,
                "is_required": false,
                "need_internationalization": false,
                "min_value": 1.0,
                "max_value": -1.0
            },
            "min_value": 1.0
        }
    ]
}'

Response

{
    "created": true,
    "content_type_guid": "cc48519491874c7f868c7e0808457cc0",
    "content_type_version_guid": "356b2a2089b14116828494bdf5e9ef87",
    "content_type_version_hash": null
}

This call created "content_type_guid": "cc48519491874c7f868c7e0808457cc0" and "content_type_version_guid": "356b2a2089b14116828494bdf5e9ef87".

You can view the content type versions list by GET /structured-content/content-types/<content_type_guid>/versions.

Create contents

The following code creates two contents using "content_type_guid": "cc48519491874c7f868c7e0808457cc0".

Content 1

curl --location 'https://api.cmp.optimizely.com/v3/structured-contents' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee' \
--data '{
    "title": "Clean Code",
    "folder_id": null,
    "content_body": {
        "content_type_guid": "cc48519491874c7f868c7e0808457cc0",
        "root_content": true,
        "title": "Clean code",
        "fields": {
            "title": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "text_value": "Clean Code",
                            "order_index": null
                        }
                    ]
                }
            ],
            "authorName": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "text_value": "Robert C. Martin",
                            "order_index": null
                        }
                    ]
                }
            ],
            "publishYear": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "num_value": 2008,
                            "order_index": null
                        }
                    ]
                }
            ]
        }
    }
}'

Response

{
    "id": "36ce1cfb137c44e58dc581aa9cc2aedb",
    "title": "Clean Code",
    "created_at": "2024-06-03T08:09:53Z",
    "modified_at": "2024-06-03T08:09:53Z",
    "folder_id": null,
    "file_location": "/",
    "is_archived": false,
    "owner_organization_id": "6409c3ac8070ad1d1d8762b3",
    "content_body": {
        "content_guid": "36ce1cfb137c44e58dc581aa9cc2aedb",
        "content_type": null,
        "content_type_guid": "cc48519491874c7f868c7e0808457cc0",
        "content_type_name": "Books",
        "created_at": "2024-06-03T08:09:53",
        "created_by": "630c9e390b6a9a1719ff2db4",
        "expired": false,
        "expiry_datetime": null,
        "latest_fields_version": {
            "content_hash": "7da99f668b9ce6c9a261522599abc81357fbdad34b0334b4719601e494260e2b26a395790c22f13fc3d996681e5448e6",
            "content_type_version_guid": "356b2a2089b14116828494bdf5e9ef87",
            "created_at": "2024-06-03T08:09:53",
            "created_by": "630c9e390b6a9a1719ff2db4",
            "fields": {
                "authorName": [
                    {
                        "field_values": [
                            {
                                "order_index": null,
                                "text_value": "Robert C. Martin"
                            }
                        ],
                        "locale": "en_US"
                    }
                ],
                "publishYear": [
                    {
                        "field_values": [
                            {
                                "num_value": 2008.0,
                                "order_index": null
                            }
                        ],
                        "locale": "en_US"
                    }
                ],
                "title": [
                    {
                        "field_values": [
                            {
                                "order_index": null,
                                "text_value": "Clean Code"
                            }
                        ],
                        "locale": "en_US"
                    }
                ]
            },
            "source_id": null,
            "source_metadata": null,
            "validation": {
                "fields": null
            },
            "version_guid": "51ef14df417d49a3bf31372f548b6214"
        },
        "links": {
            "definition": "https://api.welcomesoftware.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/versions/356b2a2089b14116828494bdf5e9ef87",
            "self": "https://api.welcomesoftware.com/v3/structured-content/contents/36ce1cfb137c44e58dc581aa9cc2aedb"
        },
        "primary_locale": "en_US",
        "root_content": true,
        "source": null,
        "source_id": null,
        "source_metadata": null,
        "title": "Clean code",
        "updated_at": "2024-06-03T08:09:53",
        "updated_by": "630c9e390b6a9a1719ff2db4"
    },
    "labels": [],
    "links": {
        "self": "https://api.cmp.optimizely.com/v3/structured-contents/36ce1cfb137c44e58dc581aa9cc2aedb"
    }
}

This call created "content_type_guid": "36ce1cfb137c44e58dc581aa9cc2aedb" and "content_type_version_guid": "356b2a2089b14116828494bdf5e9ef87".

Content 2

curl --location 'https://api.cmp.optimizely.com/v3/structured-contents' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee' \
--data '{
    "title": "Java Concurrency in Practice",
    "folder_id": null,
    "content_body": {
        "content_type_guid": "cc48519491874c7f868c7e0808457cc0",
        "root_content": true,
        "title": "Java Concurrency in Practice",
        "fields": {
            "title": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "text_value": "Java Concurrency in Practice",
                            "order_index": null
                        }
                    ]
                }
            ],
            "authorName": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "text_value": "Brian Goetz",
                            "order_index": null
                        }
                    ]
                }
            ],
            "publishYear": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "num_value": 2006,
                            "order_index": null
                        }
                    ]
                }
            ]
        }
    }
}'

Response

{
    "id": "9c1f4dbcf0eb4e3989e651f4b303692f",
    "title": "Java Concurrency in Practice",
    "created_at": "2024-06-03T08:13:01Z",
    "modified_at": "2024-06-03T08:13:01Z",
    "folder_id": null,
    "file_location": "/",
    "is_archived": false,
    "owner_organization_id": "6409c3ac8070ad1d1d8762b3",
    "content_body": {
        "content_guid": "9c1f4dbcf0eb4e3989e651f4b303692f",
        "content_type": null,
        "content_type_guid": "cc48519491874c7f868c7e0808457cc0",
        "content_type_name": "Books",
        "created_at": "2024-06-03T08:13:01",
        "created_by": "630c9e390b6a9a1719ff2db4",
        "expired": false,
        "expiry_datetime": null,
        "latest_fields_version": {
            "content_hash": "876aa9b14f41fc17c8b737f00f5cdbb28927c1026518ce3c545dee6f9fa1b46888ef86537d10f482b7873477e857d49c",
            "content_type_version_guid": "356b2a2089b14116828494bdf5e9ef87",
            "created_at": "2024-06-03T08:13:01",
            "created_by": "630c9e390b6a9a1719ff2db4",
            "fields": {
                "authorName": [
                    {
                        "field_values": [
                            {
                                "order_index": null,
                                "text_value": "Brian Goetz"
                            }
                        ],
                        "locale": "en_US"
                    }
                ],
                "publishYear": [
                    {
                        "field_values": [
                            {
                                "num_value": 2006.0,
                                "order_index": null
                            }
                        ],
                        "locale": "en_US"
                    }
                ],
                "title": [
                    {
                        "field_values": [
                            {
                                "order_index": null,
                                "text_value": "Java Concurrency in Practice"
                            }
                        ],
                        "locale": "en_US"
                    }
                ]
            },
            "source_id": null,
            "source_metadata": null,
            "validation": {
                "fields": null
            },
            "version_guid": "698f01d972e14e15b73d6aa6d7e40f41"
        },
        "links": {
            "definition": "https://api.welcomesoftware.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/versions/356b2a2089b14116828494bdf5e9ef87",
            "self": "https://api.welcomesoftware.com/v3/structured-content/contents/9c1f4dbcf0eb4e3989e651f4b303692f"
        },
        "primary_locale": "en_US",
        "root_content": true,
        "source": null,
        "source_id": null,
        "source_metadata": null,
        "title": "Java Concurrency in Practice",
        "updated_at": "2024-06-03T08:13:01",
        "updated_by": "630c9e390b6a9a1719ff2db4"
    },
    "labels": [],
    "links": {
        "self": "https://api.cmp.optimizely.com/v3/structured-contents/9c1f4dbcf0eb4e3989e651f4b303692f"
    }
}

This call created "content_type_guid": "9c1f4dbcf0eb4e3989e651f4b303692f" and "content_type_version_guid": "356b2a2089b14116828494bdf5e9ef87".

You can check content details by content_guid using the following sample:

Request

curl --location 'https://api.cmp.optimizely.com/v3/structured-content/contents/9c1f4dbcf0eb4e3989e651f4b303692f?expanded=false' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee'

Response

{
    "root_content": true,
    "title": "Java Concurrency in Practice",
    "primary_locale": "en_US",
    "expired": false,
    "expiry_datetime": null,
    "source": null,
    "source_id": null,
    "source_metadata": null,
    "latest_fields_version": {
        "fields": {
            "publishYear": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "order_index": null,
                            "num_value": 2006.0
                        }
                    ]
                }
            ],
            "title": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "order_index": null,
                            "text_value": "Java Concurrency in Practice"
                        }
                    ]
                }
            ],
            "authorName": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "order_index": null,
                            "text_value": "Brian Goetz"
                        }
                    ]
                }
            ],
            "language": [
                {
                    "locale": "en_US",
                    "field_values": [
                        {
                            "order_index": 1,
                            "text_value": "Spanish"
                        }
                    ]
                }
            ]
        },
        "created_by": "b46f11e3b01b4d6992e910f329cac8ba",
        "source_id": null,
        "source_metadata": null,
        "created_at": "2024-06-03T08:30:26",
        "version_guid": "7f58ed31378d4db68b098fa7709d9fd2",
        "content_type_version_guid": "741c5990488d4d2894af46d732486ce7",
        "content_hash": "5cbdacbb9009cae38e9bc352eb1e3e07aa63017b104b98244337e92ebfcd782854a5676bf9fd76d574bc0fe67bfdbfa5",
        "validation": {
            "fields": null
        }
    },
    "content_guid": "9c1f4dbcf0eb4e3989e651f4b303692f",
    "created_by": "630c9e390b6a9a1719ff2db4",
    "updated_by": "630c9e390b6a9a1719ff2db4",
    "created_at": "2024-06-03T08:13:01",
    "updated_at": "2024-06-03T08:13:01",
    "content_type_guid": "cc48519491874c7f868c7e0808457cc0",
    "content_type_name": "Books",
    "content_type": null,
    "links": {
        "self": "https://api.cmp.optimizely.com/v3/structured-content/contents/9c1f4dbcf0eb4e3989e651f4b303692f",
        "definition": "https://api.cmp.optimizely.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/versions/741c5990488d4d2894af46d732486ce7"
    }
}

Create content types new version (v2)

You can create content type versions by POST /structured-content/content-types/<content_type_guid>/versions.

Request

This example adds an optional text-field named language.

curl --location 'https://api.cmp.optimizely.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/versions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee' \
--data '{
    "created_by": "5756d99bddf4e48c1e00003a",
    "details": {
        "name": "Books",
        "component": false
    },
    "field_definitions": [
        {
            "core": {
                "key": "title",
                "name": "Title",
                "field_type": "text-field",
                "is_list": false,
                "is_required": true,
                "need_internationalization": false
            },
            "min_length": 1,
            "validation_pattern": ""
        },
        {
            "core": {
                "key": "authorName",
                "name": "Author Name",
                "field_type": "text-field",
                "is_list": false,
                "is_required": true,
                "need_internationalization": false
            },
            "min_length": 1,
            "validation_pattern": ""
        },
        {
            "core": {
                "key": "publishYear",
                "name": "Publish Year",
                "field_type": "number",
                "is_list": false,
                "is_required": false,
                "need_internationalization": false,
                "min_value": 1.0,
                "max_value": -1.0
            },
            "min_value": 1.0
        },
        {
            "core": {
                "key": "language",
                "name": "Language",
                "field_type": "text-field",
                "is_list": false,
                "is_required": false,
                "need_internationalization": false
            },
            "min_length": 1,
            "validation_pattern": ""
        }
    ]
}'

Response

{
    "created": true,
    "content_type_guid": "cc48519491874c7f868c7e0808457cc0",
    "content_type_version_guid": "741c5990488d4d2894af46d732486ce7",
    "content_type_version_hash": "8b909f3a17778b108e5d7f4cfa58c988ae28a2c927f216c3ace78d4586ac750e4010acc73c036774afb55dc799b9a7f3"
}

This created a content type version with a nullable text field named language and "content_type_version_guid": "741c5990488d4d2894af46d732486ce7".

You can check all content types versions by GET /structured-content/content-types/<content_type_guid>/versions.

Managed migrations

The "content_type_guid": "cc48519491874c7f868c7e0808457cc0" has two versions:

Content Type version 1: `356b2a2089b14116828494bdf5e9ef87`
Content Type version 2: `741c5990488d4d2894af46d732486ce7` [latest]

For Content Type version 1, content_type_version_guid has two contents. This example migrates the contents from "content_type_version_guid": "356b2a2089b14116828494bdf5e9ef87" to "content_type_version_guid": "741c5990488d4d2894af46d732486ce7".

The managed migrations APIs are

Validate managed migrations

You can validate the managed migrations possibility by POST /structured-content/content-types/<content_type_guid>/managed-migrations/validate.

Request

curl --location 'https://api.cmp.optimizely.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/managed-migrations/validate' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee' \
--data '{
    "source_content_type_version_id": "356b2a2089b14116828494bdf5e9ef87",
    "default_values": {
        "language": [
            {
                "locale": "en_US",
                "fieldValues": [
                    {
                        "orderIndex": 0,
                        "text_value": "English"
                    }
                ]
            }
        ]
    }
}'

This sends the added field values introduced in the latest version with default_values.

Response

{
    "is_managed_migration_possible": True
}

Create managed migrations

You can create managed migrations by POST /structured-content/content-types/<content_type_guid>/managed-migrations.

Request

curl --location 'https://api.cmp.optimizely.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/managed-migrations' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee' \
--data '{
    "source_content_type_version_id": "356b2a2089b14116828494bdf5e9ef87",
    "createdBy": "b46f11e3b01b4d6992e910f329cac8ba",
    "default_values": {
        "language": [
            {
                "locale": "en_US",
                "field_values": [
                    {
                        "order_index": 1,
                        "text_value": "English"
                    }
                ]
            }
        ]
    }
}'

Here, source_content_type_version_id is the first content_type_version_id, and default_values are default fields you want to add for contents.

Response

{
    "created": true,
    "job_id": "c4c61196bc6a4c07a7e708a8b6d74ae2"
}

The managed migration is created with "job_id": "c4c61196bc6a4c07a7e708a8b6d74ae2".

Fetch managed migrations

You can retrieve managed migrations by GET /structured-content/content-types/<content_type_guid>/managed-migrations/<job_id>.

Pass the job_id as parameter.

curl --location 'https://api.cmp.optimizely.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/managed-migrations/c4c61196bc6a4c07a7e708a8b6d74ae2' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee'

Response

{
    "id": "c4c61196bc6a4c07a7e708a8b6d74ae2",
    "instance_id": "6409c3ac8070ad1d1d8762b3",
    "content_type_id": "cc48519491874c7f868c7e0808457cc0",
    "source_content_type_version_id": "356b2a2089b14116828494bdf5e9ef87",
    "target_content_type_version_id": "741c5990488d4d2894af46d732486ce7",
    "default_values": {
        "language": [
            {
                "locale": "en_US",
                "field_values": [
                    {
                        "text_value": "English",
                        "order_index": 1
                    }
                ]
            }
        ]
    },
    "status": "not_started",
    "created_at": "2024-06-03T08:23:22",
    "updated_at": "2024-06-03T08:23:22",
    "content_migration_summary": {
        "total": 2,
        "not_started": 2,
        "succeeded": 0,
        "errored": 0,
        "skipped": 0
    }
}

Patch managed migrations

You can update managed migrations jobs by PATCH /structured-content/content-types/<content_type_guid>/managed-migrations/<job_id>.

PATCH only supports if the job status is not_started, and it can only update the default_values. This example changes the language from English to Spanish.

Request

curl --location --request PATCH 'https://api.cmp.optimizely.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/managed-migrations/c4c61196bc6a4c07a7e708a8b6d74ae2' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee' \
--data '{
    "source_content_type_version_id": "356b2a2089b14116828494bdf5e9ef87",
    "createdBy": "b46f11e3b01b4d6992e910f329cac8ba",
    "default_values": {
        "language": [
            {
                "locale": "en_US",
                "field_values": [
                    {
                        "order_index": 1,
                        "text_value": "Spanish"
                    }
                ]
            }
        ]
    }
}'

Response

{
    "updated": true
}

Delete managed migrations

You can delete managed migrations jobs by DELETE /structured-content/content-types/<content_type_guid>/managed-migrations/<job_id>.

Request

curl --location --request DELETE 'https://api.cmp.optimizely.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/managed-migrations/c4c61196bc6a4c07a7e708a8b6d74ae2' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee'

Response
The response status will be 204.

Start managed migrations job

You can start managed migrations jobs by POST /structured-content/content-types/<content_type_guid>/managed-migrations/<job_id>/start.

Request

curl --location 'https://api.cmp.optimizely.com/v3/structured-content/content-types/cc48519491874c7f868c7e0808457cc0/managed-migrations/c4c61196bc6a4c07a7e708a8b6d74ae2/start' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer dc69e65d-eee8-47b1-806a-8939b95719ee' \
--data '{
    "started": true,
    "job_id": "c4c61196bc6a4c07a7e708a8b6d74ae2"
}'

Response

{
    "started": true,
    "job_id": "c4c61196bc6a4c07a7e708a8b6d74ae2"
}

This starts the jobs and automatically migrates contents to new content type versions with default values.

Content type versions in Optimizely Graph

Every content type version is a separate schema in Optimizely Graph. Query against the base type in a schema when you query for a content type. The versions typically have a suffix of Vn where n is a positive integer of the version's sequence, such as V1,V2, and so on.

Leverage instances to test models

For omnichannel content (OCC), set up at least one additional instance alongside the production instance. Use the additional instance for modeling content types. Also, use the content type APIs to copy content types from one instance to another, which gives you greater control in developing, testing, and delivering content types to production.

The following reasons make managing content types as source code a powerful practice. This approach promotes consistency, reliability, control, and adaptability in managing your content structure—essential when scaling content operations.

  • Version control – Provide robust version tracking for your content models (with tools like Git). You can view a detailed history of changes and easy rollback options and collaborate on adjustments.
  • Automation – Define content types as code to enable seamless integration into continuous integration or continuous deployment (CI/CD) pipelines. You can test, deploy, and potentially roll back changes automatically.
  • Infrastructure as code alignment – Standardize how you manage configuration across your project alongside traditional code components.
  • Auditability and transparency – Log modifications to content types the same way as any code changes to improve record-keeping and accountability for content structure decisions.
  • Portability – Facilitate migration between environments (dev, staging, production) with code-based content types to minimize inconsistencies and manual errors.