---
slug: airtable-record-visuals
title: Airtable record visuals
outcome: "An agent generates on-brand stills with Brandiseer for Airtable records (campaign cards, product thumbs, content calendar covers, launch creatives); a person then attaches those files in an Airtable attachment field, or an agent with an Airtable personal access token writes the public imageUrl into that field. Brandiseer does not create Airtable bases and does not sync records by itself."
category: creative-mcp
featured: true
time: "~25 to 40 min setup"
methods:
  - MCP
  - REST
hosts:
  - Cursor
  - Cowork
stack:
  - name: Brandiseer
    role: Brand memory and on-brand stills via MCP or REST
    logo: /logo-b.png
    href: https://brandiseer.com
  - name: Airtable
    role: Attachment fields on records (campaign, product, content calendar)
    href: https://airtable.com
  - name: Cursor
    role: Agent host for Brandiseer MCP or REST (optional Airtable API write)
  - name: Claude Cowork
    role: Agent host for Brandiseer MCP or REST (optional Airtable API write)
developerDocs: https://brandiseer.com/developers
updated: "2026-09-29"
draft: false
status: ready-to-publish
---

# Airtable record visuals

**Brandiseer + Airtable (+ Cursor or Claude Cowork)**

![Cover: an on-brand still landing in an Airtable attachment cell](https://blog.brandiseer.com/use-case-assets/airtable-record-visuals/cover-airtable-record-visuals.png)

By the end of this guide you will have a repeatable way to make on-brand stills for Airtable records. An agent in Cursor or Claude Cowork calls Brandiseer, gets an `imageUrl` for a campaign hero, a product thumb, a content calendar cover, or a launch still, and that file is attached on the record.

Brandiseer owns the brand memory and the still. Airtable owns the base, the record, and the attachment field. Brandiseer returns `imageUrl` only. It does not create bases, does not sync records, and does not host an Airtable integration. The default handoff is a person: download the file (or open `imageUrl`) and upload it into the Attachment field. Optionally, an agent that already holds an Airtable personal access token can write that public URL into the field, or upload the file bytes when the file is 5 MB or smaller. A person still decides which record is final.

> People who brief 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). Schedules and webhooks in Zapier, Make, or n8n should use [Always-on creative automation](/use-cases/always-on-creative-automation). Webflow site stills should use [Webflow site visuals](/use-cases/webflow-site-visuals). WordPress Media Library stills should use [WordPress site visuals](/use-cases/wordpress-site-visuals). Framer site stills should use [Framer site visuals](/use-cases/framer-site-visuals). This guide does not recreate any of those.

## Who it's for

- Marketing and ops teams who already keep campaigns, products, or a content calendar in Airtable and need an on-brand still on the record without opening a separate design tool for every row
- Agencies that keep one Brandiseer Brand ID per client and one Airtable base (or a named set of bases) per client
- Operators who can download an `imageUrl` and drop it on an Attachment field, or who already give an agent an Airtable personal access token and want that agent to write the public URL into a named field

**Ideal customer profile:** a team whose records already live in Airtable, whose brand already lives in Brandiseer, and whose missing piece is a brand-safe still plus a clear handoff into an Attachment field.

## Why Brandiseer in this stack

Airtable is where the record lives. Cursor or Cowork is the agent that turns a record brief into a still. Brandiseer stores the logo and visual identity once, then applies that memory on every still. The prompt carries subject, layout, composition, and on-image text. It does not restate colours, fonts, mood, or visual style.

A content calendar drifts when every cover is a one-off export from a general image tool. Brandiseer keeps the still on the same brand as the rest of the campaign. Airtable still decides which record and which Attachment field hold the file.

This is a different job from the 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.
- [Always-on creative automation](/use-cases/always-on-creative-automation) is the HTTP step in Zapier, Make, or n8n.
- [Webflow site visuals](/use-cases/webflow-site-visuals) hands `imageUrl` into Webflow Assets or CMS image fields.
- [WordPress site visuals](/use-cases/wordpress-site-visuals) hands `imageUrl` into the WordPress Media Library.
- [Framer site visuals](/use-cases/framer-site-visuals) hands `imageUrl` into Framer Assets, the canvas, or a CMS image field.
- This guide generates record stills and hands `imageUrl` to an Airtable Attachment field. Brandiseer does not push into Airtable by itself.

