Patch a page's arrangement and metadata (RFC 6902, optimistic concurrency).
Applies an RFC 6902 JSON Patch to a page's fields document — /layout (including the htmlSlots layout.html frame string and per-breakpoint layout.items.{lg,md,sm,xs} grid geometry), /title, /background, /theme, /doc (page-level documentation — description/intent/assumptions/notes, ADR-0045 §4, surfaced by dvt_dashboard_get(view="docs") and the docs drawer) — without touching any element row or its revision history (DVT-2753). This is the non-destructive, surgical alternative to a full-spec resend (PATCH /v1/dashboards/{id} or dvt_dashboard_apply_spec), which re-keys every page and element to fresh UUIDs and resets their revision history.
Forbidden paths (400 invalid-patch), because they are owned elsewhere or out of scope for a geometry/metadata edit: /position (use the pages reorder endpoint), /id and /slug (immutable — slug uniqueness, comment-anchor remapping, and <dvt-slot ref> targets all key off them), /kind (not a geometry edit), /panels (separate element rows, not part of a page's fields document — use the element API), /hidden (page visibility is not patchable on this route, see DVT-2442), /layout/mode (grid/canvas/htmlSlots transitions are out of scope), and a whole-document replace ("" or /).
Single-page dashboards (409 single-page-field-not-patchable): a dashboard authored in the single-page shorthand (top-level layout/panels, no pages array) has a synthesized page whose fields document carries ONLY layout — its bundle has no title/background/theme/doc to receive a write, and the assembled bundle re-emits only layout + panels for that shape. Patching anything outside /layout on such a page would silently persist into storage (and version/audit it) without ever reaching the assembled spec, the renderer, or dvt_dashboard_get(format="full") — so it is refused. Only /layout (and its descendants) is patchable on a single-page dashboard's page; convert to the multi-page form first (a full-spec update with a pages array) to patch title/background/theme/doc.
The body is a pure patch document, so the current page version is supplied out-of-band: pass it via the version query parameter or an If-Match header. A stale version returns 409.
Provenance (DVT-1658): pass an optional reason query parameter (or the X-Dvt-Change-Reason header) explaining why the change was made — it is recorded as the new page revision's change summary. Unlike PatchElement (DVT-1792), a reason is NOT required here; an unsupplied reason falls back to a generated summary.
Request
- Base URL: http://localhost:8080
- URL: http://localhost:8080/v1/dashboards/{id}/pages/{pageId}
- Auth: one of:
- API key in cookie dvt_session
- HTTP bearer
Query parameters
The page's current version (optimistic concurrency). Required unless supplied via If-Match.
Optional provenance note (the "why") recorded as the new page revision's change summary (DVT-1658). 1–280 characters. May also be supplied via the X-Dvt-Change-Reason header. Falls back to a generated summary when omitted.
Headers
Alternative to the version query parameter — the page's current version.
Response
Page updated; returns the new page header.
Changes
No recorded changes to this operation across all 1 revision of this API.