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
https://api.contentful.com
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
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 thefilters
property or setting its value tonull
. 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
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
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 Asset
s 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:
Create an asset.
Process an asset.
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 tonull
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
andlocale
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
andAuthentication: 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 offields.name
will befields['en-US'].name
.For
Unpublish
andDelete
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
andCreate
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 IDsys.environment.sys.id
- environment IDsys.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": [ |
will trigger only for entity with ID main_nav |
negation of equality | {"not": {"equals": [ |
will trigger for all entities but entity with ID main_nav |
inclusion | {"in": [ |
will trigger if environment of an entity is either qa or staging |
negation of inclusion | {"not": {"in": [ |
will trigger if environment of an entity is neither qa nor staging |
regular expression | {"regexp": [ |
will trigger for all environments prefixed with ci- |
negation of regular expression | {"not": {"regexp": [ |
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 methodhas the
Content-Type
header set toapplication/vnd.contentful.management.v1+json
does not have the
Content-Length
header setsends 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
headerif automatically computed
Content-Length
header should be includedcustom 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
In your data structure introduce a string value that starts with
{
and ends with}
in a place you want to resolve the original valueIn 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 namespaceThe 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
In your data structure introduce a string value that contains an absolute JSON pointer to the property you want to resolve, wrapped with
{
and}
The original webhook body is stored in the
payload
top-level namespaceJSON pointers will be replaced with resolved values
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 payloadtopic
is a string containing the webhook topicuser
is a stripped-down version of aUser
entity for the user who executed action triggering the webhook call; the only available pointer is{ /user/sys/id }
AWS Webhook Integration
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:
Create a webhook performing a canonical AWS request to the service you use. All standard features available for webhooks are available.
Replace
amazonaws.com
withawsproxy.contentful.com
in the webhook URL.Set a
X-Contentful-AWS-Proxy-Key-Id
header with your AWS Access Key ID.Set a
X-Contentful-AWS-Proxy-Secret
header with your AWS Secret Access Key. Make sure it's marked as secret!Optionally you can set a
X-Contentful-AWS-Proxy-Content-Type
header to a customContent-Type
value if a service being called requires it (for exampleapplication/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 accesscontent_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 toactive
orresolved
- The
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 toactive
orresolved
- The
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 ascheduled
state
- The
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 appsrc
: publicly available source URL of the app; requires HTTPS with exception oflocalhost
(for development)locations
: list of places in the Web App where the app can be rendered; see belowparameters
: 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 | { |
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 AppDefinition
s. 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 HTTPStopics
: 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 theAppDefinition
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.