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 modeling 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 rate limit.

By default the Contentful Management API enforces rate limits of 7 requests per second. 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-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-Reset: 0
X-Contentful-RateLimit-Second-Limit: 7
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 specifying the time before the limit resets and another request will be accepted. As the client is rate limited per second, the header will return 1, which means the next second.

Examples:

The current rate limits for a client are the default 7 per second.

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 when paging through larger result sets to keep ordering predictable. For example, order=sys.createdAt will order results by the time the resource was first published.

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.

You can also create an environment with any other environment as a source by providing the X-Contentful-Source-Environment header and providing it with the environment ID for the desired source environment.

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.

Create an environment with a different source

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

Get a single environment

Delete an environment

Environment aliases

Disclaimer: Any user may opt-in and create the Master environment alias. Creating additional custom aliases is only available for Enterprise customers on current pricing plans.

An environment alias allows you to access and modify the data of an environment, called the target environment, through a different static identifier.

You must opt-in to this feature in the Contentful web app on the Settings > Environments page. During this opt-in process, we create a default alias with the ID master. This alias cannot be renamed or deleted. Once you've opted in, you can create up to two more aliases. Only space admins can opt-in and manage environment aliases.

Aliases and target environments can be used to enhance your development and deployment workflows. For example, you can safely apply content model changes and roll them back when necessary or use them in your CI/CD pipelines.

Check out the concepts section to find out more about environment aliases.

Creating environment aliases

When you set up this feature for your space, we create a default master environment alias for you. You can also create up to two more aliases by sending a PUT request to spaces/<id>/environment_aliases/<alias_id> and specifying the target environment in the payload as described below.

Aliases must always target an existing environment. Environments targeted by aliases cannot be deleted. The master environment alias cannot be deleted.

Updating environment aliases

To change the target environment of an environment alias, you need to be a space admin. Similar to environments, you cannot change an environment alias id.

You do this by sending a PUT request to /spaces/<id>/environment_aliases/<alias_id> specifying the target environment in the payload as described below.

Deleting environment aliases

You can delete an environment alias by sending a DELETE request to /spaces/<id>/environment_aliases/<alias_id>. It is not possible to delete the master alias or its target environment.

Accessing data using an environment alias

To request data using the environment alias, specify the alias ID instead of the ID of the target environment.

For example, if the master alias targets an environment with ID target-environment, you can access its data from /spaces/<id>/environments/master/....

Master alias

Requests without the environment alias fragment will be treated like requests to the master environment alias. For example, requests to /spaces/<id>/entries will have the same outcome as requests to /spaces/<id>/environments/master/entries.

New environment properties when using aliases

Fetching an environment can now be done through the environment's ID or alias ID.

New properties are introduced on environments that are targeted by aliases.

  • Fetching the environment using the environment identifier e.g. target-environment

GET /spaces/{space_id}/environments/{environment_id}

#  Sample response body
{
  "name": "target-environment",
  "sys": {
    "type": "Environment",
    "id": "target-environment",
    "version": 1,
    "space": { ... },
    },
    # NEW - list of environment aliases that target this environment
    "aliases": [{
      "sys": {
        "type": "Link",
        "linkType": "EnvironmentAlias",
        "id": "master"
      }
    }],

    "status": { ... },
    "createdBy": { ... },
    "createdAt": "2018-10-08T09:07:03Z",
    "updatedBy": { ... },
    "updatedAt": "2018-10-08T09:07:03Z"
  }
}
  • Fetching the environment using the environment alias identifier master

GET /spaces/{space_id}/environments/{environment_alias_id}

# Sample response body
{
  "name": "master",
  "sys": {
    "type": "Environment",
    "id": "master",
    "version": 1,
    "space": { ... },
    # NEW - the targeted environment
    "aliasedEnvironment": {
      "sys": {
        "type": "Link",
        "linkType": "Environment",
        "id": "target-environment"
      }
    },
    # NEW - list of environment aliases that target this environment
    # for consistency we also return the aliases
    "aliases": [{
      "sys": {
        "type": "Link",
        "linkType": "EnvironmentAlias",
        "id": "master"
      }
    }],

    "status": { ... },
    "createdBy": { ... },
    "createdAt": "2018-10-08T09:07:03Z",
    "updatedBy": { ... },
    "updatedAt": "2018-10-08T09:07:03Z"
  }
}

Environment alias collection

Get all environment aliases of a space

Environment alias

Get a single environment alias

Create/Update an environment alias

