Content Management API

Introduction

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

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

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:

  • Between 1 and 64 characters.

  • Consist of alphanumeric characters, minus -, underscore _ and a period ..

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

Rate limits refer to the number of requests per unit of time you can make to Contentful APIs.

There are no limits enforced on requests that hit our CDN cache, i.e. the request doesn't count towards your rate limit and you can make an unlimited amount of cache hits. For requests that do hit the API, there is a rate limit of 216000 requests per hour and 78 requests per second. Higher rate limits might apply for enterprise clients.

The limit exists to prevent unlimited usage and restrict the consumption of resources from a single account. The rate limit uses a standard mechanism of the HTTP protocol to return a 429 response code with a X-Contentful-RateLimit-Reset header that tells a user when they can make their next request.

Header Status Code Description
X-Contentful-RateLimit-Reset 429. Returned only for rate limited requests. The number of seconds until the next request can be made.

Note: The X-Contentful-RateLimit-Reset header does not return the time until the next full reset. It tells you when you can make the next request. If a per second rate limit is enforced it will return 1 (time until the next second). If an hourly rate limit is enforced it will return the time until the next sliding window.

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: None of the sys fields are editable and you can only specify the sys.id field when creating an item (as long as it's not a Space).

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.contentType Link Link to entry's content type. Entries
sys.publishedCounter Integer Number of times resource was published. Entries, assets, content types
sys.publishedVersion Integer Published version of resource. Entries, assets, content types
sys.version Integer Current version of resource. Entries, assets, content types
sys.firstPublishedAt Date Time resource was first published. Entries, assets, content types
sys.createdAt Date Time resource was created. Entries, assets, content types
sys.createdBy Link Link to creating user. Entries, assets, content types
sys.publishedAt Date Time resource was published. Entries, assets, content types
sys.publishedBy Link Link to publishing user. Entries, assets, content types
sys.updatedAt Date Time resource was updated. Entries, assets, content types
sys.updatedBy Link Link to updating user. Entries, assets, content types

Collection resources and pagination

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

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

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

API versioning

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

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

Reference

Spaces

Spaces collection

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

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

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

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.

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 {"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 optional min and max parameters and validates the size of the array (number of objects in it). Arrays, Text, Symbol {"size": { "min": 5, "max": 20}}
range Takes optional min and max parameters and validates the range of a value. Number, Integer {"range": { "min": 5, "max": 20}}
regexp Takes a string that reflects a JS regex and flags, validates against a string. See JS reference for the parameters. Text, Symbol {"regexp": {"pattern": "^such", "flags": "im"}}
unique Validates that there are no other entries that have the same field value at the time of publication. Symbol, Integer, Number {"unique": true}

Note: Validations will take effect after the content type has been activated and existing entries will not be validated until they are re-published.

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

Changing field IDs

You can change the ID of a content type field in the Contentful Web App. The API will return different data after this change, and this might break your existing code base. Read more about managing changes to content structure in our multiple environments guide.

Omitting fields

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

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

Deleting fields

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

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

Get a single content type

Delete a content type

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

Content type activation

Activate a content type

Deactivate a content type

Activated content type collection

Get all activated content types of a space

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

Editor interface

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

Editor interface

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

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

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

Get the editor interface

Update the editor interface

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

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

Create an entry

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

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

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

Entry

Create/update an entry

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

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

Get a single entry

Delete an entry

Entry publishing

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

Publish an entry

Unpublish an entry

Entry archiving

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

Archive an entry

Unarchive an entry

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

Create an asset

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

Published assets collection

Get all published assets of a space

Retrieves the published versions of all assets in a space.

Asset

Create/update an asset

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

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

Get a single asset

Delete an asset

Asset processing

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

Process an asset

Asset publishing

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

Publish an asset

Unpublish an asset

Asset archiving

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

Archive an asset

Unarchive an asset

Locales

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

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

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

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

Locale collection

Get all locales of a space

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

Create a locale

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

Field locales

Create a field locale

Use this endpoint to create locales for specific fields. You need to send data for all fields, even those you are not updating.

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.

It's not possible to change the default locale of a space, as these are permanent entities.

Deleting a locale

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

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

Search parameters

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

Webhooks

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

Headers

Every webhook request includes the following predefined headers:

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

Consuming services can use the X-Contentful-Topic header to determine the type of the payload included in the webhook call without looking into it. The Content-Type header has the application/vnd.contentful.management.v1+json value as many web frameworks and their middleware components only automatically parse a request body if the content-type header is application/json, and thus require additional configuration to parse request bodies with a different content-type header.

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

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, the webhook will periodically retry its request with increasing delays up to a maximum of 3 attempts.

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. 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 field or metadata against a specific value. 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 entry at a given time in the past. A snapshot is automatically created each time an entry is published.

Each snapshot has two top level objects, sys and snapshot. The snapshot object contains the content of the entry 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 Date 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

Snapshots collection

Get all snapshots of an entry

Snapshot

Get a snapshot

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

This endpoint allows you to manage Content Delivery API (CDA) keys. These tokens provide read-only access to a single space. You need to obtain a new token for every new space you want to access.

We recommend using different access tokens for different applications or delivery channels. For example, use one for an iOS app and another for an Android app. This allows you to revoke them individually in the future and manage your delivery channels independently.

API keys collection

Get all API keys

Create an API key