Skip to content

Open a brand portal

GET
/api/v1/portal/{slug}
curl --request GET \
--url 'http://localhost:3000/api/v1/portal/example?limit=60&offset=0'

What a visitor sees: the portal, themed, its collections with how many usable assets each has, its brands, and a page of them with their downloads. URLs are relative to the host asked, so a portal on its own domain loads from there. A password goes in X-Portal-Password, an approved request’s key in X-Portal-Key; a members portal reads the session. 401 password names how to get in (see PortalGate), 410 gone once closed.

No key needed.

slug
required
string

The portal’s address

q
string

Every word must match, each as a prefix

collection
string

Only this one of its collections

limit
integer
default: 60 >= 1 <= 200

Page size

offset
integer
0

Skip this many

The portal’s contents

Media typeapplication/json
object
portal
required
object
slug
required
string
name
required
string
intro
required
string | null
organization
required
string
access
required
string
Allowed values: public password members
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)))$/
theme
required
object
logo
required

A URL on this host: the portal’s, else its first brand’s mark, else its organization’s

string | null
accent
required

The portal’s, else its first brand’s color, else its organization’s

string | null
background
required
string | null
icon
required

The organization’s, for the browser tab

string | null
product
required

What the organization calls the product

string
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
count
required
integer
>= -9007199254740991 <= 9007199254740991
covers
required

Up to 3 of its newest pictures’ thumbnails, URLs on this host

Array<string>
brands
required

Brands it publishes: each one’s guidelines at GET /api/v1/portal/{slug}/brands/{brand}

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

Footer, quick grab and terms, as its pages have them

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
look
required

How to draw it: its first brand’s site; with no brand, the portal’s accent over the app’s own

object
brand
required
Any of:
object
slug
required
string
name
required
string
theme
required

Derived and graded, as a page view’s

object
v1
required

The accent, lifted for light and dark pages, and the faces, as before W3

object
key
additional properties
surface
required
Any of:

A hex color

string
panel
required

A hex color

string
dark
required

A hex color

string
ink
required

A hex color

string
muted
required

A hex color

string
onDark
required

A hex color

string
mutedOnDark
required

A hex color

string
accent
required

The fill, as the brand has it: bands and buttons

string
accentText
required

The accent where it is text (links), at 4.5:1 on the surface

string
onAccent
required

A hex color

string
accentUse
required
string
Allowed values: fill hairline
line
required

A hex color

string
faces
required
object
head
object
family
required
string
weight
number
file

The font file for its weight

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)$/
files

Every font file of the rule, one @font-face each

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)$/
filename
required
string
mime
required
string
fallback
string
google

From Google Fonts, with no files here yet: set in its fallback until they are imported

boolean
body
object
family
required
string
weight
number
file

The font file for its weight

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)$/
files

Every font file of the rule, one @font-face each

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)$/
filename
required
string
mime
required
string
fallback
string
google

From Google Fonts, with no files here yet: set in its fallback until they are imported

boolean
label
object
family
required
string
weight
number
file

The font file for its weight

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)$/
files

Every font file of the rule, one @font-face each

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)$/
filename
required
string
mime
required
string
fallback
string
google

From Google Fonts, with no files here yet: set in its fallback until they are imported

boolean
case
required
string
tracking
required

In em

number
radius
required
number
width
required
string
Allowed values: narrow normal wide
density
required
string
Allowed values: compact normal airy
scale
required
number
device
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)$/
logo
required
Any of:
object
key
required
string
nav
required
string
Allowed values: sidebar top overlay
band
required

Header is band

boolean
header
required
string
Allowed values: plain band split
separation
required
string
Allowed values: space hairline
numbering
required
boolean
motion
required
string
Allowed values: none subtle
toc
required

On this page: a side column, a list under the page header, or none

string
Allowed values: side inline none
checks
required

Contrast of each pair in the look: one that fails falls back to a color that reads, and says which

Array<object>
object
pair
required

Which color on which, e.g. ink on surface

string
fg
required
string
bg
required
string
ratio
required
number
need
required

The contrast it must reach: 4.5 for text, 3 for marks

number
ok
required
boolean
used
required

The color used: fg when it passes, else its fallback

string
settings
required
object
accent
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
accentUse

