Brands

List, create, update, and extract brands. Every brand carries a kernel with logos for light and dark backgrounds, contrast-safe palettes, type, surfaces, voice, and imagery.

Base URL: https://heydecks.com

All endpoints require Authorization: Bearer hd_live_….

#The brand kernel

Every brand object includes a kernel: the single source of truth for how decks in that brand look and sound. The older top-level fields (colors, typography, logos, tone, style) are still returned and accepted, and they always agree with the kernel.

JSON
{
  "version": 2,
  "identity": { "name": "Acme", "website": "https://acme.com", "tagline": "Numbers people trust." },
  "logos": {
    "primary": {
      "on_light": { "url": "https://heydecks.com/api/uploads/brands/brand_xyz/primary-on-light-3f2a9c1e0b7d4a55.svg", "format": "svg", "luminance": 0.01 },
      "on_dark": { "url": "https://heydecks.com/api/uploads/brands/brand_xyz/primary-on-dark-9a8b7c6d5e4f3a2b.svg", "format": "svg", "luminance": 1 }
    },
    "mark": { "on_light": { "url": "…", "format": "png" } },
    "placement": "top-right",
    "size": "medium"
  },
  "palette": {
    "accent": "#1b40f2",
    "light": { "background": "#ffffff", "surface": "#eff3fd", "foreground": "#111622", "muted": "#6a6e77", "line": "#d9dee8", "accent_foreground": "#ffffff" },
    "dark": { "background": "#111622", "surface": "#20242e", "foreground": "#ffffff", "muted": "#a0a2a8", "line": "#333843", "accent_foreground": "#ffffff" },
    "series": ["#1b40f2", "#af5a00", "#8b1592", "#6a7f00", "#006566"],
    "locked": []
  },
  "typography": { "heading": "Inter", "body": "Inter", "mono": "Geist Mono", "heading_weight": 500, "scale": "regular" },
  "shape": { "radius": 12, "stroke": 1, "cards": "flat" },
  "surfaces": { "allowed": ["light", "subtle", "dark", "accent"], "mode": "light", "texture": "none" },
  "voice": { "tone": "Confident, plain, specific.", "audience": "Finance leaders", "avoid": ["synergy"] },
  "imagery": { "style": "photographic", "mood": "Calm daylight" }
}

What the fields do:

  • Logos. on_light is the artwork for light backgrounds, on_dark for dark ones. Slides pick the right one for each surface. If one is missing, the other is recolored to solid black or white, but only where it would not read as is. mark is an optional compact symbol.
  • Palette. One accent is enough: the light and dark palettes and the chart series are derived from it, and every text pair passes WCAG AA on every surface. Set a palette token yourself and add its id (for example "light.muted") to locked to keep it when the accent changes.
  • Surfaces. allowed lists the slide surfaces decks may use; a slide asking for a disabled one renders on the closest allowed one. mode: "dark" puts the dark palette on the canvas.
  • Voice and imagery. AI drafts follow voice (and never write anything in avoid); image generation follows imagery.

Enumerations: placement is top-right, top-left, bottom-right, or none. size is small, medium, or large. scale is compact, regular, or expressive. heading_weight is 400 or 500. radius is 0 to 28. stroke is 1 or 1.5. cards is flat or outlined. texture is none, grid, or dots. imagery.style is photographic, illustration, 3d, or abstract.

#GET /v1/brands

List all brands in your workspace.

Shell
curl https://heydecks.com/v1/brands \
  -H "Authorization: Bearer hd_live_…"

200 Response: an array of brand objects.

