Skip to content
BetaDocs

Pages Tools

Core 0.2.0 uses one Page model for all content. See Content types and the upgrade guide for existing installations.

Field Type Description
content_type string Content type ID; defaults to page.
fields object Custom values defined by the content type.
path string Explicit public path, overriding the type URL pattern.
title string Page title. Used in nav and as default <title> tag.
slug string URL path. "" = homepage. No leading slash.
content_mode "blocks" | "html" "blocks" is the default for new pages. See Blocks for the block-mode editing surface.
html_content string Full page body HTML — used when content_mode === "html".
blocks Block[] Block tree — used when content_mode === "blocks". Edit via add_block, update_block, move_block, remove_block, duplicate_block.
template string Optional PageTemplate id. The renderer composes the template’s block tree with the page’s blocks at build time.
status "published" | "draft" | "review" | "unlisted" Only published and unlisted pages are built into the static site. unlisted pages are reachable by URL but excluded from listings and the sitemap.
publish_at string ISO 8601. Schedule the page to go live automatically at this time. Cleared once it fires.
unpublish_at string ISO 8601. Schedule the page to come down automatically.
kind "page" | "article" "article" enables Article JSON-LD schema.
seo_title string Custom <title> tag. Defaults to title + suffix.
seo_description string <meta name="description">. Describe the actual page accurately; there is no fixed length requirement.
og_title string Optional sharing title for OpenGraph/Twitter; empty uses the document title. Core 0.2.120 / MCP 0.45.90.
og_description string Optional sharing description; empty uses the SEO description and its site fallbacks. Core 0.2.120 / MCP 0.45.90.
seo_image_alt string Sharing-image description; empty uses the mapped public image alt when applicable.
og_image string Absolute CDN URL for Open Graph image.
canonical_url string Override the canonical URL (e.g. after a migration).
noindex boolean Set true to add <meta name="robots" content="noindex">.
nofollow boolean Restrict following links independently. Public noindex defaults to noindex,follow; explicit nofollow and private previews remain restricted.
language string Per-page language override (e.g. "en", "sv").
author string Article author. Used in Article JSON-LD.
date_published string ISO 8601 date. Used in Article JSON-LD.
json_ld string Custom JSON-LD schema as a JSON string. For FAQ, recipe and event pages, use the structured data tools.

The homepage has slug: "" and is stored with id: "home". The AI agent uses this automatically when you say “the homepage” or “the start page”.

Creates a new page. Required: title. Pass content_type and fields for articles or any other type. Defaults: status: "draft", content_mode: "blocks". The AI agent picks the block library to compose the body unless you ask for HTML mode explicitly.

The page id is derived from its address (/category/news/diy becomes category_news_diy). Pass id to choose it yourself, for example to keep parent or filter values stable during a migration: 1–100 letters, digits, dots, underscores or hyphens. An id that is already in use fails with 409; a supplied id is never replaced.

get_composition_starter returns an editable block tree for five common marketing pages, built only from core blocks. Nothing is saved by the read.

kind Contains
feature_page Hero, benefits grid, how it works with a guide link, FAQ, call to action
comparison_page Hero, dated summary with sources, comparison table, when to choose which, FAQ, call to action
integration_page Hero, what you can do, setup steps with a code block, FAQ, call to action
pricing_page Title, pricing table, plan comparison table, FAQ, call to action
use_case_page Hero, problem, how the product helps, example, FAQ, call to action

Pass the returned blocks to create_page or update_page. Every placeholder is in square brackets: replace each one, and remove sections you have no real content for, such as an example without a measurable outcome. The FAQ is an ordinary Accordion, so it shows the questions on the page.

Core 0.2.95 / MCP 0.45.74 add low-priority imports in Cloud and self-hosted installations running that release. Earlier versions lack this contract; ordinary API writes have editor authority.

Use create_page with write_mode: "import" for research or migration data that a person will later confirm or correct. Affected fields must explicitly include import in writable_by, directly or through their enclosing field. Defaults also receive provenance. Normal creation defaults to write_mode: "editor". The server assigns provenance; callers cannot impersonate an owner or downgrade existing editor decisions.

For existing Pages, first call read_page_authority:

{
"page_id": "example",
"paths": ["programs/@summer/legacy_anchor", "support/training"]
}

The response includes a revision, whether a working copy exists, and each requested leaf’s source. attribution is explicit, inherited or unattributed; effective_path identifies the source’s provenance path. No values, actor identities or evidence URLs are returned. Ordinary Page reads omit provenance: that does not mean the answers are unprotected.

Then pass the returned revision to import_page_fields:

{
"page_id": "example",
"base_revision": "<revision from read_page_authority>",
"import_run_id": "migration-2026-10",
"changes": [
{ "path": "programs/@summer/legacy_anchor", "value": "original-program" }
]
}

