Content Management API

Introduction

Contentful's Content Management API (CMA) helps you manage content in your spaces. To learn more about how to model your content, read our modelling guide.

Note: You can use the CMA to deliver and manage content, but you shouldn't use it to deliver large amounts of content and instead use the Content Delivery API. The structure of responses from the CMA differs from the CDA as GET responses retrieve the entirety of items (i.e. all localized and unpublished content).

Basic API information

API Base URL https://api.contentful.com
This is a read/write API

Authentication

You access the API securely via HTTPS, and it will be available to clients authenticating with an access token.

Learn about authenticating to the CMA and get your access token from the developer center.

Resource IDs

When creating resources, you can specify an ID or let the API generate a random ID for you. If you choose an ID yourself it must adhere to the following rules:

  • It has a length between 1 and 64 characters.

  • It only includes alphanumeric characters, dots ., hyphens - or underscores _.

Represented as a regular expression, this is /^[a-zA-Z0-9\.-_]{1,64}$/.

Updating content

Contentful doesn't merge changes made to content, so when updating content, you need to send the entire body of an entry. If you update content with a subset of properties, you will lose all existing properties not included in that update.

You should always update resources in the following order:

  • Fetch current resource.

  • Make changes to the current resource.

  • Update the resource by passing the changed resource along with current version number.

This way no unseen changes are overridden and unexpected conflicts are unlikely to occur.

Note: You can't update any of the sys property fields, including sys.id.

Updating and version locking

Contentful uses optimistic locking. When updating an existing resource, you need to specify its current version with the X-Contentful-Version HTTP header (this header is automatically set when using our official SDKs). Contentful compares this version with the current version stored to ensure that a client doesn't overwrite a resource that has since been updated. If the version changed in-between, Contentful would reject the update.

API rate limits

API Rate limits specify the number of requests a client can make to Contentful APIs in a specific time frame. Every request counts against a per second and a per hour rate limit.

By default the Contentful Management API enforces rate limits of 10 requests per second and 36000 requests per hour. Higher rate limits may apply depending on your current plan.

The following table lists all headers returned in every response by the Content Management API which give a client information on rate limiting:

Header Description
X-Contentful-RateLimit-Hour-Limit The maximum amount of requests which can be made in an hour.
X-Contentful-RateLimit-Hour-Remaining The remaining amount of requests which can be made until the next hourly reset.
X-Contentful-RateLimit-Second-Limit The maximum amount of requests which can be made in a second.
X-Contentful-RateLimit-Second-Remaining The remaining amount of requests which can be made until the next secondly reset.
X-Contentful-RateLimit-Reset The number of seconds until the next request can be made.

Here is a part of a Contentful Management API response example showing the headers for rate limiting:

X-Contentful-RateLimit-Hour-Limit: 36000
X-Contentful-RateLimit-Hour-Remaining: 35891
X-Contentful-RateLimit-Reset: 0
X-Contentful-RateLimit-Second-Limit: 10
X-Contentful-RateLimit-Second-Remaining: 9

When a client gets rate limited, the API responds with the 429 Too Many Requests HTTP status code and sets the value X-Contentful-RateLimit-Reset header to an integer larger than 0 specifying the time before one of the two limits resets and another request will be accepted. If the client is rate limited per second, the header will return 1, which means the next second. If the client is rate limited per hour, the next reset will be determined like this: Every request which was made in the last hour gets counted in one of four 15 minute buckets. Every time a request comes in, the API calculates how many seconds remain until the sum of all bucket counts will be below the hourly limit.

Examples:

The current rate limits for a client are the default 10 per second and 36000 per hour.

Example 1

Client: 5 requests in 1 second

HTTP/1.1 2xx
X-Contentful-RateLimit-Reset: 0

Meaning: not rate limited. More requests are allowed.

Example 2

Client: 11 requests in 1 second

HTTP/1.1 429
X-Contentful-RateLimit-Reset: 1

Meaning: wait 1 second before making more requests.

Example 3

Client: 9000 requests in 15 minutes, 9000 requests in following 15 minutes, 9000 requests in following 15 minutes, 9000 requests in following 15 minutes

HTTP/1.1 429
X-Contentful-RateLimit-Reset: 900

Meaning: wait 15 minutes before making more requests (which frees up 9000 requests - 15 minutes later 9000 requests get freed up and so on).

Common Resource Attributes

Every resource returned by the API has a sys property, which is an object containing system managed metadata. The exact metadata available depends on the resource type, but at minimum it defines the sys.type property.

Note: Once created, none of the sys properties can be changed. During creation of an entity, the value of sys.id is either automatically generated or specified in the URL (e.g. entries/entryId) of the initial PUT request. The only entity which always uses generated sys.id values is spaces.

The sys.id property is defined for every resource that is not a collection. For example, a Space resource will have a sys.type and sys.id:

{
  "sys": {
    "type": "Space",
    "id": "yadj1kx9rmg0"
  }
}
Field Type Description Applies to
sys.type String Type of resource. All
sys.id String Unique ID of resource. All except arrays
sys.space Link Link to resource's space. Entries, assets, content types
sys.environment Link Link to resource's environment. Entries, assets, content types
sys.contentType Link Link to entry's content type. Entries
sys.publishedCounter Integer Number of times resource was published. Entries, assets, content types
sys.publishedVersion Integer Published version of resource. Entries, assets, content types
sys.version Integer Current version of resource. Entries, assets, content types
sys.firstPublishedAt Date Time resource was first published. Entries, assets, content types
sys.createdAt Date Time resource was created. Entries, assets, content types
sys.createdBy Link Link to creating user. Entries, assets, content types
sys.publishedAt Date Time resource was published. Entries, assets, content types
sys.publishedBy Link Link to publishing user. Entries, assets, content types
sys.updatedAt Date Time resource was updated. Entries, assets, content types
sys.updatedBy Link Link to updating user. Entries, assets, content types

