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/apiBuilding an agent? Pick the shortest path before hand-rolling HTTP:
- MCP — connect
https://mcp.braaand.ai/mcpand 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. - The CLI —
npm i -g braaandfor 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. - The Claude skill — the packaged braaand playbook for Claude Code. See Claude skill.
- This page +
GET /api— for your own HTTP wrapper.GET /apireturns 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 (letrole, 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.txtindexes everything with deep links.
Get a key
- Go to Settings → Profile → API keys and click New key. Copy the
ae_…value right away — it's shown once and stored hashed. - Or from the terminal:
npm i -g braaand && braaand loginwalks 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/brandsA 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.pngProducing 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.
401bad or missing credentials,403not allowed,404not found,400validation,402out of credits (the body carries a machine-readablecode),507storage quota exceeded,429rate limited (with aRetry-Afterheader),409edit conflict or "run is still building". - Errors are JSON:
{ "error": "human-readable message", "code": "machine_readable_when_relevant" }. Malformed request bodies answer400 { "error": "invalid_json" }; schema failures answer400 { "error": "validation", "details": [{ "path", "message" }] }. - Edit conflicts. Templates and creatives carry a
versionnumber. Send the version your edits are based on in theX-Doc-Versionheader (or asversionin the body) and the save is compare-and-set: if someone else saved first you get a409with thecurrentVersion, 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), and16x9(1200×628) by default; each document carries its own list, so readformatsoff the doc rather than assuming. - Ids are stable strings — creatives are prefixed
crv_, keysae_, brand tokensbt_, share linksdt_. - 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. |
Share (delivery links)
| 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). |