> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://contentful.com/developers/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/developers/docs/_mcp/server.

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](/concepts/data-model) to learn more about modeling your content.

## Content type collection

[Get all content types of a space](/references/content-management-api/content-types/get-all-content-types-of-a-space)

[Create a content type with POST](/references/content-management-api/content-types/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](/references/content-management-api/content-types/create-a-content-type-with-a-specified-id)

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

> **Info**
>
> 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.

| Validation             | Description                                                                                                                                                                                                    | Applicable to                   | Example                                                                                            |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------- |
| `linkContentType`      | Takes 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"]}`                                                    |
| `in`                   | Takes an array of values and validates that the field value is in this array.                                                                                                                                  | Text, Symbol, Integer, Number   | `{"in": ["General", "iOS", "Android"]}`                                                            |
| `linkMimetypeGroup`    | Takes a MIME type group name and validates that the link points to an asset of this group.                                                                                                                     | Links to assets                 | `{"linkMimetypeGroup": ["image"]}`                                                                 |
| `size`                 | Takes 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}}`                                                                 |
| `range`                | Takes min and/or max parameters and validates the range of a value.                                                                                                                                            | Number, Integer                 | `{"range": { "min": 5, "max": 20}}`                                                                |
| `regexp`               | Takes a string that reflects a JS regex and flags, validates against a string. See [JS reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) for the parameters. | Text, Symbol                    | `{"regexp": {"pattern": "^such", "flags": "im"}}`                                                  |
| `prohibitRegexp`       | Inverse 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"}}`                              |
| `unique`               | Validates that there are no other entries that have the same field value at the time of publication.                                                                                                           | Symbol, Integer, Number         | `{"unique": true}`                                                                                 |
| `dateRange`            | Validates that a value falls within a certain range of dates.                                                                                                                                                  | Date                            | `{"dateRange": {"min": "2017-05-01","max": "2020-05-01"}}`                                         |
| `assetImageDimensions` | Validates that an image asset is of a certain image dimension.                                                                                                                                                 | Links to assets                 | `{"assetImageDimensions": {"width": {"min": 100,"max": 1000},"height": {"min": 200,"max": 2300}}}` |
| `assetFileSize`        | Validates that an asset is of a certain file size.                                                                                                                                                             | Links to assets                 | `{"assetFileSize": {"min": 1048576,"max": 8388608}}`                                               |
| `enabledNodeTypes`     | Constraints the allowed node types for Rich Text.                                                                                                                                                              | Rich Text                       | `{"enabledNodeTypes": ["heading-1", "quote", "embedded-entry-block"]}`                             |
| `enabledMarks`         | Constraints the allowed marks for Rich Text.                                                                                                                                                                   | Rich Text                       | `{"enabledMarks": ["bold", "italic"]}`                                                             |