JSON
[
  {
    "id": "brand_xyz",
    "name": "Acme",
    "is_active": true,
    "colors": { "background": "#ffffff", "foreground": "#111622", "muted": "#6a6e77", "subtle": "#eff3fd", "accent": "#1b40f2", "line": "#d9dee8" },
    "typography": { "heading_font": "Inter", "body_font": "Inter", "mono_font": "Geist Mono" },
    "logos": { "wordmark": "https://heydecks.com/api/uploads/brands/brand_xyz/primary-on-light-3f2a9c1e0b7d4a55.svg", "mark": "A" },
    "tone": "Confident, plain, specific.",
    "style": { "radius": 12, "stroke_width": 1, "card_style": "flat", "display_scale": 1, "heading_weight": 500, "heading_tracking": -0.03, "heading_case": "none", "background": "flat" },
    "kernel": { "version": 2, "…": "…" }
  }
]

The brand with is_active: true is the workspace default. It is applied automatically when brand_id is omitted from POST /v1/generate.

#GET /v1/brands/{id}

Fetch one brand. Same shape as a list item. 404 not_found when the brand is not in your workspace.

#POST /v1/brands

Create a brand. Anything you leave out is seeded from the workspace's active brand.

NameTypeRequiredDescription
namestringYesBrand display name.
kernelobjectNoA partial kernel (snake_case or camelCase). Merged over the seed; only the fields you send change.
logo_on_lightstringNoLogo for light backgrounds: an https:// URL or a data:image/… URL.
logo_on_darkstringNoLogo for dark backgrounds.
mark_on_lightstringNoCompact symbol for light backgrounds.
mark_on_darkstringNoCompact symbol for dark backgrounds.
colors, typography, tone, styleobject / stringNoThe older fields, still accepted. Kernel fields win where they overlap.
Shell
curl -X POST https://heydecks.com/v1/brands \
  -H "Authorization: Bearer hd_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme",
    "kernel": {
      "palette": { "accent": "#E2572B" },
      "typography": { "heading": "Fraunces", "body": "Inter" },
      "voice": { "tone": "Warm and direct", "avoid": ["synergy"] }
    },
    "logo_on_light": "https://acme.com/logo.svg",
    "logo_on_dark": "https://acme.com/logo-white.svg"
  }'

201 Response: the created brand object. Uploaded data URLs are stored and returned as hosted https://heydecks.com/api/uploads/brands/… URLs.

#PATCH /v1/brands/{id}

Update a brand. Send only what changes. The older fields apply first, then kernel fields on top. Set a logo field to null to remove that variant.

Shell
curl -X PATCH https://heydecks.com/v1/brands/brand_xyz \
  -H "Authorization: Bearer hd_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "kernel": { "palette": { "accent": "#00A36C" }, "surfaces": { "mode": "dark" } },
    "logo_on_dark": "https://acme.com/logo-white.svg"
  }'

Changing only palette.accent re-derives every unlocked palette token and the chart series. 200 Response: the updated brand object.

#POST /v1/brands/extract

Read a public website and return a brand ready to review. The page is loaded twice (light and dark color scheme), its real CSS colors, fonts, and header logo are measured, and one vision model reconciles them with screenshots to fill in the name, tagline, tone, audience, and image style, with a confidence per field.

Costs 50 credits. Refunded on failure. Nothing is saved.

NameTypeRequiredDescription
urlstringYesPublic https:// URL to analyse.
Shell
curl -X POST https://heydecks.com/v1/brands/extract \
  -H "Authorization: Bearer hd_live_…" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://acme.com"}'

200 Response: the same shape POST /v1/brands accepts (name, colors, typography, logos, tone, style, kernel), plus review:

JSON
{
  "name": "Acme",
  "kernel": { "version": 2, "…": "…" },
  "review": {
    "url": "https://acme.com/",
    "confidence": { "name": 0.95, "logo": 0.85, "palette": 0.9, "fonts": 0.8, "tone": 0.6, "imagery": 0.4 },
    "has_dark_theme": true,
    "declared_fonts": ["Inter"]
  }
}

To save it, post the result straight back: POST /v1/brands with {"name": …, "kernel": …}.

#Brand limits by plan

PlanBrands
Solo3
Pro15
TeamUnlimited
EnterpriseUnlimited

Exceeding the limit returns 402 brand_limit. Upgrade to add more brands.