Content Delivery API
Introduction
The Content Delivery API (CDA), available at cdn.contentful.com, is a read-only API for delivering content from Contentful to apps, websites and other media. Content is delivered as JSON data, and images, videos and other media as files.
The API is available via a globally distributed content delivery network (CDN). The server closest to the user serves all content, which minimizes latency and especially benefits mobile apps. Hosting content in multiple global data centers also improves the availability of content.
Basic API information
https://cdn.contentful.com
Authentication
Any client requesting content from the CDA needs to provide an access token that has access to the environment you're requesting content from. For example, if you create an access token that only has access to the master
environment of your space, you will not be able to use this token to access content from any other environment.
You have two options to supply the access token, either as an Authorization
request header field, or as an access_token
URI query parameter. The CDA implements the standardized OAuth 2.0 bearer token specification already supported by many HTTP clients.
You create access tokens in the APIs tab of each space in the Contentful web app. Our reference guide has more details on how authentication works with Contentful.
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.
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 Content Delivery API enforces rate limits of 55 requests per second. Higher rate limits may apply depending on your current plan.
When a client gets rate limited, the API responds with the 429 Too Many Requests HTTP status code
and sets the X-Contentful-RateLimit-Reset
header that tells the client when it can make its next request.
The value of this header is 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.
Example
The current rate limit for a client is the default 55 per second. Client: 85 uncached requests in 1 second
HTTP/1.1 429
X-Contentful-RateLimit-Reset: 1
Meaning: wait 1 second before making more requests.
Common resource attributes
Every resource returned by the Content Delivery API will have 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
in the creation of an item (If it's not a *space_).
Contentful defines the sys.id
property 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 | Resource type. | 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.revision | Integer | Published version of resource. | Entries, assets, content types |
sys.createdAt | Date | Time published resource was first created. | Entries, assets, content types |
sys.updatedAt | Date | Time resource was updated. | Entries, assets, content types |
sys.locale | String | Locale of the resource. | Entries and assets |
Note: The revision
field refers to the current number of published revisions of an entry. Find out more in the Content Management API documentation.
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.
Reference
Spaces
All content and assets in Contentful belong to a space. You will generally have at least one space for a project, but use separate spaces for testing or staging.
Space
Each space has a name, a set of locales, and metadata about the space.
Get a space
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 model
Get the content model of a space
Content type
Get a single content type
Entries
Entries represent anything defined as a Content Type in a space. Entries can have link fields that point to other entries or assets. You can learn more about links in our concept guide.
Entries collection
In the JSON response of a successful query, linked items are placed in the includes
array, when not already fetched in the items
array.
Get all entries of a Space
Entry
The include
array is not applicable while retrieving a single entry.
Get a single entry
Assets
Assets are the binary files in a space. An asset can be any file type and are usually attached to entries with links.
You can localize assets by providing separate files for each locale. Assets which are not localized are available as a single file under the default locale.
When you query for entries which contain links to assets then all assets are included by default.
Asset properties:
Field | Type | Description |
---|---|---|
sys | Sys | Common system properties. |
fields.title | Text | Title of the asset. |
fields.description | Text | Description of the asset. |
fields.file | File | File(s) of the asset. |
fields.file.fileName | Symbol | Original filename of the file. |
fields.file.contentType | Symbol | Content type of the file. |
fields.file.url | Symbol | URL of the file. |
fields.file.details | Object | Details of the file, depending on its MIME type. |
fields.file.details.size | Number | Size (in bytes) of the file. |
For image assets, the fields.file.url
field will point to images.ctfassets.net
. For other file types, it will point to assets.ctfassets.net
.
You can use query parameters to define the image size, cropping parameters and other options. Find out more in our Images API reference.
Assets collection
Get all assets of a space
Asset
Get a single 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 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.
Links
Links are a powerful way to model relationships between content entries and assets. You can learn more about links in our concept guide.
Retrieval of linked items
When you have related content (e.g. entries with links to image assets) it's possible to include both search results and related data in a single request. Using the include
parameter, you can specify the number of levels to resolve.
The maximum number of levels is 10. The API will throw a BadRequestError
for higher values or values other than an integer. The default number, if the parameter is not specified, is 1. To omit linked items, specify include
as 0.
If the standard items
array has not already retrieved the linked entries, they will be in the includes.Entry
array. Linked assets are inside the includes.Asset
array.
Note: The include
parameter resolves links between entries and assets within a space. Links between content types within a space are not included in the response.
Note: The include
parameter is only available for the entry collection endpoint /spaces/{space_id}/environments/{environment_id}/entries
.
Query entries
Links to a specific item
If you want to retrieve all items linked to a specific entry, the query URL should filter entries on their specific content_type
, linking_field
(field to link items) and entry_id
from the target entry.
Query entries
Search parameters
You can use a variety of query parameters to search and filter items in the response from any collection endpoint including entries, content types and assets.
Content type
To search for entries with a specific content type, set the content_type
URI query parameter to the ID you want to search for.
Note: When querying entries and using search filters based on fields
or ordering by fields
you must specify this parameter. You can only specify one value for content_type
at a time.
Query entries
This example finds all entries of content type 'Product'.
Select operator
The select operator allows you to choose what fields to return from an entity. You can choose multiple values by combining comma separated operators.
For example, if you want to return the sys.id
and fields.name
of an Entry you would use:
/spaces/yadj1kx9rmg0/environments/{environment_id}/entries/?select=sys.id,fields.productName&content_type=2PqfXUJwE8qSYKuM0U6w8M
You can fetch the entire sys
or fields
object and it's sub-fields by passing it to the select
operator. For example to omit the sys
object:
/spaces/yadj1kx9rmg0/environments/{environment_id}/entries/?select=fields&content_type=2PqfXUJwE8qSYKuM0U6w8M
The select operator has some restrictions:
It is only applicable for collections of Entries and Assets, and with an Entry you must provide the
content_type
query parameter.It can only select properties to a depth of 2. For example,
select=fields.productName.en-US
is not valid.If you want to select a property for a specific locale, you need to combine the
select
andlocale
operators, e.g/assets/?select=fields.productName&locale=en-US
.You can select up to 100 properties.
If you use the select operator on an Entry with linked fields, only the content linked to a field you select will be returned.
If you provide an invalid property path, e.g fields.doesNotExist
, Contentful returns a 400 Bad request
containing the invalid property path.
Query entries
To select only the productName
field of each entry.
Equality operator
You can search for exact matches by using the equality operator. This includes querying an entry by an ID value instead of retrieving the Entry directly, which allows you to include resolved links.
Note: Equality and inequality operators are not supported for text fields and you need to constrain search queries for fields with a content_type
URI query parameter.
Query entries
To find all entries with the ID 5KsDBWseXY6QegucYAoacS
(IDs are unique).
Inequality operator
Uses the [ne]
parameter to exclude items matching a certain pattern.
Query entries
To return all entries, except those with the ID 5KsDBWseXY6QegucYAoacS
.
Array equality/inequality
The equality/inequality operators also work with array fields:
Equality: If one of the items in an array matches the searched term, then it returns the entry.
Inequality: If one of the fields in an array matches the searched term, then the entry is not returned.
Note: As the query filters by a field, you need to specify a content type.
Query entries
This example finds all products tagged as accessories
by matching fields.tags
(an array) against a single value.
Array with multiple values
It's possible to use the [all]
operator to retrieve entries matching a specific set of values (e.g. fields.likes[all]=flowers,accessories
)
Query entries
To find all products tagged as flowers
and accessories
by using the all
operator with fields.tags
(an array) and the two values.
Inclusion
You can filter a field by multiple values with the [in]
operator. When applied to an array value there must be at least one matching item. Similarly, when including a field value, you need to specify a Content type.
Query entries
To retrieve entries that match accessories
and flowers
.
Exclusion
You can filter a field by multiple values with the [nin]
operator. When applied to an array value there must be at least one not matching item. Similarly, when including a field value, you need to specify a content type.
Query entries
To retrieve all products tagged as neither 'flowers' nor 'accessories'.
Existence
You can check for the presence of a field using the [exists]
operator. It checks whether a certain field is defined (i.e. it has any value) or not.
If the field is not defined, it will not be present in the JSON payload and the operator will consider it non-existent.
You can pass true
or false
as a parameter depending on if you want to retrieve entries where the field exists (true
) or does not exist (false
). Please note that the parameter is case sensitive, True
or False
are not valid values.
Query entries
To retrieve all entries that have a value for field.tags
defined.
Ranges
Four range operators are available that you can apply to date and number fields:
[lt]
: Less than.[lte]
: Less than or equal to.[gt]
: Greater than.[gte]
: Greater than or equal to.
When applied to field values, you must specify the content type in the query.
Query entries
To retrieve entries updated since midnight of January 1st 2013.
Full-text search
It's possible to perform a full-text search across all text and symbol fields with the query
parameter.
Note: Full-text search is case insensitive and might return more results than expected. A query will only take values with more than 1 character.
Query entries
To retrieve all entries containing the word 'design'.
Full-text search on a field
You can perform a full-text search on a specific field with the [match]
operator.
Note: Full-text search is case insensitive and might return more results than expected. A query will only take values with more than 1 character.
Query entries
To retrieve all entries which contain words starting with 'content' in the 'website' field.
Location proximity search
You can use a proximity search on location-enabled content to find results in a specified geographical area.
Note: Queries that include exact coordinates can't take advantage of our caching layer. With many use cases it should be enough to round the coordinates to 3 decimal places (an accuracy of about 300m), 2 decimal places (an accuracy of about 1km) or more to improve your cache hit rates.
Query entries
A common use case for location search is to search for places close to the user's current position.
Use the [near]
operator to show results closest to a specific map location and order the results by distance.
This will return all entries sorted by distance from the point at latitude=38
and longitude=-122
.
Locations in a bounding object
When displaying content on a map it's more resource efficient to retrieve only content that is in the current visible map area. For these cases, use the within
operator.
Similar to the 'near me' use case, this lets you search for locations that are within the specific area on the map and can be useful for finding related entries in the vicinity of another entry.
There are two ways to search for nearby locations.
1. Using a bounding rectangle:
To search for locations within a rectangle area object, use the structure field.center[within]=latitude1,longitude1,latitude2,longitude2
, where:
latitude1
andlongitude1
refer to the coordinates of the bottom left corner of the rectangle.latitude2
andlongitude2
refer to the coordinates of the top right corner of the rectangle.
2. Using a bounding circle:
The structure field.center[within]=latitute,longitude,radius
will return entries included in the circle with fields.center
of the given latitude, longitude and radius (in km).
Query entries
To retrieve entries where fields.center
is within the rectangle with:
Bottom left corner: latitude 1, longitude 2.
Top right corner: latitude 3, longitude 4.
Links to entry
To search for entries which have a field linking to a specific entry, set the links_to_entry
URI query parameter to the ID you want to search for.
NOTE: For most use cases it is more performant to query based on a content type's reference field if the desired content type is known. See Search on references for an example query
Query entries
Links to asset
To search for entries which have a field linking to a specific asset, set the links_to_asset
URI query parameter to the ID you want to search for.
Query entries
Order
You can order items in the response by specifying the order
search parameter. You can use sys
properties (such as sys.createdAt
) or field values (such as fields.myCustomDateField
) for ordering.
Note: You must set the content_type
URI query parameter to the ID of the content type you want to filter by. You can only use the following field types with the order
parameter:
Name | JSON Primitive | Description |
---|---|---|
Symbol | String | Basic list of characters. Maximum length is 256. |
Integer | Number | Number type without decimals. Values from -253 to 253. |
Number | Number | Number type with decimals. |
Date | String | Date/time in ISO-8601 format. |
Boolean | Boolean | Flag, true or false . |
The following field types do not support the order parameter:
Name | JSON Primitive | Description |
---|---|---|
Text | String | Same as symbol, but can be filtered via full-text search. Maximum length is 50,000. |
Link | Object | See links |
Array | Array | List of values. Value type depends on field.items.type . |
Object | Object | Arbitrary object. |
If you don't pass an explicit order value the returned collection items will be ordered
descending by publication timestamp (sys.updatedAt
) and ascending by id
(sys.id
). This means that recently published items will appear closer to
the top and for those with the same publication timestamp the order will be
based on the items' ids.
Query entries
To retrieve all entries ordered by creation date.
Reverse order
You can reverse the sort order by prefixing the field with a -
symbol.
Query entries
To order results by the time of the last update, newest to oldest.
Order with multiple parameters
You can order items by specifying the order
parameter with attributes(attribute
, attribute2
). Prefix the field with a -
sign to reverse the sort order of the attribute.
Query entries
Limit
You can specify the maximum number of results as a limit
search parameter.
Note: The maximum number of entries returned by the API is 1000. The API will throw a BadRequestError
for values higher than 1000 and values other than an integer. The default number of entries returned by the API is 100.
Query entries
To limit results to 3 entries.
Skip
You can specify an offset with the skip
search parameter.
Note: The API will throw a BadRequestError
for values less than 0 or values other than an integer.
By combining skip
and limit
you can paginate through results:
Page 1: skip=0, limit=15 Page 2: skip=15, limit=15 Page 3: skip=30, limit=15 etc.
Query entries
To skips 3 entries.
Filtering assets by MIME type
You can filter assets by their MIME type group by using the mimetype_group
query parameter. Valid groups are attachment
, plaintext
, image
, audio
, video
, richtext
, presentation
,
spreadsheet
, pdfdocument
, archive
, code
and markup
. By default, the API will return all assets.
Query assets
To return only image assets.
Search on references
You can search for entries based on the values of referenced entries.
For example, if you want to find products of a particular brand, you can use search on references to find the products with one API request.
Structure of a query
Here's how the example above would look as a query:
content_type=2PqfXUJwE8qSYKuM0U6w8M&fields.brand.sys.contentType.sys.id=sFzTZbSuM8coEwygeUYes&fields.brand.fields.companyName[match]=Lemnos
First is the
content_type
parameter which you must include when you want to filter based on the values of the fields of entries of a certain content type.Second is
fields.brand.sys.contentType.sys.id=sFzTZbSuM8coEwygeUYes
which you use to to filter on fields of entries from content type2PqfXUJwE8qSYKuM0U6w8M
.Third is
fields.brand.fields.companyName[match]=Lemnos
which filters entries to those branded as 'Lemnos'.
Note: All filters on referenced entries are scoped with the path to the field that contains the reference. In the previous example that path is fields.brand
.
You can search on multiple references at once and combine them into one singe API query with a series of field and value pairs.
Available nested filters
You can use the all
, in
, nin
, exists
, match
, gt
, gte
,lt
, lte
, ne
, near
and within
filters when searching on references. The semantics of these filters are the same as when you use them on a non referenced entry.
Restrictions
Searching on references has the following restrictions:
You can only search on references on fields which link to a single entry. Fields which hold references to many entries or fields with references to assets are not supported.
The maximum number of reference searches in one query is 2. A larger value will return an error.
Search on references
This example will return the Lemnos branded products.
Localization
Retrieve localized entries
You can specify a locale for entries using the locale
URI query parameter.
The locale parameter must be the code of a locale in the space you're querying, or the wildcard value *
. If you don't specify a locale, the default locale of the space is used.
If there's no content available for the requested locale the API will try the fallback locale of the requested locale.
For example you have the de-CH
(Swiss German) locale and configure it to fallback to de-DE
(German). When you request content for de-CH
any missing field in that locale will be replace with its fallback value in de-DE
(if they exist). For more information about locale fallbacks read the locale section of the CMA docs.
When you specify locale=*
, field values are nested in an object with keys corresponding to each locale with a defined value. Instead of writing fields.productName
when accessing the response data from your code, use fields.productName[localeCode]
.
If the result contains only a single locale, resources will include the property sys.locale
indicating the locale of that object.
Learn more about locales in our concepts document.
Query entries
fields.productName
is the only localized field in the product
content type, so returns all other fields in the default locale.
Synchronization
The Sync API allows you to keep a local copy of all content in a space up-to-date via delta updates, or only the content that has changed.
Syncing specific content
By default a sync request response includes all resource types including assets, entries of all content types and deleted resources.
To sync specific content you can specify a type
parameter for the initial sync:
Parameter | Description |
---|---|
all (default) | Include all new and changed content, i.e., assets, entries and deletions. |
Asset |
Only include new and changed assets. |
Entry |
Only include new and changed entries. |
Deletion |
Only include deletions of assets and entries. |
DeletedAsset |
Only include deletions of assets. |
DeletedEntry |
Only include deletions of entries. |
Initial synchronization
A client syncs content by using the sync endpoint. A single sync consists of one or more pages, each a separate request and response.
The first time a client synchronizes content it sends a request to the sync endpoint with the URI query parameter initial
set to true
.
You should only sync with initial=true
for the initial sync when a client has no existing content. This transfers all content from a space, but does not contain content deleted from fields or deleted assets and content entries.
The limit
parameter sets the page size for the number of retrieved entries. The limit is useful when you have very large content entries and reach the maximum response size limit. This limit is then encoded in the synchronization token and used for all following synchronizations.
Sync only contains content from the master environment and is not containing deltas from sandbox environments.
Query entries
Initial synchronization of entries of a specific content type
For entries, you can also specify a content_type
parameter. When specifying content_type
you must specify type
as Entry
(meaning there will be no deletions). You can only specify the type
and content_type
parameter at the initial sync along with the initial
parameter. Any subsequent syncs will only include the types you have specified. If you want to sync entries by content type you should separately subscribe to a Deletion
or DeletedEntry
sync to be notified when entries are deleted.
Query entries
Pagination and subsequent syncs
Synchronization responses contain either a nextPageUrl
or nextSyncUrl
attribute. If there is more content for the current sync, nextPageUrl
will contain an URL with a sync_token
which will retrieve the next page. This continues until you have retrieved all content.
At this point, the response will contain a nextSyncUrl
which you use to make requests in the future and retrieve delta updates between the current content on Contentful and what you retrieved with your last sync request. Upon completion, you will receive a new nextSyncUrl
which you can again use for future updates.
If a client loses the nextSyncUrl
, the client should delete its local content and perform an initial synchronization again.
NOTE: The initial query with sync_token
will persist across subsequent syncs.
Query entries
Structure of deleted entities
For deletions, objects of the types DeletedAsset
and DeletedEntry
are sent. Those do not contain full assets or entries.