Admin API
Maintenance jobs (pruning, scheduled publishing, search reindex) via cms.api.admin.
The admin namespace exposes bounded maintenance jobs meant to be driven by a cron or queue rather than a UI. These methods live on the system namespace at cms.api.admin.<method> and mirror on the client as client.admin.<method> with identical types. Every method requires the admin permission resource, so gate the trigger accordingly.
runPruning and runScheduled each do one capped pass and report progress, so a plain cron can ping them periodically while a queue driver re-enqueues until the work drains. None of these methods produces a commit envelope.
Run a Pruning Pass
Run one bounded, resumable pruning pass to reclaim storage: it deletes old commits, hard-deletes archived entries (roots), and frees unreferenced assets. Each call does one capped pass within its time and root-count budgets and persists its own progress, so you keep calling it (or let a cron ping it) until done is true. Throws DATA_RETENTION_NOT_CONFIGURED when data retention is not configured.
admin:delete/admin/runPruningconst data = await cms.api.admin.runPruning({
body: {
maxRoots: 10,
maxDurationMs: 5000,
},
});const { data, error } = await client.admin.runPruning({
body: {
maxRoots: 10,
maxDurationMs: 5000,
},
});dryRunboolean= falsePlan what would be deleted without persisting any changes.
maxRootsnumber= 50Maximum roots to process this pass (archived and live combined), 1 to 1000.
maxDurationMsnumber= 8000Soft wall-clock budget in milliseconds; the pass returns before exceeding it. Minimum 100.
liveRescanMsnumber= 86400000Interval in milliseconds after which a live root becomes due for re-scanning. Minimum 0.
maxAssetsnumber= 100Maximum archived, unreferenced assets to reclaim this pass, 1 to 1000.
deletedCommitsnumberOld commits deleted this pass across every root processed.
deletedBlockVersionsnumberUnreferenced block versions deleted this pass.
deletedSnapshotsnumberCommit-snapshot rows deleted this pass.
deletedMergeRequestsnumberClosed merge requests past the retention window that were deleted.
deletedApprovalsnumberStale or already-resolved approval rows deleted.
prunedRootsstring[]Ids of every entry touched this pass — the hard-deleted archived roots plus each live root that had commits to prune.
deletedRootsstring[]Ids of soft-archived entries hard-deleted this pass (past the trash window).
deletedAssetsstring[]Ids of archived, unreferenced assets reclaimed this pass (DB row plus S3 object).
processedLiveRootsnumberHow many live entries were visited for history pruning this pass.
pluginsRecord<string, Record<string, number>>Per-plugin pruning metrics keyed by plugin id; always present, empty when no plugin prunes.
stoppedReason'maxRoots' | 'budget' | 'idle'Why the pass stopped: it hit the count cap, ran out of the time budget, or drained all due work.
donebooleanTrue when the pass drained all currently-due work (stopped idle); keep re-running while it is false.
done is true when the pass drained all currently-due work (stopped idle); stoppedReason is one of 'maxRoots', 'budget', or 'idle'.
Process Scheduled Publishing
Drain the scheduled-publishing queue: every due row (scheduledAt <= now and not yet processed) is published or unpublished with the same machinery as the single publish endpoints, then stamped processed. A row whose publish or unpublish fails is still marked processed and surfaced in failed, so a permanently broken intent never re-runs forever.
admin:create/admin/runScheduledconst data = await cms.api.admin.runScheduled({
body: {
limit: 50,
},
});const { data, error } = await client.admin.runScheduled({
body: {
limit: 50,
},
});limitnumber= 100Maximum number of due rows to process this pass, 1 to 1000.
processednumberRows attempted this pass (successes plus failures).
publishednumberRows that published successfully.
unpublishednumberRows that unpublished (expired) successfully.
failed{ id, rootId, branchId, action, error }[]One entry per row whose publish or unpublish permanently failed; `error` is the CMS error code.
failed is an array of { id, rootId, branchId, action, error }, one entry per row whose publish or unpublish threw.
Rebuild the Search Index
Rebuild the entire full-text search index from scratch, re-indexing every root, comment, merge request, variable, template, asset, and notification. Reach for this after a bulk import or an index-shape change; it takes no input and hands back the per-type counts it wrote.
admin:create/admin/reindexSearchconst data = await cms.api.admin.reindexSearch();const { data, error } = await client.admin.reindexSearch();indexedRecord<string, number>Per-entity-type counts of rows re-indexed, keyed by entity type (root, comment, mergeRequest, variable, template, asset, notification).
indexed is a record of per-entity-type counts that were re-indexed.