Use this endpoint to create a new environment alias or change the environment which the environment alias references.

Note that when updating an environment alias, the following headers need to be specified:

  • X-Contentful-Version, you need to specify the last version of the environment alias you are updating with

Delete an environment alias

Note: You can never delete the master environment alias.

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"}}
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
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 an entry in the Contentful Web App.

Editor interface collection

Get all editor interfaces of a space

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. If a content type is not activated yet, the API will return a 404 response. An editor interface is created automatically on the first activation of a content type and updated when a content type field is added, removed or renamed.

Read more about how the Web App uses editor interfaces.

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 no 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

* Valid field types are:

  • {type: "Symbol"}

  • {type: "Text"}

  • {type: "RichText"}

  • {type: "Integer"}

  • {type: "Number"}

  • {type: "Date"}

  • {type: "Boolean"}

  • {type: "Location"}

  • {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.

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

Content tags

This feature is only available to a select group of organizations. Please contact Contentful support for more information.

Content tags allow you to group entries and assets within your space environment. This makes it much easier to find and organize content.

Tags are environment-scoped (meaning, they exist within and are unique to an environment). They are only available via the Content Management API.

To learn about using tags in the web app, see our content tags article in our Help Center.


A tag includes the following properties:

  • name: A human-readable unique identifier for the tag

  • id: A unique identifier for referencing the tag

Note: Currently, only space admins and users with permission to manage tags can create and manage tags.

Tag collection

Get all tags

Returns all the tags that exist in a given environment.

Tag

Create a tag

Returns a newly created tag.

Note: Both name and id must be unique to each environment. Tag names can be modified after creation, but the tag id cannot.

Get a single tag

Returns a single tag based on the given identifier.

Update a tag

Returns an updated tag.

Delete a tag

Deletes a tag from the entries and/or assets that reference it.

Content tags on entries and assets

Once a tag is created within an environment, users can add the tag to entries and/or assets within that environment. They can also remove the tag from the entries and/or assets.

Note: A new metadata property is introduced to the entry and asset payload. This metadata property has as its value a tags list. The tags list contains all the tags (in their Link form) that exist on the entry or asset.

Add a tag to an entry

Returns a specified entry with a new metadata property. The metadata property holds the list of tags added.

The same behavior applies for assets.

Remove a tag from an entry

Returns a specific entry with a new metadata property. If no other tags exist on the entry, the metadata property will hold an empty list of tags.

The same behavior applies for assets.

Querying entries or assets by content tags

You can query for entries and assets by their content tags. For entries, the search is across content types.

The query parameter starts with “metadata.tags” and the operators supported are [all], [in], [nin] and [exists].

Retrieve entries or assets that match a specific set of values

The query parameter starts with metadata.tags.sys.id[all]

Retrieve entries or assets that match at least one of the specified values

The query parameter starts metadata.tags.sys.id[in]

Check the presence of a tag on entries or assets

The query parameter starts with metadata.tags[exists]

You can pass “true” or “false” as a parameter depending on if you want to retrieve entries/assets where a tag exists (true) or does not exist (false).

This parameter is case sensitive: “True” or “False” are not valid values.

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

Use this endpoint to fetch an entry with a specified ID. All empty entry fields are omitted from the response, that means if the field is empty it's key is not going to be presented in the response. If the entry has no set fields the corresponding key is missing as well. In order to update the entry with empty fields all keys that need to be updated should be added to the entry object.

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

Deleting an asset will remove the current asset and all previously referenced files on the CDN. It can take up to 48 hours until these files will be made unavailable from (assets|images|downloads|videos).ctfassets.net.

Asset processing

To publish an asset, you need to process it before. This step is fetching the image from the given location to Contentful's system. This request might return before the asset processing is finished. The asset will have a fields.file.url for the respective locale if processing completed successfully.

Process an asset

Asset publishing

Publish an asset

After publishing the asset, it will be available via the Content Delivery API. It will also be available from our asset domain assets.ctfassets.net as specified in the fields.file.url of the asset or if it is an image, it is available from images.ctfassets.net. In this case, you can use query parameters to define the image size, cropping parameters and other options. Find out more in our Images API reference. Published assets do not need any authentication on the Images or Assets API.

Unpublish an asset

Unpublishing will put the asset back into draft state.

Asset archiving

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

Archive an asset

Archiving an asset will remove the current asset and all previously referenced files on the CDN. It can take up to 48 hours until these files will be made unavailable from (assets|images|downloads|videos).ctfassets.net.

Unarchive an asset

Unarchiving an asset will bring back the asset, the current and all previously referenced files into a draft state. It can take up to an hour for the files to be available on the CDN again.

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.

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

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. There are however some differences:

  • The CMA does not support the include and locale parameters.

With the introduction of content tags, you can query for entries / assets by their content tags via the CMA.

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\"}"
}

