Skip to content

Edit a page an operation at a time

PATCH
/api/v1/brands/{slug}/pages/{page}
curl --request PATCH \
--url http://localhost:3000/api/v1/brands/example/pages/example \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "ops": [ { "op": "add", "section": { "id": "example", "title": "example", "body": "example", "width": "text", "columns": 1, "tone": "plain", "hidden": true, "keys": [ "example" ], "eyebrow": "example", "lede": "example", "aside": "example", "tab": "example", "space": "tight", "size": "medium", "background": { "color": "example", "to": "example", "angle": 1, "image": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "scrim": 1 }, "items": [ { "key": "example", "asset": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "title": "example", "text": "example", "verdict": "do", "caption": "example", "link": "example", "label": "example", "icon": "example", "download": true, "span": 1, "at": [ "example" ], "level": 1 } ], "audience": "everyone", "contexts": [ "example" ], "only": "example", "translations": { "additionalProperty": { "title": "example", "eyebrow": "example", "lede": "example", "body": "example", "aside": "example", "items": [ { "title": "example", "text": "example", "caption": "example" } ] } }, "template": "cover", "props": { "image": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "video": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "align": "start", "height": "auto", "strip": true, "mark": "home", "markFrame": "tile", "markSize": "small", "titleSize": "medium", "by": "example", "flip": true, "ratio": "even", "fit": "auto", "layout": "cards", "show": [ "hex" ], "media": "screen", "matrix": true, "ase": true, "simulate": true, "sample": "example", "roles": true, "glyphs": true, "embed": true, "formula": { "base": 1, "ratio": 1, "steps": 1 }, "kit": true, "ask": true, "size": "medium", "backdrop": "checker", "collection": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "search": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "query": "example", "sort": "newest", "limit": 1, "downloads": true, "from": "example", "depth": 1, "kind": "clearspace", "positions": [ "tl" ], "partner": "example", "separator": "line", "asset": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "scales": [ 1 ], "form": [ { "name": "example", "label": "example" } ], "template": "example", "url": "https://example.com", "aspect": "16:9", "prompt": "example" } }, "after": "example" } ] }'

ops apply in order: add, update, move and remove sections, and page for its own fields. page with slug renames it: the old slug becomes an alias that still finds it, and the pages under it follow. All or none: a 422 lists every problem with its path, e.g. ops[0].section.props.chanel: Unrecognized key.

Scope: write.

slug
required
string

Brand slug

page
required
string

The page’s slug, e.g. logo

If-Match
string

The page’s revision (also its ETag) the change was made from. When the page says something else now, nothing is written: a 409 conflict with the revision it has in detail.revision. Left out, the write applies to the page as it is.

Media typeapplication/json
object
ops
required

Applied in order; all or none

Array
>= 1 items <= 50 items
One of:
object
op
required
string
Allowed value: add
section
required
object
id

Kept across edits

string
/^[a-z0-9_-]{1,40}$/
title
string
<= 300 characters
body

Markdown (GFM), shown under the title

string
<= 20000 characters
width

Text: a reading column

string
Allowed values: text wide full
columns
integer
>= 1 <= 4
tone

Panel: second surface; color, image: see background

string
Allowed values: plain tint brand panel dark color image pattern
hidden

Kept, but not shown to readers

boolean
keys

The rules it shows, by key, in order

Array<string>
<= 100 items
eyebrow

Above the title: a number, a chapter

string
<= 120 characters
lede

Under the title, set large; plain text

string
<= 1000 characters
aside

Markdown in a ruled column beside the body

string
<= 4000 characters
tab

Sections sharing a tab name show under one tab

string
>= 1 characters <= 40 characters
space

Room above it

string
Allowed values: tight loose
size

Title size

string
Allowed values: medium large huge
background

For tone color and tone image

object
color

Tone color: the color rule it is set on

string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
to

Tone color: a color rule to fade into

string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
angle

With to: degrees, 180 when left out

integer
<= 359
image

Tone image: the picture

string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
scrim

Tone image: darkening, 0.45 when left out

number
<= 0.9
items

What the template lists (list_templates)

Array<object>
<= 60 items
object
key

A rule it shows, by key

string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
asset

An image, video or file, from search_assets

