Managing pages over the API

The editorial side of the pages API. Page records, menus, library items, templates, template assignments, site settings and vocabularies, with each route's body, filters and status codes.

The editorial surface is where pages are drafted and composed. It shows everything an editor sees: drafts, archived pages, the trash, and every publication a page has had. A storefront does not read from it. Visitors get the published result from the delivery routes, described in Reading published pages.

Use these routes to manage the records around a page: change page records, retire pages, keep navigation menus in step with your theme, maintain the shared library and templates, and set the site-wide settings a theme styles with.

Before you start

These are server-side calls through the gateway, made with the tenant's API key. Never send them from the browser. The authentication page covers the headers.

They are for a team that manages pages from its own tooling, or for a migration. A storefront reads delivery instead.

What this API does not do

  • Block content is not here. The page routes change the page record only, so their responses have no block tree. Library items and templates are the exception: they carry their tree.
  • Publishing is not one of these routes. It happens in the editor. Setting a page's status to published here does not publish its content.
  • Library items and templates cannot be created through these routes. You make them in the editor (Cockpit); a pop-up, which is a library item too, is created with POST /v1/pages/popups. These routes read, change and remove them.

Conventions

  • Lists answer with items, filter (the filters that were applied) and page (total, returned, limit, offset, hasMore).
  • Unknown filters. Pages, menus, library items and template assignments ignore a filter key they do not read. The answer is still 200, and that key is missing from filter. Templates and revisions refuse an unknown filter key with 400 and the code unknown_filter. They also refuse a value that starts with an operator such as not., with 400 and unsupported_filter_operator. Filters match exact values, except the text searches: q on pages and text on library items match part of the title or label, ignoring case.
  • Paging uses limit (1 to 200) and offset. order takes one field, with an optional .asc or .desc. An unknown field is refused with 400.
  • Deletes. Pages, menus and library items are soft-deleted: the record is kept and hidden from normal reads. Templates, template assignments and site settings are removed outright and cannot be restored.
  • Empty updates. On menus, library items and templates, a PUT with no fields to change answers 400 with the code empty_update. A page PUT with nothing to change answers 200.
  • Every route can also answer 401, 403, 429 and 502.

Pages

RouteWhat it does
GET /v1/pages/pagesLists pages of every status, newest change first. Filters: status (draft, published, archived), bundle, and q (case-insensitive title search). deleted=only lists the trash instead. Any other deleted value is 400.
POST /v1/pages/pagesCreates a page and its source-language translation. Answers 201.
GET /v1/pages/pages/{id}Reads one page record. The record has no block tree.
PUT /v1/pages/pages/{id}Changes the record. Answers 200.
DELETE /v1/pages/pages/{id}Soft-deletes the page. Answers 200 with deleted: true.
POST /v1/pages/pages/{id}/duplicateCopies the page into a new, unpublished page. Answers 201.
POST /v1/pages/pages/{id}/restoreBrings a deleted page back. Answers 200.
GET /v1/pages/pages/{id}/revisionsLists the publication history of the page.

Create (POST /v1/pages/pages). title is required. The other fields are optional:

  • bundle, sourceLanguage and the page's default status come from the tenant's settings when you leave them out. The status is never a body field.
  • slug defaults to none. hostOptions and meta are stored as {} when left out.
  • templateId starts the page from a template. The template's blocks are copied in, and the page takes the template's bundle. If the template has a page_bundle, bundle must match it.
  • 400 when title is missing, when templateId names no template, when the template is for another page type, or when the template holds a block that cannot be copied.
  • 409 when another live page in the tenant already holds the slug.

Example body, using the spec's example values:

JSON
{
  "title": "About us",
  "slug": "about-us",
  "bundle": "standard",
  "sourceLanguage": "de"
}

Read (GET /v1/pages/pages/{id}). Returns title, slug, bundle, status, source_language, host_options, meta, the timestamps, and published_revision_id. A page with status: published but no published_revision_id is not served to visitors, because only a publication is delivered.