Helpers

In some cases, there can be a need for trimming or slightly modifying certain fields before delivering them to the webhook target. Contentful provides numerous helpers that can be used at the transformation level. For example:

{
  "content": "{ first-paragraphs 2 /payload/fields/content/en-US }",
}

Above-mentioned example limits the content field with first 2 paragraphs. If the content field has more than two paragraphs, the rest of the text gets trimmed. In addition to trimming content, helpers are useful in modifying or refining content. Following is another transformation, using the strip-stop-words helper:

{
  "keywords": "{ strip-stop-words /payload/fields/content }",
}

The above transform filters out stop words and delivers only the keywords in the content field. For example:

Art is the expression or application of human creative skill and imagination

becomes:

art expression application human creative skill imagination

Refer the table below to see the full list of available functions:

Helper name Parameter Description
first-chars Number Selects first n characters of the field.

Example:
{ first-chars 6 /payload/fields/content/en-US }
first-words Number Selects first n words of the field.

Example:
{ first-words 12 /payload/fields/content/en-US }
first-paragraphs Number Selects first n paragraphs of the field.

Example:
{ first-paragraphs 3 /payload/fields/content/en-US }
strip-stop-words - Strip out stop words (only English is supported).

Example:
{ strip-stop-words /payload/fields/content/en-US }
strip-markdown - Strip out Markdown markup.

Example:
{ strip-markdown /payload/fields/content/en-US }
stringify - Stringify the object pointed to.

Example:
{ stringify /payload/fields }

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!

  5. Optionally you can set a X-Contentful-AWS-Proxy-Content-Type header to a custom Content-Type value if a service being called requires it (for example application/x-amz-json-1.0).

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 environments in this space. Content level permissions do not apply in non-master environments.
EnvironmentAliases Can create environment aliases and change their target 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.

Note: It may take some time for a new or updated API key to propagate through Contentful systems, typically within seconds. If you encounter HTTP 401 errors, for example when using an API key recently created during CI, you may need to add a delay or poll until the 401 status resolves.

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.

Entry tasks

Tasks are the building blocks to setup editorial workflows on your content. They allow editorial teams to distribute work with clear accountability.

Unresolved tasks block entry publishing

The entry publishing method will return an error if an attempt is made to publish an entry which has unresolved tasks. This is a measure to avoid the accidental publication of content which is not ready to be released.

There can be cases where an entry has to be published even though it has unresolved tasks. There are two options in this case:

  • a space admin resolves or removes the tasks and then publishes the entry

  • the creators of the unresolved tasks remove them and then publish the entry

Availability

Tasks are only available on enterprise space types.

Task schema

A Task has four top level properties: assignedTo, body, status and sys. These are described in detail below.

Field Type Required Description
assignedTo Link true A reference to the user to whom the task is assigned
status String true Field that can take the values active or resolved
body String true The body of the task, describing what has to be done. It has maximum size of 512 bytes
sys Object true System resource properties

In addition to the common sys properties tasks have the following extra sys properties

Field Type Description
parentEntity Link A reference to the entry in which the task exists

Actors

When talking about tasks in this documentation we consider the following actors:

  • Task creator, the person who created the task.

  • Task assigner, the person who assigns a task to an user. It will usually be the same as the creator.

  • Task assignee, the person who has to do the work specified in the task and resolve once finished.

Tasks collection

Get all tasks of an entry

Use this endpoint to get all the tasks of an entry. This API does not offer pagination, calls to it will return all the existing tasks.

Permissions

Any user with read access to an entry can read all the tasks in the entry. Space admins can read all the tasks in any entry.

Create a task

Use this endpoint to create a new task. When using this endpoint, an ID will be automatically generated for the created task and returned in the response.

There's a limit of 100 tasks per entry. An attempt to create more than 100 tasks will result in an error.

Permissions

Any user with read access to an entry can create tasks in the entry. Space admins can create tasks on any entry.

The API does not check if the task assignee has read access to the entry where the task exists. If task assignees do not have read access to the entry they won't be able to resolve them.

Notifications

