Docs / Reference

Your brand, as infrastructure.

Agents and tools read your brand, check their work against it and keep it up to date. Connect over MCP, or call the REST API from anything.

MCP · https://brandbook.app/api/mcpREST · https://brandbook.app/api/v1

Start

Quick start

  1. Make a key. In Brandbook, open Settings › API & connections and create an API key. It starts with bb_live_ and is shown once. A key reads and changes every brand in its workspace, so keep it out of code you share.
  2. Send it as a bearer token on every request: Authorization: Bearer bb_live_…
  3. Try it. List your brands:
curl
curl https://brandbook.app/api/v1/brands \
  -H "Authorization: Bearer $BRANDBOOK_KEY"

MCP

Connect an agent

The MCP server speaks JSON-RPC over Streamable HTTP at https://brandbook.app/api/mcp and authenticates with the same bearer key. Any client that can send a header to a remote server can use it directly.

Cursor

In ~/.cursor/mcp.json, or .cursor/mcp.json in a project:

mcp.json
{
  "mcpServers": {
    "brandbook": {
      "url": "https://brandbook.app/api/mcp",
      "headers": {
        "Authorization": "Bearer bb_live_…"
      }
    }
  }
}

Claude Code

terminal
claude mcp add --transport http brandbook https://brandbook.app/api/mcp \
  --header "Authorization: Bearer bb_live_…"

Or check it into .mcp.json and keep the key in your environment:

.mcp.json
{
  "mcpServers": {
    "brandbook": {
      "type": "http",
      "url": "https://brandbook.app/api/mcp",
      "headers": {
        "Authorization": "Bearer ${BRANDBOOK_KEY}"
      }
    }
  }
}

VS Code

In .vscode/mcp.json:

mcp.json
{
  "servers": {
    "brandbook": {
      "type": "http",
      "url": "https://brandbook.app/api/mcp",
      "headers": {
        "Authorization": "Bearer bb_live_…"
      }
    }
  }
}

Claude Desktop

Claude Desktop adds remote servers as connectors, which sign in with OAuth rather than a key. Until Brandbook offers OAuth, run the server through the mcp-remote bridge in claude_desktop_config.json (needs Node):

claude_desktop_config.json
{
  "mcpServers": {
    "brandbook": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://brandbook.app/api/mcp",
        "--header",
        "Authorization:${BRANDBOOK_AUTH}"
      ],
      "env": {
        "BRANDBOOK_AUTH": "Bearer bb_live_…"
      }
    }
  }
}
Claude.ai and ChatGPT. Their custom connectors accept remote MCP servers with OAuth or no sign-in, not a static API key, so they can't connect to Brandbook directly yet. Use one of the clients above, or call the REST API from a GPT action or your own code.

MCP

Tools

Every tool is scoped to the key's workspace. brand is a slug from list_brands, and can be left out when the workspace has one brand. Tools that change the brand bump its version and write a line to its changelog, the same as a change made in the app. This list is read from the server itself.

list_brandsRead only

The brands this key can read, with their slugs, versions and consistency scores.

No arguments.

get_brand_contextRead only

