Was this page helpful?

The Content Management client library for PHP

This guide will show you how to get started using our PHP Content Management client library to manage content.


The easiest way to install the Contentful PHP client library is to use Composer and run the following command:

composer require contentful/contentful-management

If you haven't already, require Composer's autoload at the beginning of your application:

require_once 'vendor/autoload.php';

Setting up the Contentful client

Once you have installed the client library you need to instantiate a Client object. From that, retrieve an environment proxy: it's a utility resource which wraps resources that are environment-bound, such as entries, assets, and content types.

use Contentful\Management\Client;

$client = new Client('<accessToken>');
$environment = $client->getEnvironmentProxy($spaceId, $environmentId);

Now we need to take a brief look at the concept of proxy. In the client library, a proxy is a lazy reference to a resource, and it's designed to be used as the preferred way of working with resources that have a certain scope. There are two supported proxies: SpaceProxy, and EnvironmentProxy. The first one is supposed to be used to handle resources that are scoped to a space (API keys, roles, space memberships, file uploads, and webhooks), whereas the second is for handling resources that are scoped to an environment (assets, content types, content type snapshots, entries, entry snapshots, locales). In practice, this means that instead of relying on the client object and having to specify all required parameters on every operation, you can use a proxy and rely on that:

// Accessing environment-scoped resources with a client
$entry = $client->getEntry($spaceId, $environmentId, $entryId);
$entrySnapshot = $client->getEntrySnapshot($spaceId, $environmentId, $entryId, $snapshotId);
$asset = $client->getAsset($spaceId, $environmentId, $assetId);
$contentType = $client->getContentType($spaceId, $environmentId, $contentTypeId);
$contentTypeSnapshot = $client->getContentTypeSnapshot($spaceId, $environmentId, $contentTypeId, $snapshotId);
$locale = $client->getLocale($spaceId, $environmentId, $localeId);

// Creating a resource
$asset = new Contentful\Management\Resource\Asset();
$client->create($asset, '', ['space' => $spaceId, 'environment' => $environmentId]);

// Accessing resource through an environment proxy
$environmentProxy = $client->getEnvironmentProxy($spaceId, $environmentId);

$entry = $environmentProxy->getEntry($entryId);
$entrySnapshot = $environmentProxy->getEntrySnapshot($entryId, $snapshotId);
$asset = $environmentProxy->getAsset($assetId);
$contentType = $environmentProxy->getContentType($contentTypeId);
$contentTypeSnapshot = $environmentProxy->getContentTypeSnapshot($contentTypeId, $snapshotId);
$locale = $environmentProxy->getLocale($localeId);
$environment = $environmentProxy->toResource();

// Creating a resource
$asset = new Contentful\Management\Resource\Asset();

As you can see, an environment proxy resource is generally easier to pass around and use, as it encapsulates a reference to three things: a client, a space ID, and an environment ID. The space proxy works in the same way:

// Accessing environment-scoped resources with a client
$deliveryApiKey = $client->getDeliveryApiKey($spaceId, $deliveryApiKeyId);
$role = $client->getRole($spaceId, $roleId);
$spaceMembership = $client->getSpaceMembership($spaceId, $spaceMembershipId);
$upload = $client->getUpload($spaceId, $uploadId);
$webhook = $client->getWebhook($spaceId, $webhookId);

