Agents

REST API

Get a key, make your first render in four calls, and browse every endpoint.

Everything braaand can do is available over plain HTTPS. The MCP connector and the CLI are usually the comfortable paths, but when you're wiring braaand into your own backend, an orchestrator, or a language without an SDK, this is the surface you build against.

The base URL is:

https://www.braaand.ai/api

Building an agent? Pick the shortest path before hand-rolling HTTP:

  1. MCP — connect https://mcp.braaand.ai/mcp and your agent gets dozens of ready-made tools whose descriptions carry the on-brand rules (what to set, what to leave to the cascade). Zero integration work. See Connect an AI client.
  2. The CLInpm i -g braaand for coding agents with shell access. Auth is stored once (braaand login), renders land as files on disk instead of flowing through the model's context, and payloads too large for a request body (bulk onboards over ~4 MB) only work here. See Command line.
  3. The Claude skill — the packaged braaand playbook for Claude Code. See Claude skill.
  4. This page + GET /api — for your own HTTP wrapper. GET /api returns a prose orientation written for LLMs; feed your model that plus this page and it can drive the API. One thing neither carries in full: braaand's styling philosophy (let role, color schemes, and themes drive look — never set fonts or colors inline). If your agent will edit creatives rather than just fill copy, also feed it How your brand flows in. The docs are fetchable as raw markdown — this page lives at /docs/md/agents/rest-api, and /docs/llms.txt indexes everything with deep links.

Get a key

  1. Go to Settings → Profile → API keys and click New key. Copy the ae_… value right away — it's shown once and stored hashed.
  2. Or from the terminal: npm i -g braaand && braaand login walks you through device auth and stores a key for the CLI.

Send it as a bearer token on every request:

curl -H "Authorization: Bearer ae_..." https://www.braaand.ai/api/brands

A user key acts as you. For a single-purpose integration scoped to one brand, mint a brand token (bt_…) instead — POST /api/brands/{brandId}/tokens with { "name": "zapier", "role": "editor" } — and it can never touch other brands or manage members.

Quickstart: brief to PNG in four calls

1. Find your brand and a template.

curl -H "Authorization: Bearer $KEY" https://www.braaand.ai/api/brands
# → [{ "id": "acme", "name": "Acme", "role": "owner", ... }]

curl -H "Authorization: Bearer $KEY" https://www.braaand.ai/api/brands/acme/templates
# → [{ "id": "acme-hero-statement-1a2b3c4d", "name": "Hero statement", "elements": [...], ... }]

2. Clone the template into a creative.

curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  https://www.braaand.ai/api/brands/acme/creatives \
  -d '{ "templateId": "acme-hero-statement-1a2b3c4d", "name": "Summer sale hero" }'
# → 201 { "id": "crv_9f8e...", "elements": [{ "id": "heading", ... }], ... }

3. Put your copy in. Element ids come from the creative you just received; patches are partial and merge.

curl -X PATCH -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  https://www.braaand.ai/api/brands/acme/creatives/crv_9f8e.../elements/heading \
  -d '{ "content": "Up to 50% off" }'

4. Render it. The response is the PNG itself (an X-Render-Id header carries the id for your records).

curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  https://www.braaand.ai/api/render \
  -d '{ "kind": "creative", "brandId": "acme", "creativeId": "crv_9f8e...", "format": "1x1" }' \
  --output summer-sale-1x1.png

Producing at scale: workflows

For a batch ("give me a campaign from this brief"), launch a workflow and poll its manifest — there are no webhooks; the manifest is recomputed on every read, so polling always reflects the latest state including later edits.

curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  https://www.braaand.ai/api/brands/acme/factory/workflows \
  -d '{ "brief": { "raw": "Summer sale, warm and urgent, CTA to acme.com/sale" }, "count": 20 }'
# → 201 { "workflowId": "...", "boardId": "...", "manifestUrl": "...", "boardUrl": "...", "shareUrl": "..." }

curl -H "Authorization: Bearer $KEY" "$MANIFEST_URL"
# → { "status": "running", "creatives": [{ "id": "crv_...", "renders": { "1x1": "https://..." }, "score": 84, ... }] }

