---
title: "Layout and Placement API"
description: "Manage SDUI page layouts and route placements via the API."
canonical_url: "https://docs.bulkheados.com/api-reference/layouts/"
template: "page-node"
schema_type: "WebPage"
---

<div class="docs-content">
<p class="docs-lead">The Layout and Placement APIs let customer automations adjust page composition and routing overlays without leaving the tenant boundary. Use <code>content:read</code> to inspect published layout and active placement state, and <code>content:write</code> to create, publish, update, or archive layout and placement records.</p>
<p>Set <code>BULKHEAD_SITE_URL</code> to your workspace URL and <code>BULKHEAD_API_TOKEN</code> to a scoped token from <strong>HQ → API Keys</strong>. Layout publish, published layout create, placement slug changes, and placement archive operations enqueue compile work so public pages can reflect the change.</p>

<h2 id="list-layouts">List Layouts</h2>
<pre><code class="language-bash">curl -sS "$BULKHEAD_SITE_URL/api/v1/layouts?limit=20&amp;offset=0" \
  -H "Authorization: Bearer $BULKHEAD_API_TOKEN"</code></pre>
<p><code>content:read</code> keys see published layouts. <code>content:write</code> keys can inspect draft and published layout state.</p>

<h2 id="create-layout">Create a Layout Draft</h2>
<pre><code class="language-bash">curl -sS -X POST "$BULKHEAD_SITE_URL/api/v1/layouts" \
  -H "Authorization: Bearer $BULKHEAD_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Landing Page Layout",
    "node_id": "node-1",
    "blocks": [
      {
        "type": "rich-text",
        "props": {
          "html": "&lt;p&gt;Use source-backed content and a reviewed layout block.&lt;/p&gt;"
        }
      }
    ],
    "status": "draft"
  }'</code></pre>

<h2 id="publish-layout">Publish a Layout</h2>
<pre><code class="language-bash">curl -sS -X POST "$BULKHEAD_SITE_URL/api/v1/layouts?action=publish" \
  -H "Authorization: Bearer $BULKHEAD_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "layout-1"
  }'</code></pre>

<h2 id="list-placements">List Placements</h2>
<pre><code class="language-bash">curl -sS "$BULKHEAD_SITE_URL/api/v1/placements?node_id=node-1" \
  -H "Authorization: Bearer $BULKHEAD_API_TOKEN"</code></pre>

<h2 id="create-placement">Create a Placement</h2>
<pre><code class="language-bash">curl -sS -X POST "$BULKHEAD_SITE_URL/api/v1/placements" \
  -H "Authorization: Bearer $BULKHEAD_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "node_id": "node-1",
    "slug": "shipping-notes",
    "title_override": "Shipping Notes"
  }'</code></pre>

<h2 id="update-placement">Update a Placement</h2>
<pre><code class="language-bash">curl -sS -X PATCH "$BULKHEAD_SITE_URL/api/v1/placements" \
  -H "Authorization: Bearer $BULKHEAD_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "placement-1",
    "slug": "shipping-notes-updated"
  }'</code></pre>

<h2 id="archive-placement">Archive a Placement</h2>
<pre><code class="language-bash">curl -sS -X DELETE "$BULKHEAD_SITE_URL/api/v1/placements" \
  -H "Authorization: Bearer $BULKHEAD_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "placement-1"
  }'</code></pre>

<h2 id="response-format">Response Format</h2>
<p>Layout responses return a <code>layout</code> object and any compile enqueue result. Placement rename and archive responses include <code>stale_kv_deleted</code> for previous public route keys removed before success is reported, plus <code>recompile_enqueued</code> when public route output needs refreshing.</p>
<pre><code class="language-json">{
  "placement": {
    "id": "placement-1",
    "slug": "shipping-notes-updated",
    "kv_key": "ctx:docs:shipping-notes-updated"
  },
  "recompile_enqueued": true,
  "stale_kv_deleted": [
    "ctx:docs:shipping-notes",
    "ctx:docs:en:shipping-notes",
    "ctx:docs:ga:shipping-notes"
  ]
}</code></pre>
</div>