When a task is created an email is sent to the task assignee to let she know that a task has been assigned to her.

Errors

  • A 400 - BadRequest error is returned if there's an attempt to create more than 100 tasks in one entry.

  • A 422 - ValidationFailed error is returned if:

    • The body field has a value bigger than 512 bytes
    • The status field has a value different to active or resolved

Task

Get a single task

Use this endpoint to fetch a task with a specified ID.

Permissions

Any user with read access to an entry can read a task in the entry. Space admins can read any task in any entry.

Delete a task

Use this method to delete a task.

Permissions

Task creators can delete their own tasks. Admins can delete any task on any entry.

Notifications

No notification is sent when a task is deleted.

Update a task

Use this method to modify the body of the task, re-assign it to another member of the space or resolve it. Note that the body or the assignee of a task can't be modified if the task has already been resolved. Unresolve it first to be able to update these fields.

Permissions

Update permissions are a bit more complex so we are going to use a table to present all the possible combinations of which field can be updated by whom.

Field \ Whom Task assignee Task creator Space admin
assignedTo no yes yes
body no yes yes
status yes no yes

Errors

  • A 400 - BadRequest error is returned if a task's body or assignee are updated after the task has been resolved.

  • An 403 - AccessDenied error is returned in the following cases:

    • A user different from the task assignee or an admin marked a task as resolved.
    • A user different from the task creator or an admin changed the task assignee.
    • A user different from the task creator or an admin changed the task body.
  • A 422 - ValidationFailed error is returned if:

    • The body field has a value bigger than 512 bytes
    • The status field has a value different to active or resolved

Notifications

Depending on which field is updated and by whom the recipient of the notification will vary.

  • Updates to body
Who \ recipient task assignee task creator space admins
task creator yes no no
space admins yes yes no
  • Updates to assignedTo
Who \ recipient old task assignee new task assignee task creator space admins
task creator yes yes no no
space admins yes yes yes no
  • Updates to status
Who \ recipient task assignee task creator space admins
task assignee no yes no
space admins yes yes no

Scheduled Actions

Enables users to create actions that will be performed on an entity at given time in the future.

Currently supported actions:
  • Publish an entry

  • Unpublish an entry

Find out more regarding entry publish in entry publish docs.

Availability

Scheduled action feature is globaly available for all customers except those on legacy pricing plans.

Notifications

If an entry fails to publish at the scheduled time due to entry validation errors, the user who scheduled the action is notified via email.

Limitations

The current limit of scheduled actions in scheduled status is 500. Once it's reached, no additional scheduled actions can be created.

In addition there is a limit of 200 entries that can be scheduled to be executed in a single minute.

Scheduled action schema

The scheduled action has five top level properties: entity, environment, scheduledFor and action. These are described in detail below.

Field Type Required Description
entity Link true A reference to the entity object that the action is created for.
environment Link true A reference to the enviroment object that the action is created for.
scheduledFor Object true The body of the scheduled action, with the single property datetime
action String true Action name for action to be scheduled
sys Object true System resource properties

Scheduled action status

Every scheduled action has a sys.status field. It contains one of the following values:

Status Description
canceled The action was canceled by the user and will never be processed.
failed The action failed to process successfully.
scheduled The initial status of the scheduled action.
succeeded The action has been processed successfully.

Once the scheduled action is created the status is set to scheduled. In case the scheduled action is canceled before the execution, the status is set to canceled.

Once the scheduled action was executed the status is set to succeeded in case of successful execution and to failed if any error happened during execution process.

Scheduled actions collection

For more information about scheduled actions in the web app, see our Help Center article.

Get all scheduled actions of an entry

Use this endpoint to get all the scheduled actions of an entry.

Collection filters

Scheduled actions collection supports fillowing filters:

Params Required Description
?environment.sys.id="" Yes Filter by the external environment ID.
?entity.sys.id=1 No Filter by the list of entity ids
?sys.status[in]=<scheduled|canceled...> No Filter by the list of the scheduled actions' statuses
?sys.status=<scheduled|canceled...> No Filter by single scheduled actions' status
?scheduledFor.datetime="ISO-time" No Filter by exact match of the scheduledFor.datetime property
?scheduledFor.datetime[lt|lte|gt|gte]="ISO-time" No Filter by comparison the scheduledFor.datetime property

Collection ordering

Scheduled actions collection supports fillowing ordering options:

Params Description
?order=-scheduledFor.datetime Descending order for scheduled actions, ascending if the parameter is absent provided.