The brief is free text — how many creatives you want goes in count (1-200), never in the prose. The produced creatives land on a board (boardId) — a durable review place that can hold creatives from more than one run — pre-sorted into an Approved section (score ≥ 75) and Needs review for the rest. Every run is also a live node pipeline; open /brands/{brandId}/factory/{workflowId}/pipeline in the app to watch or edit it. boardUrl is the human review surface; shareUrl is a read-only link you can hand a client without a braaand account. For a full accounting of the run (build stages, scores, cost), pull GET .../factory/workflows/{workflowId}/log.

Conventions

  • Status codes. 401 bad or missing credentials, 403 not allowed, 404 not found, 400 validation, 402 out of credits (the body carries a machine-readable code), 507 storage quota exceeded, 429 rate limited (with a Retry-After header), 409 edit conflict or "run is still building".
  • Errors are JSON: { "error": "human-readable message", "code": "machine_readable_when_relevant" }. Malformed request bodies answer 400 { "error": "invalid_json" }; schema failures answer 400 { "error": "validation", "details": [{ "path", "message" }] }.
  • Edit conflicts. Templates and creatives carry a version number. Send the version your edits are based on in the X-Doc-Version header (or as version in the body) and the save is compare-and-set: if someone else saved first you get a 409 with the currentVersion, so you re-read and re-apply instead of overwriting their work. Partial updates without a version are merged onto a fresh read server-side.
  • Merging. Config-style PUTs (brand config, templates, creatives) only overwrite the fields present in the body — omit a field to leave it alone.
  • Rate limits (per caller): render 120/5 min, batch render 20/5 min, agent chat 60/5 min, onboarding 10/hour, workflow launch 20/hour.
  • Formats are named 1x1 (1080×1080), 4x5 (1080×1350), 9x16 (1080×1920), and 16x9 (1200×628) by default; each document carries its own list, so read formats off the doc rather than assuming.
  • Ids are stable strings — creatives are prefixed crv_, keys ae_, brand tokens bt_, share links dt_.
  • No pagination. List endpoints return everything; filter server-side where query params exist (e.g. creatives by collection, status, tag).
  • Asset and render URLs are capabilities. They contain unguessable ids and are safe to hot-link; they're also immutable and cached hard, so the URL changes whenever the content does.
  • Stability. There is no versioned prefix yet; the shapes documented here are the supported surface. Build against the documented fields and treat undocumented ones as subject to change.

Endpoints

Generated from the codebase — always current. Internal surfaces (admin, cron, webhooks) are omitted.

Brands

