Skip to main content
Pages are the structured surfaces a hub renders: homepages, sales pages, link-in-bio pages, and other public or member-facing views.

Admin page management

Pages are scoped to a team and hub:
GET  /api/v1/teams/{team_id}/hubs/{hub_id}/pages
POST /api/v1/teams/{team_id}/hubs/{hub_id}/pages
GET  /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}
PATCH /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}
DELETE /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}
Use pages when you need a hub-rendered layout, not just a content lesson.

Sections

Sections are the building blocks inside a page. They can represent text, calls to action, grids, media, search, and other structured page blocks.
GET   /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}/sections
POST  /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}/sections
PATCH /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}/sections
PATCH /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}/sections/{section_id}
DELETE /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}/sections/{section_id}

Draft-tree authoring

The draft tree is the mutable, unpublished state of a page’s node hierarchy. Write it with:
PUT /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}/tree
Team-owner only. The request body is a JSON:API envelope; the If-Match header carries the optimistic-concurrency token (OCC). Bootstrapping the token: read the page first — the admin read (GET /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{identifier}) returns the current version in both attributes.draft_version and the ETag response header. Echo that value as If-Match on your first write; every subsequent write/publish response hands you the bumped token:
PUT /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}/tree
Authorization: Bearer <token>
Content-Type: application/vnd.api+json
If-Match: "3"

{
  "data": {
    "type": "page_draft_trees",
    "attributes": {
      "tree": { "nodes": [ { "id": "hero", "type": "hero_section" } ] }
    }
  }
}
On success you get 200 with the bumped version echoed in both the ETag response header and attributes.draft_version:
HTTP/1.1 200 OK
ETag: "4"
Content-Type: application/vnd.api+json

{
  "data": {
    "id": "<page_id>",
    "type": "page_draft_trees",
    "attributes": {
      "draft_version": 4,
      "tree": { "nodes": [ { "id": "hero", "type": "hero_section" } ] }
    }
  }
}
Store the new draft_version (or echo the ETag value verbatim) as your If-Match token for the next write or publish call. Error codes
StatusCodeCause
428precondition_requiredIf-Match header absent
400invalid_if_matchIf-Match value is not an integer (weak validators W/"n" are rejected)
409stale_draftA concurrent write bumped the version; re-read and retry
422invalid_treeTree failed structural validation (node-type rules, 500-node cap)
413Request body exceeds 1 MB
404page_not_foundPage, hub, or team not found or mismatched
401/403Missing or insufficient credentials

Publish

Publishing compiles the editable tree into the served page state.
POST /api/v1/teams/{team_id}/hubs/{hub_id}/pages/{page_id}/publish
Send the current draft_version as If-Match (same OCC contract as the tree write). If a concurrent draft write happened after your last read, publish returns 409 — re-read and re-send. The backend uses optimistic concurrency for publish operations. If a frontend edits pages collaboratively, preserve and send the versioning headers shown in the generated endpoint reference.

Member and public rendering

Portal routes return hub-renderable pages:
GET /api/v1/hub/{hub_id}/pages
GET /api/v1/hub/{hub_id}/pages/home
GET /api/v1/hub/{hub_id}/pages/{identifier}
GET /api/v1/hubs/{slug}/pages/{page_type}
Access rules can prune or hide page nodes for a contact. Anonymous render endpoints return pre-pruned public artifacts when available.