Paths name custom-field leaves, without a fields/ prefix. Keyed arrays use @ followed by an existing stable item ID; escape ~ as ~0 and / as ~1 inside segments. Omitted fields and other items are preserved. This operation cannot insert/delete items, change their IDs or replace compound objects/arrays. Scalar lists such as multiselects are indivisible leaf values. Both tools accept up to 100 paths/changes and the same selected Site/version, and require editor access. Installation credentials cannot use this import/readback surface.

Import saves immediately. It does not invoke publication, but the Site’s existing automatic publishing policy still applies. A protected answer, including an owner’s deliberate null, returns 409 with rejected paths; the whole import is rejected without partial writes. An existing draft or changed Page/schema also returns 409. Resolve the conflict and read again; never blindly retry using an override. Unchanged values are not re-confirmed. Changes that alter the Page URL are rejected: use the normal route-editing flow and redirects instead.

Earlier imports stamped as editor/API decisions are not reset by this feature. Review those records separately; do not erase provenance or reimport a production library just to make owner edits pass.

Only addressed leaves are validated against the current schema. Removing a field definition does not physically delete its stored values: imports preserve such retired values and their provenance, but cannot address or change them. Stop consuming obsolete mirrors when changing a schema; do not maintain them as a second source of truth.

Create a page titled "Tjänster" at slug "tjanster" with three service sections.

A requested address is never changed silently. Creation compares the new page’s address with every page in the version — drafts, review and unlisted pages included, and the address an unsaved page draft will take when it is saved. The address comes from the content type’s URL pattern, or from an explicit path.

  • Explicit slug or path already in use: the call is refused with 409 and a stable code — slug_in_use, or path_in_use when you passed path or the content type builds its URL from fields other than the slug. details names the page that holds the address:

    {
    "error": "Slug \"tack\" is already in use: /tack belongs to page tack. Choose another slug, or edit the existing page.",
    "code": "slug_in_use",
    "details": { "page_id": "tack", "path": "/tack" }
    }

    Edit that page, or choose another slug. Nothing is created.

  • Slug derived from the title (no slug passed): the page is created with a numbered slug, such as tack-2, and the response carries a warning:

    "warnings": [{
    "code": "slug_adjusted",
    "requested": "tack",
    "slug": "tack-2",
    "path": "/tack-2",
    "conflicting_page_id": "tack",
    "message": "…"
    }]

    Scripts that link to the new page should use the returned slug and url, or pass an explicit slug to be told about the conflict instead.

clone_page follows the same rule: a slug you pass must be free, and a slug derived from the new title is numbered with a warning. The portal’s New page form names only a title, so it numbers the slug and the editor says which page already uses the requested address. Two pages may share a slug when their addresses differ, for example under different path prefixes or content types.

Switches a page between "html" and "blocks" modes. Snapshots a revision first. Typeroll does not convert HTML into blocks: switching to blocks starts an empty block tree and keeps the HTML in the page history. Build the content with blocks afterwards.

Switch the About page to blocks mode and rebuild it with blocks.
→ set_page_mode page_id=about to=blocks

Updates one or more fields on an existing page. Pass only the fields you want to change — others are preserved.

Update the Services page: change the seo_description to "..."

add_faq_schema, add_recipe_schema and add_event_schema add schema.org JSON-LD to a page without hand-writing json_ld. They validate the input, build the JSON-LD and merge it into the page’s json_ld field: an existing node of the same type is replaced, other structured data on the page is kept in an @graph. A page whose existing json_ld is not valid JSON-LD is refused rather than overwritten. Like other content edits, the result is a draft; pass save: true or save it afterwards. They need write permission and accept version.

Tool Required Optional
add_faq_schema page_id, items (question, answer) —
add_recipe_schema page_id, name, ingredients, instructions description, image_url, author, prep_time, cook_time, total_time (ISO 8601 durations such as PT30M), recipe_yield
add_event_schema page_id, name, start_date description, end_date, location_name, location_address, image_url, offers_url, offers_price, offers_currency (ISO 4217)

Validation rules: FAQ items need a question and an answer; recipes need at least one ingredient and one step, and URLs must be absolute; event dates are ISO 8601 (include the UTC offset), the end is not before the start, and a price needs a currency. The response lists warnings when the data is valid but not eligible for Google’s rich results, such as a recipe without an image or an event without a location.

The FAQ page shows five questions. Add FAQ structured data for them.
→ add_faq_schema page_id=faq items=[…]

Use FAQ markup only on a page that visibly shows those questions and answers. The built-in AI chat has tools with the same names, inputs and rules. Over the REST API, write the JSON-LD string to json_ld with PATCH /api/v1/sites/{siteId}/pages/{pageId}; for other types, use update_page with json_ld in the same way. See SEO and indexing.