Route Method Auth What it does
/api/brands/{brandId}/allow-domains/{domain} DELETE brand admin Remove one domain from the brand's auto-join allowlist.
/api/brands/{brandId}/allow-domains GET brand admin Per-brand allow-domains: new signups whose email matches are auto-added to THIS brand only (not a whole org).
/api/brands/{brandId}/allow-domains POST brand admin Email-domain auto-join allowlist for this brand.
/api/brands/{brandId}/assets/{assetId}/analyze POST brand editor Re-run the POI/metadata vision pass over an asset ALREADY in the library.
/api/brands/{brandId}/assets/{assetId} GET public Intentionally public: the asset URL is a capability (unguessable UUID) — renders, the editor preview, and exported creatives all hot-link it.
/api/brands/{brandId}/assets/{assetId} DELETE brand editor Delete the asset (cascade-cleans logo-system and default-image references).
/api/brands/{brandId}/assets/{assetId} PUT brand editor Replace an asset's bytes, keeping its id / URL / name (multipart file).
/api/brands/{brandId}/assets/{assetId} PATCH brand editor Transform the asset in place.
/api/brands/{brandId}/assets/{assetId}/usage GET brand read Which of this brand's own templates + creatives reference the asset.
/api/brands/{brandId}/assets/analyze POST brand editor Analyze an uploaded image with a vision LLM and return suggested metadata for the asset-upload form.
/api/brands/{brandId}/assets/from-url POST brand editor Import a remote image URL into the brand's asset library.
/api/brands/{brandId}/assets GET brand read List assets; ?type= filters by kind, ?query= runs the same search the in-app palette uses.
/api/brands/{brandId}/assets POST brand editor Upload an asset (multipart form: file, plus optional name / type / tags / description / metadata).
/api/brands/{brandId}/boards/{boardId}/canvas PUT brand editor Persist the board's node LAYOUT — creative positions, sections, viewport.
/api/brands/{brandId}/boards/{boardId}/chat POST brand editor Board iteration chat.
/api/brands/{brandId}/boards/{boardId}/comments POST brand editor Owner/editor comment ops on the board (add / update / delete a note).
/api/brands/{brandId}/boards/{boardId}/creatives POST brand editor Attach standalone creatives to this board (explicit curation — the REST mirror of the MCP add_to_board tool).
/api/brands/{brandId}/boards/{boardId} GET brand read The board's full content manifest — every creative that landed on it (from any run), current render URLs, scores, curation, sections.
/api/brands/{brandId}/boards/{boardId} PATCH brand editor Rename and/or re-file the board: { title?, collectionId? }{ ok, board }.
/api/brands/{brandId}/boards/{boardId}/share POST brand editor POST/DELETE /api/brands/[brandId]/boards/[boardId]/share Mint or revoke the board's read-only DELIVERY LINK — a capability token that lets a non-account party (client, external …
/api/brands/{brandId}/boards/{boardId}/share DELETE brand editor POST/DELETE /api/brands/[brandId]/boards/[boardId]/share Mint or revoke the board's read-only DELIVERY LINK — a capability token that lets a non-account party (client, external …
/api/brands/{brandId}/boards GET brand read List the brand's boards (id, title, collectionId, createdAt) for pickers.
/api/brands/{brandId}/boards POST brand editor Create a board: { title?, collectionId? } → 201 { board }.
/api/brands/{brandId}/brand-config GET brand read Read the full brand config: colors, colorRoles, schemes, themes, fonts, typeStyles, design tokens, logo system, voice and knowledge.
/api/brands/{brandId}/brand-config PUT brand editor Merge-save the config — only fields present in the body are overwritten.
/api/brands/{brandId}/brand-fit/revert POST brand editor Restore a doc's elements to their pre-brand-fit state using snapshots previously returned in a BrandFitReport.undoElements.
/api/brands/{brandId}/brand-fit POST brand editor Run the deterministic brand-fit engine on a doc (system template, brand template, or ad).
/api/brands/{brandId}/collections/{collectionId}/items GET brand read List the collection's reference links.
/api/brands/{brandId}/collections/{collectionId}/items POST brand editor Link members by reference: { kind, ids }{ linked, invalid }.
/api/brands/{brandId}/collections/{collectionId}/items DELETE brand editor Remove reference links: { kind, ids }{ unlinked }.
/api/brands/{brandId}/collections/{collectionId}/merge POST brand editor Merge sourceId into this collection: { sourceId }{ collection } (the survivor).
/api/brands/{brandId}/collections/{collectionId} GET brand read The collection manifest — runs, boards, creatives, linked templates/assets.
/api/brands/{brandId}/collections/{collectionId} PATCH brand editor Rename and/or set the description: { name?, description? }{ collection }.
/api/brands/{brandId}/collections/{collectionId} DELETE brand editor Delete the collection (un-file semantics — contents survive as Unfiled).
/api/brands/{brandId}/collections GET brand read List the brand's collections, most recently updated first.
/api/brands/{brandId}/collections POST brand editor Create a collection: { name, description? }{ collection }.
/api/brands/{brandId}/color-schemes/{schemeId} PATCH brand editor partial update of a custom scheme.
/api/brands/{brandId}/color-schemes/{schemeId} DELETE brand editor remove a custom scheme.
/api/brands/{brandId}/color-schemes GET brand read list every scheme (built-in dark/light + custom).
/api/brands/{brandId}/color-schemes POST brand editor create a custom scheme.
/api/brands/{brandId}/composition/{primitive} POST brand editor Run a composition primitive against a doc.
/api/brands/{brandId}/creatives/{creativeId}/duplicate POST brand editor Duplicate a creative.
/api/brands/{brandId}/creatives/{creativeId}/elements/{elementId} PATCH brand editor Per-creative per-element patch.
/api/brands/{brandId}/creatives/{creativeId} GET brand read Read one creative — the full braaand document.
/api/brands/{brandId}/creatives/{creativeId} PUT brand editor Merge-save the creative (the editor's autosave path; optimistic concurrency via X-Doc-Version).
/api/brands/{brandId}/creatives/{creativeId} PATCH brand editor Re-file the creative into a collection (the explicit move — the ONLY thing that re-files; board placement never does).
/api/brands/{brandId}/creatives/{creativeId} DELETE brand editor Delete the creative.
/api/brands/{brandId}/creatives/{creativeId}/to-pipeline POST brand editor "Open in node editor" — clone the creative into a fresh, IDLE workflow run seeded with a single Source node, then hand back the run id so the client can route to the pipeline ed…
/api/brands/{brandId}/creatives GET brand read List the brand's creatives — full rows (filterable/sortable), or ?summary=1 for { creatives: CreativeSummary[] } picker rows with content-hashed preview thumbs.
/api/brands/{brandId}/creatives POST brand editor Create a creative: clone a brand template ({ templateId, name }) or mint a blank one ({ empty: true }).
/api/brands/{brandId}/design-system GET brand read Export the brand's "design system light" as a { path: content } file map: styles.css (entry, with a Tailwind 4 @theme block) + tokens/*.css + optional tokens/fonts.css
/api/brands/{brandId}/fonts GET brand read Brand font config (families, weights, embedded sources) for API consumers.
/api/brands/{brandId}/images/jobs/{jobId} GET brand read Snapshot of a single image-gen job (status / phase / finished asset card).
/api/brands/{brandId}/members/{userId} PUT brand admin (user auth only — brand tokens not accepted) Change a collaborator's role.
/api/brands/{brandId}/members/{userId} DELETE brand admin (user auth only — brand tokens not accepted) Remove a collaborator.
/api/brands/{brandId}/members GET brand admin (user auth only — brand tokens not accepted) List the brand's collaborators.
/api/brands/{brandId}/members POST brand admin (user auth only — brand tokens not accepted) Invite a collaborator.
/api/brands/{brandId}/pipeline-templates/{templateId} GET brand read one recipe.
/api/brands/{brandId}/pipeline-templates/{templateId} PUT brand editor one recipe.
/api/brands/{brandId}/pipeline-templates/{templateId} DELETE brand editor one recipe.
/api/brands/{brandId}/pipeline-templates/{templateId}/run POST brand editor Instantiate a recipe with bindings and either launch a durable RUN (default, spends credits) or create a DRAFT the user runs from the canvas.
/api/brands/{brandId}/pipeline-templates GET brand read List every recipe available in the brand: the built-in starters first (flagged starter), then its saved graphs, most recently updated.
/api/brands/{brandId}/pipeline-templates POST brand editor Create a pipeline template: { name, graph, variables?, description? }.
/api/brands/{brandId}/renders GET brand read List the brand's persisted renders with issuer + trigger metadata.
/api/brands/{brandId} GET brand read Read the brand row plus your role on it.
/api/brands/{brandId} PUT brand editor Rename or re-describe the brand.
/api/brands/{brandId} DELETE brand read Delete the brand — owner only, or a current org admin for team brands.
/api/brands/{brandId}/sets/{setId} GET brand read One Set with its rows.
/api/brands/{brandId}/sets/{setId} PATCH brand editor Rename a Set, re-describe it, or REPLACE its rows (wholesale, normalized).
/api/brands/{brandId}/sets/{setId} DELETE brand editor Delete a Set.
/api/brands/{brandId}/sets/person GET brand read Resolve a person by name: ?q=<name>{ resolved, row | candidates }.
/api/brands/{brandId}/sets/resolve POST brand read Resolve a For each source: { source }{ count, sample, warnings }.
/api/brands/{brandId}/sets GET brand read List the brand's Sets, most recently updated first.
/api/brands/{brandId}/sets POST brand editor Create a Set: { name, description?, rows? | csv? }{ set, warnings }.
/api/brands/{brandId}/sync-manifest GET brand read One brand's sync manifest: every text artifact (brand.json, CLAUDE.md, dist/* token builds, guidelines/*.md) with full content, plus the asset list with server-computed local pa…
/api/brands/{brandId}/templates/{templateId}/delete-group POST brand editor Removes a group from the template: drops every member element, deletes the group entry, and strips the group's id from any cluster's memberIds.
/api/brands/{brandId}/templates/{templateId}/duplicate-group POST brand editor Deep-clones the source group's elements with fresh IDs, registers a new Group entry, and appends it to parentClusterId.memberIds.
/api/brands/{brandId}/templates/{templateId}/duplicate POST brand editor Duplicate a brand template.
/api/brands/{brandId}/templates/{templateId}/elements/{elementId} PATCH brand editor Element-level patch endpoint.
/api/brands/{brandId}/templates/{templateId} GET brand read Read one brand template.
/api/brands/{brandId}/templates/{templateId} PUT brand editor Merge-save the template (optimistic concurrency via X-Doc-Version).
/api/brands/{brandId}/templates/{templateId} DELETE brand editor Delete the template (creatives cloned from it are untouched).
/api/brands/{brandId}/templates/{templateId}/usage GET brand read Which creatives were cloned from this template (the pre-delete usage check).
/api/brands/{brandId}/templates/discover GET brand read Agent-facing template discovery catalog: every template with its slots and constraints.
/api/brands/{brandId}/templates GET brand read List the brand's templates — full rows by default, or ?summary=1 for { templates: TemplateSummary[] } picker rows with content-hashed preview thumbs (theme-builder scratch f…
/api/brands/{brandId}/templates POST brand editor Create a template from scratch (name, plus optional elements / formats / variant).
/api/brands/{brandId}/theme-builder POST brand editor open the brand's single Theme Builder doc rendered as variant, and return its templateId so the client can route into the editor.
/api/brands/{brandId}/themes/{themeId}/preview GET brand read Renders the theme-builder specimen in the theme's styling, one tonal side, just like any other preview (blob-cached via getOrRenderPreview, content- hashed so theme edits bust i…
/api/brands/{brandId}/themes/{themeId} PATCH brand editor partial update of a custom theme.
/api/brands/{brandId}/themes/{themeId} DELETE brand editor remove a custom theme.
/api/brands/{brandId}/themes GET brand read list every theme (the implicit Default + custom).
/api/brands/{brandId}/themes POST brand editor create a custom theme.
/api/brands/{brandId}/tokens/{tokenId} DELETE brand admin (user auth only — brand tokens not accepted) Revoke one brand token.
/api/brands/{brandId}/tokens GET brand admin (user auth only — brand tokens not accepted) List the brand's tokens — prefix and role only, never the secret.
/api/brands/{brandId}/tokens POST brand admin (user auth only — brand tokens not accepted) Mint a brand token ({ name, role, expiresInDays? }) — the bt_ secret is returned once.
/api/brands/{brandId}/transfer POST brand owner (user auth only — brand tokens not accepted) Move a brand between pools: into a Team (shared org pool) or back to the owner's personal account.
/api/brands GET user auth The caller's brands — list them, or create an empty brand (bulk onboarding is POST /api/onboard).
/api/brands POST user auth The caller's brands — list them, or create an empty brand (bulk onboarding is POST /api/onboard).

Factory (workflows)

Route Method Auth What it does
/api/brands/{brandId}/factory/crunch POST brand editor The "pre-run" the Crunch & match button kicks off: digest the (possibly long / messy) brief into ONE clean, structured brief + extracted goal / audience / tone / message, which …
/api/brands/{brandId}/factory/drafts POST brand editor Give an unsaved canvas a home.
/api/brands/{brandId}/factory/jobs GET brand read The live per-brand Factory table rows — running jobs first, with status, phase, creatives, nodes, creator, and attributed credit cost.
/api/brands/{brandId}/factory/run-build POST brand editor The canvas head Run.
/api/brands/{brandId}/factory/workflows/{workflowId}/apply POST brand editor Run a terminal ACTION node (Delete / Board) in place: apply it to the creatives wired into it.
/api/brands/{brandId}/factory/workflows/{workflowId}/edit-node POST brand editor In-place "Run edit" — the Edit node's interactive Run.
/api/brands/{brandId}/factory/workflows/{workflowId}/foreach-node POST brand editor Interactive "Run for each" — the For each node's per-node Run.
/api/brands/{brandId}/factory/workflows/{workflowId}/launch POST brand editor Run the CURRENT pipeline graph of an EXISTING workflow run DURABLY, server-side.
/api/brands/{brandId}/factory/workflows/{workflowId}/log GET brand read The run's shareable log (markdown by default, ?format=json for structured data, ?io=1 to include each stage's exact model input/output).
/api/brands/{brandId}/factory/workflows/{workflowId}/manifest GET brand read The workflow delivery manifest — the OUTBOUND surface for external orchestrators (Workflow Brain) and coding agents.
/api/brands/{brandId}/factory/workflows/{workflowId}/materialize-seeds POST brand editor Materialize a Source node's picked seeds into THIS run, interactively.
/api/brands/{brandId}/factory/workflows/{workflowId}/materialized GET brand read The exploded per-creative view of a run — produce expanded into one branch per creative, each branch's stages (copy/image/fit) joined with the step ledger.
/api/brands/{brandId}/factory/workflows/{workflowId}/pipeline PUT brand editor PUT — replace the run's authoring graph wholesale.
/api/brands/{brandId}/factory/workflows/{workflowId}/pipeline PATCH brand editor PATCH — apply a DELTA to the stored graph (add / set / remove / connect / disconnect), instead of replacing it wholesale.
/api/brands/{brandId}/factory/workflows/{workflowId}/rerun POST brand editor Addressable per-stage re-run — the heart of "fine tune a creative run".
/api/brands/{brandId}/factory/workflows/{workflowId} GET brand read hydrate the run status page.
/api/brands/{brandId}/factory/workflows/{workflowId} PATCH brand editor Rename: { title: string } — an empty/whitespace title clears the override so the display name falls back to the brief-derived workflowTitle.
/api/brands/{brandId}/factory/workflows/{workflowId} DELETE brand editor ?creatives=delete also deletes the run's creatives; ?creatives=keep (default) deletes only the run row and leaves the creatives in the gallery, grouped by their workflow label.
/api/brands/{brandId}/factory/workflows/{workflowId}/route POST brand editor In-place "Run route" — resolve a Route node's yes/no QUESTION rules for a set of the run's creatives RIGHT NOW (render + vision pass), caching each answer as an annotation so th…
/api/brands/{brandId}/factory/workflows/{workflowId}/score POST brand editor In-place "Run score" — render + critique a set of the run's creatives RIGHT NOW (e.g.
/api/brands/{brandId}/factory/workflows/{workflowId}/stream GET brand editor Server-sent events stream for workflow pipeline progress.
/api/brands/{brandId}/factory/workflows/{workflowId}/translate-node POST brand editor Interactive "Run translate" — the Translate node's per-node Run.
/api/brands/{brandId}/factory/workflows/{workflowId}/variation POST brand editor In-place "Run variation" — clone + transform the run's base creatives on an axis, minting variants RIGHT NOW on the existing run (no full pipeline rebuild).
/api/brands/{brandId}/factory/workflows POST brand editor Create a workflow run AND start its durable workflow (the executor runs independent of any viewer; the run status page's SSE stream reads its progress).

Rendering

Route Method Auth What it does
/api/render/batch POST brand read via body brandId + rate limit Batch-render a list of creatives × their formats.
/api/render POST brand read via body brandId + rate limit Render any persisted braaand document (creative, brand template, or system template) to PNG.
/api/renders/{renderId} GET public Download a persisted render PNG.

Previews

Route Method Auth What it does
/api/previews/{tier}/{id}/{filename} GET brand read OR dt_ share token (?t=) Lazy-rendered WebP preview cache.
/api/previews/warm POST HMAC-signed self-request (PREVIEW_WARM_SECRET) Render-on-write warm endpoint.

System templates

Route Method Auth What it does
/api/system-templates/{templateId}/elements/{elementId} PATCH admin Element-level patch endpoint for system templates.
/api/system-templates/{templateId}/instantiate POST brand editor via body brandId Note: this route gets brandId from the request body, not the URL — withBrandAccess is URL-params-only by design, so the access check stays manual here.
/api/system-templates/{templateId} GET public One system template — public read (catalog), admin merge-save and delete.
/api/system-templates/{templateId} PUT admin One system template — public read (catalog), admin merge-save and delete.
/api/system-templates/{templateId} DELETE admin One system template — public read (catalog), admin merge-save and delete.
/api/system-templates GET public System template catalog — public list (the picker reads it), admin create (full body or scaffoldFrom an existing template).
/api/system-templates POST admin System template catalog — public list (the picker reads it), admin create (full body or scaffoldFrom an existing template).

System assets

Route Method Auth What it does
/api/system-assets/{id} GET public System asset serving route.
/api/system-assets/{id} PATCH admin Update a DB-backed system asset's fields (admin-only).
/api/system-assets/{id} PUT admin Replace a DB-backed system asset's bytes, keeping its id / URL / name (admin-only).
/api/system-assets/{id} DELETE admin Delete a DB-backed system asset (admin-only).
/api/system-assets/{id}/usage GET admin Which system templates use this system asset.
/api/system-assets/analyze POST admin Analyze an admin-library upload with the vision LLM and return suggested metadata (name, tags, content description, POI, brightness…) for the upload form.
/api/system-assets GET public Shared admin/system asset library listing endpoint.
/api/system-assets POST admin Upload an asset into the shared admin library.

Onboarding

Route Method Auth What it does
/api/onboard/blob-upload POST user auth Client-upload token route for in-app onboarding.
/api/onboard/from-files POST user auth Streamed in-app onboarding from dropped brand files (guideline PDF, logos, fonts) — analyze, then create the brand.
/api/onboard POST user auth Bulk brand onboarding — brand + config + assets (+ optional website analysis) in one call; shared with the MCP onboard_brand tool.
/api/onboarding/complete POST Clerk session (writes Clerk user metadata) Mark the signed-in user's Clerk onboarding metadata complete (intent / client survey).

Account (me)

Route Method Auth What it does
/api/keys/{keyId} DELETE user auth Revoke an API key.
/api/keys GET user auth List the authenticated user's API keys.
/api/keys POST user auth Create a new API key.
/api/me/billing GET user auth Billing status for the current viewer.
/api/me/nav GET Clerk session (dual-identity nav payload) Navigation payload for the global topbar: the viewer's brands grouped by the pool that pays for them (their own account, plus each Team), and whether they're a platform admin (d…
/api/me GET user auth Return the authenticated identity.

Auth (device flow)

Route Method Auth What it does
/api/auth/device/code POST device auth flow Public endpoint.
/api/auth/device/token POST device auth flow Public endpoint.
/api/auth/device/verify POST device auth flow Authenticated endpoint.
Route Method Auth What it does
/api/share/board/{token}/approval POST dt_ share token (capability URL) The client's verdict on a delivered creative — the SECOND approval (the team already curated internally; this is the external sign-off).
/api/share/board/{token}/comments POST dt_ share token (capability URL) PUBLIC comment ops for a share-link visitor.
/api/share/board/{token} GET dt_ share token (capability URL) PUBLIC delivery manifest — the outbound surface for a non-account consumer holding a run's read-only delivery token (minted via .../runs/[workflowId]/share).

Misc

Route Method Auth What it does
/api/downloads/skill GET public Download the packaged Claude skill (public — it's the same file the learn page links; rebuilt by pnpm build:skill).
/api/images/convert POST user auth Convert / compress / resize images (deterministic sharp — no LLM, no credits) and hand back short-lived converted/ download URLs.
/api/images/edit POST user auth Apply a full image edit (crop / rotate / adjust / convert / resize) and either save the result to a brand's asset library or return a short-lived preview/download URL.
/api/images/expand POST user auth Outpaint a brand asset to a wider/taller frame (credit-metered; saves the expanded image to the brand library).
/api/images/generate POST user auth Generate an image from a prompt, or AI-edit a source image guided by a prompt + optional mask (credit-metered; deterministic post-op + save-to-library or imageops-tmp URL).
/api/images/jobs GET user auth List the caller's active + recently-settled image-gen jobs (newest first).
/api/images/jobs/run POST HMAC-signed self-request (durable image-gen worker) Detached background worker for AI image-generation jobs.
/api/models/vendors GET user auth Which model vendors are currently enabled — the node canvas reads this to filter its model pickers (the same boards-style best-effort fetch).
/api/orgs/{orgId}/domains/{domain} DELETE user auth Remove one auto-join domain from the team.
/api/orgs/{orgId}/domains GET user auth Domain auto-join is a Team-tier capability.
/api/orgs/{orgId}/domains POST user auth Team email-domain auto-join allowlist.
/api/preview-context GET brand read via query brandId Returns the upstream values needed to compute a preview-cache hash client-side (for fully-client components like the board review canvas).
/api/resolve/{entityId} GET user auth Resolve any braaand entity id to its kind, brand, and app URL.
/api GET public Agent-facing prose index of the whole REST API — the onboarding text an LLM reads when it first connects.
/api/settings/org/{orgId}/jobs GET org member (session + membership check) Live poll feed for the team (org) Factory jobs queue.
/api/sync/report POST user auth The CLI reports its local sync root + machine after each successful braaand sync, so the app and MCP sync_status can answer "where is the synced folder and how fresh is it".
/api/sync/shared GET user auth The brand-agnostic layer of the synced folder: root CLAUDE.md, the preview shell chrome, Braaand house motion presets, and vendored-script URLs.
/api/sync/status GET user auth Server side of braaand sync status: every accessible brand's sync metadata (identity version, visual hash, slug) + the caller's last-reported local sync state.
/api/workflows/running GET user auth List the caller's running + recently-settled pipeline runs (newest first).