Call before writing anything for this brand. Returns the rules to follow as data (colours with roles, logo rules, fonts, voice traits, words to use and never use, voice and imagery rules, tone, the rules checks test, print colour values, messaging, partner rules and contacts when the brand book shows them, and the channel's rules when you name one) plus the full brand.md. Follow it exactly; don't invent colours, fonts or claims it doesn't give you.

Arguments

brandstring
Brand slug from list_brands, e.g. late-club. Optional when the workspace has one brand. Add @v1.3 (late-club@v1.3) to read an earlier version of the guidelines, e.g. for a campaign pinned to it; changes always go to the latest.
channelstring
Where it will run, e.g. instagram, email, press, poster. Adds that channel's rules.

get_rulesRead only

Just the rules you need, as a list: every rule the brand has (voice, visual, legal, channel), filtered to a channel, an audience, a category or a search. Each has an id (V-07), how strict it is (must or should), what it applies to, and whether check_output tests it.

Arguments

brandstring
Brand slug from list_brands, e.g. late-club. Optional when the workspace has one brand. Add @v1.3 (late-club@v1.3) to read an earlier version of the guidelines, e.g. for a campaign pinned to it; changes always go to the latest.
channelstring
e.g. instagram, story, poster, email.
audiencestring
e.g. the crew, stockists.
categoryvoice | visual | legal | channel
querystring
Words to look for in a rule.

check_outputRead only

Call on anything you wrote or designed for the brand before you hand it over. Returns a 0–100 score, a verdict (pass, needs_fix, fail), findings with fixes, and an on-brand rewrite when the voice is off. Send text, an image URL, or both; add the non-neutral colours a design uses to check the palette. Fix every error and check again.

Arguments

brandstring
Brand slug from list_brands, e.g. late-club. Optional when the workspace has one brand. Add @v1.3 (late-club@v1.3) to read an earlier version of the guidelines, e.g. for a campaign pinned to it; changes always go to the latest.
textstring
The copy. First line is treated as the headline.
image_urlstring
A public URL of the design to check.
coloursstring[]
Hex colours the design uses, e.g. ["#1F5E46", "#F2C14E"].

ask_brandRead only

A short, direct answer to a question about the brand: "Can I put yellow text on green?", "What do we call the people we help?".

Arguments

brandstring
Brand slug from list_brands, e.g. late-club. Optional when the workspace has one brand. Add @v1.3 (late-club@v1.3) to read an earlier version of the guidelines, e.g. for a campaign pinned to it; changes always go to the latest.
questionstringrequired

update_brandChanges the brand

Change one section of the brand system. Only when the person asks you to change the brand itself, not to follow it. Object sections (logo, type, voice, imagery) merge with what is there, so { "rules": [...] } leaves the voice traits alone; arrays inside them (voice.rules, logo.donts, colours) replace the whole list, so read the current list with get_brand_context first and send it back with your change. Bumps the version and writes a changelog line.

Arguments

brandstring
Brand slug from list_brands, e.g. late-club. Optional when the workspace has one brand. Add @v1.3 (late-club@v1.3) to read an earlier version of the guidelines, e.g. for a campaign pinned to it; changes always go to the latest.
sectiontagline | description | logo | colours | type | voice | imagery | strategy | rules | channelGuiderequired
Which part of the brand to change.
valuestring | object | arrayrequired
The new value. tagline, description: a string. colours: the whole palette, [{ "name": "Club Violet", "hex": "#6B3BFF", "role": "primary" | "accent" | "ground" | "text" | "secondary", "share": 0-100 }]. logo: { monogram, wordmark, minSize, clearSpace, donts: string[] }. type: { display: { family, weight }, body: { family, weight }, notes }. voice: { traits: [{ name, weAre, weAreNot }], sayAvoid: [{ say, avoid }], rules: string[], examples: [{ channel, text }], headlines: string[] }. imagery: { description, rules: string[] }. strategy: { purpose, values: [{ name, line }], positioning, positioningFor, audiences: [{ id, name, need, message }], claims: [{ id, text, status: verified | needs_evidence, evidence }] }. rules: the whole Rules-tab list, [{ id, text, category: voice | visual | legal | channel, topic, appliesTo, severity: must | should, example: { bad, good } }]. channelGuide: { formats: [{ id, name, size, shape, format, tone, rules: string[], examples: string[] }], regions: [{ id, code, name, default, disclaimers: string[] }], campaigns: [{ id, name, from, to, note }] }.
summarystring
One line for the changelog, e.g. "Tagline for the winter appeal". Written for you when left out.

add_ruleChanges the brand

Add one rule to the brand without touching the rest. Send exactly one of: rule (a voice rule, e.g. "No exclamation marks in headlines"), say + avoid (a word swap, e.g. say "the crew", avoid "customers"), or imagery_rule (e.g. "Credit the photographer on every photo"). Only when the person asks you to add it. A rule the brand already has changes nothing.

Arguments

brandstring
Brand slug from list_brands, e.g. late-club. Optional when the workspace has one brand. Add @v1.3 (late-club@v1.3) to read an earlier version of the guidelines, e.g. for a campaign pinned to it; changes always go to the latest.
rulestring
A plain-language voice rule.
saystring
The words to use. Send with avoid.
avoidstring
The words never to use. Send with say.
imagery_rulestring
A rule for photos and illustration.

REST API

REST API

Base URL https://brandbook.app/api/v1. Send and receive JSON; every request carries Authorization: Bearer bb_live_…. A {slug} must be a brand in the key's workspace, or the answer is a 404. CORS is open, but a key in browser code is a key anyone can read: call the API from a server.

GET/api/v1/brands

The brands in the key's workspace, oldest first.

request
curl https://brandbook.app/api/v1/brands \
  -H "Authorization: Bearer $BRANDBOOK_KEY"
200
{
  "data": [
    {
      "slug": "late-club",
      "name": "Late Club",
      "domain": "lateclub.co",
      "version": "1.3",
      "health": 89,
      "status": "live",
      "guidelines": "https://brandbook.app/b/late-club"
    }
  ]
}

health is the brand's consistency score, 0–100, or null before its first check. guidelines is its microsite.

GET/api/v1/brands/{slug}

The whole brand system: the structured spec every Brandbook feature reads, and the same thing as brand.md.

Query

formatjson | markdown | tokens
markdown returns brand.md as text/markdown; tokens returns tokens.json. Default json.
request
curl https://brandbook.app/api/v1/brands/late-club \
  -H "Authorization: Bearer $BRANDBOOK_KEY"
200
{
  "slug": "late-club",
  "name": "Late Club",
  "version": "1.3",
  "guidelines": "https://brandbook.app/b/late-club",
  "spec": {
    "name": "Late Club",
    "tagline": "Dressed for after dark.",
    "description": "…",
    "logo": { "monogram": "LC", "minSize": "…", "donts": ["…"] },
    "colours": [
      { "name": "Club Violet", "hex": "#6B3BFF", "role": "primary", "share": 30 }
    ],
    "type": { "display": { "family": "…" }, "body": { "family": "…" } },
    "voice": { "traits": [], "sayAvoid": [], "rules": [], "examples": [], "headlines": [] },
    "imagery": { "description": "…", "photos": [], "rules": [] },
    "channels": {}
  },
  "markdown": "# Late Club brand\nVersion 1.3 · …"
}

PATCH/api/v1/brands/{slug}

Change one section of the brand. The value is checked against that section's schema; the change bumps the version and is logged in the changelog as “via API: …”.

Body

sectionstringrequired
One of tagline, description, logo, colours, type, voice, imagery.
valuestring | object | arrayrequired
Strings for tagline and description; the whole palette for colours. Object sections merge with what is there, so { "headlines": [...] } leaves the voice traits alone. Lists inside them replace the whole list.
summarystring
One line for the changelog. Written for you when left out.
request
curl -X PATCH https://brandbook.app/api/v1/brands/late-club \
  -H "Authorization: Bearer $BRANDBOOK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"section": "tagline", "value": "Made for the night, built to last."}'
200
{
  "brand": "late-club",
  "version": "1.4",
  "changed": true,
  "summary": "via API: Tagline: “Made for the night, built to last.”"
}

A value that matches what is there returns "changed": false and keeps the version.

POST/api/v1/brands/{slug}/rules

Add one rule without touching the rest of the brand. Send exactly one kind.

Body

rulestring
A plain-language voice rule.
say, avoidstring, string
A word swap: what to say instead of what to avoid.
imagery_rulestring
A rule for photos and illustration.
request
curl -X POST https://brandbook.app/api/v1/brands/late-club/rules \
  -H "Authorization: Bearer $BRANDBOOK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"say": "pieces", "avoid": "product"}'
200
{
  "brand": "late-club",
  "version": "1.4",
  "added": true,
  "summary": "via API: Voice: say “pieces”, not “product”"
}

A rule the brand already has returns "added": false and keeps the version.

POST/api/v1/check

Check copy, a design or a palette against the brand before it ships. The rule engine runs first; with AI on, a model review adds findings and reads images. Each check is logged on the brand's Check page.

Body

brandstring
Brand slug. Optional when the workspace has one brand.
textstring
The copy. The first line is read as the headline.
image_urlstring
A public http(s) URL of the design. Read when AI is on.
coloursstring[]
Hex colours the design uses, e.g. ["#6B3BFF"].
request
curl -X POST https://brandbook.app/api/v1/check \
  -H "Authorization: Bearer $BRANDBOOK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"brand": "late-club", "text": "Only 2 left!!! Drop 05 is selling fast", "colours": ["#6B3BFF", "#E4002B"]}'
200
{
  "brand": "late-club",
  "score": 54,
  "verdict": "needs_fix",
  "findings": [
    {
      "severity": "error",
      "category": "voice",
      "title": "Language: “only 2 left”",
      "detail": "No fake scarcity, ever"
    },
    {
      "severity": "error",
      "category": "voice",
      "title": "Language: “selling fast”",
      "detail": "No fake scarcity, ever"
    },
    {
      "severity": "error",
      "category": "voice",
      "title": "Tone: “!!!”",
      "detail": "Late Club headlines never use exclamation marks.",
      "fix": { "type": "strip_exclamations" }
    },
    {
      "severity": "warning",
      "category": "colour",
      "title": "Colour: #E4002B isn't a brand colour",
      "detail": "Use one of Club Violet, Acid Lime, Bone, After Black."
    }
  ],
  "suggestion": "Drop 05 is out now. Made once, never restocked.",
  "check_id": "dac0d0d2-…",
  "notes": []
}

verdict is pass (85 and up), needs_fix (50–84) or fail. suggestion is an on-brand rewrite when the voice is off, else null. notes says when part of the input wasn't read.

POST/api/v1/ask

A short, direct answer to a question about the brand. Without AI, colour pairings, words and logo rules are still answered from the rules.

Body

brandstring
Brand slug. Optional when the workspace has one brand.
questionstringrequired
Up to 500 characters.
request
curl -X POST https://brandbook.app/api/v1/ask \
  -H "Authorization: Bearer $BRANDBOOK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"brand": "late-club", "question": "Can I put lime text on black?"}'
200
{
  "brand": "late-club",
  "question": "Can I put lime text on black?",
  "answer": "Yes, for any size of text. Acid Lime and After Black are 16.3:1."
}

Reference

Errors

Every error has the same shape, with a message written to be shown or acted on:

404
{
  "error": {
    "code": "brand_not_found",
    "message": "No brand \"nope\" in this workspace. List brands for the slugs."
  }
}
StatuscodeWhen
400invalid_jsonThe body isn't JSON, or isn't an object.
400invalid_requestA field is missing or doesn't fit its schema. The message names it.
401unauthorizedNo key, or a revoked one. The WWW-Authenticate header says which.
404brand_not_foundNo brand with that slug in the key's workspace.
405method_not_allowedThat path doesn't take that method. See the Allow header.
429rate_limitedToo many requests. Wait for Retry-After seconds.
500internalOur side failed. Try again in a moment.

Over MCP, a problem with the arguments comes back as a tool result with isError: true and the same message, so the agent can fix the call and try again.

Reference

Rate limits

Limits are per key, over a rolling minute: 120 requests across the REST API and the MCP server, of which 30 may be /check or /ask calls. Past the limit you get a 429 with Retry-After: 60 (over MCP, a JSON-RPC error with the same status). Need more? Use a key per integration.

Reference

brand.md and tokens.json

Two files any tool can read without an SDK. brand.md is the brand as Markdown, written for a model's context window: colours with roles, type, voice, words to use and avoid, logo and imagery rules. tokens.json is the colours and type as Design Tokens (the W3C DTCG format), for Figma and code.

curl
curl https://brandbook.app/api/brands/late-club/brand.md
curl https://brandbook.app/api/brands/late-club/tokens.json?download

They are public when the brand's microsite is public; otherwise send a key for the brand's workspace. Add ?download to save as a file. The same files come from GET /api/v1/brands/{slug}?format=markdown and ?format=tokens, and are on Settings › API & connections.