Contents
- Domma CMS User Manual
- 1. Using the CMS
- 2. Tutorials
- 3. Components
- 4. API Reference
- 5. Tools
Pages API
Updated by Darryl Waterhouse on 29 September 2026 · 3 min read
Pages are Markdown files in content/pages/, addressed by their URL path. All endpoints need the pages permission for the action named (read, create, update, delete). In the paths below, * is the page's URL path without the leading slash, e.g. /api/pages/about.
GET /api/pages
Requires Bearer token + pages read permission.
List every page with its metadata (no body).
// Response 200
[ { "urlPath": "/about", "title": "About Us", "slug": "about", "status": "published", "layout": "default",
"visibility": "public", "tags": [], "sortOrder": 0, "category": null, "project": null, "resolvedProject": "core",
"plugin": null, "bundled": false, "updatedAt": "2026-09-27T10:30:00.000Z", "createdAt": "...", "versionCount": 3 } ]
A page may still carry a legacy showInNav value; nothing reads it - the site's navigation is edited in Menus.
GET /api/pages/*
Requires Bearer token + pages read permission.
One page, with its frontmatter fields and full Markdown body.
// Response 200
{ "urlPath": "/about", "title": "About Us", "body": "## Our Story\n\nWe started...", ... }
// Error 404
{ "error": "Page not found" }
POST /api/pages
Requires Bearer token + pages create permission.
Create a page.
| Field | Type | Description |
|---|---|---|
urlPath | string | Required. Public URL path, e.g. /about |
frontmatter | object | Frontmatter fields (title, status, visibility, layout, ...) |
body | string | Markdown content |
// Response 201 - the created page
// Error 409 - names the project the existing page belongs to
{ "error": "A page already exists at /about (project: core)", "urlPath": "/about", "project": "core" }
PUT /api/pages/*
Requires Bearer token + pages update permission.
Update a page, and optionally move it to a new URL path. A move re-aims menu links that pointed at the old path and drops the page's share links. Each save keeps a version (see Versions below).
| Field | Type | Description |
|---|---|---|
frontmatter | object | Frontmatter fields |
body | string | Markdown content |
newUrlPath | string | Optional. Move the page to this path |
// Response 200 - the updated page
// Error 404
{ "error": "Page not found" }
// Error 409
{ "error": "A page already exists at that path" }
DELETE /api/pages/*
Requires Bearer token + pages delete permission.
Delete a page and its share links.
// Response 200
{ "success": true }
GET /api/pages/tags
Requires Bearer token + pages read permission.
Every tag used on any page, sorted.
// Response 200
{ "tags": ["guide", "news", "tutorial"] }
POST /api/pages/preview
Requires Bearer token + pages read permission.
Render Markdown to HTML (shortcodes processed, no frontmatter), as the signed-in user sees it.
// Request body
{ "markdown": "Hello **world**" }
// Response 200
{ "html": "<p>Hello <strong>world</strong></p>" }
POST /api/pages/preview/full
Requires Bearer token + pages read permission.
Render unsaved editor content as the complete public page - layout, navbar, footer, theme and custom CSS - the editor's Live Preview.
// Request body
{ "urlPath": "/about", "frontmatter": { "title": "About" }, "body": "..." }
// Response 200
{ "html": "<!doctype html>..." }
Share links
POST /api/pages/preview-links
Requires Bearer token + pages update permission.
Make a share link that lets anyone with it see one page, draft or not, until it expires. expiresIn is 1h, 24h, 7d (default) or 30d, or a number of seconds up to 30 days. GET /api/pages/preview-links?urlPath=/about lists them and DELETE /api/pages/preview-links/:id withdraws one.
// Request body
{ "urlPath": "/about", "expiresIn": "7d", "label": "For the client" }
// Response 201
{ "id": "...", "urlPath": "/about", "expiresAt": "...", "token": "...", "url": "https://example.com/_preview?token=..." }
Versions
GET /api/versions/list/*
Requires Bearer token + pages read permission.
A page's saved versions (its History), newest first. The other version routes take a version's filename from this list:
| Route | Permission | Does |
|---|---|---|
GET /api/versions/get/:filename/* | read | One version's content |
POST /api/versions/create/* | update | Save a named version now ({"label": "..."}) |
POST /api/versions/restore/:filename/* | update | Put a version back as the page |
DELETE /api/versions/delete/:filename/* | delete | Delete one version |
POST /api/versions/bulk-delete/* | delete | Delete several ({"filenames": [...]}) |
POST /api/versions/prune/* | delete | Keep only the most recent ({"keep": 10}) |