Skip to main content

Published Page Design

A published board is a public web page. Its design — which elements sit in which region of the page, their content, and the page's background colour and typography — can be created and edited over the API, the same way the Publish editor does it.

Prerequisites

  • write scope and permission to modify the board.
  • Page layout API writes enabled for your workspace. Reads work everywhere; every write below answers 403 page_layout_api_disabled until Playbook support enables it.

1. Discover the vocabulary

curl "https://api.playbook.com/v1/page_layout_elements" \
-H "Authorization: Bearer YOUR_TOKEN"

One global response (no workspace slug) describing everything you can write:

KeyWhat it holds
templatesValid template ids — the keys — each with display_name, default background colour and typography, and the slots (page regions) it mounts itself.
elementsEvery element type (note, button, banner, section, …) and the camelCase props it accepts. Flags mark props that are HTML, URLs, asset tokens, or dead (stored but no longer rendered).
background_colors, typographiesThe values page settings accept.
operationsThe argument map for batch edits.
limitsHard payload caps, e.g. max_batch_operations.

2. Publish with a template

curl -X POST "https://api.playbook.com/v1/my-org/boards/portfolio/publish" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"template": "standard"}'

A publish with a template creates the page design that the layout endpoints read and edit. A board published without one, and never saved in the Publish editor, is still public, but has no design: the layout endpoints answer 404 page_layout_not_found until you publish it with a template.

ResponseMeaning
422 unknown_templateThe id is not a template; the message lists the valid ids.
409 page_design_existsThe page has stored element edits. They are never overwritten — publish without template to keep them, and edit the design instead. This does not protect a design that is only page settings (background colour, typography): a template publish replaces those. A page still following its template, never edited, simply switches to the new one.
409 publication_conflict / page_layout_conflictSomeone else changed the publication at the same moment. retryable: true — send the request again.
503 template_catalogue_unavailableTemplates are temporarily unavailable. Retry later, or publish without a template.

Every board response (GET /boards/{token}, lists, children) carries the page state:

"published_page": { "active": true, "template": "standard", "url": "https://playbook.com/s/my-org/portfolio" }

url is null unless the page is live, and template can be set on a page that is not.

3. Read the page layout

curl "https://api.playbook.com/v1/my-org/boards/portfolio/page_layout" \
-H "Authorization: Bearer YOUR_TOKEN"
{
"data": {
"uuid": "<uuid>",
"template": "standard",
"background_color": null,
"typography": null,
"slots": null,
"subboards_settings": [],
"version_token": "<opaque version token>"
}
}
  • slots: null is normal. A page nobody has edited stores no document and renders its template's defaults. Address such a page by slot name ("slot_id": "description", from templates[...].slots): the first write saves the defaults and its response contains real ids for everything.
  • slots and subboards_settings are returned verbatim. Their ids and camelCase keys are exactly what the write endpoints take back.
  • background_color / typography null means the page inherits them.
  • subboards_settings holds one full second document per nested board shown on the page. Edit one by sending its collectionToken as subboard_token on any write.

4. Edit elements

All paths below are under /v1/{slug}/boards/{token}/page_layout.

OperationRequest
AddPOST /elementsslot_id, at_index, element; optional parent_element_id + column_id/column_index/create_new_column to insert into a section
ReplacePATCH /elements/{element_id}slot_id, element
MovePOST /elements/{element_id}/movefrom_slot_id, to_slot_id, at_index
DeleteDELETE /elements/{element_id}?slot_id=… — addressing in the query string
ReorderPOST /slots/{slot_id}/reorderordered_ids
BatchPOST /operations — up to 50 of the above, atomically
curl -X POST "https://api.playbook.com/v1/my-org/boards/portfolio/page_layout/elements" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"slot_id": "description",
"at_index": 0,
"element": { "id": "intro-note", "elementType": "note", "props": { "text": "<p>Spring collection</p>" } },
"expected_version_token": "<version_token from the read>"
}'

Rules that matter:

  • Supply your own element.id on an add. Re-sending an identical add then succeeds without inserting twice; the same id with different content is 409 element_exists.
  • PATCH replaces the element, not a field. Every top-level key you send replaces the stored one wholesale, so {"props": {"text": "…"}} drops every other prop. Read the element, change it, send the whole props back.
  • Reorder takes the exact set. ordered_ids must be the slot's current top-level ids — none missing, repeated or extra — or 422 reorder_id_mismatch names the offenders.
  • Batches are all-or-nothing. The first failing operation rolls the batch back; the error carries operation_index. Ids the server mints inside a batch cannot be addressed later in the same batch, so give new elements your own ids. One batch edits one document (the page, or one subboard_token).
  • Props flagged as HTML or URLs must be strings. HTML is sanitized and unsafe URL schemes are dropped on write. An asset-token prop takes an asset token from your workspace; Playbook copies the asset into the page's library.

5. Page settings

curl -X PATCH "https://api.playbook.com/v1/my-org/boards/portfolio/page_layout" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"settings": {"backgroundColor": "dark", "typography": null}}'

A partial update: an omitted setting is untouched, null clears it so the page inherits again. Values outside background_colors / typographies are 422 invalid_page_setting. A board following a workspace template stops following it after a real change, so a later template roll-out does not revert your edit.

Working alongside people

  • Compare-and-swap. Send the read's version_token as expected_version_token on any write. If the page changed in between you get 409 stale_document and nothing is applied — read again, re-decide, re-send. Responses to a write that sent a token include the new version_token.
  • Did anything change? converged: true means the goal already held (deleting an id that is not there, an identical add, a no-op move). materialized: true means the call saved the template defaults for a page that had no document. Both are absent when false. PATCH on an element never reports converged.
  • Freshness. The API reflects a write immediately; the public page can serve the previous version for up to an hour.

Errors

Errors use the standard envelope; key on extensions.code, and use retryable to decide whether to repeat the same request.

StatusCodes
403page_layout_api_disabled, board_not_authorized (you cannot modify the board that governs this design), board_read_only
404page_layout_not_found, slot_not_found, element_not_found, subboard_not_configured
409stale_document (re-read), element_exists (new id or PATCH), lock_wait_timeout and page_layout_library_locked (retry as-is)
422invalid_parameter, invalid_prop_type, invalid_element_shape, ambiguous_slot_name, reorder_id_mismatch, invalid_page_setting, forbidden_prop, asset_not_found, element_too_large

Over MCP

The MCP server exposes the same surface: publish_board (with template), get_page_elements_catalog, get_page_layout, add_page_element, update_page_element, move_page_element, delete_page_element, reorder_page_slot, apply_page_operations and update_page_settings.

One difference: publish_board called without template on a board that is not live and has no page design yet applies standard (or your workspace's own version of it), so the page is editable immediately. A live page and a board that already has a design are republished unchanged. The tool response's template_applied names the template applied, if any.