Pages
Pages are v2's home ground. The only page operations that still need v1 are the ones that restructure the tree — move, copy, archive.
import { createV2Client } from 'confluence.js';
const confluence = createV2Client({ host, auth });Create
const page = await confluence.page.createPage({
body: {
spaceId: '123456',
status: 'current',
title: 'Release notes',
body: {
representation: 'storage',
value: '<p>Shipped today.</p>',
},
},
});representation: 'storage' is Confluence's own XHTML-ish format — the one the editor round-trips without loss. atlas_doc_format (ADF) and wiki are also accepted.
Pass parentId to nest the page under another:
await confluence.page.createPage({
body: {
spaceId: '123456',
parentId: String(page.id),
status: 'current',
title: 'Release notes — 3.0',
body: { representation: 'storage', value: '<p>Details.</p>' },
},
});Read
const page = await confluence.page.getPageById({ id: 12345, bodyFormat: 'storage' });
console.log(page.title, page.version?.number);
console.log(page.body?.storage?.value);Without bodyFormat the body is omitted — ask for the representation you intend to read.
List them by space:
const pages = await confluence.page.getPages({ spaceId: ['123456'], limit: 25 });
for (const page of pages.results ?? []) console.log(page.title);Update
An update is a new version, and you must say which one you are creating — Confluence uses it for optimistic locking:
const current = await confluence.page.getPageById({ id: 12345 });
await confluence.page.updatePage({
id: 12345,
body: {
id: '12345',
status: 'current',
title: 'Release notes (revised)',
body: { representation: 'storage', value: '<p>Now with detail.</p>' },
version: { number: (current.version?.number ?? 1) + 1 },
},
});Send a version.number that is not current + 1 and the call is rejected — which is the point: it means someone else edited the page since you read it.
Delete
await confluence.page.deletePage({ id: 12345 });That moves the page to the trash. purge: true removes it permanently, and draft: true deletes a draft.
Versions
const versions = await confluence.version.getPageVersions({ id: 12345 });
for (const version of versions.results ?? []) {
console.log(`v${version.number} — ${version.message ?? 'no message'}`);
}Restoring and deleting versions is v1:
const v1 = createV1Client({ host, auth });
await v1.contentVersions.restoreContentVersion({
id: '12345',
operationKey: 'restore',
params: { versionNumber: 3, message: 'back to the good one' },
});Version numbers are positions, not identities
Deleting version 2 of [4,3,2,1] leaves [3,2,1] — everything above the hole slides down to close it. A version number you held before a delete now points at a different version. Re-read the history after any delete.
The page tree
v2 reads it:
const children = await confluence.children.getPageChildren({ id: 12345 });
const descendants = await confluence.descendants.getPageDescendants({ id: 12345 });
const ancestors = await confluence.ancestors.getPageAncestors({ id: 12345 });v1 changes it:
// Move: 'append' makes it a child of the target; 'before'/'after' place it as a sibling.
await v1.contentChildrenAndDescendants.movePage({
pageId: '12345',
position: 'append',
targetId: '67890',
});
// Copy a single page.
const copy = await v1.contentChildrenAndDescendants.copyPage({
id: '12345',
destination: { type: 'parent_page', value: '67890' },
pageTitle: 'Release notes (copy)',
copyAttachments: true,
});Copying a whole hierarchy is asynchronous — you get a task, not a result:
const task = await v1.contentChildrenAndDescendants.copyPageHierarchy({
id: '12345',
destinationPageId: '67890',
copyAttachments: true,
titleOptions: { prefix: 'Copy of ' },
});
// Poll it to completion.
let status = await v1.longRunningTask.getTask({ id: task.id! });
while (!status.finished) {
await new Promise(resolve => setTimeout(resolve, 1000));
status = await v1.longRunningTask.getTask({ id: task.id! });
}Archiving works the same way — content.archivePages returns a task.