API Documentation

BrandAPI turns your design system into a single API endpoint. Call it from any app — your AI tools, design pipeline, or component library always get the latest brand tokens.

Quick Start

Three steps to your first API call.

1

Create a brand

Sign up at brandapi-ogk6.polsia.app/signup and complete the brand wizard. Define your colors, typography, spacing, voice, and custom tokens.

2

Get your API key

From the dashboard, open your brand → API Keys tab → Generate key. Your key starts with ba_ and is shown once — copy it now. Requires a Pro plan.

3

Call the endpoint

Make a single GET request to /v1/brand/context with your API key as the bearer token. You'll get back your full brand context as structured JSON.

shell
# Your first BrandAPI call
curl https://brandapi-ogk6.polsia.app/v1/brand/context \
  -H "Authorization: Bearer ba_your_api_key_here"

Authentication

All requests to /v1/brand/context require an API key. Two header formats are accepted — use whichever fits your HTTP client.

🔑

Authorization: Bearer

Standard Bearer token format. Recommended for most HTTP clients.

Authorization: Bearer ba_your_api_key
🗝️

X-API-Key

Alternative header for clients that don't support Authorization headers.

X-API-Key: ba_your_api_key
ℹ️
API keys are brand-scoped. Each key is tied to one specific brand. To serve multiple brands, generate separate keys for each brand from the dashboard.
⚠️
Keep your API key secret. Do not expose it in client-side JavaScript or commit it to version control. Use environment variables and call the API from your backend.

GET /v1/brand/context

Returns the full brand context as structured JSON, optimized for LLM consumption and developer tooling. Only non-empty token sections are included in the response.

GET https://brandapi-ogk6.polsia.app/v1/brand/context
Returns structured brand design tokens. Requires a valid, non-revoked API key.

Request Headers

Header Type Description
Authorization string Bearer ba_... — API key as bearer token.REQUIRED*
X-API-Key string Alternative: pass key directly. One of Authorization or X-API-Key is required.REQUIRED*

* Either Authorization or X-API-Key must be present.

Cache Behavior

Responses include Cache-Control: public, max-age=300, stale-while-revalidate=60. Tokens are cached for 5 minutes by CDNs. Your brand updates will propagate within that window.


Response Schema

A successful response returns HTTP 200 with a JSON object containing your brand tokens.

json — example response
{
  "brand": "Acme Corp",
  "version": "1.0",
  "updated_at": "2025-01-16T12:34:56.000Z",
  "tagline": "Build faster, ship better",
  "tokens": {
    "colors": {
      "primary": { "value": "#7c3aed", "usage": "CTAs and primary actions" },
      "accent": { "value": "#a78bfa", "usage": "Hover states and highlights" },
      "background": { "value": "#0a0a0c" }
    },
    "typography": {
      "heading": { "family": "Space Grotesk", "weight": "700", "size": "2rem" },
      "body": { "family": "Space Grotesk", "weight": "400", "size": "1rem" }
    },
    "spacing": {
      "base": "4px",
      "scale": [4, 8, 12, 16, 20, 24, 32]
    },
    "voice": {
      "tone": "professional yet approachable",
      "personality": ["clear", "direct", "innovative"],
      "do": ["Use active voice", "Keep it concise"],
      "avoid": ["Jargon", "Passive voice"]
    },
    "custom": {
      "border_radius": "12px",
      "shadow": "0 4px 24px rgba(0,0,0,0.4)"
    }
  },
  "instructions": "When generating content or code for Acme Corp, use these design tokens..."
}

Top-Level Fields

FieldTypeDescription
brand string Your brand's display name.
version string API response version. Currently "1.0".
updated_at string (ISO 8601) When the brand was last updated.
tagline string Brand tagline, if set.OPTIONAL
tokens object All design tokens. Only non-empty sections are included.
instructions string LLM-ready system instruction for applying these tokens.

tokens.colors

A map of named colors. Each key is a color role (e.g. primary, accent).

FieldTypeDescription
[name].value string Hex color value, e.g. "#7c3aed".
[name].usage string Human-readable description of where to use this color.OPTIONAL

