---
title: Migration checklist
slug: cms-saas/api/migration-checklist
docTags: 
createdAt: 2026-07-30T20:20:18.789Z
---

:::hint{type="warning"}
**Preview3 CMS REST API reaches end-of-life on August 1, 2026**
The Preview3 CMS REST API endpoints retire on August 1, 2026. After this date, Optimizely begins disabling access, and applications that still call Preview3 endpoints (URLs containing `/preview3/`) may experience failed requests and service interruptions. Migrate to CMS REST API v1 before August 1, 2026. Mixing Preview3 and v1 endpoints is supported until the retirement date.
:::

This checklist helps you systematically migrate an existing integration from the preview3 Content API to the v1 API. It breaks down required updates across endpoints, authentication, schemas, request and response structures, and validation rules. Use this checklist to ensure no breaking change is missed and to verify that your integration fully complies with the v1 API before going to production.

### URL and Endpoints

- Update base URL from `preview3` to `v1`
- Remove `/experimental` prefix from all content endpoints
- Update Packaging API base URL (paths remain under `/experimental/`)
- Update manifest operations to use the new `/v1/manifest` endpoint
- Update delete locale calls to use path-based locale: `/v1/content/{key}/locales/{locale}`
- Remove any Changesets API usage

### Security

- Remove use of `act_as` parameter in OAuth token endpoint requests

### Schema and Type Changes

- Update schema references in generated client code (OpenAPI spec changes):
  - `ContentItem` to `ContentVersion`
  - `ContentItemPage` to `ContentVersionPage`
  - `ContentMetadata` to `ContentNode`
  - `ContentMetadataPage` to `ContentNodePage`
  - Rename pagination field `totalItemCount` to `totalCount`
- Update `ContentComponent` field names:
  - `name` to `displayName`
  - `content` to `properties`
- Update property group name references:
  - `Information` to `Content`
  - `Advanced` to `Settings`
- Update boolean field names to use `is`/`has` prefix:
  - `localized` to `isLocalized`
  - `required` to `isRequired`
  - `disabled` to `isDisabled`
  - `enabled` to `isEnabled`
  - `deleted` to `isDeleted`
  - `success` to `isSuccess`

### Request Changes

- Restructure create content requests to use `NewContent` with `initialVersion`
- Move `allowDeleted` from query param to `cms-allow-deleted` header
- Remove usage of the `locale` query parameter on version endpoints
- Remove unknown/unsupported fields from all request bodies
- Update property values to use nested `{ "value": ... }` structure
- Update `richText` property values to use `{ "value": { "html": ... } }` structure
- Replace any request passing `cms-skip-validation: true` with `cms-skip-validation: *`
- Remove any usage of `cms-skip-validation: approval` (the `approval` value is no longer supported)

### Response Changes

- Expect `204 No Content` response status from successfully executed commands
- Include the `Prefer: return=representation` header with command requests when a resource is expected in the response body.

### Required Fields

- Ensure all `ContentType` objects have a non-empty `displayName`
- Ensure all `PropertyGroup` objects have a non-empty `displayName`

### Validation Changes

- Ensure choice property values match defined choices
- Ensure locales exist before creating content in that locale

### Status Transitions

- Replace all `PATCH` calls that set `status` with the corresponding transition endpoint:
  - `"status": "draft"` → `POST /content/{key}/versions/{version}:draft`
  - `"status": "ready"` → `POST /content/{key}/versions/{version}:ready`
  - `"status": "published"` → `POST /content/{key}/versions/{version}:publish`
  - `"status": "scheduled"` with `delayPublishUntil` → `POST /content/{key}/versions/{version}:publish` with `{ "delayUntil": "..." }`
- Remove `status` from create content and create version request bodies (new content is always created in `draft` status)
- Update scheduled publishing to use `:publish` with `delayUntil` instead of patching status
- Note that `delayPublishUntil` is now read-only — use `:publish` with `delayUntil` to schedule publication
- Replace use of `keepPublishedStatus: true` in `:copy` call with an explicit call to the `:publish` endpoint

### Behavior Changes

- Handle non-primary locale versions not including merged properties
- Update code that patches published versions to create a new version first
- Only `draft` versions can be updated via `PATCH` — versions in any other status return an error

### Response Handling

- Update code parsing `locales` in content nodes (now array instead of object map)
- Update code reading property values (now nested in `{ "value": ... }` objects)
- Update code reading `richText` properties (value changed from string to `{ "html": ... }` object)

### Testing

- Test all API integrations with the v1 endpoint

## Example: Before and After

### Creating Content

```http
POST /preview3/experimental/content
Content-Type: application/json

{
  "contentType": "ArticlePage",
  "displayName": "My Article",
  "container": "articles-folder",
  "locale": "en",
  "status": "draft",
  "routeSegment": "my-article",
  "properties": {
    "heading": "Welcome",
    "body": "Article content here"
  }
}
```

```http
POST /v1/content
Content-Type: application/json

{
  "contentType": "ArticlePage",
  "container": "articles-folder",
  "initialVersion": {
    "displayName": "My Article",
    "locale": "en",
    "routeSegment": "my-article",
    "properties": {
      "heading": {
        "value": "Welcome"
      },
      "body": {
        "value": "Article content here"
      }
    }
  }
}
```

### Deleting a Locale

```http
DELETE /preview3/experimental/content/my-article/versions?locale=sv
```

```http
DELETE /v1/content/my-article/locales/sv
```

### Changing Version Status

```http
PATCH /preview3/experimental/content/my-article/versions/1
Content-Type: application/json

{
  "status": "ready"
}
```

```http
POST /v1/content/my-article/versions/1:ready
```

### Scheduling a Version

```http
PATCH /preview3/experimental/content/my-article/versions/1
Content-Type: application/json

{
  "status": "scheduled",
  "delayPublishUntil": "2026-03-01T09:00:00Z"
}
```

```http
POST /v1/content/my-article/versions/1:publish
Content-Type: application/json

{
  "delayUntil": "2026-03-01T09:00:00Z"
}
```

### Getting a Deleted Content Item

```http
GET /preview3/experimental/content/my-article?allowDeleted=true
```

```http
GET /v1/content/my-article
cms-allow-deleted: true
```