// Creating a resource
$upload = new Contentful\Management\Resource\Upload(file_get_contents('puppy.jpg'));
$client->create($upload, '', ['space' => $spaceId);

// Accessing resource through a space proxy
$spaceProxy = $client->getSpaceProxy($spaceId);

$deliveryApiKey = $spaceProxy->getDeliveryApiKey($deliveryApiKeyId);
$role = $spaceProxy->getRole($roleId);
$spaceMembership = $spaceProxy->getSpaceMembership($spaceMembershipId);
$upload = $spaceProxy->getUpload($uploadId);
$webhook = $spaceProxy->getWebhook($webhookId);
$space = $spaceProxy->toResource();

// Creating a resource
$upload = new Contentful\Management\Resource\Upload(file_get_contents('puppy.jpg'));

As you can see, proxies provide a more convenient way of working with resources; for this reason, we suggest using them whenever possible. In the rest of the article, we'll be using $spaceProxy and $environmentProxy to refer to such objects.

Managing your content

Even though the client library supports all Content Management API endpoints, the main use case is programmatically handling content types, assets, and entries. This getting started tutorial will focus on these resources. For all other options, please refer to the tutorial for advanced PHP CMA client library use

Content types

Creating a content type

use Contentful\Core\Api\Exception;
use Contentful\Management\Resource\ContentType;

$contentType = new ContentType('Blog Post');

$contentType->addNewField('Symbol', 'title', 'Title');
$contentType->addNewField('Text', 'body', 'Body');

$contentType->setDescription('Lorem ipsum...');

// The second parameter is optional:
// it's the ID that is going to be used to represent the resource.
// If it's not specified, it's going to be a randomly-generated string
// Let's call the API to persist the entry
try {
    $environmentProxy->create($contentType, 'blogPost');
} catch (Exception $exception) {
    echo $exception->getMessage();

echo $contentType->getId(); // prints 'blogPost'

You'll be able to access and work with fields using the following methods:

// Contentful\Management\Resource\ContentType\Field\FieldInterface[]

// Contentful\Management\Resource\ContentType\Field\FieldInterface

// $fields = Contentful\Management\Resource\ContentType\Field\FieldInterface[]
$contentType->setFields(array $fields);

// $field = Contentful\Management\Resource\ContentType\Field\FieldInterface

In the namespace Contentful\Management\Resource\ContentType\Field you will find all possible options for fields. They are a 1:1 representation of the types exposed by the Content Management API: you can take a look at the client library API docs to learn more.

Retrieving a content type

// Get a single content type:
$contentType = $environmentProxy->getContentType('<content_type_id>');

echo $contentType->getName();

// Get a collection:
// the $query object is optional
$query = (new Contentful\Management\Query())

$contentTypes = $environmentProxy->getContentTypes($query);

foreach ($contentTypes as $contentType) {
    echo $contentType->getName();

Updating a content type

$contentType = $environmentProxy->getContentType('<content_type_id>');

$contentType->setDescription('Lorem ipsum...');


Deleting a content type

$contentType = $environmentProxy->getContentType('<content_type_id>');


Publishing a content type

In order for an entry to use a content type, you must first publish it:

$contentType = $environmentProxy->getContentType('<content_type_id>');

// You can also go back and unpublish it


Let's go through the CRUD operations that you can do on entries. These examples assumes you have a content type whose ID is blogPost.

Creating an entry

use Contentful\Core\Api\Exception;
use Contentful\Management\Resource\Entry;

$entry = new Entry('blogPost');

$entry->setField('title', 'en-US', 'My awesome blog post');
$entry->setField('body', 'en-US', 'Lorem ipsum...');

// Let's call the API to persist the entry
try {
} catch (Exception $exception) {
    echo $exception->getMessage();

echo $entry->getId();

Retrieving an entry

// Get a single entry:
$entry = $environmentProxy->getEntry('<entryId>');

echo $entry->getField('title', 'en-US');

// Get a collection:
// the $query object is optional
$query = new Contentful\Management\Query();

$entries = $environmentProxy->getEntries($query);

foreach ($entries as $entry) {
    echo $entry->getField('title', 'en-US');

Updating an entry

$entry = $environmentProxy->getEntry('<entryId>');

$entry->setField('title', 'en-US', 'Another title');


Deleting an entry

$entry = $environmentProxy->getEntry('<entryId>');


More with entries

Besides CRUD options, Contentful allows you to handle publishing and archiving entries. It looks like this:

$entry = $environmentProxy->getEntry('<entryId>');




Assets are very similar to entries, in terms of which operations you can perform on them (CRUD, publish/unpublish, archive/unarchive). The main difference in terms of usage is that assets will always have the same three fields (title, description, file), which means that the client library provides methods for dealing directly with those fields. The only tricky part is how to handle file uploads. Let's take a look:

use Contentful\Core\Api\Exception;
use Contentful\Core\File\RemoteUploadFile;
use Contentful\Core\File\UnprocessedFileInterface;
use Contentful\Management\Resource\Asset;

$asset->setTitle('en-US', 'My beautiful logo');
$asset->setDescription('en-US', 'Lorem ipsum...');

$file = new RemoteUploadFile(
$asset->setFile('en-US', $file);

try {
    $id = $asset->getId();

    // After an asset's creation, you need to process it.
    // You can optionally pass a locale code;
    // if you don't, the client library will process all available locales
    // Once an asset is processed,
    // $asset->getFile() will return an instance of
    // Contentful\Core\File\File
    // instead of
    // Contentful\Core\File\UnprocessedFileInterface
    // So poll the API until you reach that stage
    while ($asset->getFile('en-US') instanceof UnprocessedFileInterface) {
        // Optionally set a delay
        // sleep(1000);
        $asset = $environmentProxy->getAsset($id);
} catch (Exception $exception) {
    echo $exception->getMessage();

In the previous example, we saw how it is possible to upload to Contentful a file that is already hosted somewhere. But it's also possible to upload a file in the local filesystem. In order to do so, you need first to actually upload the file, then link the asset to it:

use Contentful\Core\Api\Exception;
use Contentful\Management\Resource\Asset;
use Contentful\Management\Resource\Upload;

$asset->setTitle('en-US', 'My beautiful logo');
$asset->setDescription('en-US', 'Lorem ipsum...');

// $contents can be the actual file contents
// loaded for instance with file_get_contents,
// or even a resource created by using
// $contents = fopen('image.svg', 'r');
$contents = '...';
$upload = new Upload($contents);

$asset->setFile('en-US', $upload->asAssetFile());

try {
    // ...
} catch (Exception $exception) {
    echo $exception->getMessage();

After you're done creating an asset, you can perform the usual operations on it: