Content types

Defining a content type is a fundamental step in powering your applications with Contentful. A content type consists of a set of fields and other information, read this guide to learn more about modeling your content.

Content type collection

Get all content types of a space

Create a content type with POST

Whilst it’s possible to create content types with POST, it’s strongly discouraged.

When you use this endpoint, the API will automatically generate an ID for the created content type and return it with the response.

Using the method outlined below allows you to control the ID of the created content type. This is important for content type IDs as they are often used as parameters in code.

Content type

Create a content type with PUT

To update a content type, use the above endpoint with its ID.

When updating an existing content type, you need to specify the last version of the content type you are updating with X-Contentful-Version.

Validations

When creating or updating a content type, you can add or remove validations to the fields in the content type schema by specifying the validations property of a field.

ValidationDescriptionApplicable toExample
linkContentTypeTakes an array of content type ids and validates that the link points to an entry of that content type.Links to entries{"linkContentType": ["post","doc","product"]}
inTakes an array of values and validates that the field value is in this array.Text, Symbol, Integer, Number{"in": ["General", "iOS", "Android"]}
linkMimetypeGroupTakes a MIME type group name and validates that the link points to an asset of this group.Links to assets{"linkMimetypeGroup": ["image"]}
sizeTakes min and/or max parameters and validates the size of the array (number of objects in it).Arrays, Text, Symbol, Rich Text{"size": { "min": 5, "max": 20}}
rangeTakes min and/or max parameters and validates the range of a value.Number, Integer{"range": { "min": 5, "max": 20}}
regexpTakes a string that reflects a JS regex and flags, validates against a string. See JS reference for the parameters.Text, Symbol{"regexp": {"pattern": "^such", "flags": "im"}}
prohibitRegexpInverse of regexp: Takes a string that reflects a JS regex and flags, validates against a string and expects to not match.Text, Symbol{"prohibitRegexp": {"pattern": "(bad|word|list)", "flags": "iu"}}
uniqueValidates that there are no other entries that have the same field value at the time of publication.Symbol, Integer, Number{"unique": true}
dateRangeValidates that a value falls within a certain range of dates.Date{"dateRange": {"min": "2017-05-01","max": "2020-05-01"}}
assetImageDimensionsValidates that an image asset is of a certain image dimension.Links to assets{"assetImageDimensions": {"width": {"min": 100,"max": 1000},"height": {"min": 200,"max": 2300}}}
assetFileSizeValidates that an asset is of a certain file size.Links to assets{"assetFileSize": {"min": 1048576,"max": 8388608}}
enabledNodeTypesConstraints the allowed node types for Rich Text.Rich Text{"enabledNodeTypes": ["heading-1", "quote", "embedded-entry-block"]}
enabledMarksConstraints the allowed marks for Rich Text.Rich Text{"enabledMarks": ["bold", "italic"]}
Validations will take effect after the content type has been activated and existing entries will not be validated until they are re-published.

To remove a specific validation, update the content type leaving that validation out of the field’s validations collection. To remove all the validations applied to a field, update the content type schema removing the validations property.

To update a content type with validations, use the Create a content type with PUT endpoint and pass validations in the request body, see example:

{
"name": "Blog Post",
"fields": [
{
"id": "title",
"name": "Title",
"type": "Text",
"validations": [
{
"size": ""
},
{
"regexp": ""
}
]
}
]
}

Validations for hidden and required fields

If a field’s validation is set as both disabled: true and required: true but is left empty, a validation error occurs and you cannot publish the content type. Fields that have a default value set are not considered empty and can still be published.

To continue publishing entries with hidden and required fields, change the validation of these fields to optional required: false. You can manually update the validation for each field, or run the following script to make the changes in bulk:

import contentfulManagement from 'contentful-management';
const SPACE_ID = process.env.SPACE_ID ?? 'your_space_id';
const ENVIRONMENT_ID = process.env.ENVIRONMENT_ID ?? 'your_environment_id';
const ACCESS_TOKEN = process.env.ACCESS_TOKEN ?? 'your_access_token';
const client = contentfulManagement.createClient({
accessToken: ACCESS_TOKEN,
});
const isRequiredAndHidden = (field) =>
field.required === true && field.disabled === true;
async function makeHiddenFieldsOptional() {
const space = await client.getSpace(SPACE_ID);
const environment = await space.getEnvironment(ENVIRONMENT_ID);
const contentTypes = await environment.getContentTypes();
for (const contentType of contentTypes.items) {
const requiredAndHiddenFields =
contentType.fields.filter(isRequiredAndHidden);
if (requiredAndHiddenFields.length === 0) {
continue;
}
requiredAndHiddenFields.forEach((field) => (field.required = false));
try {
const updatedContentType = await contentType.update();
await updatedContentType.publish();
console.log(`Update content type: ${contentType.name}`);
} catch (error) {
console.error(
`Failed to update content type: ${contentType.name}`,
error,
);
}
}
console.log('Done');
}
makeHiddenFieldsOptional().catch(console.error);

