Skip to content

Make a site

POST
/api/v1/sites
curl --request POST \
--url http://localhost:3000/api/v1/sites \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "name": "example", "slug": "example", "intro": "example", "url": "https://example.com", "access": "public", "password": "example", "expiresAt": "2026-04-15T12:00:00Z", "presets": [ "web" ], "theme": { "logo": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "accent": "example", "background": "example" }, "collections": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "brands": [ "example" ], "site": { "footer": { "text": "example", "links": [ { "label": "example", "href": "example" } ], "credit": "example", "feedback": "example" }, "quick": [ { "label": "example", "brand": "example", "page": "example", "asset": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "href": "example" } ], "terms": "example", "listed": true }, "rebuild": { "url": "https://example.com", "brand": "example" }, "domain": "example", "kind": "portal" }'

A curated, themed front door onto chosen collections, for press, partners or retailers, at /p/{slug} or a domain of its own. It shows only approved, unexpired, current assets, and offers images as renditions made for a purpose (presets) rather than raw originals. access: public, password, or members (people with access to the project); the last two take access requests. Needs sharing rights on each collection. domain is one of the organization’s verified domains (/api/v1/domains), not its default.

Scope: write.

Media typeapplication/json
object
name
required

What visitors see it called, e.g. Press kit

string
>= 1 characters <= 120 characters
slug
required

Its address: /p/{slug}, and {slug}.PORTAL_DOMAIN when the server has one. Lowercase letters, digits and dashes

string
/^[a-z0-9](?:[a-z0-9-]{0,46}[a-z0-9])?$/
intro
Any of:
string
<= 4000 characters
url
Any of:
string format: uri
<= 2048 characters
access

Public: anyone; password: whoever has it; members: people with access to the project. Either of the last two takes access requests

string
default: public
Allowed values: public password members
password

For access: password. Left out on a change, it stays

string
>= 4 characters <= 200 characters
expiresAt
Any of:
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)))$/
presets

What images download as; web, print and social when left out

Array<string>
<= 6 items
Allowed values: web social story print png original
theme

Left out, a setting stays; null clears it

object
logo
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)$/
accent
Any of:
string
/^#[0-9a-fA-F]{6}$/
background
Any of:
string
/^#[0-9a-fA-F]{6}$/
collections

Collections it shows, in this order. With brands, at least one of the two

Array<string>
<= 50 items
brands

Brands whose guidelines it publishes, by slug, each a tab beside the assets, in this order

Array<string>
<= 20 items
site

Its footer, quick grab, terms, and whether search engines may list it (public portals only). Replaces the whole set

object
footer
object
text

Markdown

string
<= 2000 characters
links
Array<object>
<= 8 items
object
label
required
string
>= 1 characters <= 60 characters
href
required
string
<= 2000 characters
credit
string
<= 120 characters
feedback

A URL or mailto:

string
<= 2000 characters
quick

Quick grab: pinned links in the header

Array<object>
<= 6 items
object
label
required
string
>= 1 characters <= 40 characters
brand

With page: a brand the portal carries; the first when left out

string
<= 60 characters
page
string
<= 60 characters /^[a-z0-9]+(-[a-z0-9]+)*$/
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)$/
href
string
<= 2000 characters
terms

Markdown readers accept once before their first download

string
<= 10000 characters
listed

Search engines may index it; public portals only

boolean
rebuild
Any of:
object
url
required

A deploy hook: the URL Vercel, Netlify, Cloudflare Pages or your CI gives you to start a build with a POST

string format: uri
<= 2000 characters
brand
required

The brand, by slug, whose releases start it

string
>= 1 characters <= 64 characters
domain
Any of:
string
<= 253 characters
kind

Portal: a brand portal Artbucket renders from its brands and collections; guidelines, landing, docs or storybook: a site of static files you deploy; external: a site hosted elsewhere whose CI records what it uses (artbucket site scan). Set once

string
default: portal
Allowed values: portal guidelines landing docs storybook external

The site

Media typeapplication/json
object
data
required
object
id
required
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)$/
kind
required

Portal: managed by Artbucket; external: hosted elsewhere, what it uses recorded by artbucket site scan; the others are static files deployed to it

string
Allowed values: portal guidelines landing docs storybook external
slug
required
string
name
required
string
intro
required
string | null
externalUrl
required

An external site’s own address

string | null
access
required
string
Allowed values: public password members
password
required
boolean
expiresAt
required
Any of:
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)))$/
expired
required
boolean
presets
required
Array<string>
Allowed values: web social story print png original
theme
required
object
logo
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)$/
accent
required
Any of:
string
/^#[0-9a-fA-F]{6}$/
background
required
Any of:
string
/^#[0-9a-fA-F]{6}$/
collections
required
Array<object>
object
id
required
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)$/
name
required
string
brands
required

Brands whose guidelines it publishes, in tab order

Array<object>
object
slug
required
string
name
required
string
publishedAt
required
Any of:
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)))$/
site
required
object
footer
object
text

Markdown

string
<= 2000 characters
links
Array<object>
<= 8 items
object
label
required
string
>= 1 characters <= 60 characters
href
required
string
<= 2000 characters
credit
string
<= 120 characters
feedback

A URL or mailto:

string
<= 2000 characters
quick

Quick grab: pinned links in the header

Array<object>
<= 6 items
object
label
required
string
>= 1 characters <= 40 characters
brand

With page: a brand the portal carries; the first when left out

string
<= 60 characters
page
string
<= 60 characters /^[a-z0-9]+(-[a-z0-9]+)*$/
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)$/
href
string
<= 2000 characters
terms

Markdown readers accept once before their first download

string
<= 10000 characters
listed

Search engines may index it; public portals only

boolean
rebuild
required
Any of:
object
brand
required

The brand whose releases call it, by slug; null once that brand is gone

string | null
host
required

The hook’s host; the URL itself is never shown

string
lastAt
required
Any of:
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)))$/
lastStatus
required

What it answered: an HTTP status, or why there was none

string | null
domain
required
Any of:
object
host
required
string
verified
required
boolean
record
required

What proves it: add this record at your DNS host

object
type
required
string
Allowed value: TXT
name
required
string
value
required
string
cname
required
Any of:
object
type
required
string
Allowed value: CNAME
name
required
string
value
required
string
url
required

Where visitors go: its domain once verified, else {slug}.PORTAL_DOMAIN when the server has one (not for a members portal), else /p/{slug}

string format: uri
pending
required

Access requests waiting

integer
>= -9007199254740991 <= 9007199254740991
createdBy
required
string
createdAt
required
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)))$/
updatedAt
required
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)))$/
Example
{
"data": {
"kind": "portal",
"access": "public",
"presets": [
"web"
],
"theme": {
"logo": null,
"accent": null,
"background": null
},
"domain": {
"record": {
"type": "TXT"
},
"cname": {
"type": "CNAME"
}
}
}
}

An error

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