Redirects API
Create and resolve URL redirects.
Redirects map an old source (a page reference or a literal path) to a target, so moved or retired URLs keep resolving. Methods live at cms.api.<collection>.<method> (use your collection name, e.g. cms.api.pages.createRedirect) and mirror on the client as client.<collection>.<method> with identical types.
Redirects are not versioned content, so unlike the entry and block mutation APIs these methods do not return a commit envelope. All of them require the collection to have slugs enabled.
Methods
Create a Redirect
Point an old source (a page reference or a literal path) at a target, so a moved or retired URL keeps resolving. Source paths are canonicalized and must be unique among active redirects; target paths are stored verbatim, so you can point at an external destination. You get back the stored redirect enriched with its resolved current paths. Fails with SLUG_NOT_ENABLED, REDIRECT_INVALID (a source page root does not exist or a required field is missing), or REDIRECT_SOURCE_EXISTS.
redirect:create/{collection}/createRedirectconst data = await cms.api.pages.createRedirect({
body: {
sourceType: 'path', // required
sourcePath: '/old-pricing', // required when sourceType is 'path'
targetType: 'page', // required
targetRootId: 'root_123', // required when targetType is 'page'
statusCode: 301,
},
});const { data, error } = await client.pages.createRedirect({
body: {
sourceType: 'path', // required
sourcePath: '/old-pricing', // required when sourceType is 'path'
targetType: 'page', // required
targetRootId: 'root_123', // required when targetType is 'page'
statusCode: 301,
},
});sourceType'page' | 'path'requiredWhether the source is a page reference (needs `sourceRootId`) or a literal path (needs `sourcePath`).
sourceRootIdstringRoot id of the source page. Required when `sourceType` is `'page'`.
sourcePathstringLiteral source path, canonicalized before storage. Required when `sourceType` is `'path'`.
targetType'page' | 'path'requiredWhether the target is a page reference (needs `targetRootId`) or a literal path (needs `targetPath`).
targetRootIdstringRoot id of the target page. Required when `targetType` is `'page'`.
targetPathstringTarget path or URL, stored verbatim (may be external). Required when `targetType` is `'path'`.
statusCode301 | 302 | 307 | 308= 301HTTP redirect status code.
redirectRedirectThe created redirect: the stored row plus resolved current paths.
The returned redirect carries the stored row plus resolved sourceCurrentPath and targetCurrentPath (page references resolve to their current published path), matching the rows from listRedirects.
List Redirects
List the active redirects in a collection, newest first, with pagination and resolved current paths for page references. You get an empty list back when slugs are not enabled.
redirect:read/{collection}/listRedirectsconst data = await cms.api.pages.listRedirects({
query: { limit: 25, offset: 0 },
});const { data, error } = await client.pages.listRedirects({
query: { limit: 25, offset: 0 },
});limitnumber= 50Page size, 1 to 100.
offsetnumber= 0Rows to skip.
redirectsRedirect[]The active redirects on this page, newest first, each enriched with resolved `sourceCurrentPath` and `targetCurrentPath`.
totalnumberTotal active redirects across all pages, ignoring limit/offset.
hasMorebooleanWhether more redirects exist after this page.
Update a Redirect
Change a redirect's source, target, or status code. Source uniqueness is re-checked (excluding the redirect itself), so you can safely re-point it. Fails with SLUG_NOT_ENABLED, REDIRECT_NOT_FOUND, REDIRECT_INVALID, or REDIRECT_SOURCE_EXISTS.
redirect:update/{collection}/updateRedirectconst data = await cms.api.pages.updateRedirect({
body: {
redirectId: 'redirect_123', // required
sourceType: 'path', // required
sourcePath: '/old-pricing', // required when sourceType is 'path'
targetType: 'page', // required
targetRootId: 'root_456', // required when targetType is 'page'
statusCode: 301,
},
});const { data, error } = await client.pages.updateRedirect({
body: {
redirectId: 'redirect_123', // required
sourceType: 'path', // required
sourcePath: '/old-pricing', // required when sourceType is 'path'
targetType: 'page', // required
targetRootId: 'root_456', // required when targetType is 'page'
statusCode: 301,
},
});redirectIdstringrequiredId of the redirect to update.
sourceType'page' | 'path'requiredWhether the source is a page reference (needs `sourceRootId`) or a literal path (needs `sourcePath`).
sourceRootIdstringRoot id of the source page. Required when `sourceType` is `'page'`.
sourcePathstringLiteral source path, canonicalized before storage. Required when `sourceType` is `'path'`.
targetType'page' | 'path'requiredWhether the target is a page reference (needs `targetRootId`) or a literal path (needs `targetPath`).
targetRootIdstringRoot id of the target page. Required when `targetType` is `'page'`.
targetPathstringTarget path or URL, stored verbatim (may be external). Required when `targetType` is `'path'`.
statusCode301 | 302 | 307 | 308= 301HTTP redirect status code.
redirectRedirectThe updated redirect: the stored row plus resolved current paths, matching `listRedirects` rows.
Resolve a Redirect
Resolve an incoming request path to its redirect decision, if one matches. This is the consumer's public routing call: it runs the full auth chain (so plugin scope is enforced) but is conventionally anonymous-readable. You get back { redirect: null } when no redirect matches or slugs are not enabled.
/{collection}/resolveRedirectconst data = await cms.api.pages.resolveRedirect({
query: { path: '/old-pricing' }, // required
});const { data, error } = await client.pages.resolveRedirect({
query: { path: '/old-pricing' }, // required
});pathstringrequiredThe request path to resolve, e.g. `/old-pricing`.
redirect{ status, location } | nullThe routing decision to apply: `status` (the HTTP redirect code) and `location` (the resolved target URL), or `null` when nothing matches.
The resolved redirect carries the target URL and status code, or is null when nothing matches.
Archive a Redirect
Soft-delete an active redirect by stamping its archivedAt timestamp, so it stops resolving without losing the record. Fails with REDIRECT_NOT_FOUND if the redirect does not exist, is already archived, or is out of scope.
redirect:delete/{collection}/archiveRedirectconst data = await cms.api.pages.archiveRedirect({
body: {
redirectId: 'redirect_123', // required
},
});const { data, error } = await client.pages.archiveRedirect({
body: {
redirectId: 'redirect_123', // required
},
});redirectIdstringrequiredId of the redirect to archive.
redirectIdstringThe id of the archived redirect.