Brand Kits

A brand kit is your identity as a W3C Design Tokens (DTCG) document — colors, fonts, and slide-specific extensions, stated once and reused everywhere. Create one from tokens, from your existing PowerPoint template, or from your website. Pass theme_id to any render endpoint; the 9 builtins below remain always available and need no kit at all.

GET /v1/brands

List your brand kits plus the built-in theme ids.

curl
curl https://api.slideforge.dev/v1/brands \
  -H "Authorization: Bearer sf_live_YOUR_KEY"
Response — 200
{
  "brands": [
    { "slug": "acme-corp", "name": "Acme Corp", "version": 3, "locked": false }
  ],
  "builtins": [
    "slideforge_standard", "consulting_graphite", "dark_keynote", "product_bold",
    "technical_lab", "education_warm", "healthcare_calm", "scientific_paper", "sales_warm"
  ]
}

POST /v1/brands

Create a kit from a DTCG document (Tokens Studio dialect accepted — a bare hex string or font-family name works, not just the full colorSpace/components object). Six tokens are identity — never defaulted: color.canvas, color.text.primary, color.brand.primary, color.accent, font.display, font.body. Miss one and the request is refused — a brand is never guessed. Requires a linked account; needs no top-up.

curl
curl -X POST https://api.slideforge.dev/v1/brands \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "acme-corp",
    "name": "Acme Corp",
    "document": {
      "color": {
        "canvas": { "$type": "color", "$value": "#FFFFFF" },
        "text": { "primary": { "$type": "color", "$value": "#0F172A" } },
        "brand": { "primary": { "$type": "color", "$value": "#003366" } },
        "accent": { "$type": "color", "$value": "#FF6600" }
      },
      "font": {
        "display": { "$type": "fontFamily", "$value": "Calibri" },
        "body": { "$type": "fontFamily", "$value": "Calibri" }
      }
    }
  }'
Response — 201
{
  "theme_id": "acme-corp",
  "name": "Acme Corp",
  "version": 1,
  "locked": false,
  "pinned_id": "acme-corp@1",
  "document": { "...": "the stored DTCG document, with defaults/derived tokens filled in" },
  "report": { "brand": "acme-corp", "stated": 6, "defaulted": 12, "derived": 3, "tokens": ["..."] }
}
Response — 422 brand_kit_incomplete
{
  "code": "brand_kit_incomplete",
  "title": "Identity tokens missing",
  "detail": "brand kit incomplete — identity tokens missing: color.brand.primary, font.display",
  "missing": ["color.brand.primary", "font.display"],
  "remedy": "State the missing tokens — a brand is never guessed or defaulted."
}

Using a kit

theme_id: "acme-corp"resolves to the kit's latest version; "acme-corp@3" pins version 3 forever, even after a newer version publishes.

curl
# Pass theme_id (unpinned = latest version, or pin @N) to any render endpoint
curl -X POST https://api.slideforge.dev/v1/render/auto \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "brief": "Q1 KPI dashboard: revenue, clients, margin, NPS",
    "theme_id": "acme-corp@3"
  }'

POST /v1/brands/upload

Upload a company template (.pptx, .potx, or .thmx, max 50MB) and colors, fonts, and logo are extracted into the kit; the template itself is kept so exports and native render carry your actual slide master. Re-uploading your own slug's file publishes a new version rather than costing a second kit. Requires a topped-up wallet.

curl
# Upload a company template — .pptx, .potx, or .thmx, max 50MB
curl -X POST https://api.slideforge.dev/v1/brands/upload \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -F "file=@acme_corp_template.pptx" \
  -F "slug=acme-corp" \
  -F "name=Acme Corp"

POST /v1/brands/from-url

Import a brand from its website. $0.10, charged once per domain per account— a second import of the same domain (e.g. publishing a new version after the site's colors change) is free. If the site doesn't state a full identity, the request is refused with 422 and a stated block listing what it did find, so you can complete the rest via POST /v1/brands. Requires a topped-up wallet.

curl
curl -X POST https://api.slideforge.dev/v1/brands/from-url \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "acme-corp.com" }'
Response — 201
{
  "theme_id": "acme-corp",
  "name": "Acme Corp",
  "version": 1,
  "pinned_id": "acme-corp@1",
  "document": { "...": "..." },
  "report": { "...": "..." },
  "cost": 0.10
}
Response — 422 brand_kit_incomplete
{
  "code": "brand_kit_incomplete",
  "title": "The site does not state a full identity",
  "missing": ["color.accent"],
  "domain": "acme-corp.com",
  "remedy": "POST /v1/brands with a DTCG document stating the missing tokens (the site's stated tokens are in `stated`), or upload the company template.",
  "stated": { "colors": ["#003366", "#FFFFFF"], "fonts": ["Calibri"] }
}

GET /v1/brands/{slug}

The kit plus its fidelity report — one row per token, stating where its value came from (dtcg:… you stated it, default the model's fallback, derived computed at read time; an importer overwrites with its own provenance like pptx:theme/lt1 or url:brandfetch/colors.brand), its confidence, and its disposition (a font can come back named_not_embedded — named in the template but not carried in the file, so a render machine without that font falls back).

curl
curl https://api.slideforge.dev/v1/brands/acme-corp \
  -H "Authorization: Bearer sf_live_YOUR_KEY"

POST /v1/brands/{slug}/versions

Publish a new version of a kit you own. Versions are append-only — nothing is overwritten, so acme-corp@1 keeps rendering exactly as it did the day it was pinned, even after acme-corp@2ships. A token-only update keeps the kit's uploaded template.

curl
# Publish a new version — the slug keeps its slot, the old version stays reachable pinned
curl -X POST https://api.slideforge.dev/v1/brands/acme-corp/versions \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "document": {
      "color": { "accent": { "$type": "color", "$value": "#FF6600" } }
    }
  }'

Exports

Get the kit back out as the file format you need. tokens.json requires only a linked account; potx/thmx require a topped-up wallet. Neither export carries a per-call charge beyond that.

GET /v1/brands/{slug}/potx — PowerPoint template, native on your uploaded master when you have one
GET /v1/brands/{slug}/thmx — Office theme file
GET /v1/brands/{slug}/tokens.json — the DTCG document itself, the same file Figma, Tokens Studio, and Style Dictionary read
curl
curl https://api.slideforge.dev/v1/brands/acme-corp/potx \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -o acme-corp.potx

curl https://api.slideforge.dev/v1/brands/acme-corp/thmx \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -o acme-corp.thmx

curl https://api.slideforge.dev/v1/brands/acme-corp/tokens.json \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -o acme-corp.tokens.json

DELETE /v1/brands/{slug}

Delete a kit you own, freeing your personal kit slot. A locked kit refuses with 409. No wallet top-up required to delete.

curl
curl -X DELETE https://api.slideforge.dev/v1/brands/acme-corp \
  -H "Authorization: Bearer sf_live_YOUR_KEY"
Response — 200
{ "deleted": "acme-corp" }

Plan limits

  • Not linked to an account — built-in themes and a one-off inline theme_json render only; nothing persists.
  • Linked, no top-up yet — one personal kit, created from a DTCG document; view, publish new versions, delete.
  • Topped up (any amount, $10 minimum) — plus template upload, URL import, and .potx/.thmx export for that one kit.
  • The personal plan holds one kit. Updating it publishes a new version, not a second kit; deleting it frees the slot for a different brand. Org libraries with multiple kits, locking, and versions beyond the latest are a B2B plan, not available yet on personal.
Brand kits replace the legacy theme layer as the customer-facing brand story. The /v1/themes CRUD was removed (410 signpost) — this page is for removal — see Themes.