Rich text node type validations

ValidationDescriptionApplicable toExample
linkContentTypeTakes an array of content type ids and validates that the link points to an entry of that content type.embedded-entry-block, embedded-entry-inline, entry-hyperlink{"linkContentType": ["post","doc","product"]}
sizeTakes min and/or max parameters and validates the number of entries.asset-hyperlink, embedded-asset-block, embedded-entry-block, embedded-entry-inline, entry-hyperlink, embedded-resource-block, embedded-resource-inline, resource-hyperlink{"size": { "min": 5, "max": 20}}
allowedResourcesDefines the entities that can be referenced by the field. It is only used for cross-space references.embedded-resource-block, embedded-resource-inline, resource-hyperlink{"allowedResources": []}

Rich text node type validations contain validations and allowed resources for the specified node type. See the example below:

1{
2 "nodes":{
3 "embedded-entry-block":[
4 {
5 "size":{
6 "min":1,
7 "max":5
8 },
9 "message":"..."
10 },
11 {
12 "linkContentType":[
13 "foo"
14 ],
15 "message":"..."
16 }
17 ],
18 "embedded-resource-block":{
19 "validations":[
20 {
21 "size": {
22 "min": 0,
23 "max": 10
24 },
25 "message": "..."
26 }
27 ],
28 "allowedResources":[
29 {
30 "type":"Contentful:Entry",
31 "source":"crn:contentful:::content:spaces/<spaceId>/environments/<environmentId>",
32 "contentTypes":[
33 "foo",
34 "bar"
35 ]
36 }
37 ]
38 }
39 }
40}

For details about allowedResources see Cross-space referencess.

Default values

Using the defaultValue property of a field, you can define a value that is applied when entries are created. If defaultValue is omitted the field will not be pre-filled with any value. See the example below:

1{
2 "name": "foo",
3 "fields": [
4 {
5 "id": "title",
6 "name": "Title",
7 "type": "Text",
8 "defaultValue": {
9 "en-US": "default title",
10 "it-IT": "titolo predefinito",
11 "fr-FR": null
12 },
13 "localized": true
14 },
15 {
16 "id": "color",
17 "name": "Color",
18 "type": "Symbol",
19 "defaultValue": {
20 "en-US": "blue"
21 },
22 "localized": false
23 },
24 {
25 "id": "labels",
26 "name": "Labels",
27 "type": "Array",
28 "localized": false,
29 "items": {
30 "type": "Symbol"
31 },
32 "defaultValue": {
33 "en-US": ["quick_read", "easy"]
34 }
35 },
36 {
37 "id": "breaking_news",
38 "name": "Breaking news",
39 "localized": true
40 }
41 ]
42}

You can localize default values by providing separate values for each locale. When the value is omitted, in the entry creation request, then the configured default value is applied and the entry saved with it. In case of a non-localized field, only the default value targeting the default locale will be applied to the new entry.

You can set the default value for a locale to be null. This can be helpful to interrupt the locale fallback and see your field empty after the entry is created.

Default values are not validated according to the field validations property. This means that they are applied to new entries even if they are invalid. In this case, those entries can’t be published until the field value is fixed.

Limitations: If the default locale of an environment changes, the default value configuration is not modified. So the value targeting the previous default locale will still be applied to it. Currently not all the field types support default values. The supported field ones are:

  • {type: "Symbol"}
  • {type: "Text"}
  • {type: "Integer"}
  • {type: "Number"}
  • {type: "Date"}
  • {type: "Boolean"}
  • {type: "Array", items: {type: "Symbol"}} only short texts arrays are supported
Default values are applied to fields during entry creation and are only applied for activated content types. Changing defaultValue for a content type field will not change previously created entries; it will only apply to entries created after defaultValue has been updated.

Annotations

Annotations provide you with means to attach semantic metadata to a content type or parts of it. Once assigned, they can be interpreted by applications and services to adjust their behaviour accordingly.

For example, in Compose an annotation can be assigned to any content type. Once assigned, this content type will be available for use as a page type in Compose, making all entries of that content type available for editing.

We provide a small set of system annotations to drive the behaviour of Experiences and Compose. You can find a list of the annotations below.

