HTTP Adding: a real request and answer on this site's sandbox page
PUT /cdna-api/pages/page/1885?properties={id,activeRevision{id}}
Content-Type: application/json
{
"patchRevision": {
"originRevision": 3447,
"activeRevision": true,
"appendAreaCollectionElement(pageSections)": {
"layout": 58,
"name": "Sandbox figure",
"areas": {"image": 1185, "alt": "A blue and green gradient", "caption": "Uploaded through the API"}
}
}
}
# 200 {"result":"success","data":{"id":1885,"activeRevision":{"id":3482}},"message":"The Page has been saved successfully."}
Reordering and removing, as a script: it reads each page, applies your change to a plain list, and writes the list back. The mapping from the read shape to the write shape is the part to get right; this one handles text, switch, image, file, record and component areas, and keeps global components as references.
JavaScript
// rewrite-sections.js (Node 18 or later); coredna() is your client module, as in
// https://hub.coredna.com/books/apis/client/client-layer
import { coredna } from './coredna.js';
function toWrite(area) { // one area of areasContent -> the value a write takes
if (!area || typeof area !== 'object') return area ?? null;
switch (area.category) {
case 'collection': return (area.collection ?? []).map(componentToWrite);
case 'component': return area.component ? componentToWrite(area.component) : null;
case 'image': return area.imageId ?? null;
case 'file': return area.fileId ?? null;
case 'record': return area.record?.id ?? null;
case 'records': return (area.records ?? []).map((r) => r.id);
default:
if ('active' in area) return area.active; // a switch
return area.text ?? null; // text, rich text, select, date; a multiselect's JSON string
}
}
function componentToWrite(c) {
if (c.componentGlobal) return { global: true, id: c.componentId }; // keep the reference, not a copy
const areas = {};
for (const [name, area] of Object.entries(c)) {
if (name.startsWith('component')) continue;
const value = toWrite(area);
if (value !== null) areas[name] = value;
}
return { name: c.componentName, layout: c.componentLayout, areas };
}
// change(list) returns the new list: reordered, filtered, or both
export async function rewriteSections(pageId, change) {
const { data } = await coredna('GET', 'pages/page/' + pageId, {
query: { properties: '{id,activeRevision{id,areasContent}}' },
});
const live = data.activeRevision;
const before = toWrite(live.areasContent.pageSections) ?? [];
const after = change(before);
const result = await coredna('PUT', 'pages/page/' + pageId, {
query: { properties: '{id,activeRevision{id}}' },
body: { patchRevision: { originRevision: live.id, activeRevision: true, 'areaContent(pageSections)': after } },
});
console.log(pageId, live.id, '->', result.data.activeRevision.id, before.length, '->', after.length);
}
// remove every section built on a retired component layout:
// await rewriteSections(1885, (list) => list.filter((s) => s.layout !== 41));
// move the last section to the top:
// await rewriteSections(1885, (list) => [list.at(-1), ...list.slice(0, -1)]);