The page model
Every field on a page, its type and limits, and which endpoint sets it.
A page is one JSON document. POST /api/agent/pages takes the fields under page; PATCH /api/profiles/{id} takes any subset of the same fields; GET /api/profiles/{id} returns them all plus the read-only ones.
| Field | Type | Notes |
|---|---|---|
username | string, 3–30, [a-z0-9-] | The subdomain. Set at creation; not changed over the API. |
displayName | string ≤ 60 | Shown as the heading. Empty falls back to @username. |
bio | string ≤ 300 | One or two sentences. Also the page's meta description. |
avatar | storage key or null | From POST /api/upload. Never a URL — see Images. |
avatarFocus | { x, y } percent or null | Where the round crop is anchored; centre when absent. |
templateId | one of ten ids | See Templates. Default editorial. |
layout | list or grid | grid shows link cards two abreast, best with images. Default list. |
headerAlign | left, center, right or null | null uses the template's own alignment. |
theme.accent | #rrggbb | Accent colour for buttons and marks. Optional. |
theme.backgroundImage | storage key or null | Kind background from the upload route. |
theme.backgroundFocus | { x, y } percent or null | Where the full-bleed crop is anchored. |
theme.overlay | number 0–1 | Darkening over the background image so text stays legible. |
pageLocale | locale code | Language of the page's own UI strings. See Languages. |
isPublished | boolean | Off means the address answers 404 to everyone but the owner. |
utm | boolean | Append utm_source=tapmy etc. to outgoing links. Default off: it rewrites someone else's URL. |
blocks | array ≤ 80 | The content. See Blocks. |
Read-only fields
| Field | Meaning |
|---|---|
id | The page id used in /api/profiles/{id}. |
moderationStatus | ok, review or banned. A banned page cannot be edited (403 banned). |
createdAt, updatedAt | ISO timestamps. |
Full example
{
"displayName": "Studio Kōri",
"bio": "Ceramics from a small studio in Kyoto. Shop opens the first Sunday of each month.",
"templateId": "whisper",
"layout": "grid",
"headerAlign": "center",
"theme": { "accent": "#2B4C7E" },
"pageLocale": "en",
"isPublished": true,
"blocks": [
{ "type": "link", "label": "Shop", "url": "https://kori.example/shop", "path": "shop", "featured": true },
{ "type": "link", "label": "Workshops", "url": "https://kori.example/workshops", "note": "Two Saturdays a month" },
{ "type": "socialRow", "items": [ { "platform": "instagram", "url": "https://instagram.com/studiokori" } ] }
]
}