tokens.typography

A map of font roles (e.g. heading, body, mono).

FieldTypeDescription
[role].familystringFont family name.OPTIONAL
[role].weightstringFont weight, e.g. "700".OPTIONAL
[role].sizestringFont size, e.g. "2rem".OPTIONAL
[role].line_heightstringLine height ratio.OPTIONAL

tokens.spacing

FieldTypeDescription
basestringBase spacing unit, e.g. "4px".
scalenumber[]Spacing scale in pixels, e.g. [4,8,12,16,20,24,32].

tokens.voice

FieldTypeDescription
tonestringOverall voice tone description.OPTIONAL
personalitystring[]List of personality traits.OPTIONAL
dostring[]Writing guidelines — things to do.OPTIONAL
avoidstring[]Writing anti-patterns to avoid.OPTIONAL

tokens.custom

Freeform key-value pairs for any additional tokens your brand needs — border radii, shadow values, animation speeds, etc.


Code Examples

shell
# Fetch your brand tokens
curl https://brandapi-ogk6.polsia.app/v1/brand/context \
  -H "Authorization: Bearer ba_your_api_key_here"

# Pretty-print with jq
curl https://brandapi-ogk6.polsia.app/v1/brand/context \
  -H "Authorization: Bearer ba_your_api_key_here" | jq '.'

# Extract just the primary color
curl https://brandapi-ogk6.polsia.app/v1/brand/context \
  -H "Authorization: Bearer ba_your_api_key_here" \
  | jq '.tokens.colors.primary.value'
javascript
// fetch-brand.js — call from your backend (Node.js)
const API_KEY = process.env.BRANDAPI_KEY;

async function getBrandTokens() {
  const res = await fetch(
    'https://brandapi-ogk6.polsia.app/v1/brand/context',
    {
      headers: {
        'Authorization': `Bearer ${API_KEY}`
      }
    }
  );

  if (!res.ok) {
    const err = await res.json();
    throw new Error(err.error);
  }

  return res.json();
}

// Usage
const brand = await getBrandTokens();
console.log(brand.tokens.colors.primary.value); // "#7c3aed"
console.log(brand.tokens.typography.heading.family); // "Space Grotesk"
python
# fetch_brand.py
import os
import requests

API_KEY = os.environ["BRANDAPI_KEY"]

def get_brand_tokens():
    resp = requests.get(
        "https://brandapi-ogk6.polsia.app/v1/brand/context",
        headers={"Authorization": f"Bearer {API_KEY}"}
    )
    resp.raise_for_status()
    return resp.json()

# Usage
brand = get_brand_tokens()
colors = brand["tokens"]["colors"]
primary = colors["primary"]["value"]  # "#7c3aed"

# Pass to an LLM system prompt
system_prompt = brand["instructions"] + " " + str(brand["tokens"])

Try It Live

Paste your API key below and hit the endpoint. Response appears inline — no Postman required.

GET /v1/brand/context

Live
Response
200 OK

Integration Examples

Practical patterns for consuming brand tokens in your codebase.

jsx
// brand-provider.jsx — fetch tokens server-side, pass as context
import { createContext, useContext } from 'react';

const BrandContext = createContext(null);

export async function loadBrand() {
  const res = await fetch('/v1/brand/context', {
    headers: { 'Authorization': `Bearer ${process.env.BRANDAPI_KEY}` },
    next: { revalidate: 300 } // Next.js ISR
  });
  return res.json();
}

// Use in a component
export function Button({ children }) {
  const brand = useContext(BrandContext);
  const primary = brand?.tokens?.colors?.primary?.value ?? '#7c3aed';
  const font = brand?.tokens?.typography?.body?.family ?? 'sans-serif';

  return (
    <button style={{
      background: primary,
      fontFamily: font,
      color: '#fff',
      padding: '0.6rem 1.25rem',
      borderRadius: '8px',
      border: 'none',
      cursor: 'pointer'
    }}>
      {children}
    </button>
  );
}
javascript — tailwind.config.js
// tailwind.config.js — inject brand tokens at build time
const { getBrandTokens } = require('./scripts/brand');