Updates multiple pages in one call. More efficient than individual updates for bulk changes like SEO fixes.

Over the REST API this is POST /api/v1/sites/{siteId}/pages/batch-write, taking [{ page_id, patch, save? }] up to 200 entries and answering { results: [{ page_id, ok, saved, error? }] }. Each entry applies independently, so one failed page does not abort the rest, and save: true commits that page’s working copy in the same call. Prefer it to a loop of single-page writes: a per-page loop across a whole site is slower, has no per-entry report, and leaves a partial result you have to reconstruct by reading the data back.

Write meta descriptions for all pages.

The AI agent uses batch_update_pages automatically for multi-page operations.

For block-based Pages, update blocks. Read the saved tree first, preserve existing block IDs, and give new blocks unique IDs, including blocks nested in children or slots. An ID must contain 1–128 letters, digits, underscores or hyphens. The supplied tree replaces the Page’s entire block tree; it is not a list of individual block patches. Use save: true on each batch entry to commit its working copy before deploying, and check every entry’s result for errors.

Returns all pages with title, slug, status and SEO fields — but not the HTML body (to keep responses small).

Add full: true to include html_content — use sparingly on large sites.

Returns a single page including its full html_content. The AI agent uses this before editing a page.

Reads multiple pages by ID in one call. Returns { pages_by_id: { id: page }, not_found: [] }.

Over the REST API this is POST /api/v1/sites/{siteId}/pages/batch-read, taking { page_ids: [...] } up to 200 ids and answering { pages: [{ page_id, found, page? }] }. Each page carries fields and blocks, which list_pages omits by default.

It reads accepted content. A page with an uncommitted working copy is returned as it was last saved, not as it currently reads in the editor — so use read_page when you need to tell a draft from accepted content.

Finds the Page behind a URL or path on the selected site and version, including addresses created by Content type routes. Pass url and optionally version. It never fetches the URL and refuses addresses on other sites. A #fragment points to a place on the returned page, not to a separate page.

Which page is https://example.com/blog/moving-tips/ ?

Finds pages whose saved content contains a substring (contains) or matches a regular expression (regex). It searches the same editorial text that bulk_replace_text edits: block data in block-mode pages, html_content in HTML-mode pages, and the content type’s text fields. Block ids and block types are not searched. Each match reports field (blocks, html_content or fields.<name>) and an excerpt around the first hit:

search_pages contains="<h1" ← pages with an H1
search_pages contains="calendly" ← pages with a Calendly embed
search_pages contains="/old-path" ← pages with a stale internal link

Permanently deletes a page. This also removes it from the next deploy.

Set publish_at on a draft and it goes live on its own — no one has to be at a keyboard:

Publish the spring campaign page on 1 April at 08:00.
Take the winter offer down on 28 February.

Saved schedules create a pending task for the chosen time. The task updates anything that’s due, clears the timer so a re-run can’t double-fire, and triggers one deploy per site no matter how many pages changed, regardless of content type.

The times are absolute (ISO 8601). A scheduled publish still only shows content that was saved — a page with unsaved drafts publishes its saved version.

When a page is in content_mode: "html", the AI agent follows these conventions for the body content:

  • CSS variables for colours and fonts — var(--color-primary), var(--font-heading), never hardcoded hex
  • One <h1> per page — the page title. Sections use <h2>.
  • No <nav>, <header>, <footer> in page HTML — those live in partials
  • Inline <style> blocks are allowed — scoped to the page’s classes
  • <iframe> allowed for YouTube, Vimeo, Calendly, Google Maps
  • No <script> tags — use site settings for analytics/chat widgets

In block-mode pages, none of these conventions apply directly — the block library handles structure and the renderer enforces semantics. See the Blocks reference.

Set optional breadcrumb_label through create_page, update_page, the Pages API (including batch writes), or Page settings → Breadcrumb label. A label is at most 200 characters; null, empty or whitespace-only values use the normal page title. It changes the breadcrumb label only, not title, SEO title, slug, path, canonical or hierarchy. Parent labels are shared by their descendants. For inferred Content-type trails, the published hub’s short label takes precedence over the type’s plural label. A home page has no breadcrumb trail.

For example, a hub titled “Our complete guide to moving” may have breadcrumb_label: "Moving tips". Its child keeps its full page title and route. Republish after changing a parent label so affected descendants update too. MCP 0.45.24 exposes the optional field; Cloud/self-hosted servers require Core 0.2.28.

clone_page creates a draft, preserving body, Content type, template, parent, custom fields, language and page CSS. For an explicit path such as /offers/summer/, slug: "autumn" produces /offers/autumn/ under the site’s trailing-slash policy. Otherwise routing follows the Content type and parent. An occupied explicit path returns a conflict; choose another slug. Canonical overrides and custom JSON-LD are not copied. Pass version to keep both the source read and clone creation in the selected site version.