A page is an ordered list of blocks. Each block carries a type, a config object whose shape is determined by type, and rendering hints (sort_order, spacing). This page documents the wire shape for every block type currently registered.
The dashboard editor is the authority for block authoring — v1 Pages is read-only. This page describes the read shape your client receives from GET /pages/{id}.
The block envelope
Every block has the same outer shape:
{
"id": "11111111-1111-4111-8111-111111111111",
"type": "heading",
"config": { /* depends on type */ },
"sort_order": 0,
"spacing_top": 0,
"spacing_bottom": 16
}
Stable UUID for this block. Referenced from form submissions (each submitted field is keyed on its block id).
Block type. One of the values listed below. New types may be added without an OpenAPI version bump — treat unknown types as opaque.
Configuration for this block. Shape depends on type. The schema types this as unknown; see the per-type sections below for the exact shape.
Display order. The blocks[] array is already returned sorted by this field — use it for stable ordering across refetches.
Bottom padding in pixels.
Categories
| Category | Types |
|---|
| Content | heading, text, image, video, divider, banner |
| Action | button, contact, file |
| Form | form_text, form_textarea, form_email, form_phone, form_number, form_select, form_radio, form_switch, form_checkbox, form_rating, form_date, form_hidden, form_media, form_submit |
Content blocks
heading
{
"type": "heading",
"config": {
"text": "Welcome",
"level": 2,
"alignment": "center",
"color": "#212b45"
}
}
| Key | Type | Notes |
|---|
text | string | Heading text. Required. |
level | 1–6 | HTML heading level. Defaults to 1. |
alignment | left | center | right | Defaults to center. |
color | string (hex) | Optional override. Inherits page text colour when omitted. |
text
{
"type": "text",
"config": {
"content": "Some rich text.",
"alignment": "center",
"color": "#444444"
}
}
| Key | Type | Notes |
|---|
content | string | Body text. Required. Plain string (no rich-text markup). |
alignment | left | center | right | Defaults to center. |
color | string (hex) | Optional override. |
image
{
"type": "image",
"config": {
"url": "https://files.awardee.dev/orgs/.../hero.jpg",
"fileName": "hero.jpg",
"linkUrl": "https://example.com"
}
}
| Key | Type | Notes |
|---|
url | string | Image URL. Required. Always served from Awardee storage. |
fileName | string | Original filename. Used as alt text on render. |
linkUrl | string | Optional click-through URL. |
video
{
"type": "video",
"config": {
"url": "https://www.youtube.com/watch?v=abc123",
"provider": "youtube"
}
}
| Key | Type | Notes |
|---|
url | string | Video URL. Required. |
provider | upload | youtube | upload means a video file in Awardee storage; youtube is any YouTube watch URL. Defaults to upload. |
fileName | string | Original filename for uploaded videos. Ignored for YouTube. |
divider
{
"type": "divider",
"config": {
"style": "line",
"thickness": 1,
"color": "#E2E7E8"
}
}
| Key | Type | Notes |
|---|
style | line | dashed | space | space renders an invisible spacer. Defaults to line. |
thickness | integer | Stroke thickness in px. Defaults to 1. |
color | string (hex) | Stroke colour. Defaults to a neutral grey. |
banner
{
"type": "banner",
"config": {
"title": "Important notice",
"description": "Service will be unavailable Sunday 02:00–04:00 UTC.",
"variant": "warning",
"icon": { "prefix": "fas", "iconName": "triangle-exclamation" }
}
}
| Key | Type | Notes |
|---|
title | string | Banner headline. Required. |
description | string | Optional supporting copy. |
variant | info | success | warning | destructive | Visual tone. Defaults to info. |
icon | FaIcon | Optional. Overrides the variant’s default icon. |
Action blocks
{
"type": "button",
"config": {
"label": "Reserve a tasting",
"icon": { "prefix": "fas", "iconName": "arrow-right" },
"iconPosition": "end-gap",
"destination": {
"type": "url",
"value": { "url": "https://example.com/book" }
},
"style": {
"variant": "filled",
"bgColor": "#212b45",
"textColor": "#ffffff",
"borderRadius": 24,
"borderWidth": 1
}
}
}
| Key | Type | Notes |
|---|
label | string | Button label. Required. |
icon | FaIcon | Optional. Omit for a text-only button. |
iconPosition | start | start-gap | end-gap | end | Where the icon sits relative to the label. Defaults to start. |
destination | PageDestination | Required. Where the button sends visitors. |
style | object | Optional visual overrides. See Button style. |
{
"type": "contact",
"config": {
"name": "John Smith",
"title": "Sales Manager",
"company": "Awardee",
"phone": "+61 412 345 678",
"email": "[email protected]",
"website": "https://example.com",
"address": "1 Lygon St, Carlton VIC 3053",
"avatarUrl": "https://files.awardee.dev/.../avatar.jpg"
}
}
| Key | Type | Notes |
|---|
name | string | Required. |
title, company, phone, email, website, address, avatarUrl | string | All optional. |
Renders as a tap-to-save vCard on mobile.
file
{
"type": "file",
"config": {
"url": "https://files.awardee.dev/.../specsheet.pdf",
"fileName": "specsheet.pdf",
"fileSizeBytes": 184320,
"mimeType": "application/pdf",
"label": "Download the spec sheet",
"icon": { "prefix": "fas", "iconName": "file-pdf" },
"color": "#212b45"
}
}
| Key | Type | Notes |
|---|
url | string | File URL. Required. |
fileName | string | Filename. Required. |
fileSizeBytes | integer | null | Size in bytes. |
mimeType | string | null | MIME type. |
label | string | Display label. Defaults to filename. |
icon | FaIcon | Optional. |
color | string (hex) | Accent colour for the file chip. |
All form fields share a formBase schema and extend it with field-specific keys. The base:
| Key | Type | Notes |
|---|
label | string | Visible label. Empty string hides the label row. |
placeholder | string | Optional placeholder text. |
required | boolean | Defaults to false. |
prefillParam | string | null | When set, auto-fills from the named URL query string param. |
textColor | string (hex) | Label/text colour. |
The submitted value is keyed by block id in the submission’s data map — see Submissions.
form_text
{
"type": "form_text",
"config": {
"label": "Your name",
"required": true,
"placeholder": "John Smith",
"maxLength": 100
}
}
Extra keys: maxLength (integer).
form_textarea
{
"type": "form_textarea",
"config": {
"label": "Your message",
"rows": 4,
"placeholder": "Tell us a bit more…",
"maxLength": 1000
}
}
Extra keys: rows (integer, default 4), maxLength (integer).
{ "type": "form_email", "config": { "label": "Email", "required": true } }
Form-base only. The renderer enforces email validation.
{ "type": "form_phone", "config": { "label": "Phone" } }
Form-base only. The renderer renders a phone-input widget.
{
"type": "form_number",
"config": {
"label": "Quantity",
"min": 1,
"max": 100,
"step": 1
}
}
Extra keys: min, max, step (numbers).
{
"type": "form_select",
"config": {
"label": "Choose one",
"options": [
{ "label": "Option A", "value": "a" },
{ "label": "Option B", "value": "b" }
]
}
}
Extra keys: options[] with { label, value, description? }. Always renders as a native-style dropdown — no variant.
{
"type": "form_radio",
"config": {
"label": "Pick one",
"variant": "cards",
"accentColor": "#212b45",
"options": [
{ "label": "Option A", "value": "a", "description": "Best for X" },
{ "label": "Option B", "value": "b" }
]
}
}
Extra keys: variant (list | cards, default cards), accentColor (hex), options[].
Same shape as form_radio — multi-select toggle cards or list.
Same shape as form_radio — multi-select with checkboxes.
{
"type": "form_rating",
"config": {
"label": "Rate this",
"max": 5,
"icon": "star",
"color": "#212b45"
}
}
| Key | Type | Notes |
|---|
max | integer 1–6 | Number of icons. Default 5. |
icon | star | emoji | heart | custom | Built-in icon set. custom uses customIcon. |
customIcon | FaIcon | Required when icon = "custom". |
color | string (hex) | Selected-icon colour. |
{
"type": "form_date",
"config": {
"label": "When can you start?",
"mode": "date",
"minDate": "2026-01-01",
"maxDate": "2026-12-31"
}
}
| Key | Type | Notes |
|---|
mode | date | datetime | time | Default date. |
minDate, maxDate | string (ISO 8601) | null | Bounds. |
relativeMax | { unit: "days" | "weeks" | "months", value: integer } | Computed at render time; takes precedence over maxDate. |
{
"type": "form_hidden",
"config": {
"label": "Source",
"value": "tabletop-qr"
}
}
| Key | Type | Notes |
|---|
label | string | Column label in the submissions table. Required. |
value | string | Static value attached to every submission. |
Hidden fields are never visually rendered. Prefill-from-URL is handled by the visible field blocks; this is a pure constant.
{
"type": "form_media",
"config": {
"label": "Upload",
"title": "Upload your photo",
"description": "JPEG, PNG, or HEIC. Up to 15 MB.",
"icon": { "prefix": "fas", "iconName": "cloud-arrow-up" },
"color": "#212b45",
"allowed": { "media": true, "files": false, "any": false }
}
}
| Key | Type | Notes |
|---|
title | string | Title above the dropzone. |
description | string | Supporting copy. |
icon | FaIcon | Dropzone icon. |
color | string (hex) | Accent for icon and border. |
allowed | { media, files, any } (booleans) | Which kinds of uploads. any wins if set. |
{
"type": "form_submit",
"config": {
"label": "Submit",
"iconPosition": "end-gap",
"icon": { "prefix": "fas", "iconName": "paper-plane" },
"loadingLabel": "Sending…",
"style": {
"variant": "filled",
"bgColor": "#212b45",
"textColor": "#ffffff",
"borderRadius": 24
},
"redirectRules": [
{
"condition": {
"blockId": "22222222-2222-4222-8222-222222222222",
"operator": "eq",
"value": "yes"
},
"destination": {
"type": "url",
"value": { "url": "https://example.com/yes" }
}
},
{
"condition": null,
"destination": {
"type": "url",
"value": { "url": "https://example.com/thanks" }
}
}
]
}
}
| Key | Type | Notes |
|---|
label | string | Submit label. Default "Submit". |
icon | FaIcon | Optional. |
iconPosition | same as button | Default start. |
loadingLabel | string | Shown while the submission is in flight. |
style | object | Same shape as button. |
redirectRules | array | Where to send the visitor after a successful submission. |
Redirect rules are evaluated top-to-bottom, first match wins. The last rule should have condition: null (the fallback). Each rule:
{
"condition": {
"blockId": "form-block-uuid",
"operator": "eq",
"value": "yes"
},
"destination": { /* PageDestination */ }
}
Operators: eq, neq, gt, gte, lt, lte, in, not_in, contains.
Shared types
FaIcon
Font Awesome icon reference.
{ "prefix": "fas", "iconName": "arrow-right" }
prefix — FA style prefix (fas, far, fab, fad, etc.).
iconName — kebab-case icon name.
{
"variant": "filled",
"bgColor": "#212b45",
"textColor": "#ffffff",
"borderRadius": 24,
"borderWidth": 1
}
variant — filled or outline.
bgColor, textColor — hex.
borderRadius — px.
borderWidth — px. Ignored when variant = "filled".
Page destination
The destination object used by button blocks (and form submit redirects). Discriminated on type:
| Type | value shape |
|---|
url | { url } |
page | { id, title, slug, publicSlug } |
article | { id, title, slug, knowledgeBasePublicSlug, categoryPath } |
chatbot | { id, name, slug, publicSlug } |
knowledge_base | { id, name, slug, publicSlug } |
file | { url, fileName, fileSizeBytes?, mimeType? } |
email | { email, subject?, body? } |
phone | { phone } |
google_review | { placeId, businessName? } |
{
"type": "page",
"value": {
"id": "a1c2e4f6-8b0d-4e2a-9c1b-3d5e7f9a2c4e",
"title": "Reservations",
"slug": "reservations",
"publicSlug": "reservations"
}
}
The destination embeds enough of the target’s metadata (title, slug, etc.) so renderers can hyperlink without an extra lookup. The embedded values are a snapshot — refresh by re-reading the page if you need the latest.
Forward compatibility
New block types may be added without an OpenAPI version bump — they’re additive. Treat any unknown type as opaque and skip rendering rather than crashing. The config field is typed as unknown on the wire precisely so additions don’t break existing consumers.