Hairline: the accent draws rules and marks, never fills

string
Allowed values: fill hairline
surface
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
panel
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
dark
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
ink
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
muted
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
head
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
body
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
label
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
logo
Any of:
string
<= 120 characters /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*$/
device
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)$/
radius

Corner radius in px

integer
<= 40
width
string
Allowed values: narrow normal wide
density
string
Allowed values: compact normal airy
scale

Heading size ratio; 1.25 when left out

number
>= 1.067 <= 1.618
nav
string
Allowed values: sidebar top overlay
band

Every page opens on a band of the brand color; header band says the same

boolean
header

A page’s opening: on the page, on a band of the brand color, or beside its cover

string
Allowed values: plain band split
separation

Between two sections on the page’s own ground: space alone, or a hairline too

string
Allowed values: space hairline
numbering

Number chapters and pages: 01, 01.2

boolean
motion

Subtle: sections reveal as they scroll in; never with reduced motion

string
Allowed values: none subtle
toc

On this page: a side column, a list under the page header, or hidden

string
Allowed values: side inline none
titles

Section titles: headings (medium), or headlines (large, huge); a section’s own size wins

string
Allowed values: medium large huge
grounds

Alternate: every other section on the page’s own ground sits on the panel, so a long page has rhythm; canvas: under its header the page sits on the panel, dotted like a whiteboard, its section titles centered

string
Allowed values: plain alternate canvas
languages

The languages readers pick from; the first is the one the pages are written in

Array<object>
<= 12 items
object
code
required
string
<= 20 characters /^[a-z]{2,3}(-[a-z0-9]{2,8})?$/
label
required
string
>= 1 characters <= 40 characters
dir

From the language when left out

string
Allowed values: ltr rtl
links

Links beside search and print on the brand’s pages: its repository, its Figma library, its site

Array<object>
<= 8 items
object
label
required
string
>= 1 characters <= 40 characters
url
required

Http or https; a link to GitHub, Figma, npm and the like shows its icon

string format: uri
<= 2000 characters
signed
required

Signatures for the theme’s font files and device

object
key
additional properties
string
madeWith
required

Its pages carry “Powered by Artbucket”: a public portal whose organization’s plan has no white-label

boolean
data
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)$/
filename
required
string
title
required
string | null
description
required
string | null
creator
required
string | null
copyright
required
string | null
mime
required
string
size
required
integer
>= -9007199254740991 <= 9007199254740991
width
required
Any of:
integer
>= -9007199254740991 <= 9007199254740991
height
required
Any of:
integer
>= -9007199254740991 <= 9007199254740991
thumbnail
required

A URL on this host

string | null
preview
required

Larger, for a closer look

string | null
downloads
required
Array<object>
object
preset
required
string
Allowed values: web social story print png original
label
required
string
hint
required
string
url
required
string
filename
required
string
total
required
integer
>= -9007199254740991 <= 9007199254740991
Example
{
"portal": {
"access": "public",
"look": {
"theme": {
"accentUse": "fill",
"faces": {
"head": {
"google": true
},
"body": {
"google": true
},
"label": {
"google": true
}
},
"width": "narrow",
"density": "compact",
"nav": "sidebar",
"header": "plain",
"separation": "space",
"motion": "none",
"toc": "side",
"settings": {
"accentUse": "fill",
"width": "narrow",
"density": "compact",
"nav": "sidebar",
"header": "plain",
"separation": "space",
"motion": "none",
"toc": "side",
"titles": "medium",
"grounds": "plain",
"languages": [
{
"dir": "ltr"
}
]
}
}
}
},
"data": [
{
"downloads": [
{
"preset": "web"
}
]
}
]
}

Not in yet: how to get in

Media typeapplication/json
object
error
required
object
code
required
string
Allowed value: password
message
required
string
detail
required
object
name
required
string
access
required
string
Allowed values: password members
theme
required
object
logo
required

A URL on this host: the portal’s, else its first brand’s mark, else its organization’s

string | null
accent
required

The portal’s, else its first brand’s color, else its organization’s

string | null
background
required
string | null
icon
required

The organization’s, for the browser tab

string | null
product
required

What the organization calls the product

string
Example
{
"error": {
"code": "password",
"detail": {
"access": "password"
}
}
}

An error

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