---
slug: always-on-creative-automation
title: Always-on creative automation
outcome: "Zapier, Make, or n8n triggers generate on-brand stills via Brandiseer REST and deliver image URLs downstream (Drive, Slack, Sheets, CMS, email tools)."
category: automation
featured: true
time: "~20 to 35 min setup"
methods:
  - REST
stack:
  - name: Brandiseer
    role: Brand memory and on-brand stills via REST
    logo: /logo-b.png
    href: https://brandiseer.com
  - name: Zapier
    role: Triggers and HTTP delivery (no native Brandiseer app)
  - name: Make
    role: Scenarios and HTTP delivery (no native Brandiseer app)
  - name: n8n
    role: Workflows and HTTP delivery (no native Brandiseer app)
developerDocs: https://brandiseer.com/developers
updated: "2026-09-24"
draft: false
status: ready-to-publish
---

# Always-on creative automation

**Brandiseer + Zapier, Make, or n8n**

![Cover: a trigger generates an on-brand still and passes the image URL downstream](https://blog.brandiseer.com/use-case-assets/always-on-creative-automation/cover-always-on-creative-automation.png)

By the end of this guide you will have an always-on creative step inside the orchestrator you already run. A schedule, a new spreadsheet or Airtable row, a form webhook, or another app event calls Brandiseer REST, waits for an on-brand still, and hands the image URL to Drive, Slack, Sheets, a CMS, or an email tool.

Zapier, Make, and n8n move data. Brandiseer owns brand memory for the image step. There is no official Brandiseer app on any of the three. The integration is an HTTP Request, a webhook module, or a custom API module calling Brandiseer REST with `X-API-Key`.

> Humans briefing stills inside Slack should use [Slack creative desk](/use-cases/slack-creative-desk). Recurring captions and Buffer scheduling should use [Social media automation](/use-cases/social-media-automation). This guide does not recreate either one.

## Who it's for

- Growth and ops teams that already live in Zapier, Make, or n8n and need recurring or event-driven on-brand stills without opening a design tool
- Agencies that keep one Brandiseer Brand ID per client and want the orchestrator to route `brandId` from a column, form field, or webhook payload
- Operators who can store an API key in a credential store and would rather deliver an `imageUrl` than export files by hand

**Ideal customer profile:** a team whose trigger already exists (a Monday batch, a new row, a form submit) and whose missing piece is a brand-safe image, not another place to chat about the brief.

## Why Brandiseer in this stack

Orchestrators are good at triggers, branches, delays, and "send this URL to the next app". They do not remember a brand. Brandiseer stores the logo and visual identity once, then applies that memory on every still. Your scenario sends subject, layout, composition, and on-image text. It does not restate colours, fonts, mood, or visual style.

This is a different job from the two sibling guides:

- [Slack creative desk](/use-cases/slack-creative-desk) is a request-and-return desk. A person writes a brief in Slack and an agent posts a still back in the thread.
- [Social media automation](/use-cases/social-media-automation) writes captions and schedules posts with Buffer.
- This guide is the HTTP step in Zapier, Make, or n8n. Brandiseer returns an image URL. Your scenario decides what happens next. Brandiseer does not post, publish, or approve claims.

![Example strip: trigger event through to a finished on-brand still](https://blog.brandiseer.com/use-case-assets/always-on-creative-automation/example-strip.png)

## Stack

| Layer | Tool | Role |
| --- | --- | --- |
| Brand visuals | Brandiseer REST (prefer v2) | Generate on-brand stills. Auth header `X-API-Key: bds_...` |
| Orchestrator (pick one) | Zapier | Schedule, Webhooks by Zapier, Code or Formatter, Delay, HTTP Request |
| Orchestrator (pick one) | Make | Webhooks, watchers, or schedulers; HTTP module; Sleep and Repeater for polling |
| Orchestrator (pick one) | n8n | Webhook or Schedule Trigger, Set or Code, HTTP Request, Wait or a loop |

![Stack diagram: Zapier, Make, or n8n calling Brandiseer over HTTP](https://blog.brandiseer.com/use-case-assets/always-on-creative-automation/stack-diagram.png)

You only connect one orchestrator. The Brandiseer contract is the same on all three. Do not look for a Brandiseer Zapier app, Make app, or n8n node. None of those is the integration. Use the HTTP modules above.

**Docs:** [Developers](https://brandiseer.com/developers) · [guide/docs](https://brandiseer.com/guide/docs) · [guide/image](https://brandiseer.com/guide/image) · [Settings → API](https://brandiseer.com/settings/api)

Endpoint tables and HTTP contracts are in API reference at the end of this guide.

## How it works

Architecture, from trigger to delivered URL:

1. Something you already automate fires: a clock, a new row, a form, or another app event.
2. A Code, Formatter, or Set step normalises fields (headline, crop, `brandId`, mode, `useLogo`) and runs the prompt rewriter so style words never reach Brandiseer.
3. HTTP `POST https://brandiseer.com/api/v2/generate/async` with `X-API-Key` and the JSON body. Read `data.jobId`.
4. Wait 3 to 5 seconds, then `GET https://brandiseer.com/api/v2/jobs/:jobId` with the same key. Repeat until `data.status` is `done` or `failed`, or until the job is about 10 minutes old.
5. On `done`, pass `data.imageUrl` to the next module (Drive, Slack, Sheets, CMS, email). On `failed`, stop, surface `data.error`, and expect the credits back. Do not publish from Brandiseer. Brandiseer only returns the URL.

![Workflow infographic: trigger, normalise, async HTTP, poll, deliver imageUrl](https://blog.brandiseer.com/use-case-assets/always-on-creative-automation/workflow-infographic.png)

## What you need

- Company website URL, if the brand is not in Brandiseer yet
- Brandiseer account with at least one finished brand profile
- API key (`bds_...`) from [Settings → API](https://brandiseer.com/settings/api) or [Developers](https://brandiseer.com/developers)
- Brand ID (`bds_c_...`) for every brand the scenario may call
- Credits for the batch size you actually run (see the table in Limits & FAQ)
- One orchestrator you already use: Zapier, Make, or n8n
- A credential store on that host for the API key (Zap action headers that are not copied into a public doc, a Make connection, or n8n Credentials)
- A downstream destination for `imageUrl` (Drive, Slack, Sheets, CMS, or email)
- Optional: a sheet or Airtable base with columns for headline, crop, subject, brand, mode, and logo

## Setup

### Stage 1: Add your brand on Brandiseer

1. Go to [brandiseer.com](https://brandiseer.com). In the homepage input, enter your company website URL and click **Try My Brand**.
2. Wait about one minute while Brandiseer analyses the site and picks a logo and visuals.
3. Review those visuals carefully. They teach Brandiseer your look. Every later still is influenced by what you leave here.
4. Remove anything off-brand (partner logos, stock, irrelevant screenshots). Add campaign creatives or product photography that match the look you want.
5. Click **Add Brand**, sign up if prompted, then wait about 30 seconds for the brand profile to finish.

Agencies repeat this once per client. Do not point two clients at one Brand ID.

### Stage 2: API key and Brand ID

1. Open [brandiseer.com/developers](https://brandiseer.com/developers) or [Settings → API](https://brandiseer.com/settings/api).
2. Create an API key (`bds_...`). Put it in the orchestrator's credential store. Do not paste it into Sheets, Airtable, Slack, or a shared scenario export.
3. Copy the Brand ID (`bds_c_...`).
4. Confirm the key with `GET https://brandiseer.com/api/v1/credits` and `GET https://brandiseer.com/api/v1/brands`, header `X-API-Key`. The credits JSON includes `credits`. The brands list includes each brand `id`.
5. Optional reachability check, no key required: `GET https://brandiseer.com/api/v1/health` returns `{ "status": "ok" }`.

Read [guide/docs](https://brandiseer.com/guide/docs) and [guide/image](https://brandiseer.com/guide/image) once while you build the rewriter. Those pages are the live contract if a field name ever moves.

### Stage 3: Pick one host

Build the same HTTP contract in whichever product you already run. Prefer async plus poll on all three.

#### Zapier

1. Create a Zap. Trigger comes in Stage 4 (Schedule, Webhooks by Zapier Catch Hook, or an app event).
2. Add **Code by Zapier** (JavaScript) or **Formatter**. Map headline, crop, subject, `brandId`, mode, and `useLogo`. Run the prompt rewriter from System prompt. Stop the Zap if `needsSubject` is true.
3. Add **Webhooks by Zapier** (Custom Request) or an **HTTP Request** step.
   - Method: `POST`
   - URL: `https://brandiseer.com/api/v2/generate/async`
   - Header `X-API-Key`: the key from the credential store
   - Header `Content-Type`: `application/json`
   - Body: the JSON in API reference
4. A Zap does not jump back to an earlier step. Poll by unrolling **Delay** + GET + **Paths**, or by re-entering a Catch Hook (see API reference). For a first Zap, add **Delay** for 5 seconds, then a Webhooks or HTTP Request step:
   - Method: `GET`
   - URL: `https://brandiseer.com/api/v2/jobs/` plus `data.jobId` from the 202 response
   - Same `X-API-Key` header
5. Add **Paths**:
   - `data.status` is `done`: continue with `data.imageUrl`
   - `data.status` is `failed`: alert a human and stop
   - otherwise: **Delay** again (5 to 15 seconds) and GET once more, then Paths again. Two or three polls cover a Design still that finishes in 40 to 70 seconds. Stop well before the 10 minute expiry. If you need to follow a slow job for longer, the "still running" path should POST `jobId` back into a Catch Hook that only polls, instead of pasting dozens of Delay steps.
6. Deliver `data.imageUrl` with the next Zapier app step (Slack, Drive, Sheets, email, CMS). If the trigger was a Catch Hook and the caller is waiting, you can finish with a webhook response that returns the URL. That response is yours. It is not a Brandiseer feature.

Zapier HTTP steps often time out before Design mode finishes. Do not use sync `POST /api/v2/generate` as the default here.

#### Make

1. Start a scenario with **Webhooks**, a **Watcher**, or a **Scheduler**.
2. Map fields, then run the prompt rewriter (Make's HTTP body can use the mapped variables; use a code step first if you need the strip list).
3. Add the **HTTP** module.
   - Method: `POST`
   - URL: `https://brandiseer.com/api/v2/generate/async`
   - Headers: `X-API-Key` and `Content-Type: application/json`
   - Body: the JSON in API reference
4. Add a **Repeater**. Inside it, add **Sleep** for 3 to 5 seconds, then a second **HTTP** module: `GET` `https://brandiseer.com/api/v2/jobs/` plus the `jobId` you mapped from `data.jobId`, with the same API key. Design stills often finish within 70 seconds, so start around 15 to 20 repeats and do not run past the 10 minute job life.
5. After the repeater, use a **Router** on `data.status`. Keep the bundle where status is `done` or `failed`. Intermediate "still running" bundles should not trigger delivery.
6. On `done`, pass `data.imageUrl` into the next Make modules. On `failed`, stop. There is no Brandiseer Make app to install.

#### n8n

1. Add a **Webhook** node or a **Schedule Trigger**.
2. Add a **Set** node or a **Code** node. Map fields and run the prompt rewriter. If `needsSubject` is true, stop on an error output.
3. Add an **HTTP Request** node.
   - Method: `POST`
   - URL: `https://brandiseer.com/api/v2/generate/async`
   - Header `X-API-Key` from n8n Credentials (do not hard-code the key in a workflow JSON you commit)
   - Body: the JSON in API reference
4. Add a **Wait** node for 3 to 5 seconds.
5. Add an **HTTP Request** node: `GET` `https://brandiseer.com/api/v2/jobs/` plus `data.jobId`, same credential.
6. Add an **IF** node:
   - `data.status` equals `done`: continue
   - `data.status` equals `failed`: error branch
   - else: connect back to **Wait** if your canvas allows that cycle. If it does not, call this workflow again (Execute Workflow, or a Webhook that only polls) with the same `jobId`, and stop at about 10 minutes.
7. Optional next nodes: Slack, Google Drive, or Google Sheets. Send `data.imageUrl` only.

### Stage 4: Choose a trigger

Use one trigger to start. Add others after the smoke test.

- **Schedule.** Zapier Schedule, Make Scheduler, or n8n Schedule Trigger. Example: Monday 08:00 local time, read rows marked ready, generate one still per row, write the URL back. Cap the batch so a mistake cannot spend the whole credit balance.
- **New row.** Google Sheets or Airtable "new row" trigger. Columns: subject, headline, crop, brandId (or a brand name you map), mode, useLogo.
- **Form webhook.** Point the form at Webhooks by Zapier Catch Hook, a Make webhook, or an n8n Webhook. Map the form JSON onto the same fields. Treat the output as a draft URL, not a published page.

### Stage 5: Smoke test

1. `GET https://brandiseer.com/api/v1/health` and expect `{ "status": "ok" }`.
2. `GET https://brandiseer.com/api/v1/credits` with `X-API-Key` and note `credits`.
3. `GET https://brandiseer.com/api/v1/brands` and confirm your Brand ID is present.
4. Run one async job with a layout-only prompt (the Spring drop example in API reference). Use `mode: design` so you prove the poll, not only a fast sync call.
5. Confirm the loop stops on `data.status` `done`, and that `data.imageUrl` arrives in the downstream step (a sheet cell, a Slack message, or a Drive upload of that URL).
6. Send a second brief that only says "make it premium and moody". The rewriter should strip that, and the scenario should ask for a subject instead of generating.

## Prompting rules for Brandiseer images

When the scenario builds `prompt`:

- Keep subject, layout, composition, and on-image text (what the words say and where they sit).
- Never send brand colours, fonts, mood, or visual style. Brand memory already applies those. Style words fight the brand and produce off-brand stills.
- Put crop in `aspectRatio`, quality in `mode`, pixel size in `resolution`, and logo on/off in `useLogo`. Those are body fields, not prompt prose.
- Prefer `design` for finished stills, and call it through async on these hosts. `fast` is the API default if you omit `mode`, and it is the right fallback if a design job fails once.
- Set `useLogo` true only when the trigger asked for a logo (or your default says so).
- Full rules: [Prompt compatibility](https://brandiseer.com/guide/image).

## System prompt

Zapier, Make, and n8n do not load an agent system prompt for this flow. Paste the rewriter below into Code, Formatter, Set, or an n8n Code node. Field mapping, example JSON, and polling steps are in API reference. MCP system prompts belong on agent hosts, not on these HTTP modules.

### Prompt rewriter

Paste this into Zapier Code, a Make code step, or an n8n Code node. It does not call Brandiseer. It only cleans text before you put it in `prompt`. The word list is a starting filter, not an official dictionary. If a phrase still describes colour, type, mood, or look, delete it by hand.

```javascript
// Local rewriter for Zapier Code, Make, or n8n Code.
// Keeps subject, layout, composition, and on-image text.
// Strips colour, type, mood, and visual-style language.

const STYLE_WORDS =
  /\b(colou?rs?|palette|hex|fonts?|typefaces?|typography|serif|sans-serif|moods?|vibes?|aesthetics?|minimalist|luxury|playful|cinematic|pastel|neon|gradients?|moody|elegant|on-brand)\b/gi;

const CROP_TO_RATIO = {
  "1:1": "1:1",
  square: "1:1",
  feed: "1:1",
  "16:9": "16:9",
  landscape: "16:9",
  banner: "16:9",
  "9:16": "9:16",
  story: "9:16",
  reel: "9:16",
  portrait: "9:16",
  "4:3": "4:3",
  slide: "4:3",
};

function rewriteBrandiseerPrompt(input) {
  const headline = String(input.headline || "").trim();
  const subject = String(input.subject || input.brief || "").trim();
  const cropKey = String(input.crop || "").trim().toLowerCase();
  const aspectRatio = CROP_TO_RATIO[cropKey] || "";

  let prompt = [subject, headline ? `On-image text: "${headline}".` : ""]
    .filter(Boolean)
    .join(" ");

  prompt = prompt
    .replace(/#[0-9a-f]{3,8}\b/gi, " ")
    .replace(STYLE_WORDS, " ")
    .replace(/\s+/g, " ")
    .trim();

  return {
    prompt,
    aspectRatio,
    needsSubject: prompt.length < 12 || !aspectRatio,
  };
}
```

If `needsSubject` is true, notify a human and do not POST. An empty or style-only brief has nothing physical to put in frame.

## Example flows

### Flow A: Schedule batch

Monday 08:00, the scenario reads up to 10 sheet rows flagged ready. Each row runs the rewriter, then one async Design job, then a poll. The URL is written back to that row. Each Design 2K still costs 6 credits, so 10 rows cost 60 if all succeed. Failures refund. If `GET /api/v1/credits` shows fewer credits than the batch needs, skip the run.

### Flow B: New Airtable or Sheets row

A new row triggers the scenario. Columns: subject, headline, crop, brandId, mode, useLogo. The rewriter fills `prompt` and `aspectRatio`. Async POST, poll, then write `data.imageUrl` into an `imageUrl` column. Leave a `status` column for your own workflow (`draft`, `approved`). That column is not a Brandiseer field.

### Flow C: Webhook from a form

The form posts subject, headline, crop, and a brand key to a Catch Hook (Zapier), a Make webhook, or an n8n Webhook. Map those fields, generate async, and email the requester the `imageUrl` or store it as a CMS draft. Do not flip the CMS entry to published in the same run.

### Flow D: Slack notify after generate

After `data.status` is `done`, a Slack step posts the brand id, mode, aspect ratio, and `data.imageUrl` to a channel. Brandiseer is not posting to Slack. The orchestrator is. This is a notification, not [Slack creative desk](/use-cases/slack-creative-desk). People who need to brief from Slack should use that guide instead of turning this scenario into a chat bot.

### Flow E: Credit check before a burst

Before Flow A, call `GET https://brandiseer.com/api/v1/credits` with `X-API-Key` and read `credits`. Compare it with a soft limit you choose (for example 40). Below the limit, do not start the batch. A later `402` on a single generate means that call was refused for insufficient credits. `GET /api/v1/usage` is a browser session endpoint. Do not call it from Zapier, Make, or n8n.

## Add-ons

Add these in the orchestrator after the smoke test passes. They do not change Brandiseer's image contract.

### Approval gate

After `imageUrl` exists, send a Slack message or an email with the URL and wait for an explicit approve action (a Slack reaction, a button, or a reply from a named reviewer). Only then run a publish, CMS, or send step. Until that happens, label the asset as a draft. Brandiseer does not approve legal claims or offers.

### Multi-brand routing

Keep a table in the scenario: brand name to `bds_c_...`. Require a brand token on every row when more than one Brand ID exists. Look the token up before the POST. If it misses, stop and list the names you configured. Confirm ids with `GET /api/v1/brands`. Never fall through to another client's Brand ID.

### Credit soft-limit

Same check as Flow E, installed as a permanent first branch. When `credits` is under your threshold, switch queued jobs to `mode: fast` and `resolution: 1K`, or skip them. Fast at 1K costs 4 credits. An explicit "run anyway" flag on the row can override the skip. The threshold is yours, not a Brandiseer default.

### Drive or Sheets logging

Append a row on every attempt: time, `brandId`, `mode`, `aspectRatio`, `resolution`, `data.status`, `data.imageUrl` (blank on failure), `data.creditsUsed` when the job body includes it, and `data.error.message` on failure. Upload the file to Drive only if your Drive step can fetch the URL. Brandiseer does not write to your Drive.

### Handoff to the sibling guides

- Approved stills that need a person to brief the next crop in Slack: [Slack creative desk](/use-cases/slack-creative-desk).
- Approved stills that need captions and a Buffer schedule: [Social media automation](/use-cases/social-media-automation).

Do not embed Buffer scheduling or a Slack desk agent inside this HTTP scenario.

### Optional motion (v2.1, not the MVP)

Video is image-to-video only. Generate the still first, then send its public `imageUrl` to `POST https://brandiseer.com/api/v2.1/video/generate`. Poll `GET https://brandiseer.com/api/v2.1/video/jobs/:jobId`. Video jobs use `status` `completed` and a `videoUrl`, which is a different contract from image jobs (`done` and `imageUrl`). Read [guide/video](https://brandiseer.com/guide/video) for tier, duration, and resolution before you enable this. Video credits are per second and are not the still table below. A video failure does not undo the still. Leave this branch off unless the trigger explicitly asks to animate.

## Limits & FAQ

### Is there a Brandiseer app for Zapier, Make, or n8n?

No. Use HTTP Request, Webhooks, or a custom API module against Brandiseer REST. There is no official SDK either. MCP is for agent hosts, not for these HTTP modules.

### Why do sync calls time out?

Design mode often takes 40 to 70 seconds. If the HTTP client times out under about 60 seconds, use `POST /api/v2/generate/async` and poll. That is the default for Zapier, Make, and n8n.

### Where does the API key live?

In the host credential store. Never in a sheet column, a Slack message, a form payload, or a workflow export that lands in git. Rotate the key if it leaks. Poll with the same key that submitted the job.

### What do stills cost?

Credits per still. Failures refund. Async submits deduct immediately and refund if the job fails.

| Mode | 1K | 2K | 4K |
| --- | --- | --- | --- |
| Fast | 4 | 6 | 8 |
| Design | 5 | 6 | 8 |
| Pro | 6 | 8 | 10 |

`402` means not enough credits. Pricing context: [brandiseer.com/pricing](https://brandiseer.com/pricing).

### Why is the still off-brand?

Almost always because the prompt contained colours, fonts, mood, or visual style. Strip them and generate again. See [guide/image](https://brandiseer.com/guide/image).

### Does Brandiseer publish the image?

No. Brandiseer returns `imageUrl`. Your scenario, and a human when the claim matters, decide whether it is posted, emailed, or put live. Keep a person on approval for offers, prices, and legal lines.

### How long can I poll?

About 10 minutes, then the job expires. Poll every 3 to 5 seconds. Stop on `done` or `failed` as well. Do not start a second job for the same row while the first is still open, or you will pay twice.

### Which generate URL should new scenarios use?

`POST /api/v2/generate/async` for these hosts. Legacy `POST /api/v1/generate` remains for older callers and only supports Fast and Pro via `proMode` boolean.

## Demo / motion

**Motion brief only. This is not an embed, and there is no walkthrough URL yet.**

**Working title:** Always-on creative automation
**Length:** 45 to 75 seconds

**Story beats:**

1. A schedule or a new sheet row fires in Zapier, Make, or n8n
2. The scenario shows a layout-only prompt (no colour, font, or mood words) and POSTs to Brandiseer async REST
3. The poll returns `data.status` `done` and an on-brand still
4. `imageUrl` lands in Slack, Sheets, or Drive
5. A human approves before any publish step

**On screen:** the orchestrator canvas, the HTTP module URL `https://brandiseer.com/api/v2/generate/async`, and one finished still. Blur the API key. Do not show a fake video player in the guide.

## Related use cases

- [Slack creative desk](/use-cases/slack-creative-desk): people request stills in Slack and get them back in-thread
- [Social media automation](/use-cases/social-media-automation): on-brand images, captions, and Buffer scheduling

## Links

| Resource | URL |
| --- | --- |
| Brandiseer | https://brandiseer.com |
| Developers | https://brandiseer.com/developers |
| API reference (guide/docs) | https://brandiseer.com/guide/docs |
| Image prompt compatibility | https://brandiseer.com/guide/image |
| Video prompting (optional motion) | https://brandiseer.com/guide/video |
| MCP endpoint (agent hosts only) | https://brandiseer.com/api/mcp |
| API keys | https://brandiseer.com/settings/api |
| Pricing / credits | https://brandiseer.com/pricing |
| Visual pack manifest | `assets/MANIFEST.md` |
| Sibling: Slack creative desk | https://blog.brandiseer.com/use-cases/slack-creative-desk |
| Sibling: Social media automation | https://blog.brandiseer.com/use-cases/social-media-automation |

## Source

Public Use case README for always-on creative automation. Brandiseer REST v2 image generation from Zapier, Make, or n8n HTTP modules. Aligned with [guide/docs](https://brandiseer.com/guide/docs) and [guide/image](https://brandiseer.com/guide/image) (23 September 2026). No native Brandiseer connector on those three products. Distinct from Slack creative desk and from Buffer social scheduling.

## API reference

Wiring reference for agents and HTTP modules. The sections above are the human path.

### REST (this is the Zapier, Make, and n8n path)

Send `X-API-Key: bds_...` on every authenticated call. There is no official SDK. Any HTTP client is enough.

| Call | What you get |
| --- | --- |
| `POST https://brandiseer.com/api/v2/generate` | Sync still. `200` body `{ "imageUrl", "creditsUsed" }`. Design mode often takes 40 to 70 seconds. |
| `POST https://brandiseer.com/api/v2/generate/async` | `202` body `{ "data": { "jobId" } }` (ids look like `bds_job_...`). Credits are deducted when you submit. |
| `GET https://brandiseer.com/api/v2/jobs/:jobId` | Poll every 3 to 5 seconds with the same API key. `data.status` becomes `done` or `failed`. Jobs expire after about 10 minutes. Failures refund credits. |
| `POST https://brandiseer.com/api/v1/generate` | Legacy only. `proMode` boolean. Fast and Pro only. Prefer v2. |
| `GET https://brandiseer.com/api/v1/credits` | JSON includes `credits`, the current balance for that key. |
| `GET https://brandiseer.com/api/v1/brands` | Brands for the key. Each brand `id` looks like `bds_c_...`. |
| `GET https://brandiseer.com/api/v1/health` | `{ "status": "ok" }`. No API key. |

Image body fields: `brandId`, `prompt`, optional `aspectRatio` (`1:1`, `16:9`, `9:16`, `4:3`), `resolution` (`1K`, `2K`, `4K`), `mode` (`fast`, `design`, or `pro`; default `fast` if you omit it), `useLogo`.

Sync status codes you should branch on: `200` success, `400` bad body, `401` bad key, `402` not enough credits, `404` brand not found, `500` server error.

Done job body: `{ "data": { "status": "done", "imageUrl", "creditsUsed", "referenceImage" } }`. Deliver `data.imageUrl`. Failed job body: `{ "data": { "status": "failed", "error": { "code", "message" } } }`.

Prefer async on Zapier, Make, and n8n. Their HTTP timeouts are often under 60 seconds, and Design mode often needs 40 to 70 seconds. A sync `POST /api/v2/generate` is fine only when you know the client waits long enough.

### MCP (optional, not this path)

Agent hosts such as Cursor or Claude can use `https://brandiseer.com/api/mcp` with `Authorization: Bearer` and only these tools: `brandiseer_list_brands`, `brandiseer_check_credits`, `brandiseer_generate_image`. Zapier, Make, and n8n HTTP modules do not speak MCP. Do not point those modules at the MCP URL.

### 1. Field mapping

| Incoming field | API | Rule |
| --- | --- | --- |
| headline | inside `prompt` only | On-image text and placement. Not a separate body field. |
| crop | `aspectRatio` | `1:1`, `16:9`, `9:16`, or `4:3`. Map square/feed to `1:1`, story/reel/portrait to `9:16`, banner/landscape to `16:9`, slide to `4:3`. |
| brandId | `brandId` | `bds_c_...`. Required. |
| mode | `mode` | `fast`, `design`, or `pro`. Omit and the API uses `fast`. Prefer `design` via async for finished stills. |
| useLogo | `useLogo` | `true` or `false`. |
| subject or brief | `prompt` | After the rewriter. Required in substance: if the cleaned text is empty, do not call Brandiseer. |
| resolution (optional) | `resolution` | `1K`, `2K`, or `4K`. |

### 2. Example JSON

Use this body for both sync and async. Only the URL and the response change.

```json
{
  "brandId": "bds_c_...",
  "prompt": "Square product still. Bottle centred on a table. On-image text: \"Spring drop\" in the top third. Empty corner bottom right.",
  "aspectRatio": "1:1",
  "resolution": "2K",
  "mode": "design",
  "useLogo": true
}
```

Sync: `POST https://brandiseer.com/api/v2/generate`. A Design 2K still costs 6 credits, so a success body looks like:

```json
{
  "imageUrl": "https://...",
  "creditsUsed": 6
}
```

Async (use this on Zapier, Make, and n8n): `POST https://brandiseer.com/api/v2/generate/async`. HTTP `202`:

```json
{
  "data": {
    "jobId": "bds_job_..."
  }
}
```

Poll `GET https://brandiseer.com/api/v2/jobs/bds_job_...` with the same `X-API-Key`. When it finishes:

```json
{
  "data": {
    "status": "done",
    "imageUrl": "https://...",
    "creditsUsed": 6,
    "referenceImage": null
  }
}
```

When it fails (credits are refunded):

```json
{
  "data": {
    "status": "failed",
    "error": {
      "code": "...",
      "message": "..."
    }
  }
}
```

Ignore `referenceImage` for delivery. Downstream steps get `data.imageUrl` only.

### 3. Polling steps

Repeat until `data.status` is `done` or `failed`, or until about 10 minutes have passed since the `202`. Wait 3 to 5 seconds between GETs. Use the same API key that submitted the job.

**Zapier.** After the 202, Delay about 5 seconds, GET the job, then Paths. "Done" maps `data.imageUrl` to delivery. "Failed" sends `data.error.message` to Slack or email and stops. "Still running" cannot jump backward, so add another Delay + GET + Paths, or POST the `jobId` to a Catch Hook that only polls. Two or three polls are enough for a Design still that finishes in 40 to 70 seconds. Give up at about 10 minutes.

**Make.** Sleep about 5 seconds, then HTTP GET the job, inside a Repeater. Start near 15 to 20 cycles so you cover a typical Design still without polling past 10 minutes. Router: `done` continues, `failed` stops, anything else is not delivered.

**n8n.** Wait 3 to 5 seconds, HTTP Request GET, IF on `data.status`. Wire the incomplete branch back to Wait when the editor allows it. Otherwise re-call the workflow with the same `jobId` and stop at about 10 minutes. Do not use the MCP URL as the HTTP Request URL.