Annotation IDCan be assigned toDescription
Contentful:ExperienceTypeContent typeA content type with this annotation defines the data structure for Experiences. Learn more
Contentful:AggregateRootContent typeAdding this annotation to a content type will make it available as a page type in Compose. Learn more
Contentful:AggregateComponentContent type fields of type Link pointing to an entry (single and multiple references)Adding this annotation to a field will turn it into a page component in Compose. Learn more
You are able to assign only the system annotations that are listed above to any of your content types. We don’t provide either means of listing annotations or capabilities to create and assign custom annotations.

Some of the annotations are assigned automatically. You can find a list of them below.

Annotation IDIs assigned toDescription
Contentful:ManagedByEnvironmentTemplateContent typeThis annotation is automatically assigned to every content type installed by Content model templates. It indicates which content types are managed by a template by showing a small icon in the Contentful web app and Compose.
Contentful:GraphQLFieldResolverFieldWhen the “Resolve content on delivery” checkbox is selected in the field settings under the appearance tab in the content model editor, an annotation is automatically assigned to that field. This annotation specifies the app responsible for resolving third party content in GraphQL queries.

Assigning annotations

By adding a metadata.annotations property to the payload, you can assign annotations to either the content type itself or individual fields of that content type. Annotations that can be assigned to individual fields will usually have additional restrictions to which type of field they can be assigned (see Contentful:AggregateComponent above).

The example payload below shows you how to assign annotations to a sample content type. It will do the following things:

  • Assign the Contentful:AggregateRoot annotation to the content type itself
  • Assign the Contentful:AggregateComponent annotation the the reference field sections
1{
2 "name": "Page",
3 "displayField": "title",
4 "fields": [
5 {
6 "id": "title",
7 "name": "Name",
8 "type": "Symbol"
9 },
10 {
11 "id": "slug",
12 "name": "Slug",
13 "type": "Symbol"
14 },
15 {
16 "id": "sections",
17 "name": "Sections",
18 "type": "Array",
19 "items": {
20 "type": "Link",
21 "linkType": "Entry"
22 }
23 }
24 ],
25 "metadata": {
26 "annotations": {
27 "ContentType": [
28 {
29 "sys": {
30 "id": "Contentful:AggregateRoot",
31 "type": "Link",
32 "linkType": "Annotation"
33 }
34 }
35 ],
36 "ContentTypeField": {
37 "sections": [
38 {
39 "sys": {
40 "id": "Contentful:AggregateComponent",
41 "type": "Link",
42 "linkType": "Annotation"
43 }
44 }
45 ]
46 }
47 }
48 }
49}

Changing field IDs

You can change the ID of a content type field in the Contentful web app. You can also change it via the API, by sending the newId property in the field’s payload to override the current ID. The API will return different data after this change, and this might break your existing code base. Read more about managing changes to content structure in our multiple environments guide.

To update a content type with field ID, use the Create a content type with PUT endpoint and pass the newId in the request body, see example:

{
"name": "Blog Post",
"description": "Simple blog post with headline and body fields.",
"fields": [
{
"id": "title",
"newId": "headline",
"name": "Headline",
"type": "Text"
},
{
"id": "body",
"name": "Body",
"type": "Text"
}
]
}

Omitting fields

If you have fields in your content type and entries you don’t want to distribute to end users (e.g. workflow states), you can omit fields from the CDA and CPA responses. To do so, update the content type with the omitted property set to true in the chosen field and activate it.

The field will still be available as part of the CMA responses and in the web app but skipped in the CDA and CPA. To revert this, repeat this but with omitted set to false.

Disabling fields

If you have fields in your content type and entries you don’t want to distribute to end users (e.g. workflow states), you can disable them from the CDA and CPA responses. To do so, update the content type with the disabled property set to true in the chosen field and activate it.

The field will still be available as part of the CMA responses and in the web app but skipped in the CDA and CPA. To revert this, repeat this but with disabled set to false.

If a field’s validation is set as both disabled: true and required: true but is left empty, a validation error occurs and you cannot publish the content type. Fields that have a default value set are not considered empty and can still be published. For more information, see the Validations for hidden and required fields section.

Deleting fields

To delete fields you no longer need, first, omit the field you’re targeting for deletion and activate the content type. This step is mandatory to avoid accidental data loss. It allows you to try whether your client applications can handle the deletion and provides an easy way to revert that change.

Once you have confirmed it’s safe to delete the field, update your content type with the corresponding field removed from the payload, or with the deleted property set to true on the content type field you intend to delete. The deletion becomes final after you once again activate the content type. This action is permanent and cannot be undone.

Get a content type

Delete a content type

Before you can delete a content type you need to deactivate it.

Content type activation

Activate a content type

Deactivate a content type

Activated content type collection

Get all activated content types of a space

Retrieves the activated versions of content types, ignoring any changes made since the last activation.