let brand = { tokens: {} };
try {
  brand = await getBrandTokens();
} catch { /* use defaults */ }

const colors = Object.fromEntries(
  Object.entries(brand.tokens.colors ?? {})
    .map(([name, token]) => [name, token.value])
);

const fonts = Object.fromEntries(
  Object.entries(brand.tokens.typography ?? {})
    .map(([role, t]) => [role, [t.family, 'sans-serif']])
);

module.exports = {
  theme: {
    extend: {
      colors,              // bg-primary, text-accent, etc.
      fontFamily: fonts,   // font-heading, font-body
    }
  }
};
javascript — generate CSS variables
// generate-tokens.js — run at build time or in a server endpoint
const res = await fetch('https://brandapi-ogk6.polsia.app/v1/brand/context', {
  headers: { 'Authorization': `Bearer ${process.env.BRANDAPI_KEY}` }
});
const brand = await res.json();
const colors = brand.tokens.colors ?? {};
const spacing = brand.tokens.spacing?.scale ?? [];

// Build :root { --primary: #...; ... }
const colorVars = Object.entries(colors)
  .map(([name, t]) => `  --color-${name}: ${t.value};`)
  .join('\n');

const spaceVars = spacing
  .map((val, i) => `  --space-${i + 1}: ${val}px;`)
  .join('\n');

const css = `:root {\n${colorVars}\n${spaceVars}\n}`;

// Write to tokens.css
require('fs').writeFileSync('./src/tokens.css', css);

/* Output: tokens.css
:root {
  --color-primary: #7c3aed;
  --color-accent:  #a78bfa;
  --space-1: 4px;
  --space-2: 8px;
}
*/

Error Codes

All errors return a JSON body with an error field and an optional hint.

json — error shape
{
  "error": "API key required",
  "hint": "Pass your API key via Authorization: Bearer ba_xxx or X-API-Key: ba_xxx header"
}
401

API key required

No API key was found in the request headers. Add Authorization: Bearer ba_....

401

Invalid API key

The provided key doesn't match any active key. Check for typos or regenerate from the dashboard.

401

API key has been revoked

This key was revoked. Generate a new key from the dashboard → API Keys tab.

404

Brand not found

The brand associated with this API key no longer exists. Check if the brand was deleted.

429

Rate limit exceeded

Too many requests. Back off and retry. See Rate Limits for details.

500

Internal server error

Something went wrong on our end. Retry after a brief pause. If it persists, contact support.


Rate Limits & Caching

💡
Brand tokens rarely change. Cache the API response at your application layer for at least 5 minutes. Calling on every request is unnecessary and burns rate-limit headroom.

Response Caching

Every response includes Cache-Control: public, max-age=300, stale-while-revalidate=60. CDNs and HTTP caches will respect this automatically. Your server should also cache the parsed response in memory.

javascript — simple in-memory cache
// cache-brand.js — cache for 5 minutes
let cache = { data: null, ts: 0 };
const TTL = 5 * 60 * 1000; // 5 min

export async function getBrand() {
  if (cache.data && Date.now() - cache.ts < TTL) return cache.data;

  const res = await fetch('https://brandapi-ogk6.polsia.app/v1/brand/context', {
    headers: { 'Authorization': `Bearer ${process.env.BRANDAPI_KEY}` }
  });

  if (!res.ok) throw new Error(`BrandAPI error: ${res.status}`);

  cache = { data: await res.json(), ts: Date.now() };
  return cache.data;
}

Rate Limit Guidance

BrandAPI does not enforce strict per-second rate limits, but excessive polling is detected and may result in temporary 429 responses. Follow these guidelines:

PatternRecommendation
Server startup Fetch once, cache in process memory. Re-fetch every 5 min or on 404.
Per-request (SSR) Cache in Redis or memory with 5-minute TTL.
CI / build pipeline One fetch per build is fine. Cache the output artifact.
Client-side (browser) Don't call from the browser — your API key would be exposed. Proxy through your backend.