> **Info**
>
> 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](/references/content-management-api/content-types/create-a-content-type-with-a-specified-id) 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](#validations-for-hidden-and-required-fields)

> **Info**
>
> 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

| Validation         | Description                                                                                             | Applicable to                                                                                                                                                                              | Example                                         |
| ------------------ | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------- |
| `linkContentType`  | Takes 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"]}` |
| `size`             | Takes 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}}`              |
| `allowedResources` | Defines 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:

```json
{
  "nodes":{
    "embedded-entry-block":[
      {
        "size":{
          "min":1,
          "max":5
        },
        "message":"..."
      },
      {
        "linkContentType":[
          "foo"
        ],
        "message":"..."
      }
    ],
    "embedded-resource-block":{
      "validations":[
        {
            "size": {
                "min": 0,
                "max": 10
            },
            "message": "..."
        }
      ],
      "allowedResources":[
        {
          "type":"Contentful:Entry",
          "source":"crn:contentful:::content:spaces/<spaceId>/environments/<environmentId>",
          "contentTypes":[
            "foo",
            "bar"
          ]
        }
      ]
    }
  }
}
```

For details about `allowedResources` see [Cross-space referencess](/references/content-management-api/cross-space-references#create-a-content-type-with-a-resourcelink-field).

#### 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:

```json
{
  "name": "foo",
  "fields": [
    {
      "id": "title",
      "name": "Title",
      "type": "Text",
      "defaultValue": {
        "en-US": "default title",
        "it-IT": "titolo predefinito",
        "fr-FR": null
      },
      "localized": true
    },
    {
      "id": "color",
      "name": "Color",
      "type": "Symbol",
      "defaultValue": {
        "en-US": "blue"
      },
      "localized": false
    },
    {
      "id": "labels",
      "name": "Labels",
      "type": "Array",
      "localized": false,
      "items": {
        "type": "Symbol"
      },
      "defaultValue": {
        "en-US": ["quick_read", "easy"]
      }
    },
    {
      "id": "breaking_news",
      "name": "Breaking news",
      "localized": true
    }
  ]
}
```

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](/references/content-management-api/locales) and
see your field empty after the entry is created.

Default values are not validated according to the field [`validations` property](#validations). 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

> **Info**
>
> 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](/compose/what-is-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](/experiences/overview) and [Compose](/compose/what-is-compose). You can find a list of the annotations below.

| Annotation ID                   | Can be assigned to                                                                       | Description                                                                                                                                |
| ------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `Contentful:ExperienceType`     | Content type                                                                             | A content type with this annotation defines the data structure for Experiences. [Learn more](/experiences/data-structures#experience-type) |
| `Contentful:AggregateRoot`      | Content type                                                                             | Adding this annotation to a content type will make it available as a page type in Compose. [Learn more](/compose/page-types)               |
| `Contentful:AggregateComponent` | Content 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](/compose/page-types#page-components)         |

> **Info**
>
> 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 ID                             | Is assigned to | Description                                                                                                                                                                                                                                                                                        |
| ----------------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Contentful:ManagedByEnvironmentTemplate` | Content type   | This annotation is automatically assigned to every content type installed by [Content model templates](/references/content-management-api/overview). It indicates which content types are managed by a template by showing a small icon in the Contentful web app and Compose.                     |
| `Contentful:GraphQLFieldResolver`         | Field          | When 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 to the reference field `sections`

```json
{
  "name": "Page",
  "displayField": "title",
  "fields": [
    {
      "id": "title",
      "name": "Name",
      "type": "Symbol"
    },
    {
      "id": "slug",
      "name": "Slug",
      "type": "Symbol"
    },
    {
      "id": "sections",
      "name": "Sections",
      "type": "Array",
      "items": {
        "type": "Link",
        "linkType": "Entry"
      }
    }
  ],
  "metadata": {
    "annotations": {
      "ContentType": [
        {
          "sys": {
            "id": "Contentful:AggregateRoot",
            "type": "Link",
            "linkType": "Annotation"
          }
        }
      ],
      "ContentTypeField": {
        "sections": [
          {
            "sys": {
              "id": "Contentful:AggregateComponent",
              "type": "Link",
              "linkType": "Annotation"
            }
          }
        ]
      }
    }
  }
}
```

#### 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](/concepts/multiple-environments).

To update a content type with field ID, use the [Create a content type with PUT](/references/content-management-api/content-types/create-a-content-type-with-a-specified-id) 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](/references/content-delivery-api/overview) and [CPA](/references/content-preview-api/overview) 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](/references/content-delivery-api/overview) and [CPA](/references/content-preview-api/overview).
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](/references/content-delivery-api/overview) and [CPA](/references/content-preview-api/overview) 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](/references/content-delivery-api/overview) and [CPA](/references/content-preview-api/overview).
To revert this, repeat this but with `disabled` set to `false`.

> **Info**
>
> 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](/references/content-management-api/overview) 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](/references/content-management-api/content-types/get-a-content-type)

[Delete a content type](/references/content-management-api/content-types/delete-a-content-type)

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

## Content type activation

[Activate a content type](/references/content-management-api/content-types/activate-a-content-type)

[Deactivate a content type](/references/content-management-api/content-types/deactivate-a-content-type)

## Activated content type collection

[Get all activated content types of a space](/references/content-management-api/content-types/get-all-activated-content-types-of-a-space)

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