![Example strip: campaign hero, product thumb, calendar cover, and launch still](https://blog.brandiseer.com/use-case-assets/airtable-record-visuals/example-strip.png)

## Stack

| Layer | Tool | Role |
| --- | --- | --- |
| Brand visuals | Brandiseer MCP and/or REST v2 | Generate on-brand stills. MCP uses `Authorization: Bearer`. REST uses `X-API-Key: bds_...` |
| Agent host (pick one) | Cursor | Read the record brief, call Brandiseer, return `imageUrl` and an attachment note. Optional Airtable API write |
| Agent host (pick one) | Claude Cowork | Same contract as Cursor for interactive record stills |
| Records | Airtable | Attachment fields on campaign, product, content calendar, and launch records. A person uploads by default |

![Stack diagram: Cursor or Cowork, Brandiseer, and Airtable attachment fields](https://blog.brandiseer.com/use-case-assets/airtable-record-visuals/stack-diagram.png)

You only need one agent host. The Brandiseer contract is the same on both. There is no Brandiseer Airtable app that drops a still onto a record. The handoff is an image URL, a download, or an Airtable Web API write that you perform with Airtable's own API. This guide does not use an Airtable MCP. Do not invent one.

**Brandiseer 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)

**Airtable docs:** [Authentication](https://airtable.com/developers/web/api/authentication) · [Personal access tokens](https://airtable.com/create/tokens) · [Attachment field model](https://airtable.com/developers/web/api/field-model#multipleattachment) · [Update record](https://airtable.com/developers/web/api/update-record) · [Create records](https://airtable.com/developers/web/api/create-records) · [Get record](https://airtable.com/developers/web/api/get-record) · [Upload attachment](https://airtable.com/developers/web/api/upload-attachment)

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

### Airtable (placement, not generation)

Three practical paths. Use the first one until an API write is actually needed.

1. **Attachment field in the Airtable UI (default).** Download the file or open `imageUrl`. On the record, upload it into the Attachment field the human named (campaign hero, product thumb, calendar cover, or launch still). Brandiseer stops at the URL. Airtable stores its own file.
2. **Web API URL write (optional).** When creating or updating a record, set the Attachment field to an array of objects with a public `url`. Airtable fetches that file. A new object needs `url`. `filename` is optional. The field type is `multipleAttachments`. See the [field model](https://airtable.com/developers/web/api/field-model#multipleattachment). This is an Airtable call with the human's token. It is not a Brandiseer push.
3. **Web API bytes upload, 5 MB or smaller (optional).** `POST https://content.airtable.com/v0/{baseId}/{recordId}/{attachmentFieldIdOrName}/uploadAttachment` with `contentType`, a base64 `file`, and `filename`. Use this when you have the bytes and the file is within the 5 MB limit on that endpoint. Larger files that Airtable can fetch from a public URL use path 2. See [Upload attachment](https://airtable.com/developers/web/api/upload-attachment).

Attachment URLs that Airtable returns on a read expire about 2 hours after the response. Do not save those URLs as the durable copy. The durable file, until someone attaches it, is the Brandiseer `imageUrl`.

## How it works

Architecture, from record brief to a still sitting on an Airtable record:

1. You store the brand once in Brandiseer (logo and reference visuals teach the look).
2. The agent host (Cursor or Cowork) has Brandiseer MCP or REST, the Brand ID (`bds_c_...`), and the standing instructions in this guide.
3. You name the slot: campaign hero, product thumb, calendar cover, or launch still. The agent rewrites that brief into subject, layout, and on-image text, then sets `aspectRatio`, `resolution`, `mode`, and `useLogo` as fields.
4. Brandiseer returns `imageUrl`. The agent reports the URL, the crop, the mode, and a one-line attachment note (which base, table, record, and Attachment field it is for). It does not claim the record changed unless an Airtable write you actually performed returned success.
5. A person uploads the file into the Attachment field, or an agent with a personal access token writes the public `imageUrl` (or uploads the bytes). A person reviews the record when the creative is ready.

![Workflow infographic: brief, Brandiseer still, imageUrl, Airtable attachment field, human reviews](https://blog.brandiseer.com/use-case-assets/airtable-record-visuals/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 agent may call
- Credits for the stills you actually generate (see the table in Limits & FAQ)
- Cursor or Claude Cowork, with Brandiseer MCP or a way to call REST
- An Airtable base you can edit, with an Attachment field on the table that holds the records
- The base, table, record, and Attachment field name (or field id) for any row you want updated. Read them from Airtable. Do not guess names
- Optional, only for API writes: an Airtable personal access token with scope `data.records:write`, created at [airtable.com/create/tokens](https://airtable.com/create/tokens). Add only the bases the human named. The user who owns the token needs editor access on those bases. See [Authentication](https://airtable.com/developers/web/api/authentication)
- Optional, only when an API write must keep files already on the cell: also grant `data.records:read`, because a write replaces the attachment array and you have to read the current objects first. See [Get record](https://airtable.com/developers/web/api/get-record)
- Store the Airtable token in the agent secret store. Never in a record, a prompt you commit, Slack, or git

## 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 Airtable 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 client bases 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 agent host's secret store. Do not paste it into an Airtable field, a page, Slack, or a git repo.
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 write the standing instructions. Those pages are the live contract if a field name ever moves.

### Stage 3: Connect Brandiseer to the agent host

Use Cursor or Cowork. One host is enough.

**A. MCP**

1. Add the Brandiseer MCP server at `https://brandiseer.com/api/mcp`.
2. Authenticate with `Authorization: Bearer` and the API key, in the secret field your host provides.
3. Confirm the tool list shows `brandiseer_list_brands`, `brandiseer_check_credits`, and `brandiseer_generate_image`. If a fourth Brandiseer tool appears, ignore it until [guide/docs](https://brandiseer.com/guide/docs) documents it.

**B. REST**

1. On [Developers](https://brandiseer.com/developers), open **View Docs** and use **Copy for LLM** if you want the reference inside the session.
2. Tell the agent to prefer `POST https://brandiseer.com/api/v2/generate` or `POST https://brandiseer.com/api/v2/generate/async` with `X-API-Key`.
3. If Design mode times out, switch that call to async and poll `GET https://brandiseer.com/api/v2/jobs/:jobId` every 3 to 5 seconds.

### Stage 4: Save the standing instructions

1. Paste the **System prompt** from this guide into the Cursor rule or Cowork instructions that will run record stills.
2. Fill the defaults the prompt asks for: Brand ID, default crops per slot, resolution, mode, and whether `useLogo` is on when the brief is silent.
3. If API writes are in scope, also fill the Airtable base id, table id or name, and Attachment field name. Leave the token in the secret store.
4. Ask the agent to call `brandiseer_list_brands` (or `GET /api/v1/brands`) and confirm the Brand ID exists before the first paid still.

### Stage 5: Smoke test a campaign hero in the Attachment field

1. Ask for one campaign hero with a layout-only brief (the Spring hero in Example flows).
2. Confirm the agent checked the brand, avoided colour and mood words, and returned `imageUrl` plus crop and mode.
3. Open the Airtable record, upload that file into the Attachment field, and confirm the thumbnail shows.
4. Leave the row unmarked as approved if you are only proving the handoff.
5. Send a second brief that only says "make the hero premium and moody". The agent should ask what is physically in the frame instead of generating.

### Stage 6: Optional Airtable API write

Skip this stage if people will attach stills by hand. Use it only when a personal access token is already in the secret store and the human named the base.

1. Create the token at [airtable.com/create/tokens](https://airtable.com/create/tokens) with scope `data.records:write`. Add `data.records:read` only if the agent must keep attachments already on the cell. Limit the token to the bases the human named. The token acts as that user, so the user needs editor access on the base. Do not share the token with a third-party service. Brandiseer is not that service.
2. Send Airtable calls with `Authorization: Bearer` and the token, over HTTPS. Do not pass the token as a legacy `api_key` query parameter. Airtable does not support that.
3. **URL write.** `PATCH https://api.airtable.com/v0/{baseId}/{tableIdOrName}/{recordId}` with a `fields` object. Set the Attachment field to an array of objects. A new file is `{ "url": "<public imageUrl>", "filename": "campaign-hero.png" }`. Airtable fetches `url`. Use `PATCH`, not `PUT`. `PUT` clears every cell you do not send. The attachment array you send still replaces that one field. To keep files already there, `GET` the record first and send the full existing attachment objects plus the new `{ "url" }` object. Airtable's scripting reference states that shape: new items need `url` (optional `filename`); an existing item must be the full object. See [cell values](https://airtable.com/developers/scripting/api/cell_values) and the [field model](https://airtable.com/developers/web/api/field-model#multipleattachment).
4. **Bytes upload.** Only when the file is 5 MB or smaller. `POST https://content.airtable.com/v0/{baseId}/{recordId}/{attachmentFieldIdOrName}/uploadAttachment` with JSON `contentType`, base64 `file`, and `filename`. Same bearer token and `data.records:write` scope.
5. Confirm the response record shows the new attachment, and that `details.reasons` does not include `attachmentsFailedUploading` or `attachmentUploadRateIsTooHigh`. Then stop. A person reviews the record. Do not treat an Airtable read URL as durable. Those URLs expire about 2 hours after Airtable returns them.

## Prompting rules for Brandiseer images

When the agent 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.
- Map the Airtable slot to a documented ratio. Campaign hero: `16:9`. Product thumb: `1:1`. Calendar cover: `16:9` or `4:3`, matching the cover the human named. Launch still: `16:9`. Portrait slots, if a record really needs one: `9:16`. Brandiseer does not offer a 1.91:1 ratio. Crop in Airtable if the gallery view is tighter than the still.
- Prefer `design` for finished record stills. `fast` is the API default if you omit `mode`, and it is the right fallback if a design job fails once.
- Prefer `1K` or `2K` for record stills unless the brief asks for `4K`. A bytes upload cannot exceed 5 MB. If the file would, use the UI upload or the public URL write instead of `uploadAttachment`.
- Set `useLogo` true only when the brief asked for a logo (or your default says so). Titles that an Airtable text field will hold should stay off the image. Say "empty region" for that area instead of describing a font.
- Full rules: [Prompt compatibility](https://brandiseer.com/guide/image).

## System prompt

Paste this into Cursor or Cowork as the standing instructions for record stills. Replace the placeholders before the first generate.

```text
You generate on-brand stills for Airtable records. Brandiseer returns an image
URL. You do not create Airtable bases, you do not sync records, and you do
not claim an Attachment field changed unless an Airtable write you actually
performed returned success.

Brandiseer:
- MCP: https://brandiseer.com/api/mcp with Authorization: Bearer.
  Tools you may call: brandiseer_list_brands, brandiseer_check_credits,
  brandiseer_generate_image. Do not invent tool names.
- REST: X-API-Key: bds_... (secret store only).
  Prefer POST https://brandiseer.com/api/v2/generate
  or POST https://brandiseer.com/api/v2/generate/async
  then poll GET https://brandiseer.com/api/v2/jobs/:jobId every 3 to 5 seconds
  until data.status is done or failed, or about 10 minutes have passed.
- Live contract: https://brandiseer.com/guide/docs and
  https://brandiseer.com/guide/image
- Brandiseer does not host an Airtable integration. There is no native
  Brandiseer to Airtable app in this guide.

Defaults for this workspace (fill in once):
- Brand ID: bds_c_...
- Campaign hero aspectRatio: 16:9
- Product thumb aspectRatio: 1:1
- Calendar cover aspectRatio: ask if the cover is not known (16:9 or 4:3)
- Launch still aspectRatio: 16:9
- mode: design
- resolution: 2K (use 1K if file size or speed matters)
- useLogo when the brief is silent: false
- Multi-brand map, if any: brand name to bds_c_...
- Airtable base id, table id or name, and Attachment field name, only if
  the human already asked for an API write. Otherwise leave them blank.

On every request:
1. Resolve brandId from the brief or the default. If more than one brand
   exists and the brief does not name one, ask. Never fall through to
   another client's Brand ID.
2. Check credits before a batch (brandiseer_check_credits or
   GET https://brandiseer.com/api/v1/credits). A single still can proceed
   if the last known balance covers the mode and resolution in the table
   you were given. On 402, stop.
3. Rewrite the brief into subject, layout, composition, and on-image text.
   Strip colours, fonts, mood, and visual style. If stripping leaves no
   physical subject, ask what is in the frame. Do not generate.
4. Choose aspectRatio from the slot. Put resolution, mode, and useLogo in
   API fields, not in the prompt.
5. Generate one still. Return imageUrl, aspectRatio, mode, resolution,
   useLogo, and an attachment note: which record and which Attachment
   field the human named.
6. Do not tell the user the Airtable record changed unless an Airtable
   write you actually performed returned the new attachment without
   attachmentsFailedUploading or attachmentUploadRateIsTooHigh.

Airtable placement, only when the human already asked for it:
- Default path: the human downloads imageUrl (or opens it) and uploads it
  into the Attachment field. You do not claim that happened.
- URL write (optional): PATCH or create the record. The Attachment field
  value is an array of objects with a public url. filename is optional.
  Airtable fetches the file. Docs:
  https://airtable.com/developers/web/api/field-model#multipleattachment
  https://airtable.com/developers/web/api/update-record
  https://airtable.com/developers/web/api/create-records
- The array you send replaces that field. To keep existing files, GET the
  record first (scope data.records:read) and include the full current
  attachment objects plus the new { url } object.
- Bytes upload (optional, 5 MB max): POST
  https://content.airtable.com/v0/{baseId}/{recordId}/{attachmentFieldIdOrName}/uploadAttachment
  with contentType, base64 file, and filename.
  Docs: https://airtable.com/developers/web/api/upload-attachment
- Auth: Airtable personal access token, Authorization: Bearer, scope
  data.records:write, secret store only. Limit the token to bases the
  human named. Do not invent an Airtable MCP.
- Airtable attachment URLs returned on reads expire about 2 hours later.
  Keep imageUrl as the durable URL until the file is attached.
- imageUrl must be publicly fetchable for a URL write. If it is not, the
  human uploads the file, or you use the bytes upload when the file is
  5 MB or smaller.

Out of scope:
- Slack replies, Buffer scheduling, and Zapier, Make, or n8n scenarios.
- Webflow, WordPress, and Framer site handoffs (use those guides).
- Creating Airtable bases, tables, or fields.
- Legal approval of claims, prices, or offers printed on the image.
- GET https://brandiseer.com/api/v1/usage (browser session only).
```

### Prompt rewriter

Use this when a brief arrives as messy notes. 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 a Cursor or Cowork helper script.
// 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|premium|on-brand)\b/gi;

const SLOT_TO_RATIO = {
  campaign: "16:9",
  hero: "16:9",
  "campaign hero": "16:9",
  launch: "16:9",
  "launch still": "16:9",
  "16:9": "16:9",
  product: "1:1",
  thumb: "1:1",
  thumbnail: "1:1",
  "product thumb": "1:1",
  square: "1:1",
  "1:1": "1:1",
  calendar: "16:9",
  cover: "16:9",
  "calendar cover": "16:9",
  "4:3": "4:3",
  card: "4:3",
};

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

  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, ask the human for a subject and a slot. Do not POST. The `calendar` and `cover` keys above default to `16:9` only so a named cover can proceed. If the human has not confirmed `16:9` or `4:3`, ask before you generate.

## Example flows

### Flow A: Campaign hero, attached by a person

The brief: "Campaign hero for the spring row. Product on the left. Leave the right half empty. The record's title field will hold the headline. No logo on the image."

The agent selects the default `brandId`, sets `aspectRatio` to `16:9`, `mode` to `design`, `resolution` to `2K`, and `useLogo` to false, and returns `imageUrl`. You download the file and upload it into the campaign Attachment field on that record. You mark the row reviewed later, after the still looks right next to the title.

### Flow B: Product thumbs for a set of rows

The brief lists four products. Each one says what the object is and that the thumb is square, with the product name kept in a text field rather than on the image. The agent generates four stills, all `1:1`, and labels them with the record name. You upload each file onto its row. Four Design 2K stills cost 24 credits if all succeed. Failures refund.

### Flow C: Calendar cover via URL write, not yet approved

The content calendar already has an Attachment field. You have asked for an API write, and the token is in the secret store with `data.records:write` on that base only. The brief names a `4:3` cover. The agent generates the still, then `PATCH`es the record with an attachment array whose new object is the public `imageUrl`. You open the record, confirm Airtable fetched the file, and leave approval for a separate step. If the cell already had files, the agent read them first and sent the full existing objects plus the new URL. It did not wipe the cell.

### Flow D: Launch still

The brief: "Launch still for the announcement record. Product left of centre. On-image text Spring launch on the right. 16:9."

The agent uses `16:9` and says so in the attachment note. You upload the file into the launch Attachment field, or you leave that upload for the person who owns the row.

### Flow E: Credit check before a product set

Before Flow B, the agent calls `brandiseer_check_credits` or `GET https://brandiseer.com/api/v1/credits` and reads `credits`. Four Design 2K stills need 24 credits. If the balance is lower, it stops or switches the batch to `fast` at `1K` (4 credits each) only if you asked for that fallback. `GET /api/v1/usage` is a browser session endpoint. Do not call it from the agent.

### Flow F: Style-only brief

The brief: "Make the campaign hero feel premium and moody."

The agent does not generate. It asks which record, what is physically in the frame, whether any words must appear on the image, and whether the logo is on. Colour, font, and mood stay out of the prompt.

## Add-ons

Add these after the hero smoke test passes. They do not change Brandiseer's image contract, and they do not give Brandiseer an Airtable sync.

### Approval before the row is treated as final

After `imageUrl` is on the Attachment field, a named reviewer checks the still in Airtable. Until that happens, leave the row's status field on its current value. Brandiseer does not approve legal claims, prices, or offers. Brandiseer also does not know your status field name. Do not invent one.

### One brand per client base

Keep a table: Airtable base name, base id, Attachment field name, token secret name, and `bds_c_...`. Require a named base on every API write when more than one base exists. If the name misses, stop and list the bases you configured. Confirm Brand IDs with `GET /api/v1/brands`. Never fall through to another client's Brand ID or another base's token.

### Credit soft-limit

When `credits` is under a threshold you choose (for example 40), switch new record stills to `mode: fast` and `resolution: 1K`, or skip them. Fast at 1K costs 4 credits. An explicit "run anyway" from the human can override the skip. The threshold is yours, not a Brandiseer default.

### Placement log

Keep a short note next to the work: base, table, record, Attachment field, `brandId`, `mode`, `aspectRatio`, `resolution`, `imageUrl`, and whether a person uploaded it, a URL write attached it, or a bytes upload attached it. Brandiseer does not write this log. Airtable does not send it back to Brandiseer.

### Handoff to the sibling guides

- Stills requested in Slack, returned in a thread: [Slack creative desk](/use-cases/slack-creative-desk).
- Captions and a Buffer schedule: [Social media automation](/use-cases/social-media-automation).
- A Zapier, Make, or n8n trigger that should deliver `imageUrl` on a schedule: [Always-on creative automation](/use-cases/always-on-creative-automation).
- Webflow Assets or CMS: [Webflow site visuals](/use-cases/webflow-site-visuals).
- WordPress Media Library: [WordPress site visuals](/use-cases/wordpress-site-visuals).
- Framer Assets, canvas, or CMS: [Framer site visuals](/use-cases/framer-site-visuals).

Do not embed Buffer, a Slack desk, an always-on HTTP scenario, Webflow, WordPress, or Framer inside this Airtable guide.

### Optional motion (not the record 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. An Airtable attachment can hold the video file only after a person, or an Airtable write, puts that file on the record. Leave this off unless the brief explicitly asks to animate.

## Limits & FAQ

### Does Brandiseer update the Airtable record?

No. Brandiseer returns `imageUrl`. A person uploads that file into an Attachment field, or an agent with an Airtable personal access token writes the public URL (or the file bytes) through Airtable's Web API. None of those paths create a base or sync records by themselves.

### Is there a Brandiseer app inside Airtable?

No. There is no Brandiseer Airtable integration in this guide. Do not look for a native "send to Airtable" button on the Brandiseer side.

### Do I need an Airtable MCP?

No. This guide uses the Airtable UI, or the documented Web API with a personal access token. Do not invent an Airtable MCP tool. Brandiseer still only returns the still.

### Which Airtable calls are in this guide?

Only calls confirmed on Airtable's Web API docs:

- Create records: `POST https://api.airtable.com/v0/{baseId}/{tableIdOrName}` on [Create records](https://airtable.com/developers/web/api/create-records)
- Update a record: `PATCH https://api.airtable.com/v0/{baseId}/{tableIdOrName}/{recordId}` on [Update record](https://airtable.com/developers/web/api/update-record). Use `PATCH`. `PUT` clears cells you omit
- Read a record before you append: `GET https://api.airtable.com/v0/{baseId}/{tableIdOrName}/{recordId}` on [Get record](https://airtable.com/developers/web/api/get-record)
- Attachment write shape: array of objects with a public `url` (optional `filename`) on the [field model](https://airtable.com/developers/web/api/field-model#multipleattachment). Airtable's [scripting cell values](https://airtable.com/developers/scripting/api/cell_values) spell out that object, and they note that the array overwrites the cell
- Bytes upload, 5 MB maximum: `POST https://content.airtable.com/v0/{baseId}/{recordId}/{attachmentFieldIdOrName}/uploadAttachment` on [Upload attachment](https://airtable.com/developers/web/api/upload-attachment)

Field names, base ids, and record ids come from your base. This guide does not invent a "set campaign hero" Brandiseer endpoint.

### Where do the keys live?

The Brandiseer key (`bds_...`) and the Airtable personal access token live in the agent host's secret store. Never in an Airtable field, a Slack message, a prompt you commit, or a workflow export in git. The Airtable token needs `data.records:write` and should list only the bases the human named. Add `data.records:read` when the agent must read the current attachment array before an append. Rotate either secret if it leaks. Poll a Brandiseer job with the same Brandiseer key that submitted it. Send the Airtable token as `Authorization: Bearer`. Do not put it in the query string.

### 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).

### Why does the crop look wrong in the gallery?

Brandiseer aspect ratios are `1:1`, `16:9`, `9:16`, and `4:3`. Generate the campaign hero and the launch still at `16:9`, the product thumb at `1:1`, and the calendar cover at `16:9` or `4:3`. Crop in Airtable if that view uses a tighter frame.

### 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 slot while the first is still open, or you will pay twice.

### Which generate URL should new record work use?

`POST /api/v2/generate` when the agent host waits long enough. `POST /api/v2/generate/async` when it does not. Legacy `POST /api/v1/generate` remains for older callers and only supports Fast and Pro via `proMode` boolean.

### Do Airtable attachment URLs last?

URLs Airtable returns when you read an Attachment field expire about 2 hours after that response. Download the file if you need to keep it, or keep the Brandiseer `imageUrl` until a person or an API write has attached it. See the [field model](https://airtable.com/developers/web/api/field-model#multipleattachment).

### What if the URL write does not stick?

Check three things. The `url` must be public, because Airtable fetches it. The token must include the base and `data.records:write`, and the user must be a base editor. The response may be a partial success: `details.reasons` can include `attachmentsFailedUploading` or `attachmentUploadRateIsTooHigh`. Do not tell the human the cell updated when those reasons are present. If the file is over 5 MB, do not use `uploadAttachment`. Use the public URL write or the Airtable UI.

### Does the agent approve claims on the image?

No. If the still has a price, a discount, or a legal line, a person reads it before the row is treated as final. Brandiseer does not review the claim.

## Demo / motion

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

**Working title:** Airtable record visuals
**Length:** 45 to 75 seconds

**Story beats:**

1. A person asks Cursor or Cowork for a campaign hero with a layout-only brief
2. The agent calls Brandiseer (MCP or REST v2) and shows an on-brand still
3. `imageUrl` is uploaded into an Airtable Attachment field on the record
4. Optional cut: a calendar cover is written with the public URL through the Airtable Web API, still unapproved
5. A human reviews the row only after the still looks right next to the record fields

**On screen:** the agent transcript with the prompt (no colour or mood words), one finished still, and the Airtable grid with the attachment thumbnail. Blur the Brandiseer API key and the Airtable personal access token. Do not show a fake video player in the guide.

## Related use cases

- [Always-on creative automation](/use-cases/always-on-creative-automation): Zapier, Make, or n8n calls Brandiseer REST and delivers `imageUrl` downstream
- [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
- [Webflow site visuals](/use-cases/webflow-site-visuals): Brandiseer stills placed in Webflow Assets or CMS
- [WordPress site visuals](/use-cases/wordpress-site-visuals): Brandiseer stills placed in the WordPress Media Library
- [Framer site visuals](/use-cases/framer-site-visuals): Brandiseer stills placed in Framer Assets, on the canvas, or on a CMS image field

## 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) | https://brandiseer.com/api/mcp |
| API keys | https://brandiseer.com/settings/api |
| Pricing / credits | https://brandiseer.com/pricing |
| Airtable | https://airtable.com |
| Airtable authentication | https://airtable.com/developers/web/api/authentication |
| Airtable personal access tokens | https://airtable.com/create/tokens |
| Airtable attachment field model | https://airtable.com/developers/web/api/field-model#multipleattachment |
| Airtable scripting cell values | https://airtable.com/developers/scripting/api/cell_values |
| Airtable update record | https://airtable.com/developers/web/api/update-record |
| Airtable create records | https://airtable.com/developers/web/api/create-records |
| Airtable get record | https://airtable.com/developers/web/api/get-record |
| Airtable upload attachment | https://airtable.com/developers/web/api/upload-attachment |
| Visual pack manifest | `assets/MANIFEST.md` |
| Sibling: Always-on creative automation | https://blog.brandiseer.com/use-cases/always-on-creative-automation |
| 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 |
| Sibling: Webflow site visuals | https://blog.brandiseer.com/use-cases/webflow-site-visuals |
| Sibling: WordPress site visuals | https://blog.brandiseer.com/use-cases/wordpress-site-visuals |
| Sibling: Framer site visuals | https://blog.brandiseer.com/use-cases/framer-site-visuals |

## Source

Public Use case README for Airtable record visuals. Brandiseer MCP and REST v2 image generation from Cursor or Claude Cowork, then a human uploads `imageUrl` into an Airtable Attachment field, or an agent with an Airtable personal access token writes that public URL (or file bytes of 5 MB or less) through Airtable's Web API. Aligned with [guide/docs](https://brandiseer.com/guide/docs) and [guide/image](https://brandiseer.com/guide/image) (29 September 2026), and with Airtable's attachment field model and upload attachment docs. Brandiseer returns `imageUrl` only. It does not create Airtable bases and does not sync records by itself. Distinct from Slack creative desk, Buffer social scheduling, Zapier/Make/n8n always-on HTTP, Webflow site visuals, WordPress site visuals, and Framer site visuals.

## API reference

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

### MCP (interactive stills in Cursor or Cowork)

Connect `https://brandiseer.com/api/mcp` with `Authorization: Bearer` and the API key. The only tools this guide uses are:

- `brandiseer_list_brands`
- `brandiseer_check_credits`
- `brandiseer_generate_image`

Do not invent extra Brandiseer tool names. If the host needs explicit `mode`, `aspectRatio`, or async polling, use REST v2 below. MCP does not edit Airtable. Do not invent an Airtable MCP.

### REST (prefer v2 images)

Send `X-API-Key: bds_...` on every authenticated Brandiseer call. There is no official SDK. Any HTTP client the agent host can run 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" } }`. Hand `data.imageUrl` to Airtable. Failed job body: `{ "data": { "status": "failed", "error": { "code", "message" } } }`.

Cursor and Cowork can wait on a sync Design call when the session allows it. If the HTTP client times out under about 60 seconds, use async and poll. Do not point Airtable at the Brandiseer MCP URL.

### Airtable Web API (placement only)

Send `Authorization: Bearer` and the personal access token. Scope `data.records:write` is required for create, update, and `uploadAttachment`. Scope `data.records:read` is required for the GET that precedes an append. Add only the bases the human named. The owning user must be a base editor for writes.

| Call | What you get |
| --- | --- |
| `PATCH https://api.airtable.com/v0/{baseId}/{tableIdOrName}/{recordId}` | Updates the fields you send. Other fields stay. The Attachment field value you send replaces that cell. |
| `PUT` on the same URL | Destructive update. Clears cell values you do not send. Do not use it for this guide. |
| `POST https://api.airtable.com/v0/{baseId}/{tableIdOrName}` | Creates a record. A single record can be a top-level `fields` object. |
| `GET https://api.airtable.com/v0/{baseId}/{tableIdOrName}/{recordId}` | Current record. Read this before an append. Attachment `url` values in the response expire about 2 hours later. |
| `POST https://content.airtable.com/v0/{baseId}/{recordId}/{attachmentFieldIdOrName}/uploadAttachment` | Uploads file bytes, 5 MB maximum. JSON body: `contentType`, base64 `file`, `filename`. |

On create and update, a response can include `details.message` of `partialSuccess` and `details.reasons` of `attachmentsFailedUploading` or `attachmentUploadRateIsTooHigh`. Treat that as a failed attach.

### Field mapping

Brandiseer generate body:

| Incoming field | API | Rule |
| --- | --- | --- |
| Slot (campaign hero, product thumb, calendar cover, launch still) | `aspectRatio` | Campaign hero: `16:9`. Product thumb: `1:1`. Calendar cover: `16:9` or `4:3`. Launch still: `16:9`. Portrait: `9:16`. |
| headline | inside `prompt` only | On-image text and placement. Not a separate body field. Leave it out when an Airtable text field will hold the title. |
| brandId | `brandId` | `bds_c_...`. Required. |
| mode | `mode` | `fast`, `design`, or `pro`. Omit and the API uses `fast`. Prefer `design` for record stills. |
| useLogo | `useLogo` | `true` or `false`. |
| subject or brief | `prompt` | After the rewriter. If the cleaned text has no subject, do not call Brandiseer. |
| resolution | `resolution` | `1K`, `2K`, or `4K`. Prefer `2K` or `1K` for record stills. |

Airtable attachment write. The field name below is whatever Attachment field the human named. Do not invent it.

| Incoming value | Airtable | Rule |
| --- | --- | --- |
| Public Brandiseer `imageUrl` | `url` on a new attachment object | Required for a URL write. Airtable fetches this URL. It must be public. |
| Readable file name | `filename` | Optional on a new object. |
| Existing attachments you must keep | full attachment objects in the same array | The array replaces the cell. Read them first. Pass each existing object whole. |
| Record | `{recordId}` on update, GET, or upload | The human names the record. |
| Attachment field | field name or field id | On URL writes, the key inside `fields`. On bytes upload, `{attachmentFieldIdOrName}` in the path. |
| File bytes, 5 MB or smaller | `file` (base64), plus `contentType` and `filename` | `uploadAttachment` only. Do not send a data URL to Brandiseer. |

### Example JSON

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

```json
{
  "brandId": "bds_c_...",
  "prompt": "Wide campaign hero. Product centred on the left third. Empty right half for a title the Airtable record will hold. No on-image text.",
  "aspectRatio": "16:9",
  "resolution": "2K",
  "mode": "design",
  "useLogo": false
}
```

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: `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. Airtable gets `imageUrl` (or a file you downloaded from it).

URL write. Replace `Cover` with the Attachment field the human named. `PATCH` this body to `https://api.airtable.com/v0/{baseId}/{tableIdOrName}/{recordId}` with `Authorization: Bearer` and the Airtable token. This example replaces the cell with one new file. To keep existing files, include their full objects in the same array.

```json
{
  "fields": {
    "Cover": [
      {
        "url": "https://...",
        "filename": "spring-campaign-hero.png"
      }
    ]
  }
}
```

Bytes upload, 5 MB maximum. `POST` to `https://content.airtable.com/v0/{baseId}/{recordId}/{attachmentFieldIdOrName}/uploadAttachment`:

```json
{
  "contentType": "image/png",
  "file": "<base64>",
  "filename": "spring-campaign-hero.png"
}
```

Slot prompts that stay layout-only:

| Slot | aspectRatio | Prompt |
| --- | --- | --- |
| Campaign hero | `16:9` | Wide campaign hero. Product centred on the left third. Empty right half for a title the Airtable record will hold. No on-image text. |
| Product thumb | `1:1` | Square product thumb. Single product centred, full item in frame. Plain surrounding space. No on-image text. |
| Calendar cover | `16:9` | Landscape calendar cover. Subject left of centre. On-image text: "May" in the right third. |
| Calendar cover | `4:3` | Calendar cover. Single subject centred. Open space above the subject. No on-image text. |
| Launch still | `16:9` | Landscape launch still. Product left of centre. On-image text: "Spring launch" in the right third. |