string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
title
string
<= 200 characters
text

Markdown

string
<= 4000 characters
verdict

A do (green) or a don’t (red)

string
Allowed values: do dont
caption

The asset’s description when left out

string
<= 500 characters
link
string
>= 1 characters <= 2000 characters
label

A small tag: Figma, PDF, Partners only

string
<= 40 characters
icon

One of the icons a page takes

string
download

False: never offered as a download

boolean
span

Gallery bento: 2 takes two cells

integer
>= 1 <= 2
at

Annotated: [x, y], % from the top left

array
>= 2 items <= 2 items
level

Cards tree: 0 at the top

integer
<= 2
audience

On portals: who may read it

string
Allowed values: everyone partners members
contexts

A tab per context: [“default”, “dark-background”]

Array<string>
>= 2 items <= 8 items
only

Shown only in this context

string
<= 64 characters /^[a-z0-9]+(-[a-z0-9]+)*$/
translations

By language tag; what is left out falls back

object
key
additional properties
object
title
string
<= 300 characters
eyebrow
string
<= 120 characters
lede
string
<= 1000 characters
body
string
<= 20000 characters
aside
string
<= 4000 characters
items
Array
<= 60 items
Any of:
object
title
string
<= 200 characters
text
string
<= 4000 characters
caption
string
<= 500 characters
template
required
string
Allowed values: cover header text statement quote split cards palette type logos dodont gallery collection icons links pages diagram updates annotated specs specimen pattern chart copy faq embed request
props
object
image

Cover: Over the color; header: In the band; quote: A portrait; split: Beside the words; annotated

string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
video

Cover: A muted loop over the image, its poster

string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
align

Cover: start, center, end; statement, split: start, center

string
Allowed values: start center end
height

Cover

string
Allowed values: auto tall screen
strip

Cover: true when left out

boolean
mark

Cover: Logo above the title

string
Allowed values: home always never
markFrame

Cover

string
Allowed values: tile bare
markSize

Cover

string
Allowed values: small medium large
titleSize

Cover

string
Allowed values: medium large huge
by

Quote: Who said it

string
<= 120 characters
flip

Split: Image on the left

boolean
ratio

Split: The wider side

string
Allowed values: even words picture
fit

Split

string
Allowed values: auto fill whole
layout

Cards: cards, list, stats, steps, checklist, tree; dodont: pairs, grid, rows; gallery: grid, bento, carousel, strip, collage, crops; collection: grid, masonry, list; links, pages: cards, list; faq: accordion, definitions

string
Allowed values: cards list stats steps checklist tree pairs grid rows bento carousel strip collage crops masonry accordion definitions
show

Palette: Values listed; all it has when left out

Array<string>
<= 8 items
Allowed values: hex rgb hsl cmyk pantone ral token css
media

Palette: Values it opens on; screen when left out

string
Allowed values: screen print
matrix

Palette: Contrast of every pair

boolean
ase

Palette: An .ase swatch download

boolean
simulate

Palette: Color blindness views

boolean
sample

Type: The specimen’s starting text

string
<= 200 characters
roles

Type: A table of roles

boolean
glyphs

Type: Character sets

boolean
embed

Type: Code to load the faces

boolean
formula

Type: base in px

object
base
required
number
>= 4 <= 200
ratio
required
number
>= 1 <= 4
steps
required
integer
>= 1 <= 12
kit

Logos: A zip of every mark; true when left out

boolean
ask

Logos: Which mark for which context

boolean
size

Logos, icons: In its tile

string
Allowed values: medium small large
backdrop

Logos

string
Allowed values: checker light dark
collection

Collection, icons: A collection’s id

string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
search

Collection, icons: A saved search’s id

string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
query

Collection, icons: q=poster&type=image&tag=campaign

string
<= 2000 characters
sort

Collection, icons: newest, oldest, name

string
Allowed values: newest oldest name
limit

Collection: 24 when left out; icons; updates: 5 when left out, 20 at most

integer
>= 1 <= 200
downloads

Collection, icons: true when left out

boolean
from

Pages: Whose children; this page when left out

string
<= 60 characters /^[a-z0-9]+(-[a-z0-9]+)*$/
depth

Pages: Levels down

integer
>= 1 <= 3
kind