Update (PUT /v1/pages/pages/{id}). Only five fields change: title, slug, status, meta and bundle. Other body fields are dropped without an error.

  • meta is replaced as a whole, not merged.
  • A new slug works on delivery at once, and the slug the page had at its last publish keeps working too until the page is published again in the editor. The delivery response also shows that older slug until then. slug: null clears the record's slug, but the slug from the last publish keeps serving the page until the next publish.
  • 409 when the slug belongs to another live page.

Delete (DELETE /v1/pages/pages/{id}). The page leaves every list, read and delivery response at once, and its slug is free for another page immediately. Nothing is erased: translations, blocks, revisions and comments stay, so the page can be restored. 404 when the page is unknown or already deleted.

Duplicate (POST /v1/pages/pages/{id}/duplicate). Copies what the source shows: its blocks as published, every language's title, its bundle, language, display options and metadata. An open draft on the source is not copied. The copy gets new block ids, but a block that uses a library item keeps referencing it. The copy is unpublished, has no revisions, and starts at the default page status.

  • Body: title and slug are both optional. Without a slug the copy has none, so it cannot collide. An empty body gives the source title plus a copy suffix.
  • 409 when the slug, or a slug on a translation of a live page, is taken.

Restore (POST /v1/pages/pages/{id}/restore). Brings the deleted page back with its translations, revisions and published revision as they were. Only the slug can have changed, because deleting freed it.

  • 404 when the page is not deleted. Only a page in the trash can be restored.
  • 409 when another live page now holds the page's slug. The page stays in the trash; free the slug or change it, then restore again.

Publication history (GET /v1/pages/pages/{id}/revisions). One entry per publication, newest first. The list does not include the published content, only the entries. Filters are exact matches: label, created_by (user id), created_by_name, and created_at (RFC 3339, exact match only). 404 when the page id is unknown.

Menus are the navigation a theme renders, for example main, footer and account. Each menu has a menu_key, which is how a theme asks for it.

RouteWhat it does
GET /v1/pages/menusLists menus. Takes paging and order only. A menu_key filter is ignored.
POST /v1/pages/menusCreates a menu by key, or replaces the label and items of the menu that already has the key.
GET /v1/pages/menus/{id}Reads one menu by the menu's id, including the whole nested items tree.
PUT /v1/pages/menus/{id}Replaces the label, items and metadata of one menu, by the menu's id.
DELETE /v1/pages/menus/{id}Soft-deletes a menu.
  • Upsert (POST). Send menuKey (required) and items. Send items on every call: when it is missing, the menu is saved with no items, so an update that only changes label empties the navigation. label is required when the key is new. An update keeps the old label if you leave it out. The answer is 201 when the key was free and 200 when an existing menu was replaced. 400 when menuKey is missing, or label is missing on a create.
  • items is replaced, never merged. Sending an empty list empties the navigation.
  • Keys are kept unique by this route only. If two menus ever share a key, this route updates whichever one it finds first.
  • Update (PUT). Do not send menu_key. Changing a menu's key empties the slot a theme reads, and nothing reports an error.
  • Delete. The menu disappears from the management list and from delivery at once. A theme that reads the key gets nothing back, with no error. The key is free again immediately, so re-seeding the theme restores it. Check what reads the key before you delete it.

Library

The library holds reusable blocks. A library item is shared by reference: pages that use it render the item's current tree, so an edit to the item changes every page that uses it, without any page being edited or republished. Compare templates, which are copied.

RouteWhat it does
GET /v1/pages/librarySearches the library. Filters: bundles (comma-separated block types) and text (substring of the label). Paged, default 24.
GET /v1/pages/library/{id}Reads one item, including its tree.
PUT /v1/pages/library/{id}Replaces bundle, label, metadata or tree of one item. Answers 200.
DELETE /v1/pages/library/{id}Soft-deletes an item. Answers 200 with deleted: true.
  • The filter is bundles, plural. ?bundle= is ignored.
  • Pop-ups are library items too, with the bundle popup. An unfiltered library list includes them. Edit pop-ups through the pop-up routes instead; see Pop-ups.
  • Update. Replacing tree changes every page that references the item, including published pages. No publication records the change, because the pages themselves did not change. metadata is replaced as a whole.
  • Delete. The item leaves the picker and the lists. Blocks that point at it keep their reference, but a reference holds no content of its own: delivery then renders each one as an empty block of its bundle, on published pages too, with no error. The API does not list which pages use an item, so check before you delete it.
  • 404 when the item is unknown or deleted.

