Overview

Introduction

In addition to the Content Delivery API (CDA) for published content, is the Preview API for previewing both published and unpublished content. It maintains the same behaviour and parameters as the CDA, but delivers the latest drafts for entries and assets. The Content Preview API is used to display the latest version of an entry.

Note: For EU data residency customers, the Base URL is https://preview.eu.contentful.com.

Basic API information

API Base URL https://preview.contentful.com This is a read-only API

Preview API authentication

You authenticate with the Preview API in the same way as the CDA, but using a preview access token.

Your production access tokens will not work with the Preview API. The use of a separate token helps prevent accidentally leaking unpublished content. Every delivery API key has an associated preview access token, which you can view in the APIs tab of a space in the Contentful web app.

Using the Preview API

You use the Preview API as though it were the CDA, but replacing the hostname cdn.contentful.com with preview.contentful.com, and the production access token with a preview access token.

It is possible to configure a default preview environment for your entries. This guide includes examples for the generic app, custom and local preview environments.

Preview API limitations

The Preview API does not implement the Sync API, so applications that rely exclusively on the Sync API to load data will not be usable with the Preview API.

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 Preview API enforces rate limits of 14 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 limits for a client are the default 14 per second.

Example 1

Client: 21 requests in 1 second

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

Meaning: wait 1 second before making more requests.

Example 2

Client: 72,000 requests in 15 minutes:

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

Meaning: wait 1 hour before making more requests.

Example 3

Client: 100 requests in 15 mins, 0 requests in following 15 mins, 0 requests in following 15 mins, 71,000 requests in following 15 mins

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

Meaning: wait 15 mins before making more requests (which frees up 100 requests - 45 mins later 71,000 requests freed up).

Common resource attributes

Every resource returned by the Preview 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:

1{
2 "sys": {
3 "type": "Space",
4 "id": "yadj1kx9rmg0"
5 }
6}
FieldTypeDescriptionApplies to
sys.typeStringResource type.All
sys.linkTypeStringType of an entity the link is referring to.Links
sys.idStringUnique ID of resource.All except arrays
sys.spaceLinkLink to resource’s space.Entries, assets, content types
sys.environmentLinkLink to a resource’s environment.Entries, assets, content types
sys.contentTypeLinkLink to entry’s content type.Entries
sys.revisionIntegerPublish counter of the resource.Entries, assets, content types
sys.createdAtDateDate and time a resource was generated in the system.Entries, assets, content types
sys.updatedAtDateDate and time a resource was updated in the system.Entries, assets, content types
sys.localeStringLocale of a resource.Entries and assets
sys.publishedVersionIntegerPublished version of the resourceEntries, assets, content types
sys.firstPublishedAtDateDate and time a resource was first publishedEntries, assets, content types
sys.publishedAtDateDate and time a resource was publishedEntries, assets, content types

Note: The revision field refers to the current number of published revisions of an entry. Find out more in the Content Management API documentation.

Sys properties - difference in meaning in Contentful APIs Some of sys properties, while having the same label, render different kinds of data depending on the API. Please see the descriptions of these properties per API in the table below: | Property name per API | Description | | | | --- | --- | --- | --- | | CMA | CDA | CPA | | | firstPublishedAt | createdAt | - | Date and time a resource was published for the first time. | | publishedAt | updatedAt | - | Date and time a resource was published after an update. | | createdAt | - | createdAt | Date and time a resource was generated in the system. | | updatedAt | - | updatedAt | Date and time a resource was updated in the system. |

Collection resources and pagination

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

1{
2 "sys": { "type": "Array" },
3 "skip": 0,
4 "limit": 100,
5 "total": 1256,
6 "items": [ /* 100 individual resources */ ]
7}

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.

Cursor pagination

Overview

Cursor pagination is an approach to paginating datasets in Contentful APIs. Unlike traditional offset-based pagination, which uses skip and limit parameters, cursor-based pagination uses opaque cursor tokens and dedicated next/prev links to mark the position in the dataset. This can dramatically improve performance, especially for datasets with large numbers of items.

How cursor pagination works

  • Initial Request:
    Add the query parameter cursor=true to your API request, e.g.

    GET /spaces/:space_id/entries?cursor=true

    The response contains:

    • items: The current page of resources.
    • pages: Contains next (and optionally prev) URLs for paginating forward and backward.
  • Paginate forward:
    Use the pages.next URL from the previous response for the next page request:

    GET /spaces/:space_id/entries?pageNext={cursor_token}

    Continue this process until the next link is omitted, which means you’ve reached the end of the dataset.

  • Paginate backward: If the response contains a pages.prev link, you can fetch previous pages:

    GET /spaces/:space_id/entries?pagePrev={cursor_token}
  • Consistency: All query parameters used in the initial request apart from limit are locked and encoded in the cursor token. They cannot be changed between pages.

    The limit parameter can be updated, and the new value will be persisted for subsequent pages until it’s updated again.

    GET /spaces/:space_id/entries?pageNext={cursor_token}&limit={limit}

    This can be useful when you need to adjust the page size, for example, if a page size (in bytes) exceeds the response limit.

  • Total count: The response does not include a total count or a skip property. This is a key feature for performance, as the API avoids costly full counts on large datasets.

Example response

1{
2 "sys": { "type": "Array" },
3 "limit": 100,
4 "items": [ ... ],
5 "pages": {
6 "next": "/spaces/:space_id/entries?pageNext=cursor_token",
7 "prev": "/spaces/:space_id/entries?pagePrev=cursor_token"
8 }
9}

Advantages

  • Considerable performance improvements, particularly for large datasets.

If your environment contains 10s of thousands of entries or assets, consider switching to cursor pagination, it can make requests to fetch lists of entries or assets of such an environment much faster.

If you don’t paginate at all, particularly when working with CDA and you don’t need the total property from the response, we highly recommend using requests with cursor=true.

Limitations

  • The “total” property is not included in the API responses. Make sure you don’t rely on it in your workflow prior to making the switch.

Enablement and access

  • The feature is currently available in the CMA, CPA and CDA.