Diagram: clearspace when left out; specimen: spacing, radius, shadow, motion, grid; chart: bar, line, donut; request: asset, review, question

string
Allowed values: clearspace minsize placement cobrand spacing radius shadow motion grid bar line donut asset review question
positions

Diagram: placement: where it may sit

Array<string>
<= 9 items
Allowed values: tl tc tr ml mc mr bl bc br
partner

Diagram: cobrand: their name

string
<= 60 characters
separator

Diagram: cobrand: line when left out

string
Allowed values: line x none
asset

Pattern: The tile

string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
scales

Pattern: Tile sizes, as multiples

Array<number>
>= 1 items <= 6 items
form

Copy: Fields readers fill

Array<object>
<= 8 items
object
name
required
string
<= 30 characters /^\w+$/
label
required
string
>= 1 characters <= 60 characters
template

Copy: Their words go in its {name} slots

string
<= 2000 characters
url

Embed: https

string format: uri
<= 2000 characters
aspect

Embed

string
Allowed values: 16:9 4:3 1:1 auto
prompt

Request: What to ask for

string
<= 300 characters
after

Null for the top; the end when left out

string | null

The page

Media typeapplication/json
object
data
required
object
brand
required
string
page
required
object
slug
required
string
title
required
string
position
required
integer
>= -9007199254740991 <= 9007199254740991
hidden
required
boolean
parent
required

The page it sits under; null at the top

string | null
eyebrow
required
string | null
lede
required
string | null
cover
required
Any of:
string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
icon
required
string | null
audience
required

On portals: who may read it

string
Allowed values: everyone partners members
tabs
required

Its child pages show as tabs across its top

boolean
aliases
required

Slugs it had before a rename: they still find it

Array<string>
layout
required

Landing: a front with no nav column, on-this-page or pager; book: a chapter

string
Allowed values: book landing
updatedAt
required

The last change to what it says

string format: date-time
/^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$/
revision
required

What it says, as a hash: send it back in If-Match (edit_page and save_page: revision) to refuse a write over a change you haven’t seen

string
translations
Any of:
object
key
additional properties
object
title
string
eyebrow
string
lede
string
sections
required
Array<object>
object
id
required
string
template
required

GET /api/v1/brand/templates lists them

string
title
required
string
body
required

Markdown

string
width
required
string
Allowed values: text wide full
columns
required
integer
>= -9007199254740991 <= 9007199254740991
tone
required

Its ground: plain, tint, brand, panel, dark, color, image or pattern

string
hidden
required
boolean
keys
required

The rules it shows, by key, in order

Array<string>
props
required

Its template’s own settings

object
key
additional properties
eyebrow
string
lede
string
aside

Markdown

string
tab

Sections sharing a tab name show under one tab

string
background
object
color
string
to
string
angle
number
image
string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
scrim
number
items
Array<object>

A thing a template lists: a do or a don’t with its picture, a picture in a gallery

object
key

A rule it shows

string
asset
string format: uuid
/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/
title
string
text

Markdown

string
verdict
string
Allowed values: do dont
caption
string
link
string
label
string
icon
string
download

False: for reference, never offered as a download

boolean
audience
string
Allowed values: everyone partners members
contexts

A tab per context, its rules resolved for each

Array<string>
only

Shown only in this context

string
translations

Its words by language tag; readers get them already in their language

object
key
additional properties
object
title
string
<= 300 characters
eyebrow
string
<= 120 characters
lede
string
<= 1000 characters
body
string
<= 20000 characters
aside
string
<= 4000 characters
items
Array
<= 60 items
Any of:
object
title
string
<= 200 characters
text
string
<= 4000 characters
caption
string
<= 500 characters
warnings
required

What a reader would trip on, though it saves: links that go nowhere, keys with no rule

Array<string>
url
required

Where a member reads it in the app

string format: uri
Example
{
"data": {
"page": {
"audience": "everyone",
"layout": "book",
"sections": [
{
"width": "text",
"items": [
{
"verdict": "do"
}
],
"audience": "everyone"
}
]
}
}
}

The page changed since the If-Match revision: read it again, redo the change on what it says now

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
detail
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"detail": "example"
}
}

An error

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
detail
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"detail": "example"
}
}