Templates

A template is copied into a new page. Nothing links back from the pages built from it, so editing a template changes only what future pages start from.

RouteWhat it does
GET /v1/pages/templatesLists templates. Every field is an exact-match filter: id, label, description, page_bundle, field_name, is_default, created_by, created_at, updated_at.
GET /v1/pages/templates/{id}Reads one template, including its tree.
PUT /v1/pages/templates/{id}Replaces the fields you send. Answers 200.
DELETE /v1/pages/templates/{id}Removes the template. This cannot be undone.
  • Fields. label, description, page_bundle, field_name, is_default and tree. A page_bundle or field_name of null offers the template everywhere. Filtering by page_bundle does not return templates that have none.
  • is_default is a marker. A client can look it up with ?is_default=true. Nothing in the API starts a page from it: a page starts from a template only when templateId is sent on create.
  • Update. Does not change pages that already exist.
  • Delete. Pages built from the template keep their own copy of the blocks.
  • 404 when the template id is unknown.

Template assignments

Template assignments choose the page that renders a single record, such as one product, instead of the theme's default template. A record without an assignment is not an error; it renders with the default.

RouteWhat it does
GET /v1/pages/template-assignmentsLists assignments. Filters: resource_type (one kind of record) and page_slug (every record one page is the template of).
PUT /v1/pages/template-assignments/{resource_type}/{resource_id}Assigns a page to one record. Answers 200.
DELETE /v1/pages/template-assignments/{resource_type}/{resource_id}Removes the assignment outright. Answers 200 with deleted: true.
  • Assign (PUT). The body needs pageSlug, the slug of a live page. The page need not be published, but the storefront uses it only once it is. The record is the address, so a second PUT moves the assignment rather than adding one. resource_type is lower-case letters, digits and underscores, starts with a letter, and is up to 64 characters (a hyphen is refused). resource_id is 1 to 255 characters. The app does not look the record up.
  • 400 for an invalid type or id, a missing pageSlug, or a slug that no live page holds. 409 when two requests first assign the same record at the same moment; send the call again.
  • Remove (DELETE). Hard delete. The page itself is not touched. 404 when the record has no assignment.

Site settings

Site settings are the theme-wide values a storefront styles itself with. The keys the storefront themes read are appearance, design and customCss. The API stores any JSON value under a key; the theme that reads it decides its shape.

RouteWhat it does
GET /v1/pages/settings/siteLists every key that is set, ordered by key. Answers items only, with no page block. The list is capped at 200 keys.
GET /v1/pages/settings/site/{key}Reads one key with its value and who set it last.
PUT /v1/pages/settings/site/{key}Creates or replaces a key. Answers 200 either way.
DELETE /v1/pages/settings/site/{key}Unsets a key outright. Answers 200 with deleted: true.
  • Key format. A lower-case letter followed by letters and digits, up to 64 characters in total. Anything else is 400.
  • Read. A key that was never set answers 404, so "not set" and "set to nothing" are different.
  • Write. value is required and must not be null; to remove a key use DELETE. The value is replaced as a whole, not merged. The serialized value can be at most 128 KiB; a larger one is 413 and nothing is written. 409 when two requests first set the same key at the same moment; send the call again.
  • Delete. Setting the key again starts afresh. On delivery, an unset appearance, design or customCss comes back as null. Any other unset key is absent.

Vocabularies

Vocabularies are the enumerated values the page API uses, such as page statuses. Each comes with its title and a plain sentence explaining it, so a select or a status badge can label the values without keeping a copy of its own.

RouteWhat it does
GET /v1/pages/vocabulariesLists the vocabularies by name, title and description. The values are not included.
GET /v1/pages/vocabularies/{name}Returns one vocabulary with all its values, in the order a select should offer them.
  • Names. edit-state-statuses, page-statuses and translation-statuses.
  • Values. Each value comes with a title, a description and the badge tone to render it in. The tones are neutral, info, success, warning and danger. Text fields can be a plain string or a map keyed by language tag; read your language and fall back to en.
  • closed: true means the list is complete. A value outside it is stale data.
  • 404 when the name is not published.
Was this page helpful?