---
title: Manage content sources using the REST API
slug: cms-saas/docs/manage-content-sources-using-the-rest-api
createdAt: 2026-07-30T20:18:08.000Z
---

[Optimizely Graph](docId\:aM0WpNsNXe_n26IhkX5sG) supports additional content sources created alongside the CMS source. By registering a content source with CMS, editors can reference data from another source within CMS content. A developer building the frontend application can then consume the Graph URIs indexed within CMS data to fetch additional data from other content sources in Graph.

Content sources work together with [content type bindings](docId\:FzmJu99kGwLUVC7U8Z4Vx). While a content source defines the external source and maps its properties to CMS, a content type binding defines how properties from one content type map to another, letting you [bind content instances](docId:0CbdbBgMdSFXXEBB6KSmi) so that mapped properties are automatically linked.

The content sources API is available at `https://api.cms.optimizely.com/v1/contentsources`. The endpoint requires a valid token, as described in [Authentication and authorization](docId:2uVhCnJr4BdL9e5UNkN4L).

:::hint{type="info"}
**Prerequisites**
Before registering a content source in CMS, you must define a content source and its content types in Optimizely Graph. See [Synchronize content types for external data](docId\:DIZAH_f7NZNuTCYz6Do_z) and [Synchronize content data](docId\:tIqHVF16LM60H8_VzdvzU). The content source must be created in the same Graph account as CMS. You can find access keys to Optimizely Graph on the [dashboard](docId\:HUBBeDq79qozFDiK7uz91) for the CMS instance.
:::

## Content source data model

The content source resource has the following fields:

- **key** – Unique identifier for the content source. Must start with a letter and contain only letters, digits, and underscores (A–Z, a–z, 0–9, \_). Minimum two characters, maximum 255.
- **displayName** – Display name shown in the CMS UI. Required, maximum 255 characters.
- **sourceKey** – The key or identifier of the content source in Optimizely Graph. Required, maximum 50 characters.
- **sourceType** – The key of the content type in the Optimizely Graph content source. Required, maximum 255 characters.
- **type** – The type of content source. The only currently supported value is `graph`. Required, maximum 50 characters.
- **baseType** – The CMS base type used to represent the content type from the Graph content source. Required. Supported values are `_page`, `_component`, `_element`, `_media`, `_image`, `_video`, `_folder`, `_experience`, and `_section`.
- **propertyMappings** – Defines how properties from the source content type map to CMS. Required. Contains:
  - **key** – The property in the source to use as the content key in CMS. Maximum 255 characters. Required if the source content type does not implement the `_Item` global contract. If the content type implements `_Item`, set this to `_itemMetadata.key` or omit it.
  - **displayName** – The property in the source to use as the display name in CMS. Maximum 255 characters. Required if the source content type does not implement the `_Item` global contract. If the content type implements `_Item`, set this to `_itemMetadata.displayName` or omit it.
  - **keyFormat** – The format of the source identifier key. Valid values are `digits`, `digitsWithHyphens`, `digitsWithHyphensAndBraces`, `digitsWithHyphensAndParentheses`, or `undefined` for non-GUID-based string identifiers.
- **created** – Read-only timestamp indicating when the content source was created.
- **createdBy** – Read-only field indicating who created the content source.
- **lastModified** – Read-only timestamp indicating when the content source was last modified.
- **lastModifiedBy** – Read-only field indicating who last modified the content source.

## Create a content source

You can create a content source using the content sources API. See [Create a content source](docId\:PmYC04lNnDr0GJLpbHXkm) for the full API reference.

The request supports the following optional headers:

- `cms-skip-validation` – Skip reference validation. Valid values are `*` (skip all) and `references`. When set, reference properties pointing to external types that are not mapped as a content source in CMS are ignored during validation.
- `Prefer: return=representation` – Return the created resource in the response body.

```http
POST https://api.cms.optimizely.com/v1/contentsources
Content-Type: application/json
```

```json
{
    "key": "rece",
    "displayName": "Recipes",
    "sourceKey": "rece",
    "sourceType": "Recipe",
    "type": "graph",
    "baseType": "_component",
    "propertyMappings": {
        "key": "id",
        "displayName": "name",
        "keyFormat": "digits"
    }
}
```

## Get a content source

You can retrieve a specific content source using its unique key. See [Get a content source](docId\:riizlTYjr50_JmoYNloPq) for the full API reference.

The request supports the following optional headers for conditional requests:

- `If-None-Match` – Return the resource only if the current ETag does not match.
- `If-Modified-Since` – Return the resource only if it was modified after the specified date.

```http
GET https://api.cms.optimizely.com/v1/contentsources/rece
```