Collection pagination

The scheduled actions collection endpoint implements cursor-based pagination. The pages object contains the next key which contains the relative URL to the next batch of items. The URL contains the same set of filters and limit as initially requested. This key is presented only if there are available elements to be fetched that weren't returned from the current request because of the requested limit. The pages object also contains the prev key for every request after the initial request. It contains the relative URL to the batch of items requested in the previous request. The default page size if 100 and the maximum allowed limit is 1000.

Permissions

Any user can read all the scheduled actions in the entry.

Create a scheduled action

Use this endpoint to create a new scheduled action. When using this endpoint, an ID will be automatically generated for the created scheduled action and returned in the response.

There's a limit of 200 scheduled actions in pending status per environment. An attempt to create more than 200 pending scheduled actions will result in an error.

Permissions

Any user with publish access to an entry can read all the scheduled actions in the entry.

Errors

  • 400 Error is returned in case:

    • Enviroment is not found
    • Exceeds pending actions limit
  • 422 Invalid request payload input return in following cases:

    • The body contains invalid payload
    • The scheduledFor.datetime is in the past or is not corrent ISO format
    • The action is unsupported

Scheduled action

Cancel a scheduled action

Use this method to mark a scheduled action as canceled.

Permissions

Any user with publish access to an entry can set a scheduled action to canceled state.

Errors

  • 400 Error is returned in case:
    • The sys.status is not in a scheduled state

App definitions

AppDefinition is an entity type that stores all information about a single Contentful app on the organization level. By itself this entity does not do anything. To use an app you need to create an AppInstallation in a selected space-environment pointing to your definition.

Definitions centralize app management within an organization. Changes to a definition will automatically be propagated to all of its installations. There is no need to update installations when updating a definition.

App definition properties

  • name: a human-readable name of the app

  • src: publicly available source URL of the app; requires HTTPS with exception of localhost (for development)

  • locations: list of places in the Web App where the app can be rendered; see below

  • parameters: definitions of configuration parameters

App locations

Locations are described in more detail in the SDK reference.

The locations property is an array of one or more of:

Location locations array item Description
Entry field
{
"location": "entry-field",
"fieldTypes": [
{ "type": "Symbol" }
]
}
Renders as an entry field editor; requires at least one field type (see below)
Entry sidebar { "location": "entry-sidebar" } Renders in the entry sidebar
Entry editor { "location": "entry-editor" } Replaces the entire entry editor
Dialog { "location": "dialog" } Renders in a dialog window
App configuration { "location": "app-config" } Renders on the app configuration screen
Page { "location": "page" } Renders a separate page. You can add an optional navigationItem property, see below.

Entry field location

All valid fieldTypes are:

  • Short text: { "type": "Symbol" }

  • Short text, list: { "type": "Array", "items": { "type": "Symbol" } }

  • Long text: { "type": "Text" }

  • Rich text: { "type": "RichText" }

  • Number, integer: { "type": "Integer"}

  • Number, decimal: { "type": "Number" }

  • Boolean: { "type": "Boolean" }

  • Date and time: { "type": "Date" }

  • Location: { "type": "Location" }

  • JSON object: { "type": "Object" }

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

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

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

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

Page location

When you add a page location in your AppDefinition, there is the possibility to add an optional navigationItem property to it.

{
  "location": "page",
  "navigationItem": {
    "name": "My app",
    "path": "/my-app"
  }
}
{
"location": "page",
"navigationItem": {
"name": "My app",
"path": "/my-app"
}
}

If provided, a link will be added to the "Apps" navigation item in the Contentful Web App pointing to your app installation.

Example

The following app definition is called "Hello world" which is served from https://example.com/hello-app.html and can be rendered both as an editing widget for short text fields and as an app configuration screen:

{
  "name": "Hello world",
  "src": "https://example.com/hello-app.html",
  "locations": [
    {
      "location": "entry-field",
      "fieldTypes": [
        { "type": "Symbol" }
      ]
    },
    {
      "location": "app-config"
    }
  ]
}

App definitions collection

Get all app definitions

Create a new app definition

App definition

Get one app definition

Update an app definition

Delete an app definition

App event subscriptions

AppEventSubscription is an entity type that defines Contentful event topics (for example: "entry publication") to which an app is subscribed. Event subscriptions can be defined only for existing AppDefinitions. An app only receives events about content entities in a space-environment of its installation.

App definition properties:

  • targetUrl: a URL to be called with events specified as topics; requires HTTPS

  • topics: list of event topics

All listed properties are required.

All valid topics are:

  • Entry.create

  • Entry.delete

  • Entry.save

  • Entry.publish

  • Entry.unpublish

  • Entry.archive

  • Entry.unarchive

  • Asset.create

  • Asset.delete

  • Asset.save

  • Asset.publish

  • Asset.unpublish

  • Asset.archive

  • Asset.unarchive

  • ContentType.create

  • ContentType.delete

  • ContentType.save

  • ContentType.publish

  • ContentType.unpublish

App event subscription

Get an app event subscription

Update or subscribe to events

Delete an app event subscription

App keys

AppKey is an entity that represents a key pair that can be used by an app to make a signed request to Contentful in order to issue an access token for a specific app installation.

The top-level jwk property holds a standard JSON Web Key. The following properties require constant values:

  • alg: "RS256"

  • kty: "RSA"

  • use: "sig"

As shown, the generated key must be a RSA key using the RS256 algorithm. To generate such a key pair, openssl (you may need to download a binary if you're not on Mac or Linux) can be used:

openssl req -x509 -newkey rsa:4096 -nodes -batch -noout -keyout key.pem
openssl rsa -in key.pem -pubout -outform DER -out key.der.pub

The content of key.der.pub can be used as the first element of the x5c array. Please note:

  • the string needs to be encoded as a base64 string

  • Contentful never expects your private keys: make sure you're uploading the public key!

The signature value is used as both kid and x5t. We will also use it as a globally unique key identifier within Contentful. To generate a signature use:

openssl dgst -binary -sha256 < key.der.pub | openssl base64 | sed 's/+/-/g; s/\//_/g; s/=*$//'

Limitations:

  • the same key pair cannot be used for more than one app

  • the limit of keys per app is 3 (which makes it possible to perform a rotation while keeping one backup key operational)

If you do not want to create your own key pair with openssl, we also offer the functionality to generate the key pair for you. It is important to note that we do not store any private keys on our side and only store the public key. We show the private key only once in the response of the POST request, so make sure that you store the private key and keep it safe. Once the response is lost, there is no other way to retrieve the private key.

App keys

Get all app keys

Create a new app key

Generate a new key pair

App key

Get one app key

Delete an app key

App installations

AppInstallation is an entity type that indicates if an app described by some AppDefinition is installed in a space-environment.

An app installation can store app-specific configuration variables in its parameters property. This property is optional, and when present it can be a free-form object with values managed by the code of the app with the SDK. The only limitation is that the stringified value of parameters cannot be longer than 16kB.

App installations are copied in the process of environment creation. This means that when app X is installed in the master environment and then you create a staging environment out of it, both the installation and its parameter will be copied to the target (staging) environment.

App installations collection

Get all app installations

App installation

Install or update an app

Get one app installation

Uninstall an app

App access token

AppAccessToken entities allow apps to act on their own in space-environments in which they are installed.

In terms of access, an access token for an app:

  • is scoped to a specific space-environment matching the space-environment of an app installation

  • allows all actions on the following entity types: ContentType, EditorInterface, Entry, Asset

  • allows reading of the app's configuration parameters

To obtain an access token, an app needs to use one of its active private keys (with a corresponding public key registered as an AppKey) to sign a JWT.

The following claims are mandatory:

  • iss: Issuer - sys.id value of the AppDefinition

  • exp: Expiry - number of seconds the JWT should be valid; not longer than 10 minutes

The following header properties are mandatory:

  • typ: "JWT"

  • alg: "RS256"

A JWT created this way can be used to call the endpoint described below. The response will contain the value of the app access token as the token property. The token can be used to call CMA endpoints (as outlined above) for 10 minutes. The token can be cached until it expires.

App access token

Issue a token for an app installation in a space-environment

Usage

Enables users to query organization API usage data. You can further filter by Contentful API types (cma, cda, cpa, gql) through the parameter metric. Results are paginated and support ordering.

Permissions

Usage API is available to Enterprise, Team and Community tiers. Enterprise and Team customers can access historical usage data with API batch size of 45 days. Community tiers can access the last 45 days of historical usage data. Usage API calls can only be made by a user with the Organization Admin or Organization Owner role.

Organization usage

Query organization usage by metric for a given date range. If startAt and endAt are not passed through the query a historical data for the last 45 days will be returned by default.

Get organization usage

Space usage

Query organization usage by space and metric for a given date range.

Get space usage