2692 lines
75 KiB
YAML
2692 lines
75 KiB
YAML
|
|
openapi: 3.1.0
|
||
|
|
info:
|
||
|
|
title: go-bananas
|
||
|
|
version: 1.0.0
|
||
|
|
summary: Runtime design-token service.
|
||
|
|
description: 'Author design-token themes and serve them to any application at run time.
|
||
|
|
|
||
|
|
|
||
|
|
## Two surfaces, two postures
|
||
|
|
|
||
|
|
|
||
|
|
`/rt/v1` is the **runtime** API: public, aggressively cacheable, and designed to be consumed from
|
||
|
|
a `<link>` tag with no credential. A theming service that required a credential could not be consumed
|
||
|
|
the way a theme is actually consumed.
|
||
|
|
|
||
|
|
|
||
|
|
`/api/v1` is the **administrative** API: authenticated, never cached, and every mutation audited.
|
||
|
|
|
||
|
|
|
||
|
|
## Versioning
|
||
|
|
|
||
|
|
|
||
|
|
Both surfaces are independently versioned. Adding an optional field, a new endpoint or a new query
|
||
|
|
parameter is not a breaking change. Changing the meaning of an existing one is, and gets a new major
|
||
|
|
version served alongside the old one for at least one cycle.'
|
||
|
|
license:
|
||
|
|
name: MIT
|
||
|
|
identifier: MIT
|
||
|
|
contact:
|
||
|
|
name: urpi platform team
|
||
|
|
url: https://github.com/urpi/go-bananas
|
||
|
|
servers:
|
||
|
|
- url: '{origin}'
|
||
|
|
description: This deployment.
|
||
|
|
variables:
|
||
|
|
origin:
|
||
|
|
default: https://themes.example.com
|
||
|
|
description: The externally reachable origin.
|
||
|
|
tags:
|
||
|
|
- name: runtime
|
||
|
|
description: Public. Consumed by applications and browsers.
|
||
|
|
- name: themes
|
||
|
|
description: Theme management. Requires authentication.
|
||
|
|
- name: history
|
||
|
|
description: Version history, diffing and rollback.
|
||
|
|
- name: tokens
|
||
|
|
description: Read-only analysis of a token document.
|
||
|
|
- name: auth
|
||
|
|
description: Session introspection and the login flow.
|
||
|
|
- name: preferences
|
||
|
|
description: The caller's own interface preferences. Any authenticated role.
|
||
|
|
- name: admin
|
||
|
|
description: Keys, users, settings and the audit log. Admin role.
|
||
|
|
- name: operational
|
||
|
|
description: Probes and metrics.
|
||
|
|
paths:
|
||
|
|
/rt/v1/theme.css:
|
||
|
|
get:
|
||
|
|
summary: A theme stylesheet
|
||
|
|
description: 'Returns the theme rendered as CSS custom properties, plus a small component layer
|
||
|
|
in `@layer bananas`, so an application''s own unlayered CSS always wins the cascade.
|
||
|
|
|
||
|
|
|
||
|
|
Responses are **immutable by URL**: publishing a theme changes its version, and a version-pinned
|
||
|
|
URL never changes. That lets a CDN cache them hard. `If-None-Match` and `If-Modified-Since` are
|
||
|
|
both honoured, so a redeploy costs a revalidation and no body.
|
||
|
|
|
||
|
|
|
||
|
|
A draft theme returns **404 rather than 403**, so a probe cannot confirm that it exists.'
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The stylesheet.
|
||
|
|
content:
|
||
|
|
text/css:
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
example: "[data-bananas-theme=\"midnight\"] {\n --bn-color-semantic-primary: #7c6bf5;\n\
|
||
|
|
}"
|
||
|
|
headers: &id001
|
||
|
|
ETag:
|
||
|
|
description: A strong validator for the response.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
X-Theme-Version:
|
||
|
|
description: The version served.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
X-Theme-Updated-At:
|
||
|
|
description: When it was published.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
Cache-Control:
|
||
|
|
description: The caching policy applied.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
X-Request-ID:
|
||
|
|
description: Correlation id for the server log.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: appearance
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: The colour scheme. Defaults to the theme's own default, which is what makes a dark-first
|
||
|
|
theme correct without the parameter being passed.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- light
|
||
|
|
- dark
|
||
|
|
- name: variant
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: '`full` includes the component layer, `tokens` omits it, `minified` strips comments
|
||
|
|
for production.'
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- full
|
||
|
|
- tokens
|
||
|
|
- minified
|
||
|
|
- name: v
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: 'Pin a version. This URL never changes, which is what makes a safe deploy possible:
|
||
|
|
build against version 7 and the render cannot change underneath you.'
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
security: []
|
||
|
|
/rt/v1/theme.json:
|
||
|
|
get:
|
||
|
|
summary: A theme's resolved tokens
|
||
|
|
description: Carries both a flat custom-property map and the nested DTCG document, so a consumer
|
||
|
|
can read either without a transformation step. Derived tokens such as the `on-*` foreground pairs
|
||
|
|
and the `-hover` / `-active` interaction states are included.
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The resolved theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ResolvedTheme'
|
||
|
|
headers: *id001
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: appearance
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: The colour scheme. Defaults to the theme's default.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- light
|
||
|
|
- dark
|
||
|
|
security: []
|
||
|
|
/rt/v1/manifest.json:
|
||
|
|
get:
|
||
|
|
summary: The theme manifest
|
||
|
|
description: 'The discovery document a loader fetches once to build a theme picker. Deliberately
|
||
|
|
small: no token data, so a page with a picker does not download every theme. Cached briefly, because
|
||
|
|
it changes whenever a theme is published.'
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The manifest.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Manifest'
|
||
|
|
headers:
|
||
|
|
Cache-Control:
|
||
|
|
description: Short-lived.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security: []
|
||
|
|
/rt/v1/embed:
|
||
|
|
get:
|
||
|
|
summary: An integration snippet
|
||
|
|
description: 'Generates the markup to paste, from this deployment''s own configuration, so it cannot
|
||
|
|
drift from reality. Always answers JSON, whatever the target: the admin UI fetches this with a
|
||
|
|
JSON parser and an HTML response for the default target is what made the Integrate page report
|
||
|
|
that it could not parse the reply. The slug must name an existing theme, and every interpolated
|
||
|
|
value is escaped for the target language, because the output is pasted into someone else''s application.'
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The snippet.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/EmbedSnippet'
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: No such theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: The theme to generate for.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: target
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: The integration shape.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- html
|
||
|
|
- react
|
||
|
|
- javascript
|
||
|
|
security: []
|
||
|
|
/rt/v1/themes/{slug}/theme.css:
|
||
|
|
get:
|
||
|
|
summary: A theme stylesheet, by path
|
||
|
|
description: A REST-shaped equivalent of `/rt/v1/theme.css`, for consumers that prefer a path to
|
||
|
|
a query string, or a CDN configured with path patterns.
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The stylesheet.
|
||
|
|
content:
|
||
|
|
text/css:
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
headers: *id001
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security: []
|
||
|
|
/rt/v1/themes/{slug}/theme.json:
|
||
|
|
get:
|
||
|
|
summary: A theme's resolved tokens, by path
|
||
|
|
description: A REST-shaped equivalent of `/rt/v1/theme.json`.
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The resolved theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ResolvedTheme'
|
||
|
|
headers: *id001
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security: []
|
||
|
|
/rt/v1/runtime.js:
|
||
|
|
get:
|
||
|
|
summary: The runtime.js bundle
|
||
|
|
description: 'The framework-free ES module: `applyTheme`, `setAppearance`, `loadManifest`, `getVariables`,
|
||
|
|
`watchSystemAppearance`, `subscribe`.
|
||
|
|
|
||
|
|
|
||
|
|
Served from this origin so a consuming application needs no build step and no npm dependency.
|
||
|
|
React is imported as a **bare specifier** and resolved by the consumer''s own import map, which
|
||
|
|
is what guarantees a single React instance in the page: two copies would each have their own hook
|
||
|
|
dispatcher.'
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The bundle.
|
||
|
|
content:
|
||
|
|
application/javascript:
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
headers:
|
||
|
|
Cache-Control:
|
||
|
|
description: Immutable. The filename is stable so an import map can name it.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security: []
|
||
|
|
/rt/v1/react.js:
|
||
|
|
get:
|
||
|
|
summary: The react.js bundle
|
||
|
|
description: 'The React provider and hooks: `BananasProvider`, `useBananas`, `useThemeVariable`,
|
||
|
|
`useThemeVariables`, `useAvailableThemes`.
|
||
|
|
|
||
|
|
|
||
|
|
Served from this origin so a consuming application needs no build step and no npm dependency.
|
||
|
|
React is imported as a **bare specifier** and resolved by the consumer''s own import map, which
|
||
|
|
is what guarantees a single React instance in the page: two copies would each have their own hook
|
||
|
|
dispatcher.'
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The bundle.
|
||
|
|
content:
|
||
|
|
application/javascript:
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
headers:
|
||
|
|
Cache-Control:
|
||
|
|
description: Immutable. The filename is stable so an import map can name it.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security: []
|
||
|
|
/rt/v1/global.js:
|
||
|
|
get:
|
||
|
|
summary: The global.js bundle
|
||
|
|
description: 'The same API attached to `window.Bananas`, for a page that cannot use modules.
|
||
|
|
|
||
|
|
|
||
|
|
Served from this origin so a consuming application needs no build step and no npm dependency.
|
||
|
|
React is imported as a **bare specifier** and resolved by the consumer''s own import map, which
|
||
|
|
is what guarantees a single React instance in the page: two copies would each have their own hook
|
||
|
|
dispatcher.'
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The bundle.
|
||
|
|
content:
|
||
|
|
application/javascript:
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
headers:
|
||
|
|
Cache-Control:
|
||
|
|
description: Immutable. The filename is stable so an import map can name it.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security: []
|
||
|
|
/rt/v1/embed.js:
|
||
|
|
get:
|
||
|
|
summary: The embed.js bundle
|
||
|
|
description: 'The one-line script-tag embed. Configured with data attributes.
|
||
|
|
|
||
|
|
|
||
|
|
Served from this origin so a consuming application needs no build step and no npm dependency.
|
||
|
|
React is imported as a **bare specifier** and resolved by the consumer''s own import map, which
|
||
|
|
is what guarantees a single React instance in the page: two copies would each have their own hook
|
||
|
|
dispatcher.'
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The bundle.
|
||
|
|
content:
|
||
|
|
application/javascript:
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
headers:
|
||
|
|
Cache-Control:
|
||
|
|
description: Immutable. The filename is stable so an import map can name it.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security: []
|
||
|
|
/auth/login:
|
||
|
|
get:
|
||
|
|
summary: Begin the login flow
|
||
|
|
description: Redirects to the identity provider. The return path and the PKCE verifier are carried
|
||
|
|
in a signed cookie rather than server-side state, so any replica behind the load balancer can
|
||
|
|
complete the flow.
|
||
|
|
tags:
|
||
|
|
- auth
|
||
|
|
responses:
|
||
|
|
'302':
|
||
|
|
description: Redirect to the provider.
|
||
|
|
'404':
|
||
|
|
description: No identity provider is configured.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: returnTo
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: 'A **local** path to return to. An absolute URL is rejected: it would be an open
|
||
|
|
redirect that also primes a phishing flow.'
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security: []
|
||
|
|
/auth/callback:
|
||
|
|
get:
|
||
|
|
summary: Complete the login flow
|
||
|
|
description: Exchanges the authorization code, verifies the ID token signature, issuer, audience
|
||
|
|
and nonce, resolves roles from the user's groups, and sets the session cookie. The transaction
|
||
|
|
state is single-use.
|
||
|
|
tags:
|
||
|
|
- auth
|
||
|
|
responses:
|
||
|
|
'302':
|
||
|
|
description: Redirect to the return path, with a session cookie set.
|
||
|
|
'401':
|
||
|
|
description: The login could not be completed. The message names the reason, because "invalid
|
||
|
|
state" and "user declined" need different actions.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'502':
|
||
|
|
description: The provider returned an unexpected response.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security: []
|
||
|
|
/auth/logout:
|
||
|
|
get:
|
||
|
|
summary: End the session
|
||
|
|
description: Clears the session cookie and, when an OIDC provider is configured, ends the provider
|
||
|
|
session too.
|
||
|
|
tags:
|
||
|
|
- auth
|
||
|
|
responses:
|
||
|
|
'302':
|
||
|
|
description: Redirect, to the provider when configured.
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
post:
|
||
|
|
summary: End the session
|
||
|
|
description: Clears the session cookie and, when an OIDC provider is configured, ends the provider
|
||
|
|
session too.
|
||
|
|
tags:
|
||
|
|
- auth
|
||
|
|
responses:
|
||
|
|
'302':
|
||
|
|
description: Redirect, to the provider when configured.
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/auth/me:
|
||
|
|
get:
|
||
|
|
summary: The current session
|
||
|
|
description: The session, and what the caller may do.
|
||
|
|
tags:
|
||
|
|
- auth
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The session.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Session'
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security: []
|
||
|
|
/api/v1/auth/config:
|
||
|
|
get:
|
||
|
|
summary: Client-visible configuration
|
||
|
|
description: What the UI needs before a session exists. Contains no secret material.
|
||
|
|
tags:
|
||
|
|
- auth
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The configuration.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/AppConfig'
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security: []
|
||
|
|
/api/v1/me/preferences:
|
||
|
|
get:
|
||
|
|
summary: The caller's interface preferences
|
||
|
|
description: Empty when nothing is stored, which is every account until it chooses once.
|
||
|
|
tags:
|
||
|
|
- preferences
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The stored preference.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/UserPreferences'
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
put:
|
||
|
|
summary: Record the caller's interface preferences
|
||
|
|
description: 'Any authenticated role may call this. The preference is keyed to the caller''s own
|
||
|
|
subject and grants nothing. An empty selectedTheme clears the choice. The response is authoritative:
|
||
|
|
the server rejects a theme that is not published, and reports a stored theme that has since disappeared
|
||
|
|
as no choice. tags: - preferences requestBody: required: true content: application/json: schema:
|
||
|
|
$ref: '
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: What the server stored.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/UserPreferences'
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
delete:
|
||
|
|
summary: Forget the caller's preferences
|
||
|
|
description: Returns the interface to its defaults.
|
||
|
|
tags:
|
||
|
|
- preferences
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The empty preference.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/UserPreferences'
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
/api/v1/themes:
|
||
|
|
get:
|
||
|
|
summary: List themes
|
||
|
|
description: A page of themes, without their token documents.
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: A page of themes.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ThemePage'
|
||
|
|
headers: &id002
|
||
|
|
Cache-Control: &id003
|
||
|
|
description: '`no-store`. Administration responses are per-user and change on every write.'
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
X-Request-ID: &id004
|
||
|
|
description: Correlation id for the server log.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'403':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: q
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Matches slug, name or description. LIKE wildcards are escaped, so a literal `%` matches
|
||
|
|
a literal `%`.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: status
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Filter by publication state.
|
||
|
|
schema: &id005
|
||
|
|
$ref: '#/components/schemas/ThemeStatus'
|
||
|
|
- name: system
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Filter on the built-in flag.
|
||
|
|
schema:
|
||
|
|
type: boolean
|
||
|
|
- name: tag
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Requires the tag in the metadata.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: limit
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
maximum: 200
|
||
|
|
default: 50
|
||
|
|
- name: offset
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 0
|
||
|
|
default: 0
|
||
|
|
- name: sort
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Resolved through an allow-list. An unrecognised value falls back to the default rather
|
||
|
|
than reaching the SQL statement.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- updated
|
||
|
|
- created
|
||
|
|
- name
|
||
|
|
- slug
|
||
|
|
default: updated
|
||
|
|
- name: order
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- asc
|
||
|
|
- desc
|
||
|
|
default: desc
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
post:
|
||
|
|
summary: Create a theme
|
||
|
|
description: 'Creates a **draft**. A draft may be incomplete: validation gates publication, not
|
||
|
|
editing, which is what makes building a theme up incrementally practical.'
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'201':
|
||
|
|
description: The created theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Theme'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'403':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'409':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ThemeMutation'
|
||
|
|
example:
|
||
|
|
name: Acme Product
|
||
|
|
slug: acme
|
||
|
|
description: The default theme for customer-facing applications
|
||
|
|
status: draft
|
||
|
|
tokens:
|
||
|
|
color:
|
||
|
|
semantic:
|
||
|
|
primary:
|
||
|
|
$type: color
|
||
|
|
$value: '#4f46e5'
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/{slug}:
|
||
|
|
get:
|
||
|
|
summary: Get a theme
|
||
|
|
description: The theme with its full token document.
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Theme'
|
||
|
|
headers: *id002
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
patch:
|
||
|
|
summary: Update a theme
|
||
|
|
description: 'A partial update: absent fields are left unchanged. Every write bumps the version,
|
||
|
|
because the version is the render cache key and must change whenever the rendered output could.
|
||
|
|
|
||
|
|
|
||
|
|
`baseVersion` gives optimistic concurrency. Without it, two editors silently overwrite each other;
|
||
|
|
with it, the loser gets a 409 naming both versions.'
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The updated theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Theme'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'403':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'409':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ThemeMutation'
|
||
|
|
example:
|
||
|
|
tokens:
|
||
|
|
color:
|
||
|
|
semantic:
|
||
|
|
primary:
|
||
|
|
$type: color
|
||
|
|
$value: '#7c6bf5'
|
||
|
|
baseVersion: 3
|
||
|
|
message: rebalanced the neutrals
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
delete:
|
||
|
|
summary: Delete a theme
|
||
|
|
description: 'Removes the theme and its history. Refused for a built-in theme with 409: built-ins
|
||
|
|
are immutable so that a consumer pinned to the slug cannot break on upgrade. Duplicate it instead.'
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'204':
|
||
|
|
description: Deleted.
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'403':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'409':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/{slug}/publish:
|
||
|
|
post:
|
||
|
|
summary: Publish a theme
|
||
|
|
description: 'Validates the token document first: errors block, warnings do not. On success the
|
||
|
|
theme is served to every consuming application within one `s-maxage` window. A built-in theme
|
||
|
|
can be published but not deleted.'
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The published theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Theme'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/{slug}/archive:
|
||
|
|
post:
|
||
|
|
summary: Archive a theme
|
||
|
|
description: Hidden from listings and from the runtime manifest. The last published revision stays
|
||
|
|
resolvable for a pinned consumer, so archiving does not break a deployment in progress.
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The archived theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Theme'
|
||
|
|
headers: *id002
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/{slug}/duplicate:
|
||
|
|
post:
|
||
|
|
summary: Duplicate a theme
|
||
|
|
description: Copies a theme under a new slug as a draft, with its own history starting at version
|
||
|
|
1. The copy is no longer flagged as built-in, so it can then be deleted.
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'201':
|
||
|
|
description: The copy.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Theme'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'409':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The source theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- slug
|
||
|
|
properties:
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
description: The slug for the copy.
|
||
|
|
example:
|
||
|
|
slug: acme-v2
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/{slug}/export:
|
||
|
|
get:
|
||
|
|
summary: Export a theme
|
||
|
|
description: A portable document. Import and export are exact inverses, so migrating a theme between
|
||
|
|
environments is a file copy rather than a project.
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The export.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ThemeExport'
|
||
|
|
headers:
|
||
|
|
Cache-Control: *id003
|
||
|
|
X-Request-ID: *id004
|
||
|
|
Content-Disposition:
|
||
|
|
description: A download filename.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/import:
|
||
|
|
post:
|
||
|
|
summary: Import a theme
|
||
|
|
description: Creates or replaces a theme from a portable document. The document is validated before
|
||
|
|
anything is written, so a malformed import never reaches the database.
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'201':
|
||
|
|
description: The imported theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Theme'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'409':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ImportRequest'
|
||
|
|
example:
|
||
|
|
slug: acme
|
||
|
|
name: Acme
|
||
|
|
asDraft: true
|
||
|
|
tokens: {}
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/{slug}/versions:
|
||
|
|
get:
|
||
|
|
summary: A theme's history
|
||
|
|
description: 'Summaries newest first, without token documents: a hundred revisions of a hundred-token
|
||
|
|
theme would otherwise be a very large response for no benefit.'
|
||
|
|
tags:
|
||
|
|
- history
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The history.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- items
|
||
|
|
properties:
|
||
|
|
items:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/ThemeVersion'
|
||
|
|
headers: *id002
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: limit
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
maximum: 200
|
||
|
|
default: 50
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/{slug}/versions/{version}:
|
||
|
|
get:
|
||
|
|
summary: A historical snapshot
|
||
|
|
description: One immutable revision, including its token document.
|
||
|
|
tags:
|
||
|
|
- history
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The snapshot.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ThemeVersion'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: version
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The revision number.
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/{slug}/versions/{version}/rollback:
|
||
|
|
post:
|
||
|
|
summary: Roll back to a revision
|
||
|
|
description: Restores a snapshot as a **new** version rather than rewinding. History is append-only,
|
||
|
|
so an application deployed against version 7 can never have version 7 taken away from it.
|
||
|
|
tags:
|
||
|
|
- history
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The theme after rollback.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Theme'
|
||
|
|
headers: *id002
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: version
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The revision to restore.
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/themes/{slug}/diff:
|
||
|
|
get:
|
||
|
|
summary: Diff two revisions
|
||
|
|
description: A token-level comparison. Only the token tree is compared; a metadata change is reported
|
||
|
|
as a boolean rather than field by field.
|
||
|
|
tags:
|
||
|
|
- history
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The differences.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/VersionDiff'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
description: The theme slug.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: from
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
description: The base revision.
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
- name: to
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
description: The comparison revision.
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/tokens/validate:
|
||
|
|
post:
|
||
|
|
summary: Validate a token document
|
||
|
|
description: Runs the engine's validator without persisting anything. The editor calls it as the
|
||
|
|
user works, which is exactly why it must not write.
|
||
|
|
tags:
|
||
|
|
- tokens
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The findings.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ValidationResult'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- tokens
|
||
|
|
properties:
|
||
|
|
tokens: &id006
|
||
|
|
$ref: '#/components/schemas/TokenDocument'
|
||
|
|
example:
|
||
|
|
tokens:
|
||
|
|
color:
|
||
|
|
semantic:
|
||
|
|
primary:
|
||
|
|
$type: color
|
||
|
|
$value: '#4f46e5'
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/tokens/contrast:
|
||
|
|
get:
|
||
|
|
summary: Measure WCAG contrast
|
||
|
|
description: Reports the ratio and the highest conformance level it satisfies. The editor uses this
|
||
|
|
to flag an unreadable combination before it is saved rather than after it is published.
|
||
|
|
tags:
|
||
|
|
- tokens
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The measurement.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ContrastResult'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: fg
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
description: The foreground colour.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: bg
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
description: The background colour.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/tokens/palette:
|
||
|
|
get:
|
||
|
|
summary: Generate a colour ramp
|
||
|
|
description: Produces the canonical 11-step ramp for a hue. Exposed so the editor's palette builder
|
||
|
|
and the built-in themes cannot diverge from the engine's ramp curve.
|
||
|
|
tags:
|
||
|
|
- tokens
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The ramp.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/RampResponse'
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: hue
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Hue in degrees.
|
||
|
|
schema:
|
||
|
|
type: number
|
||
|
|
minimum: 0
|
||
|
|
maximum: 360
|
||
|
|
default: 250
|
||
|
|
- name: saturation
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Saturation at the mid steps, percent.
|
||
|
|
schema:
|
||
|
|
type: number
|
||
|
|
minimum: 0
|
||
|
|
maximum: 100
|
||
|
|
default: 78
|
||
|
|
- name: lightness
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Lightness at step 500, percent.
|
||
|
|
schema:
|
||
|
|
type: number
|
||
|
|
minimum: 20
|
||
|
|
maximum: 80
|
||
|
|
default: 55
|
||
|
|
- name: hueSpread
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Hue drift from the lightest to the darkest step. A value of 12 reproduces the warm-to-cool
|
||
|
|
lean of a modern perceptual ramp.
|
||
|
|
schema:
|
||
|
|
type: number
|
||
|
|
minimum: 0
|
||
|
|
maximum: 40
|
||
|
|
default: 12
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/tokens/schema:
|
||
|
|
get:
|
||
|
|
summary: The token schema
|
||
|
|
description: The group and kind registry, so a client renders the right control per token type instead
|
||
|
|
of duplicating a list that would drift.
|
||
|
|
tags:
|
||
|
|
- tokens
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The schema.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/TokenSchema'
|
||
|
|
headers:
|
||
|
|
Cache-Control:
|
||
|
|
description: Cacheable.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/admin/users:
|
||
|
|
get:
|
||
|
|
summary: List known accounts
|
||
|
|
description: Accounts seen at least once at login. Roles are overwritten from the provider on every
|
||
|
|
login rather than merged, so a user removed from a group actually loses access.
|
||
|
|
tags:
|
||
|
|
- admin
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The users.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
items:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/User'
|
||
|
|
headers: *id002
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'403':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: limit
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
maximum: 500
|
||
|
|
default: 100
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/admin/audit:
|
||
|
|
get:
|
||
|
|
summary: Read the activity log
|
||
|
|
description: Every mutation in the administration API.
|
||
|
|
tags:
|
||
|
|
- admin
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: A page of entries.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/AuditPage'
|
||
|
|
headers: *id002
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'403':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
parameters:
|
||
|
|
- name: actor
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Filter by actor.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: action
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: Filter by action.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: entityType
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: entityId
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
- name: since
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
- name: limit
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
maximum: 500
|
||
|
|
default: 50
|
||
|
|
- name: offset
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: ''
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 0
|
||
|
|
default: 0
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/admin/settings:
|
||
|
|
get:
|
||
|
|
summary: Read instance settings
|
||
|
|
description: The settings the engine reads at run time. Everything requiring a restart is environment
|
||
|
|
configuration and belongs in the Helm chart, not in a database row.
|
||
|
|
tags:
|
||
|
|
- admin
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The settings.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
items:
|
||
|
|
type: object
|
||
|
|
additionalProperties:
|
||
|
|
$ref: '#/components/schemas/Setting'
|
||
|
|
headers: *id002
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'403':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
put:
|
||
|
|
summary: Write instance settings
|
||
|
|
description: Writing the default theme clears the render cache, because it is baked into the runtime
|
||
|
|
manifest. Unrecognised keys are rejected rather than silently stored.
|
||
|
|
tags:
|
||
|
|
- admin
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The keys written.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
updated:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
headers: *id002
|
||
|
|
'400':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'403':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
additionalProperties:
|
||
|
|
type: string
|
||
|
|
description: 'Setting keys to values. Recognised keys: `default.theme`, `default.appearance`,
|
||
|
|
`runtime.public`, `runtime.apiBase`.'
|
||
|
|
example:
|
||
|
|
default.theme: midnight
|
||
|
|
default.appearance: dark
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/admin/cache/rebuild:
|
||
|
|
post:
|
||
|
|
summary: Rebuild the render cache
|
||
|
|
description: 'Clears and re-warms it. Useful after a bulk change, or to reclaim memory: the cache
|
||
|
|
holds every published theme multiplied by appearance and variant.'
|
||
|
|
tags:
|
||
|
|
- admin
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: What was warmed.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
themes:
|
||
|
|
type: integer
|
||
|
|
artefacts:
|
||
|
|
type: integer
|
||
|
|
headers: *id002
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'403':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/api/v1/stats:
|
||
|
|
get:
|
||
|
|
summary: Dashboard counters
|
||
|
|
description: Theme, key, user and audit counts, plus the render cache hit rate.
|
||
|
|
tags:
|
||
|
|
- themes
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The counters.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Stats'
|
||
|
|
headers: *id002
|
||
|
|
'401':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|
||
|
|
/healthz:
|
||
|
|
get:
|
||
|
|
summary: Liveness, with build information
|
||
|
|
description: Does **not** touch the database, deliberately. A liveness probe that failed on a slow
|
||
|
|
database would have the orchestrator restart a process that is otherwise healthy, turning a dependency
|
||
|
|
blip into an outage.
|
||
|
|
tags:
|
||
|
|
- operational
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: Healthy.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Health'
|
||
|
|
'500':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security: []
|
||
|
|
/livez:
|
||
|
|
get:
|
||
|
|
summary: Liveness
|
||
|
|
description: Answers as long as the process can serve HTTP.
|
||
|
|
tags:
|
||
|
|
- operational
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: Healthy.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Health'
|
||
|
|
'500':
|
||
|
|
description: Error
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security: []
|
||
|
|
/readyz:
|
||
|
|
get:
|
||
|
|
summary: Readiness
|
||
|
|
description: Reports whether the service can actually serve traffic, which means the database must
|
||
|
|
answer within a bounded time. Warns when the database is in-memory, which is legitimate in a test
|
||
|
|
and never in production.
|
||
|
|
tags:
|
||
|
|
- operational
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: Ready.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Health'
|
||
|
|
headers: *id002
|
||
|
|
'503':
|
||
|
|
description: Not ready.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Health'
|
||
|
|
security: []
|
||
|
|
/metrics:
|
||
|
|
get:
|
||
|
|
summary: Prometheus metrics
|
||
|
|
description: Request counts labelled by **route pattern** rather than concrete path — a thousand
|
||
|
|
distinct theme slugs must not become a thousand time series — a latency histogram, the render
|
||
|
|
cache hit rate, and Go runtime gauges. Disabled when `config.enableMetrics` is false.
|
||
|
|
tags:
|
||
|
|
- operational
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The exposition text.
|
||
|
|
content:
|
||
|
|
text/plain:
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
headers: *id002
|
||
|
|
security: []
|
||
|
|
/rt/v1/embed-page:
|
||
|
|
get:
|
||
|
|
summary: A shareable integration page
|
||
|
|
description: 'A complete HTML page showing the snippet for a theme next to a live preview of it.
|
||
|
|
Separate from /rt/v1/embed because the two have different callers: this one is a page a human
|
||
|
|
opens, that one is data a UI fetches. Every code sample on the page comes from the same builders,
|
||
|
|
so what is copied here is byte-for-byte what the admin UI shows.'
|
||
|
|
tags:
|
||
|
|
- runtime
|
||
|
|
parameters:
|
||
|
|
- name: slug
|
||
|
|
in: query
|
||
|
|
required: false
|
||
|
|
description: The theme to show.
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
responses:
|
||
|
|
'200':
|
||
|
|
description: The page.
|
||
|
|
content:
|
||
|
|
text/html:
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
'400':
|
||
|
|
description: Invalid slug.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
'404':
|
||
|
|
description: No such theme.
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/ApiError'
|
||
|
|
security: []
|
||
|
|
components:
|
||
|
|
securitySchemes:
|
||
|
|
sessionCookie:
|
||
|
|
type: apiKey
|
||
|
|
in: cookie
|
||
|
|
name: go-bananas-session
|
||
|
|
description: An HMAC-signed session cookie. Set `HttpOnly`, `Secure` and `SameSite`. Issued by the
|
||
|
|
OIDC login flow. There is no server-side session table, so any replica can authenticate any request.
|
||
|
|
bearerToken:
|
||
|
|
type: http
|
||
|
|
scheme: bearer
|
||
|
|
description: An API key. May also be supplied as a `token` query parameter, because a stylesheet
|
||
|
|
link cannot carry a header. Stored as a SHA-256 digest.
|
||
|
|
schemas:
|
||
|
|
ApiError:
|
||
|
|
type: object
|
||
|
|
description: 'The uniform error body. `code` is stable and part of the contract: clients branch
|
||
|
|
on it, so its meaning must not change between releases.'
|
||
|
|
required:
|
||
|
|
- code
|
||
|
|
- message
|
||
|
|
properties:
|
||
|
|
code:
|
||
|
|
type: string
|
||
|
|
description: A stable machine-readable code.
|
||
|
|
examples:
|
||
|
|
- validation_failed
|
||
|
|
message:
|
||
|
|
type: string
|
||
|
|
description: A human-readable explanation.
|
||
|
|
details:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/FieldError'
|
||
|
|
requestId:
|
||
|
|
type: string
|
||
|
|
description: Correlates the response with the server log.
|
||
|
|
FieldError:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- field
|
||
|
|
- message
|
||
|
|
properties:
|
||
|
|
field:
|
||
|
|
type: string
|
||
|
|
description: The JSON path or dotted token path.
|
||
|
|
message:
|
||
|
|
type: string
|
||
|
|
Token:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- $value
|
||
|
|
description: A single token leaf, in the W3C Design Tokens Community Group format.
|
||
|
|
properties:
|
||
|
|
$type:
|
||
|
|
type: string
|
||
|
|
description: The token type.
|
||
|
|
examples:
|
||
|
|
- color
|
||
|
|
- dimension
|
||
|
|
- fontSize
|
||
|
|
- cubicBezier
|
||
|
|
$value:
|
||
|
|
description: 'The value: a string, number, boolean or number array.'
|
||
|
|
oneOf:
|
||
|
|
- type: string
|
||
|
|
- type: integer
|
||
|
|
- type: boolean
|
||
|
|
- type: array
|
||
|
|
items:
|
||
|
|
type: integer
|
||
|
|
$description:
|
||
|
|
type: string
|
||
|
|
TokenDocument:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
description: A design-token document. `$appearances` holds a partial document per colour scheme,
|
||
|
|
deep-merged over the base, so a token absent from the dark overrides simply inherits its light
|
||
|
|
value.
|
||
|
|
properties:
|
||
|
|
$schema:
|
||
|
|
type: string
|
||
|
|
$appearances:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
ThemeStatus:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- draft
|
||
|
|
- published
|
||
|
|
- archived
|
||
|
|
description: Publication state. Only `published` is served to the runtime.
|
||
|
|
Appearance:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- light
|
||
|
|
- dark
|
||
|
|
description: Colour scheme.
|
||
|
|
Theme:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- id
|
||
|
|
- slug
|
||
|
|
- name
|
||
|
|
- status
|
||
|
|
- defaultAppearance
|
||
|
|
- tokens
|
||
|
|
- system
|
||
|
|
- version
|
||
|
|
- createdAt
|
||
|
|
- updatedAt
|
||
|
|
properties:
|
||
|
|
id:
|
||
|
|
type: string
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
pattern: ^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
status: *id005
|
||
|
|
defaultAppearance: &id007
|
||
|
|
$ref: '#/components/schemas/Appearance'
|
||
|
|
tokens: *id006
|
||
|
|
meta:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
description: Opaque to the engine apart from `tags`.
|
||
|
|
system:
|
||
|
|
type: boolean
|
||
|
|
description: A built-in theme. Cannot be deleted.
|
||
|
|
version:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
description: Bumped on every mutation. The render cache key.
|
||
|
|
createdAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
updatedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
createdBy:
|
||
|
|
type: string
|
||
|
|
updatedBy:
|
||
|
|
type: string
|
||
|
|
ThemeSummary:
|
||
|
|
type: object
|
||
|
|
description: 'A theme without its token document. Listings never include them: they are the bulk
|
||
|
|
of each row and a listing does not need them.'
|
||
|
|
properties:
|
||
|
|
id:
|
||
|
|
type: string
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
status: *id005
|
||
|
|
defaultAppearance: *id007
|
||
|
|
meta:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
system:
|
||
|
|
type: boolean
|
||
|
|
version:
|
||
|
|
type: integer
|
||
|
|
createdAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
updatedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
createdBy:
|
||
|
|
type: string
|
||
|
|
updatedBy:
|
||
|
|
type: string
|
||
|
|
ThemePage:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- items
|
||
|
|
- total
|
||
|
|
- limit
|
||
|
|
- offset
|
||
|
|
properties:
|
||
|
|
items:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/ThemeSummary'
|
||
|
|
total:
|
||
|
|
type: integer
|
||
|
|
limit:
|
||
|
|
type: integer
|
||
|
|
offset:
|
||
|
|
type: integer
|
||
|
|
ThemeMutation:
|
||
|
|
type: object
|
||
|
|
description: Create or update. Absent fields are left unchanged on update.
|
||
|
|
properties:
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
pattern: ^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
status: *id005
|
||
|
|
defaultAppearance: *id007
|
||
|
|
tokens: *id006
|
||
|
|
meta:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
message:
|
||
|
|
type: string
|
||
|
|
description: Recorded in the version history.
|
||
|
|
baseVersion:
|
||
|
|
type: integer
|
||
|
|
description: Optimistic concurrency. The write is rejected with 409 when the stored version
|
||
|
|
differs, which stops two editors silently overwriting each other.
|
||
|
|
ThemeVersion:
|
||
|
|
type: object
|
||
|
|
description: 'An immutable snapshot. History is append-only: a rollback restores a snapshot as a
|
||
|
|
new version rather than rewinding, so a deployed application can never lose the revision it was
|
||
|
|
built against.'
|
||
|
|
required:
|
||
|
|
- themeId
|
||
|
|
- version
|
||
|
|
- slug
|
||
|
|
- name
|
||
|
|
- createdAt
|
||
|
|
properties:
|
||
|
|
themeId:
|
||
|
|
type: string
|
||
|
|
version:
|
||
|
|
type: integer
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
status: *id005
|
||
|
|
defaultAppearance: *id007
|
||
|
|
tokens: *id006
|
||
|
|
message:
|
||
|
|
type: string
|
||
|
|
author:
|
||
|
|
type: string
|
||
|
|
createdAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
VersionDiff:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- fromVersion
|
||
|
|
- toVersion
|
||
|
|
- added
|
||
|
|
- removed
|
||
|
|
- changed
|
||
|
|
properties:
|
||
|
|
fromVersion:
|
||
|
|
type: integer
|
||
|
|
toVersion:
|
||
|
|
type: integer
|
||
|
|
added:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
removed:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
changed:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/TokenDiff'
|
||
|
|
metaChanged:
|
||
|
|
type: boolean
|
||
|
|
TokenDiff:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- path
|
||
|
|
- from
|
||
|
|
- to
|
||
|
|
properties:
|
||
|
|
path:
|
||
|
|
type: string
|
||
|
|
from:
|
||
|
|
type: string
|
||
|
|
to:
|
||
|
|
type: string
|
||
|
|
ValidationIssue:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- path
|
||
|
|
- severity
|
||
|
|
- message
|
||
|
|
properties:
|
||
|
|
path:
|
||
|
|
type: string
|
||
|
|
severity:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- error
|
||
|
|
- warning
|
||
|
|
- info
|
||
|
|
message:
|
||
|
|
type: string
|
||
|
|
hint:
|
||
|
|
type: string
|
||
|
|
ValidationResult:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- valid
|
||
|
|
- tokenCount
|
||
|
|
- issues
|
||
|
|
properties:
|
||
|
|
valid:
|
||
|
|
type: boolean
|
||
|
|
description: False when any issue is an error. Errors block publication; warnings do not.
|
||
|
|
tokenCount:
|
||
|
|
type: integer
|
||
|
|
issues:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/ValidationIssue'
|
||
|
|
ContrastResult:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- foreground
|
||
|
|
- background
|
||
|
|
- ratio
|
||
|
|
- level
|
||
|
|
properties:
|
||
|
|
foreground:
|
||
|
|
type: string
|
||
|
|
background:
|
||
|
|
type: string
|
||
|
|
ratio:
|
||
|
|
type: number
|
||
|
|
rounded:
|
||
|
|
type: number
|
||
|
|
level:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- fail
|
||
|
|
- aa-large
|
||
|
|
- aa
|
||
|
|
- aaa
|
||
|
|
thresholds:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
aaLarge:
|
||
|
|
type: number
|
||
|
|
aa:
|
||
|
|
type: number
|
||
|
|
aaa:
|
||
|
|
type: number
|
||
|
|
bestForeground:
|
||
|
|
type: string
|
||
|
|
RampResponse:
|
||
|
|
type: object
|
||
|
|
description: A generated colour ramp.
|
||
|
|
properties:
|
||
|
|
options:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
Hue:
|
||
|
|
type: number
|
||
|
|
Saturation:
|
||
|
|
type: number
|
||
|
|
Lightness:
|
||
|
|
type: number
|
||
|
|
HueSpread:
|
||
|
|
type: number
|
||
|
|
shades:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
ramp:
|
||
|
|
type: object
|
||
|
|
additionalProperties:
|
||
|
|
$ref: '#/components/schemas/Token'
|
||
|
|
TokenSchema:
|
||
|
|
type: object
|
||
|
|
description: The engine's group and kind registry, so a client renders the right control per token
|
||
|
|
type instead of duplicating a list that would drift.
|
||
|
|
properties:
|
||
|
|
id:
|
||
|
|
type: string
|
||
|
|
prefix:
|
||
|
|
type: string
|
||
|
|
kinds:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
groups:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
kind:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
recommended:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
shades:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
ImportRequest:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- slug
|
||
|
|
- tokens
|
||
|
|
properties:
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
tokens: *id006
|
||
|
|
meta:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
asDraft:
|
||
|
|
type: boolean
|
||
|
|
default: true
|
||
|
|
description: Import as a draft, so an import can never publish something by accident.
|
||
|
|
overwrite:
|
||
|
|
type: boolean
|
||
|
|
description: Replace an existing theme. Without it, an existing slug is a 409 rather than a
|
||
|
|
silent overwrite.
|
||
|
|
message:
|
||
|
|
type: string
|
||
|
|
ThemeExport:
|
||
|
|
type: object
|
||
|
|
description: The portable document. Import and export are exact inverses, so migrating a theme between
|
||
|
|
environments is a file copy rather than a project.
|
||
|
|
properties:
|
||
|
|
$schema:
|
||
|
|
type: string
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
status: *id005
|
||
|
|
version:
|
||
|
|
type: integer
|
||
|
|
tokens: *id006
|
||
|
|
meta:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
exportedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
exportedBy:
|
||
|
|
type: string
|
||
|
|
Session:
|
||
|
|
type: object
|
||
|
|
description: 'The current session. Always answers 200: an absent session is the normal state on
|
||
|
|
first load, not an error the UI should have to handle as one.'
|
||
|
|
required:
|
||
|
|
- authenticated
|
||
|
|
- mode
|
||
|
|
properties:
|
||
|
|
authenticated:
|
||
|
|
type: boolean
|
||
|
|
mode:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- oidc
|
||
|
|
- dev
|
||
|
|
- none
|
||
|
|
identity:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
subject:
|
||
|
|
type: string
|
||
|
|
email:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
roles:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- viewer
|
||
|
|
- editor
|
||
|
|
- admin
|
||
|
|
method:
|
||
|
|
type: string
|
||
|
|
expiresAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
permissions:
|
||
|
|
type: object
|
||
|
|
additionalProperties:
|
||
|
|
type: boolean
|
||
|
|
description: A UI convenience only. The server enforces every check, so hiding a control is
|
||
|
|
never the control.
|
||
|
|
preferences:
|
||
|
|
$ref: '#/components/schemas/UserPreferences'
|
||
|
|
description: Present once authenticated. Reported with the session so the UI can preselect a
|
||
|
|
theme without a second request.
|
||
|
|
devBypass:
|
||
|
|
type: boolean
|
||
|
|
loginUrl:
|
||
|
|
type: string
|
||
|
|
UserPreferences:
|
||
|
|
type: object
|
||
|
|
description: 'Per-account interface preferences. Both fields empty means nothing has been chosen,
|
||
|
|
which is a valid state rather than a missing one: the client then applies its own default.'
|
||
|
|
properties:
|
||
|
|
selectedTheme:
|
||
|
|
type: string
|
||
|
|
description: A published theme slug, or empty for no choice. Names the theme rather than copying
|
||
|
|
it, so editing or unpublishing that theme shows through everywhere. A stored value naming
|
||
|
|
a theme that has since been deleted or archived reads back as empty.
|
||
|
|
selectedAppearance:
|
||
|
|
$ref: '#/components/schemas/Appearance'
|
||
|
|
description: Which of the theme''s two colour schemes to render. Ignored, and dropped on write,
|
||
|
|
when selectedTheme is empty.
|
||
|
|
AppConfig:
|
||
|
|
type: object
|
||
|
|
description: What the UI needs before a session exists. Contains no secret material.
|
||
|
|
properties:
|
||
|
|
mode:
|
||
|
|
type: string
|
||
|
|
issuer:
|
||
|
|
type: string
|
||
|
|
runtimeBase:
|
||
|
|
type: string
|
||
|
|
publicBase:
|
||
|
|
type: string
|
||
|
|
basePath:
|
||
|
|
type: string
|
||
|
|
runtimeApiVersion:
|
||
|
|
type: string
|
||
|
|
variablePrefix:
|
||
|
|
type: string
|
||
|
|
defaultTheme:
|
||
|
|
type: string
|
||
|
|
User:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
subject:
|
||
|
|
type: string
|
||
|
|
email:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
roles:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
method:
|
||
|
|
type: string
|
||
|
|
firstSeen:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
lastLogin:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
AuditEntry:
|
||
|
|
type: object
|
||
|
|
description: One recorded action. The actor comes from the authenticated identity, never from the
|
||
|
|
request body.
|
||
|
|
required:
|
||
|
|
- id
|
||
|
|
- at
|
||
|
|
- actor
|
||
|
|
- action
|
||
|
|
properties:
|
||
|
|
id:
|
||
|
|
type: integer
|
||
|
|
at:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
actor:
|
||
|
|
type: string
|
||
|
|
actorEmail:
|
||
|
|
type: string
|
||
|
|
action:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- theme.create
|
||
|
|
- theme.update
|
||
|
|
- theme.delete
|
||
|
|
- theme.publish
|
||
|
|
- theme.archive
|
||
|
|
- theme.duplicate
|
||
|
|
- theme.rollback
|
||
|
|
- theme.import
|
||
|
|
- key.create
|
||
|
|
- key.revoke
|
||
|
|
- auth.login
|
||
|
|
- auth.logout
|
||
|
|
entityType:
|
||
|
|
type: string
|
||
|
|
entityId:
|
||
|
|
type: string
|
||
|
|
summary:
|
||
|
|
type: string
|
||
|
|
detail:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
remoteIp:
|
||
|
|
type: string
|
||
|
|
AuditPage:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- items
|
||
|
|
- total
|
||
|
|
- limit
|
||
|
|
- offset
|
||
|
|
properties:
|
||
|
|
items:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/AuditEntry'
|
||
|
|
total:
|
||
|
|
type: integer
|
||
|
|
limit:
|
||
|
|
type: integer
|
||
|
|
offset:
|
||
|
|
type: integer
|
||
|
|
Setting:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- key
|
||
|
|
- value
|
||
|
|
- updatedAt
|
||
|
|
properties:
|
||
|
|
key:
|
||
|
|
type: string
|
||
|
|
value:
|
||
|
|
type: string
|
||
|
|
updatedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
updatedBy:
|
||
|
|
type: string
|
||
|
|
Stats:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
store:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
themes:
|
||
|
|
type: integer
|
||
|
|
themesByStatus:
|
||
|
|
type: object
|
||
|
|
additionalProperties:
|
||
|
|
type: integer
|
||
|
|
users:
|
||
|
|
type: integer
|
||
|
|
auditEntries:
|
||
|
|
type: integer
|
||
|
|
databaseSizeBytes:
|
||
|
|
type: integer
|
||
|
|
versionsRetaind:
|
||
|
|
type: integer
|
||
|
|
cache:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
CSSHits:
|
||
|
|
type: integer
|
||
|
|
CSSMisses:
|
||
|
|
type: integer
|
||
|
|
JSONHits:
|
||
|
|
type: integer
|
||
|
|
JSONMisses:
|
||
|
|
type: integer
|
||
|
|
Entries:
|
||
|
|
type: integer
|
||
|
|
ResolvedTheme:
|
||
|
|
type: object
|
||
|
|
description: A theme with every token resolved for one appearance, including derived tokens, because
|
||
|
|
consumers should not reimplement the derivation.
|
||
|
|
required:
|
||
|
|
- theme
|
||
|
|
- tokens
|
||
|
|
- variables
|
||
|
|
properties:
|
||
|
|
theme:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
version:
|
||
|
|
type: integer
|
||
|
|
appearance: *id007
|
||
|
|
defaultAppearance: *id007
|
||
|
|
updatedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
tokens: *id006
|
||
|
|
variables:
|
||
|
|
type: object
|
||
|
|
additionalProperties:
|
||
|
|
type: string
|
||
|
|
description: Flat CSS custom property name to rendered value.
|
||
|
|
meta:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
ManifestEntry:
|
||
|
|
type: object
|
||
|
|
required:
|
||
|
|
- slug
|
||
|
|
- name
|
||
|
|
- defaultAppearance
|
||
|
|
- version
|
||
|
|
- css
|
||
|
|
- tokens
|
||
|
|
properties:
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
defaultAppearance: *id007
|
||
|
|
version:
|
||
|
|
type: integer
|
||
|
|
tags:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
css:
|
||
|
|
type: string
|
||
|
|
format: uri
|
||
|
|
tokens:
|
||
|
|
type: string
|
||
|
|
format: uri
|
||
|
|
Manifest:
|
||
|
|
type: object
|
||
|
|
description: 'The discovery document a loader fetches once to build a theme picker. Deliberately
|
||
|
|
small: no token data, so a page with a picker does not download every theme.'
|
||
|
|
required:
|
||
|
|
- apiVersion
|
||
|
|
- baseUrl
|
||
|
|
- themes
|
||
|
|
properties:
|
||
|
|
apiVersion:
|
||
|
|
type: string
|
||
|
|
default:
|
||
|
|
type: string
|
||
|
|
baseUrl:
|
||
|
|
type: string
|
||
|
|
format: uri
|
||
|
|
themes:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/ManifestEntry'
|
||
|
|
Health:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
status:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- ok
|
||
|
|
- ready
|
||
|
|
- not ready
|
||
|
|
version:
|
||
|
|
type: string
|
||
|
|
uptime:
|
||
|
|
type: string
|
||
|
|
checks:
|
||
|
|
type: object
|
||
|
|
additionalProperties: true
|
||
|
|
EmbedSnippet:
|
||
|
|
type: object
|
||
|
|
description: A ready-to-paste integration snippet for one theme.
|
||
|
|
required:
|
||
|
|
- slug
|
||
|
|
- name
|
||
|
|
- version
|
||
|
|
- baseUrl
|
||
|
|
- language
|
||
|
|
- snippet
|
||
|
|
properties:
|
||
|
|
slug:
|
||
|
|
type: string
|
||
|
|
description: 'The theme, which exists: the endpoint validates it.'
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description: The theme's display name.
|
||
|
|
version:
|
||
|
|
type: integer
|
||
|
|
description: The version the snippet was generated against.
|
||
|
|
baseUrl:
|
||
|
|
type: string
|
||
|
|
description: The runtime base URL baked into the snippet.
|
||
|
|
language:
|
||
|
|
type: string
|
||
|
|
enum:
|
||
|
|
- html
|
||
|
|
- js
|
||
|
|
- tsx
|
||
|
|
description: The syntax of the snippet.
|
||
|
|
snippet:
|
||
|
|
type: string
|
||
|
|
description: The code to paste. Values interpolated into it are escaped for the language.
|
||
|
|
note:
|
||
|
|
type: string
|
||
|
|
description: Anything else the integrator needs to know.
|
||
|
|
security:
|
||
|
|
- sessionCookie: []
|
||
|
|
- bearerToken: []
|