```json
{
    "key": "rece",
    "displayName": "Recipes",
    "sourceKey": "rece",
    "sourceType": "Recipe",
    "type": "graph",
    "baseType": "_component",
    "propertyMappings": {
        "key": "id",
        "displayName": "name",
        "keyFormat": "digits"
    },
    "created": "2025-01-15T10:30:00+00:00",
    "createdBy": "admin@example.com",
    "lastModified": "2025-01-15T10:30:00+00:00",
    "lastModifiedBy": "admin@example.com"
}
```

## List content sources

You can list content sources using the content sources API. See [List content sources](docId\:JQoEE53KosG70a7t1xSDj) for the full API reference.

The endpoint supports the following query parameters for pagination:

- `pageIndex` – The zero-based index of the page to retrieve.
- `pageSize` – The number of items per page.

```http
GET https://api.cms.optimizely.com/v1/contentsources
```

```json
{
    "items": [
        {
            "key": "rece",
            "displayName": "Recipes",
            "sourceKey": "rece",
            "sourceType": "Recipe",
            "type": "graph",
            "baseType": "_component",
            "propertyMappings": {
                "key": "id",
                "displayName": "name",
                "keyFormat": "digits"
            },
            "created": "2025-01-15T10:30:00+00:00",
            "createdBy": "admin@example.com",
            "lastModified": "2025-01-15T10:30:00+00:00",
            "lastModifiedBy": "admin@example.com"
        }
    ],
    "pageSize": 10,
    "pageIndex": 0,
    "totalCount": 1
}
```

## Update a content source

You can update individual fields on an existing content source using a merge patch request. See [Update a content source](docId\:x0y_-dGNVHgqh_vAqJAFT) for the full API reference.

The request supports the following optional headers:

- `cms-skip-validation` – Skip reference validation. Valid values are `*` (skip all) and `references`. When set, reference properties pointing to external types that are not mapped as a content source in CMS are ignored during validation.
- `Prefer: return=representation` – Return the updated resource in the response body.
- `If-Match` – Update only if the current ETag matches (optimistic concurrency).
- `If-Unmodified-Since` – Update only if the resource was not modified after the specified date.

```http
PATCH https://api.cms.optimizely.com/v1/contentsources/rece
Content-Type: application/merge-patch+json
```

```json
{
    "displayName": "Recipes Updated"
}
```

## Delete a content source

You can delete an existing content source using its unique key. See [Delete a content source](docId\:Hx38M-C71WSlkZPAUKQ9N) for the full API reference.

The request supports the following optional headers:

- `Prefer: return=representation` – Return the deleted resource in the response body.
- `If-Match` – Delete only if the current ETag matches (optimistic concurrency).
- `If-Unmodified-Since` – Delete only if the resource was not modified after the specified date.

```http
DELETE https://api.cms.optimizely.com/v1/contentsources/rece
```

## Reference content from a content source

After you register a content source with CMS, you can search and reference content from that source in the content editor if the Graph content source type is associated with global contracts like `_Item`, `_AssetItem`, or `_ImageItem`. The content editor provides a search interface where you can perform a full-text search against the Graph source. Only properties defined as searchable are included in the search. To reference an entry from a content source to a `contentReference` property, select an item from the search results and add it to your CMS property.

## Query content source references with Graph

When you create a `contentReference` property on a content type, you can specify an item type for the property. The item type is reflected in the generated Graph schema. If you do not specify an item type, the Graph schema uses the common `IData` type. You can then project results to concrete types when querying through Graph.

The following example queries a `MyPage` content type with a `contentReference` property named `MainImage` that has no item type specified:

```graphql
query PageWithAssetsQuery {
  MyPage {
    items {
      _id
      Title
      MainImage {
        url {
          graph
        }
        item {
          ... on PublicImageAsset {
            Id
            Url
            Title
          }
        }
      }
    }
  }
}
```

If you set the item type for the `contentReference` to `PublicImageAsset`, the Graph schema uses that type directly, so you can query the fields directly without specifying the type:

```graphql
query PageWithAssetsQuery {
  MyPage {
    items {
      _id
      Title
      MainImage {
        url {
          graph
        }
        item {
          Id
          Url
          Title
        }
      }
    }
  }
}
```

The `contentReference` property includes a `url` field with a `graph` value in the format `graph://<content_source>/<content_type>/<id>`:

```json
{
    "url": {
        "base": null,
        "graph": "graph://gure/Recipe/042c950a9fba4122b13458df679404e6",
        "internal": "cms://content/042c950a9fba4122b13458df679404e6",
        "hierarchical": null,
        "default": null,
        "type": "GRAPH"
    }
}
```
