Brand Kit
Colors, typography, logos and instructions.
Privacy and analytics
We use necessary technical cookies and, only with your consent, analytics and marketing pixels to improve the website and measure campaigns.
Colors, typography, logos and instructions.
Colors with their role, the Kit typography (families pending review included, marked proposed), approved logos and usage instructions. Bounded to what agents may use; never returns storage paths (use library.asset.get for a file).
| Field | Value |
|---|---|
| Kind | Read |
| HTTP method | POST /api/v1/kit.read |
| MCP tool | kit_read |
| Scope | kit.read |
| Minimum role | Viewer |
| Human confirmation | No |
| Doors | Nödo, Voice, MCP, API, Chat, Screens, Apps |
| Status | Available |
| Widget | palette |
Input
{
parts?: Array<"colors" | "typography" | "logos" | "instructions">
}Output
{
colors: Array<{
name: string
hex: string
role: "primary" | "secondary" | "accent" | "background" | "foreground" | "neutral" | "unspecified"
}>
typography: Array<{
family: string
role: string
weights: string[]
provider?: "google" | "custom"
status?: "approved" | "proposed"
}>
logos: Array<{
assetId: string // uuid
name: string
form: string
theme: string
primary: boolean
}>
instructions: Record<string, string>
}Adds one color to the Kit with a name and role. The HEX value is normalized; an existing HEX with the same role is rejected.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.colors.add |
| MCP tool | kit_colors_add |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | Nödo, MCP, API, Chat, Screens, Apps |
| Status | Available |
| Widget | confirm |
Input
{
name: string // ≤ 60
hex: string
role?: "primary" | "secondary" | "accent" | "background" | "foreground" | "neutral" | "unspecified" // default "unspecified"
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Finds Google Fonts families (open licences) by name or category, most popular first, shown as specimens. Only Google Fonts: other foundries need a licence the brand must upload itself.
| Field | Value |
|---|---|
| Kind | Read |
| HTTP method | POST /api/v1/kit.fonts.search |
| MCP tool | kit_fonts_search |
| Scope | kit.read |
| Minimum role | Viewer |
| Human confirmation | No |
| Doors | Nödo, Voice, MCP, API, Chat, Screens, Apps |
| Status | Available |
| Widget | fonts |
Input
{
query?: string // ≤ 80
category?: "sans-serif" | "serif" | "display" | "handwriting" | "monospace"
limit?: integer // 1–6 · default 4
}Output
{
items: Array<{
family: string
category: "sans-serif" | "serif" | "display" | "handwriting" | "monospace"
weights: string[]
}>
}Adds a Google Fonts family to the Kit with a role and its upright weights (all of them when none are given). The family must exist in Google Fonts; it is stored in the brand and approved once the person confirms.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.fonts.add |
| MCP tool | kit_fonts_add |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | Nödo, MCP, API, Chat, Screens, Apps |
| Status | Available |
| Widget | confirm |
Input
{
family: string // ≤ 80
role?: "heading" | "body" | "accent" // default "body"
weights?: string[] // ≤ 9 items
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Replaces the usage text of one Kit section (logos, colors, typography, imagery).
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.instructions.update |
| MCP tool | kit_instructions_update |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | Nödo, MCP, API, Chat, Screens, Apps |
| Status | Available |
| Widget | confirm |
Input
{
section: "logos" | "colors" | "typography" | "imagery" | "general"
text: string // ≤ 4000
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}The brand's design system: its status, versions, the run at work (with any questions it is waiting on) and the files asked for — by default README.md (the brand book, written as rules) and tokens.json of the PUBLISHED version, falling back to the newest ready one. Read it before designing any piece for the brand: README first, then tokens; a component's README before using it. status: none means the brand has no system yet (kit.system.build makes one).
| Field | Value |
|---|---|
| Kind | Read |
| HTTP method | POST /api/v1/kit.system.read |
| MCP tool | kit_system_read |
| Scope | kit.read |
| Minimum role | Viewer |
| Human confirmation | No |
| Doors | Nödo, Voice, MCP, API, Chat, Screens, Apps |
| Status | Available |
Input
{
version?: "published" | "latest" | string // default "published" · `published` (default; falls back to the newest ready version), `latest`, or a version id.
files?: string[] // ≤ 60 items · Paths to return, e.g. ["README.md", "tokens.json", "components/Button/README.md"]. Default README.md and tokens.json.
assetUrls?: boolean // default false · Also return a short-lived URL for each asset system.json lists (marks, imagery).
}Output
{
status: "none" | "draft" | "published"
title: string | null
version: {
id: string // uuid
number: integer // -9007199254740991–9007199254740991
state: "building" | "ready" | "failed"
note: string | null
createdAt: string // date-time
readyAt: string | null
publishedAt: string | null
published: boolean
issues: integer // -9007199254740991–9007199254740991
}
| null
paths: Array<{
path: string
bytes: integer // -9007199254740991–9007199254740991
generated: boolean
}>
files: Array<{
path: string
content: string
}>
versions: Array<{
id: string // uuid
number: integer // -9007199254740991–9007199254740991
state: "building" | "ready" | "failed"
note: string | null
createdAt: string // date-time
readyAt: string | null
publishedAt: string | null
published: boolean
issues: integer // -9007199254740991–9007199254740991
}>
run: {
id: string // uuid
kind: "build" | "refresh" | "update"
status: "queued" | "running" | "waiting" | "succeeded" | "failed" | "canceled"
phase: "reading" | "asking" | "writing" | "checking" | "saving" | null
instruction: string | null
questions: Array<{
key: string
title: string
reason?: string
options: Array<{
value: string
label: string
recommended?: boolean
}>
multiple?: boolean
}>
summary: string | null
errorCode: string | null
versionId: string | null
createdAt: string // date-time
finishedAt: string | null
usage: Record<string, unknown> | null
}
| null
assets: Array<{
group: string
name: string
type: string | null
url: string | null
libraryId: string | null
}>
}Starts the background job (Opus) that builds the brand's design system from everything Nömad knows — the Genome, the site, the Kit and the Library — or refreshes an existing one from those sources (a refresh keeps every note and anything a person added). It takes minutes; a brand's first system is on Nömad, refreshes spend the brand's AI budget. The result is a new version to review and publish. A run that stopped with questions continues when called with answers (question key → chosen value). Never ask the person stock questions first: the job reads the sources and asks only what they cannot settle.
Consumes the brand AI budget.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.system.build |
| MCP tool | kit_system_build |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | Nödo, MCP, API, Chat, Screens, Apps |
| Status | Available |
| Widget | confirm |
Input
{
mode?: "build" | "refresh" // default "build" · `build` for a first system or a fresh start, `refresh` to update one from the sources.
instruction?: string // ≤ 2000 · What the person asked for, in their words, when it adds something.
answers?: Record<string, string> // Answers to the questions of the run waiting on them.
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
status: "queued" | "running"
}A targeted change to an existing brand system, in the person's words ("square corners on buttons", "add a story template", "the accent is too loud in dark mode"). The background job (Opus) changes only that, checks it and saves a new version to publish; it spends the brand's AI budget. Use kit.system.build for a first system or a refresh from the sources.
Consumes the brand AI budget.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.system.update |
| MCP tool | kit_system_update |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | Nödo, MCP, API, Chat, Screens, Apps |
| Status | Available |
| Widget | confirm |
Input
{
instruction: string // ≤ 2000
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
status: "queued" | "running"
}Publishes a ready version of the brand system (default: the newest). From then on it is the version Nödo, generations and every agent read. Publishing an older version rolls back.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.system.publish |
| MCP tool | kit_system_publish |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | Nödo, MCP, API, Chat, Screens, Apps |
| Status | Available |
| Widget | confirm |
Input
{
versionId?: string // uuid
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
number: integer // -9007199254740991–9007199254740991
}Removes one color from the Kit. Returns the deleted row so kit.colors.restore can put it back.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.colors.delete |
| MCP tool | kit_colors_delete |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
colorId: string // uuid
}Output
{
color: {
id: string // uuid
brand_id: string // uuid
name: string
hex_code: string
category: string | null
position: integer // -9007199254740991–9007199254740991
sort_order: integer | null
description: string | null
show_in_brand_kit: boolean
created_at: string
}
}Shows or hides one Library file in the Brand Kit.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.assets.toggle |
| MCP tool | kit_assets_toggle |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
assetId: string // uuid
show: boolean
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Shows up to 100 Library logos, icons or typography files in the Brand Kit at once, all or nothing. Returns the ids shown.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.assets.add |
| MCP tool | kit_assets_add |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
assetIds: string[] // ≤ 100 items
}Output
{
ids: string[]
}Undo of kit.colors.delete: puts back the same row, with its id and place. Needs the same right as deleting it.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.colors.restore |
| MCP tool | kit_colors_restore |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
color: {
id: string // uuid
brand_id: string // uuid
name: string // ≤ 120
hex_code: string
category: string | null
position: integer // -9007199254740991–9007199254740991
sort_order: integer | null
description: string | null
show_in_brand_kit: boolean
created_at: string
}
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Changes the name, role or HEX of one Kit color. Any manual edit takes ownership: the website extractor no longer overwrites it. Only six-digit HEX values are stored.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.colors.update |
| MCP tool | kit_colors_update |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
colorId: string // uuid
name?: string // ≤ 120
category?: string | null
hex?: string // ≤ 16
description?: string // ≤ 2000
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Saves the palette order in one write. It never changes roles or extraction provenance; every color must belong to the brand.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.colors.reorder |
| MCP tool | kit_colors_reorder |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
colors: Array<{
id: string // uuid
sortOrder: integer // -9007199254740991–9007199254740991
}> // ≤ 200 items
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Adds a typeface to the Kit by name, family and role only, without a font file. Approved and shown in the Kit.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.fonts.create |
| MCP tool | kit_fonts_create |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
name: string // ≤ 160
family: string // ≤ 120
role?: string // ≤ 40
provider?: string // ≤ 40
}Output
{
font: {
id: string // uuid
}
}Downloads one weight (400, 700italic…) of a Google Fonts family, stores the WOFF2 in the brand and adds it to the Kit.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.fonts.install_weight |
| MCP tool | kit_fonts_install_weight |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
family: string // ≤ 120
variant: string // ≤ 20
role?: string // ≤ 40
}Output
{
font: {
id: string // uuid
}
}Installs the chosen weights of a Google Fonts family in the Kit, each one as a brand font file. Returns how many were installed and their files.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.fonts.install |
| MCP tool | kit_fonts_install |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
family: string // ≤ 120
variants: string[] // ≤ 40 items
role?: string // ≤ 40 · default "body"
}Output
{
count: integer // -9007199254740991–9007199254740991
assets: Array<{
id: string // uuid
}>
}Changes the variant of a logo, the role of a font or the section of a visual resource of the Kit. expectedUpdatedAt must match the stored file (conflict otherwise).
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.identity.update |
| MCP tool | kit_identity_update |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
assetId: string // uuid
expectedUpdatedAt: string | null
change: {
kind: "logo" | "font" | "resource"
}
}Output
{
asset: {
id: string // uuid
}
}Makes an approved Library logo or icon the brand primary logo, shown in the header, sidebar and switcher.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.logo.set_primary |
| MCP tool | kit_logo_set_primary |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
assetId: string // uuid
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Makes the Brand Kit private or public (a link anyone can open).
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.visibility.set |
| MCP tool | kit_visibility_set |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
visibility: "private" | "public"
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Registers an already-uploaded private PNG as a brand sticker. The object must belong to the caller and brand.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/kit.stickers.register |
| MCP tool | kit_stickers_register |
| Scope | kit.write |
| Minimum role | Admin |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
name: string // ≤ 80
storagePath: string // ≤ 180
sha256: string
}Output
{
id: string // uuid
}The Kit's colours, logos and typefaces with the primary logo and signed links, as the home card draws them. For the full Kit use kit.read.
| Field | Value |
|---|---|
| Kind | Read |
| HTTP method | POST /api/v1/kit.overview |
| MCP tool | kit_overview |
| Scope | kit.read |
| Minimum role | Viewer |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps, Nödo |
| Status | Available |
Input
{
asClient?: boolean // Read as the brand sees it (a staff viewer previewing as client). Only narrows.
primaryLogoId?: string | null // The brand's primary logo when the caller already knows it (saves a read); it must belong to the brand.
}Output
{
colors: Record<string, unknown>[]
logos: Record<string, unknown>[]
fonts: Record<string, unknown>[]
primaryLogo: Record<string, unknown> | null
}Updated on January 1, 1970