Collection resources and pagination

Contentful returns collections of resources in a wrapper object that contains extra information useful for paginating over large result sets:

{
  "sys": { "type": "Array" },
  "skip": 0,
  "limit": 100,
  "total": 1256,
  "items": [ /* 100 individual resources */ ]
}

In the above example, a client retrieves the next 100 resources by repeating the same request, changing the skip query parameter to 100. You can use the order parameter, for example, order=sys.createdAt, when paging through larger result sets to keep ordering predictable.

API versioning

All API requests should specify a Content-Type header of application/vnd.contentful.management.v1+json.

If not specified, Contentful will route your request to the latest version of the API. This could break clients which expect the outdated API version. To be certain, always specify the Content-Type header.

Reference

Spaces

Spaces collection

Spaces are containers for content types and content, and API clients can fetch data from one or more spaces. You can be a member of multiple organizations, and owner and admin roles in the organization can create spaces in organizations.

When you sign up to Contentul for the first time, you create a new organization. When you're invited to an existing organization, you become a member of that organization.

Note: If you have a single organization, any space you create will be automatically associated with that organization. If you're an admin or an owner in multiple organizations you need to pass the ID of the organization with the X-Contentful-Organization header that you want to create the space in.

Note: If you are on our latest pricing model and have plans attached to your spaces, creating a new space via the API will assign the smallest available plan to it. If you've reached your limit of free spaces and have no payment details on file, you won't be able to create more spaces until you add payment details.

Get all spaces an account has access to

Create a space

Create a new space, specifying attributes in the request body.

Space

Get a space

Update a space name

The X-Contentful-Organization header is optional if an account belongs to one organization. Attributes are sent in the body of the request as a JSON payload, and you need to set the X-Contentful-Version to the Contentul API version you are using.

Delete a space

You delete an existing space by issuing a DELETE request to /spaces/ID. Deleting a space will remove all its resources, including content types, entries and assets. This action can not be undone.

Environments

This feature is only available with subscriptions created since 16th April 2018. Please sign up or contact our support team to upgrade your account.

Environments allow you to develop and test changes to data in isolation from other environments. You can use them for all purposes in your development process like QA, staging environments or in continuous integration.

Environments are resources in a space and can be accessed by a unique identifier. This means that two spaces can have an environment with the same name.

A space can have multiple environments. A space has a minimum of one environment, which is called master. The master environment cannot be changed, deleted or renamed.

For a best practise explanation on how to use environments in your development workflow, please read the Managing multiple environments article in our knowledgebase.

Creating environments

To create other environments next to master, you need to have the default space admin role or a role, which allows you to manage and use all sandbox environments in this space. While creating an environment, you need to understand that it can only be a copy of the current state of the master environment. See the Environment aware Resources chapter below for more information on what resources are copied to an environment. It is not possible to create or have empty environments or environments based on older versions of a master environment.

To create an environment, make a request to PUT /spaces/<id>/environments/staging specifying the name in the payload like {"name": "My staging environment"}. After this request got a successful response, please query the single endpoint of that environment to check if the environment is already available.

Access content in an environment

To request content from an environment, you need to provide another fragment in the url. For example to get all entries from the previously created staging environment, use /spaces/<id>/environments/staging/entries.

Requests to /spaces/<id>/entries without the environment fragment will implicitly request content from the master environment.

Environment aware resources

The following resources are environment aware. This means upon creation of an environment, the following resources are copied from the master environment to the environment you want to create:

  • Content Types

  • Entries

  • Assets

  • Locales

  • Extensions

  • Editor Interfaces

Upon copying, all resources maintain their original metadata like sys.id or createdAt.

All other resources are available on a space level only. Personal access tokens allow access according to your role. This means if you have access to a space and have the default space admin role or a role, which allows to manage and use all sandbox environments in this space, you can use your PAT to access all environments. For CDA/CPA API key pairs, you can select the environments for which they have access, please refer to the API keys section in this document for more information.

Environment states

An environment can have different states determined by the sys.state property.

Status Description
queued The environment was queued successfully and will be created soon.
inProgress The environment is currently being created.
ready The environment is ready to use.
failed The environment failed to get to a ready state.

The master environment is always in state ready.

Environments and rate limiting

All requests to environments in a space count against the organizations rate limits bucket.

Environments and webhooks

Webhooks can be triggered for one or multiple environments by using the filters property of a webhook. Supported scenarios are:

  • trigger only for specific environments by specifying environment constraints in the filters property (e.g. {"filters": [{"equals": [{"doc": "sys.environment.sys.id"}, "some-env-id"]}]})

  • trigger for all environments by not setting any environment filters (e.g. {"filters": []})

  • trigger only for the master environment by omitting the filters property or setting its value to null. This scenario handles webhooks created prior to introduction of environments in a backwards compatible manner.

Please refer the webhooks reference for more details.

There are no events for creating or deleting an environment.

Environments and snapshots

Snapshots are only available for entries and content types belonging to the master environment.

Environment collection

Get all environments of a space

Create an environment

Whilst it's possible to create an environment with POST, it's strongly discouraged.

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

Using the method outlined below allows you to control the ID of the created environment.

Environment

Create/update an environment

Use this endpoint to create a new environment with the specified ID.

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

Get a single environment

Delete an environment

Note: When deleting an existing environment, you need to specify the last version of the environment you are deleting with X-Contentful-Version.

Organizations

Organizations are the top level entity in Contentfuls hierarchy, consisting of spaces, users and a subscription plan, which defines the limits for the Organization. They allow the management of projects with separate pricing as well as an additional permission system, which manages users' roles within the Organization.

Organizations collection

Get all organizations an account has access to

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 modelling your content.

Content type collection

Get all content types of a space

Create a content type

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/update a content type

Use this endpoint to create a new content type with the specified ID, or to update a specific content type using its ID.

Note: 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, Rich Text {"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 for the parameters. Text, Symbol {"regexp": {"pattern": "^such", "flags": "im"}}
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", "italics"]}

Note: 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.

Changing field IDs

You can change the ID of a content type field in the Contentful Web App. 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.

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 the Web App but skipped in the CDA and CPA. To revert this, repeat this but with omitted set to false.

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 single 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.

Editor interface

An editor interface represents the look and feel of content type fields in the web app and are tightly coupled to a specific content type.

Editor interface

An editor interface is a singleton resource of a content type, that means that there can only be one editor interface per content type at a time. It is created automatically on the first publish of a content type and updated when a content type field is added, removed or changed.

Note: Cascading updates happen when the content type is published. As the editor interface is created on the server side, it's not possible to create an editor interface manually via an HTTP request.

The API will return a 404 response if there is no editor interface for the requested content type. This typically happens when the content type was not yet published or if it was created before the automatic editor interface creation feature was added (June 20, 2016). (Re-)Publishing the content type should fix both scenarios.

Get the editor interface

Update the editor interface

You can use this endpoint to update an existing editor interface. You will need to specify its last version with X-Contentful-Version.

UI Extensions

UI Extensions allow you to customize and extend the functionality of the Contentful Web App's entry editor. Extensions can be simple user interface controls, such as a dropdown, or more complex micro applications such as our Markdown editor.

To get started with UI extensions please refer to our dedicated extensibility section.

An extension resource describes to which fields your extension can be applied and where its code can be found. The following is a list of the properties of an extension resource:

Property Required Type Description
name yes String Extension name
fieldTypes yes Array[Object] * Field types where an extension can be used
src ** String URL where the root HTML document of the extension can be found
srcdoc ** String String representation of the extension (e.g. inline HTML code)
sidebar no Boolean Controls the location of the extension. If true it will be rendered on the sidebar instead of replacing the field's editing control
parameters no Object Definitions of configuration parameters. See the following section for more details.

* Valid field types are:

  • {type: "Symbol"}

  • {type: "Text"}

  • {type: "Integer"}

  • {type: "Number"}

  • {type: "Date"}

  • {type: "Boolean"}

  • {type: "Object"}

  • {type: "Link", linkType: "Asset"}

  • {type: "Link", linkType: "Entry"}

  • {type: "Array", items: {type: "Symbol"}}

  • {type: "Array", items: {type: "Link", linkType: "Entry"}}

  • {type: "Array", items: {type: "Link", linkType: "Asset"}}

** One of src or srcdoc has to be present:

  • Use srcdoc if you want to host the extension code in Contentful. Note that extensions hosted in Contentful have a size limit of 200KB.

  • Use src if you host the extension yourself. Note that on this case your extension must be hosted on a HTTPS domain with CORS enabled.

Configuration parameters

WARNING: Configuration parameters can be read by anybody who is allowed to use the extension. It's not secure to use parameters to inject access tokens with access level permitting data manipulation. Read-only tokens can be used but keep in mind their value is not hidden.

It's important to achieve separation of the code that forms your UI Extension and configuration that is used by it. This way UI Extensions can be shared and reused without any code changes. There are two types of configuration parameters that can be set up for an extension:

  • Installation parameters that are set when extensions are created/updated in a space.

  • Instance parameters that are set when a space member with access to the Content Model assigns an extension to a field of a content type.

Parameter definition is an object constructed as described in the table below. You can define up to 8 installation and instance parameters for each UI Extension.

Property Type and value Is required? Remarks
id String yes Can contain only letters, numbers and underscores
name String yes Human readable name of the parameter
description String no Further explanation of the purpose of the parameter
type String, one of Symbol, Enum, Number, Boolean yes Enum parameters hold a predefined list of Symbols
required Boolean no, defaults to false Parameter value needs to be provided
default Should match type no Default value to use for the parameter. For Enums it has to be defined on the options list
options
  • list of allowed values: ["one", "two"]
  • can be a list of {"value": "Label"} pairs to provide labels for values
yes
  • applicable only to Enums
  • ["x", "y"] is equivalent to [{"x": "x"}, {"y": "y"}]
labels
  • for Enums: {"empty": "Choose a value"}
  • for Booleans: {"true": "sí", "false": "no"}
no Used for rendering a form. All labels are optional and have sensible defaults in English

Parameters are defined in the Extension entity:

{
  "extension": {
    "name": "My parametrized object editor",
    "fieldTypes": [{type: "Object"}],
    "srcdoc": "<!DOCTYPE html>...",
    "parameters": {
      "installation": [
        {
          "id": "devMode",
          "type": "Boolean",
          "name": "Run in development mode"
        },
        {
          "id": "retries",
          "type": "Number",
          "name": "Number of retries for API calls",
          "required": true,
          "default": 3
        }
      ],
      "instance": [
        {
          "id": "helpText",
          "type": "Symbol",
          "name": "Help text",
          "description": "Help text for a user to help them understand the editor"
        },
        {
          "id": "theme",
          "type": "Enum",
          "name": "Theme",
          "options": [{"light": "Solarized light"}, {"dark": "Solarized dark"}],
          "default": "light",
          "required": true
        }
      ]
    }
  }
}

Instance parameters are set in the Editor Interface entity. Installation parameters are provided as a space-wide property of the Extension entity.

{
  "extension": {...},
  "parameters": {
    "devMode": true,
    "retries": 10
  }
}

Use UI Extensions SDK to access parameters during runtime of your extension.

Extensions collection

Get all extensions of a space

Create an extension

Extension

Use this endpoint to create a new extension with a specified ID, or to update a specific extension via its ID. When updating an existing extension, you need to specify the last version of the extension you are updating with X-Contentful-Version.

Create/update an extension

Get a single extension

Delete an extension

Entries

Entries collection

Entries represent text content in a space, and the data structure of an entry must adhere to a certain content type.

Get all entries of a space

To fetch specific entries like e.g. entries of a particular content type use query search parameters.

Create an entry

Before you can create an entry you need to create and activate a content type as outlined above.

When creating a new entry, you need to pass the ID of the desired content type as the X-Contentful-Content-Type header and pass the field data as a JSON payload.

When using this endpoint, an ID will be automatically generated for the created entry and returned in the response.

Entry

Create/update an entry

Use this endpoint to create a new entry with a specified ID, or to update a specific entry via its ID. When updating an existing entry, you need to specify the last version of the entry you are updating with X-Contentful-Version.

When creating a new entry, you need to pass the ID of the entry's desired content type as the X-Contentful-Content-Type header. For updating an entry, passing the ID of the entry's content type is not required.

Get a single entry

Delete an entry

Entry publishing

After publishing the entry, it will be available via the Content Delivery API.

Publish an entry

Unpublish an entry

Entry archiving

You can only archive an entry when it's not published.

Archive an entry

Unarchive an entry

Uploads

The Upload API, available at upload.contentful.com, provides Contentful SDKs with a direct file upload service. You can upload any binary data (including images, videos and text files) and associate the uploaded files with different Assets within a Space.

The Upload API enables the uploading of files to remote storage. To complete an upload, the uploaded file must be associated with an Asset and that asset must be processed. If the association and processing steps are not executed successfully within 24 hours after uploading, the file and its metadata will expire and be deleted from the storage area. The expiration date of the file is indicated in the API response data as expiresAt.

You can associate an Upload resource with more than one Asset and/or locale

Uploading a file

To upload a file, you send a POST request to the create upload endpoint with the binary data in the request body, and include Content-Type: application/octet-stream in the request headers. Depending on the size of your file, a success response may take some time to return. Once the upload finishes, you will receive an Upload resource in the response body.

Associating an upload with an asset

When the upload request is successful you will receive an Upload resource containing an upload_id within the sys.id field that references the uploaded file. You need to use the upload_id to associate the Upload resource with an Asset.

To associate an Upload resource with an Asset, you need to pass upload_id to the asset creation end point of the CMA with the following structure:

{
  "fields": {
      "title": {
          "en-US": "My cute cat pic"
      },
      "file": {
          "en-US": {
              "contentType": "image/png",
              "fileName": "cute_cat.png",
              "uploadFrom": {
                  "sys": {
                    "type": "Link",
                    "linkType": "Upload",
                    "id": "<use sys.id of an upload resource response here>"
                  }
              }
          }
      }
  }
}

Maximum file size

The maximum file size should not exceed 1000MB per uploaded asset. See our Fair Usage Policy for more information. If you try to upload a larger file you will receive a Request Timeout error from the API.

Resumability

The current version of the Upload API doesn't support resumability. If you encounter an error during the upload process, you need to begin the process from the beginning. It's the client's responsibility to take recovery actions in case of an error.

Upload resource

The JSON structure for an Upload has the following structure:

"sys": {
    "id": "73DfxdBnwyhQNy95A8dvSf",
    "type": "Upload",
    "createdAt": "2017-02-21T07:49:25.000Z",
    "expiresAt": "2017-02-23T00:00:00.000Z",
    "space": {
        "sys": {
            "type": "Link",
            "linkType": "Space",
            "id": "qa65bkvd5q1q"
        }
    },
    "createdBy": {
        "sys": {
            "type": "Link",
            "linkType": "User",
            "id": "1QaAgxMYKvdas32K4v319F"
        }
    }
}

Upload a file

NOTE: The API base URL for this action is https://upload.contentful.com.

Uploads a file to temporary file storage. Include the binary data you want to send in the request body, and Content-Type: application/octet-stream in the headers.

Creating an upload resource

Retrieving an upload

NOTE: The API base URL for this action is https://upload.contentful.com.

Retrieves an unmodified image. This is the same URL from an asset's file.url field, containing the token ids and image name.

Retrieve an upload

Deleting an upload

NOTE: The API base URL for this action is https://upload.contentful.com.

Deletes a file from temporary data storage and all the metadata associated with the given upload_id.

Note: This action can not be undone.

By default, all uploaded files are automatically deleted after 24 hours starting from when first upload request is issued.

Delete an upload

Assets

Assets collection

Assets represent files in a space. An asset can be any file, including an image, a video, an audio file, or PDF. Assets are usually attached to entries with links.

You can localize assets by providing separate files for each locale. Assets which are not localized provide a single file under the default locale.

Creating an asset requires three steps and API calls:

  1. Create an asset.

  2. Process an asset.

  3. Publish an asset.

Get all assets of a space

To fetch specific assets use query search parameter.

Create an asset

When using this endpoint, an ID will be automatically generated for the created asset and returned with the response.

Published assets collection

Get all published assets of a space

Retrieves the published versions of all assets in a space.

Asset

Create/update an asset

Use this endpoint to create a new asset with a specified ID, or update an existing asset with its ID.

Note: When updating an existing asset, you need to specify the last version you have of the asset with X-Contentful-Version.

Get a single asset

Delete an asset

Asset processing

Asset processing happens asynchronously, the call will not block other calls until it has finished.

Process an asset

Asset publishing

After publishing the asset, it will be available via the Content Delivery API.

Publish an asset

Unpublish an asset

Asset archiving

You can only archive an asset when it's unpublished.

Archive an asset

Unarchive an asset

Locales

Locales allow you to define translatable content for assets and entries. A locale includes the following properties:

  • name: A human readable identifier for a locale. For example, 'British English'.

  • code: An identifier used to differentiate translated content in API responses. For example, 'en-GB'.

  • fallbackCode: The code of the locale to use if there is no translated content for the requested locale. For example, en-US. You can set it to null if you don't want a default locale. This can only be set via the API, and not with the Web app or SDKs.

Locale collection

Get all locales of a space

The locales endpoint returns a list of all created locales. One will have the flag default set to true and is the locale used in the CDA, and you specified no other locale in the request.

Create a locale

Use this endpoint to create a new locale for the specified space. You cannot create two locales with the same locale code.

Locale

Get a locale

This endpoint returns a single locale and its metadata.

Update a locale

Use this endpoint to update existing locales in the specified space.

Note: Changing the code of a locale changes the responses for upcoming requests, which might break your existing code. Changes to the code property of locales used as a fallback are not allowed. You have to first ensure that the locale is not used as a fallback by any other locale before changing its code.

A space's default locale is permanent. This means you cannot change a locale's default property.

Deleting a locale

This endpoint deletes an existing locale. It's not possible to recover from this action, all content associated with this specific locale will be deleted and cannot be recreated by creating the same locale again.

Deleting a locale used as a fallback is not allowed. You first have to ensure that a locale is not used as a fallback before being able to delete it.

Search parameters

You can add search parameters to your query, read the reference documentation for the Content Delivery API for a full list of search parameters supported. The CMA does not support the include and locale parameters.

Webhooks

Webhooks notify a person or service when content has changed by calling a preconfigured HTTP endpoint. You can use this for notifications, static site generators or other forms of post-processing sourced from Contentful.

Headers

Every webhook request includes the following predefined headers:

Header Name Value
X-Contentful-Topic ContentManagement.[Type].[Action]
X-Contentful-Webhook-Name Webhook's name
Content-Type application/vnd.contentful.management.v1+json

Consuming services can use the X-Contentful-Topic header to determine the type of the payload included in the webhook call without looking into it. The topics depend on various actions which are described in the concepts section.

The `X-Contentful-Topic` header can have the following values:
  • `ContentManagement.ContentType.create`
  • `ContentManagement.ContentType.save`
  • `ContentManagement.ContentType.publish`
  • `ContentManagement.ContentType.unpublish`
  • `ContentManagement.ContentType.delete`
  • `ContentManagement.Entry.create`
  • `ContentManagement.Entry.save`
  • `ContentManagement.Entry.auto_save`
  • `ContentManagement.Entry.archive`
  • `ContentManagement.Entry.unarchive`
  • `ContentManagement.Entry.publish`
  • `ContentManagement.Entry.unpublish`
  • `ContentManagement.Entry.delete`
  • `ContentManagement.Asset.create`
  • `ContentManagement.Asset.save`
  • `ContentManagement.Asset.auto_save`
  • `ContentManagement.Asset.archive`
  • `ContentManagement.Asset.unarchive`
  • `ContentManagement.Asset.publish`
  • `ContentManagement.Asset.unpublish`
  • `ContentManagement.Asset.delete`

Custom headers

Besides these headers, you can configure webhooks to be called with a set of additional headers of your choice. When creating or updating a webhook, you can provide a list of headers that will be included in successive calls to that webhook.

For example assume that:

  • One of your entries has just been published.

  • The name of your webhook is 'Notify subscribers'.

  • You have defined two custom headers, X-Notify: subscribers and Authentication: subscribers.

The webhook would be called with the following set of headers:

X-Contentful-Topic: ContentManagement.Entry.publish
X-Contentful-Webhook-Name: Notify subscribers
X-Notify: subscribers
Authentication: subscribers

Custom headers are provided with the headers property of the Webhook Definition:

{
  ...,
  "headers": [
    { "key": "X-Notify", "value": "subscribers" },
    { "key": "Authentication", "value": "subscribers" }
  ]
}

You can mark a header as secret. Value of secret headers is hidden in the Web App, API responses and logs. The first time you define a secret header you need to provide its value and the secret flag set to true:

{
  ...,
  "headers": [
    { "key": "X-Notify", "value": "subscribers" },
    { "key": "Authentication", "value": "subscribers", "secret": true }
  ]
}

Any consecutive update can omit the value property as long as the secret is true. Previously provided value will be used in this scenario:

{
  ...,
  "headers": [
    { "key": "X-Notify", "value": "updated subscribers" },
    { "key": "Authentication", "secret": true }
  ]
}

Body

The payload received by a webhook will change depending on the action type:

  • For Publish it will receive the latest published version. The same payload as the CDA with the exception that the payload for Entries and Assets will contain all locales, e.g. instead of fields.name will be fields['en-US'].name.

  • For Unpublish and Delete it will receive a deletion object. In the case of Entries, the deletions are extended with the id of their Content Type.

  • For Auto Save, Archive, Unarchive and Create it will receive the latest draft version at the time the webhook was triggered. That's the same payload as the one available through the Management API.

Error handling

Contentful will use the HTTP response status code of the webhook call to decide whether it succeeded or failed:

  • Success: The webhook responded with an HTTP status code < 300.

  • Error: The webhook responded with an HTTP status code >= 300.

In case of an error with a status code >= 500, the webhook will periodically retry its request with increasing delays up to a maximum of 3 attempts.

Filtering webhook calls

In many use cases receiving a webhook call for all the events taking place in Contentful leads to complex filtering logic that has to be implemented on the receiving side. There are two mechanisms allowing webhook calls to be triggered conditionally:

  • selection of a triggering event(s)

  • filtering based on properties of a webhook payload

An event is a combination of the entity type and an action performed on it. For example the Entry.save event happens when an entry is updated with the CMA. ContentManagement.Entry.save is the topic for this event.

To select which events should trigger a webhook call set the topics property of a webhook to one or more event names. You can use a wildcard character * to indicate all entity types or actions should cause a webhook call. Please note that if you use the wildcard character and we add new entity types or actions your webhook receiver will be called with new events.

Possible values for topics are:

  • ["*.*"] will trigger a webhook call for all the supported events in Contentful

  • ["Entry.*"] will trigger a webhook call for all actions performed on entries

  • ["*.save"] will trigger a webhook call when any of supported entities is saved

  • ["Entry.save", "Entry.delete"] will trigger a webhook call only for the events listed

Once triggering events are selected webhook calls can be narrowed down further using webhook payload filtering.

There are 3 webhook payload properties you can filter on:

  • sys.id - entity ID

  • sys.environment.sys.id - environment ID

  • sys.contentType.sys.id - content type ID (applicable only to entries)

These properties can be used as doc in the filters. There are 6 filters available:

Operator Example Behavior
equality
{"equals": [
{"doc": "sys.id"},
"main_nav"
]}
will trigger only for entity with ID main_nav
negation of equality
{"not": {"equals": [
{"doc": "sys.id"},
"main_nav"
]}}
will trigger for all entities but entity with ID main_nav
inclusion
{"in": [
{"doc": "sys.environment.sys.id"},
["qa", "staging"]
]}
will trigger if environment of an entity is either qa or staging
negation of inclusion
{"not": {"in": [
{"doc": "sys.environment.sys.id"},
["qa", "staging"]
]}}
will trigger if environment of an entity is neither qa nor staging
regular expression
{"regexp": [
{"doc": "sys.environment.sys.id"},
{"pattern": "^ci-.+$"}
]}
will trigger for all environments prefixed with ci-
negation of regular expression
{"not": {"regexp": [
{"doc": "sys.environment.sys.id"},
{"pattern": "^ci-.+$"}
]}}
will trigger for all environments that are not prefixed with ci-

The filters property of a webhook holds zero or more filters in an array. While deciding if a webhook should be called all filters are joined with logical AND.

If there is no value for the filters property (or it is null) then by default a webhook will be triggered only in the master environment.

Combining all the mechanisms together we can achieve fine-grained webhook calls. The following webhook will be triggered only for (un)publish actions performed on entries with IDs main_nav or footer_nav in all environments prefixed with test-:

{
  "name": "My webhook",
  "url": "https://my-webhook-receiver.com/ping",
  "topics": [
    "Entry.publish",
    "Entry.unpublish"
  ],
  "filters": [
    {"in": [{"doc": "sys.id"}, ["main_nav", "footer_nav"]]},
    {"regexp": [{"doc": "sys.environment.sys.id"}, {"pattern": "^test-.+$"}]}
  ]
}

Transforming webhook calls

By default every webhook call:

  • uses the POST HTTP method

  • has the Content-Type header set to application/vnd.contentful.management.v1+json

  • does not have the Content-Length header set

  • sends a predefined body depending on the triggering event (as described above)

If you control the code of your webhook receiver you can respond to the default webhook call appropriately by implementing a custom logic in your receiver. The situation is different if you try to call an API you don't control with a webhook: most likely the default webhook payload won't adhere to the format expected by the API.

The transformation property of a webhook definition allows you to define:

  • custom HTTP method

  • custom Content-Type header

  • if automatically computed Content-Length header should be included

  • custom webhook call body that may or may not make use of the default webhook body

The transformation property is an optional object containing the following properties. None of these properties is required.

transformation.method can be one of:

  • POST (default)

  • GET

  • PUT

  • PATCH

  • DELETE

transformation.contentType can be one of:

  • application/vnd.contentful.management.v1+json (default)

  • application/vnd.contentful.management.v1+json; charset=utf-8

  • application/json

  • application/json; charset=utf-8

  • application/x-www-form-urlencoded

  • application/x-www-form-urlencoded; charset=utf-8

Using the last two options will convert the JSON body to URL encoded form data.

transformation.includeContentLength can be either true or false. If true the Content-Length header will be present with its value set to automatically computed byte length of the request body.

transformation.body can be any arbitrary JSON data structure. It will be used as the webhook call body. It's possible to use values from the original webhook payload in the transformed body. There are two ways to resolve original values:

Resolving a whole value

  1. In your data structure introduce a string value that starts with { and ends with } in a place you want to resolve the original value

  2. In between curly braces put an absolute JSON pointer to the property you want to resolve; the original webhook body is stored in the payload top-level namespace

  3. The string value containing a pointer will be replaced with the resolved value

For example, given the following original payload:

{
  "sys" {
    "id": "entry-id"
    "type": "Entry"
  },
  "fields": {
    "title": {
      "en-US": "hello world"
    }
  }
}

And the following body transformation:

{
  "entryId": "{ /payload/sys/id }",
  "title": "{ /payload/fields/title }"
}

Your webhook will be called with:

{
  "entryId": "entry-id",
  "title": {
    "en-US": "hello world"
  }
}

Using string templates

  1. In your data structure introduce a string value that contains an absolute JSON pointer to the property you want to resolve, wrapped with { and }

  2. The original webhook body is stored in the payload top-level namespace

  3. JSON pointers will be replaced with resolved values

  4. All values, including complex ones, will be stringified

For example, given the following original payload:

{
  "sys" {
    "id": "entry-id"
    "type": "Entry"
  },
  "fields": {
    "title": {
      "en-US": "hello world"
    }
  }
}

And the following body transformation:

{
  "entityInfo": "Entity of type { /payload/sys/type } with ID { /payload/sys/id }",
  "title": "Entity title is { /payload/fields/title/en-US }",
  "stringified": "Let's try to stringify an object: { /payload/fields/title }"
}

Your webhook will be called with:

{
  "entityInfo": "Entity of type Entry with ID entry-id",
  "title": "Entity title is hello world",
  "stringified": "Let's try to stringify an object: {\"en-US\":\"hello world\"}"
}

URL transformation

Webhook URLs can contain JSON pointers as described in the previous section. They always follow string template resolution logic. For example a webhook defined as follows will result in a call to https://my-webhook-endpoint.com/my-entry-1 for an entity with ID my-entry-1.

{
  "name": "Dynamic URL",
  "url": "https://my-webhook-endpoint.com/{ /payload/sys/id }"
}

Transformation context

When transforming both request body and URL, JSON pointers are used to resolve values. Values are resolved from a context object. Currently the context object has three properties:

  • payload contains the original webhook payload

  • topic is a string containing the webhook topic

  • user is a stripped-down version of a User entity for the user who executed action triggering the webhook call; the only available pointer is { /user/sys/id }

AWS Webhook Integration

AWS Webhook Integration is available on our enterprise-grade Professional and Scale platforms (via Committed, annual plans). Contact us if you are interested in learning more about this feature.

AWS offers over 100 cloud services, with the most prominent examples being data stores (S3, DynamoDB), serverless engines (Lambda), queuing systems (SQS) and many more.

Most AWS services use AWS Signature Version 4 to authenticate requests to their APIs. Computing the signature requires a prepared canonical request (a request without the Authorization header) and AWS credentials. They are all used as the input for the AWS Signature Version 4 algorithm. Its output is a value that should be used as the Authorization header.

The headers and body values of a webhook are likely changing between individual requests. This means the canonical request will differ and previously computed Authorization headers will be invalid. The proxy that the AWS Webhook Integration is using will re-compute the signature for every request.

If you have AWS Webhook Integration enabled you can use its proxy within a webhook so all requests will be automatically signed. You can either start from a webhook template or follow these steps to configure it manually:

  1. Create a webhook performing a canonical AWS request to the service you use. All standard features available for webhooks are available.

  2. Replace amazonaws.com with awsproxy.contentful.com in the webhook URL.

  3. Set a X-Contentful-AWS-Proxy-Key-Id header with your AWS Access Key ID.

  4. Set a X-Contentful-AWS-Proxy-Secret header with your AWS Secret Access Key. Make sure it's marked as secret!

The proxy will automatically sign all requests using the credentials provided. Credentials have to have IAM role assigned allowing to perform selected action.

The proxy is an internal system and cannot be accessed from the public Internet. Only our webhook system can use this proxy.

Webhooks collection

Get all webhooks of a space

Create a webhook

Webhook

Create/update a webhook

Get a single Webhook

Delete a webhook

Webhook calls

You often need to analyze the exact request and response payloads and headers to verify that the setup is correct or to diagnose issues. To help with this, some API endpoints are available that expose this information.

Webhook call overview

This call returns a list of the most recent webhook calls made, their status, possible errors, and the target URL.

Get an overview of recent calls

Webhook call details

The call details provide detailed information about the outgoing request and the response, including headers, body and possible errors. Request and response body are currently truncated at 500kb and 200kb respectively.

Get the webhook call details

Webhook health

The health endpoint provides an overview of recently successful webhook calls:

Get webhook health

Roles

Creating custom roles allows an administrator to restrict the access of users to certain resources. Roles follow a whitelisting approach, which means that you need to define everything a user is allowed to do. A role contains a name, description, permissions and policies.

Permissions can be basic rules which define whether a user can read or create content types, settings and entries.

The following permissions are supported:

Permission Purpose
ContentModel Can modify content types (the content type builder is only shown to users who have this permission).
ContentDelivery Can create and update API keys for this space
Environments Can manage and use all sandbox environments in this space. Content level permissions do not apply in a sandbox environment.
Settings Can modify space settings. This permission allows users to modify locales, webhooks, and the space name. It does not grant permission to update users roles or delete the space.

and each of those permission can have the following values:

Value Effect
null, [] Disable the permission
[ "read" ] Allow only reading (not supported for Settings and Environments)
[ "manage" ], "all" Allow reading and writing

You can also create policies to allow or deny access to resources in fine-grained detail. With these polices you can, for example, limit read access to only entries of a specific content type or write access to only certain parts of an entry (e.g. a specific locale).

The following constraints are supported.

and

This constraint evaluates if all conditions are true. The value is an array of other constraints.

For example, to limit a user to a particular content type:

{"and": [
    { "equals": [{ "doc": "sys.type" }, "Entry"] },
    { "equals": [{ "doc": "sys.contentType.sys.id" }, "2PqfXUJwE8qSYKuM0U6w8M"] }
]}

equals

This constraint compares an entity's system metadata against a specific value. Note that fields of an entry or an asset are not currently supported, only system metadata. This is a basic constraint and typically used to ensure the type of a document or to match entries of a content type.

not

This constraint inverts the result of its value.

A typical use case for this constraint is the inversion of whitelists to a blacklist. For example, if a user should not be able to see entries of a specific content type, you can deny access to those content types or allow access to all but entries of that content type:

{"and": [
  { "equals": [{ "doc": "sys.type" }, "Entry"] },
  { "not": { "equals": [{ "doc": "sys.contentType.sys.id" }, "2PqfXUJwE8qSYKuM0U6w8M"] } }
]}

or

This constraint evaluates if one condition returns true. The value is an array of constraints.

Use the constraint to enable an action for different resources. E.g. a user should only be allowed to read entries of a specific content type or all assets:

{"or": [
  {"and": [
      { "equals": [{ "doc": "sys.type" }, "Entry"] },
      { "not": { "equals": [{ "doc": "sys.contentType.sys.id" }, "2PqfXUJwE8qSYKuM0U6w8M"] } }
  ]},
  { "equals": [{ "doc": "sys.type" }, "Asset"] }
]}

Roles collection

Get all roles

This endpoint returns a paginated list of roles for a given space. Each role contains a name, a description, permissions and policies, which describe what a user can and cannot do.

Create a role

Use this endpoint to create a custom role. The role name must be unique within the space.

Role

Get a single role

Use this endpoint to read an existing single role.

Update a single role

Use this endpoint to update an existing role. You cannot use the endpoint to create a new role with a specific id.

Delete a single role

Use this endpoint to delete an existing role. You can only delete roles if there is no user in the space with only that role assigned, i.e. a user must have at least one role.

Snapshots

Snapshots represent an entity at a given time in the past. A snapshot is automatically created each time an entry or a content type is published.

Snapshots are only available for entries and content types belonging to the master environment.

Each snapshot has two top level objects, sys and snapshot. The snapshot object contains the content of the entity at the moment the snapshot was taken. The sys object contains meta information about the snapshot and has the following nested properties:

Field Type Description
type String Type of the resource. For snapshots it will always be Snapshot
createdAt Date Timestamp with the moment when the snapshot was created
createdBy Link A reference to the user who created the snapshot
id String The unique identifier for this snapshot
snapshotType String The type of snapshot. For now the only valid value is publish
snapshotEntityType String Type of the entity in the snapshot. Entry or ContentType

Entry Snapshots collection

Get all snapshots of an entry

Entry Snapshot

Get a snapshot of an entry

Content Type Snapshots collection

Get all snapshots of a content type

Content Type Snapshot

Get a snapshot of a content type

Space memberships

Space memberships collection

Get all space memberships

This endpoint returns a paginated list of all space memberships.

Create a space membership

Use this endpoint to create a space membership (or invite a user to a space). A user can and must be flagged as 'admin' or assigned to certain roles.

Space membership

Get a single space membership

This endpoint returns details about an existing space membership.

Update a single space membership

This endpoint allows you to change a space membership. Use this to assign additional roles or flag a user as 'admin'.

Delete a single space membership

This endpoint allows you to delete a space membership. It only changes if a user can access a space, and not the user record.

Note: It's possible to remove every administrator from a space which could mean there is no one left to manage the users. You can fix this by inviting a new user through the web app organization settings.

API keys

These endpoints allow you to manage Content Delivery API (CDA) and Content Preview API (CPA) keys. These tokens provide read-only access to one or more environments. For each environment you want to access with a given token, you need to include a link to this environment in the environments property when creating or updating. Only the environments specified in this property can be accessed using this token and any CDA or CPA request using this token to access content from an environment not specified here will result in a 404 error. If the environments key is not specified, the token will have access to the master environment by default.

We recommend using different access tokens for different environments in your development process. For example, use one for your production environment and another for staging or continuous integration. This allows you to revoke them individually in the future and manage your delivery channels independently.

Delivery API keys collection

Get all Delivery API keys

Create a Delivery API key

This endpoint allows you to create a Delivery API key and its corresponding Preview API key.

Delivery API key

Get a single Delivery API key

This endpoint returns details about an existing Delivery API key.

Update a single Delivery API key

This endpoint allows you to update a Delivery API key and its corresponding Preview API key.

Note: When updating an existing API key, you need to specify the last version you have of the API key with X-Contentful-Version.

Delete a single Delivery API key

This endpoint allows you to delete a Delivery API key and its corresponding Preview API key.

Preview API keys collection

Even though they are accessed through a different endpoint, Preview API keys are handled together with Delivery API keys. This means that when you create a CDA key, the corresponding CPA key will be created. A Delivery API key object will contain a link to its corresponding CPA key, which will need to be resolved calling the appropriate endpoint. Preview API keys also cannot be deleted, as they will be deleted along with their Delivery API keys.

Get all Preview API keys

Preview API key

Get a single Preview API key

This endpoint returns details about an existing Preview API key.

Personal access tokens

This set of endpoints allows you to manage personal access tokens. These tokens provide you with access to the Content Management API (CMA) and are an alternative means of authentication to our existing OAuth 2.0 flow.

A personal access token inherits the same access rights as your Contentful account. In other words, if you have access to multiple spaces and organizations, your token will too.

Personal access tokens collection

Create a personal access token

This endpoint allows you to create a personal access token. When creating, you'll need to specify at least one scope, which is used to limit a tokens access. The following scopes are supported:

  • content_management_read - Read-only access

  • content_management_manage - Read and write access

Since content_management_manage allows you to read and write, specifying

"scopes": ["content_management_manage"] is equivalent to:

"scopes": ["content_management_read", "content_management_manage"]

Note: This is the only time you will be displayed the token attribute, which contains your access token for the Content Management API. Please ensure you copy it and keep it in a safe place (e.g. outside of your source code repository, an environment variable on your server, ...)

Get all personal access tokens

This endpoint will return all active personal access tokens. Revoked tokens will not be returned with this collection.

Personal access token

Get a single personal access token

This endpoint returns details about an existing personal access token.

Token revoking

Revoke a personal access token

This endpoint allows you to revoke a personal access token. It will set revokedAt to the timestamp of when the request was received.

Note: This action can not be undone.

Users

User

Get the authenticated user

This endpoint returns details about your Contentful user account.