{"schemaVersion":"1.0.0","kind":"brandiseer.use-case","id":"hubspot-campaign-creatives","canonicalUrl":"https://blog.brandiseer.com/use-cases/hubspot-campaign-creatives","contentHash":"5003c4cc5f9fcfd6a760778a1e446bce4dafbb35632d3623bf54895368a8b076","metadata":{"title":"HubSpot campaign creatives","outcome":"An agent generates on-brand email headers, landing-page heroes, ad stills, and campaign thumbnails with Brandiseer; a person then places those image URLs in HubSpot.","category":"email","featured":true,"timeEstimate":"~25 to 40 min setup","methods":["MCP","REST"],"hosts":["Cursor","Cowork"],"image":"https://blog.brandiseer.com/use-case-assets/hubspot-campaign-creatives/cover-hubspot-campaign-creatives.png","updated":"2026-09-24"},"stack":[{"name":"Brandiseer","role":"Brand memory and on-brand stills via MCP or REST","logo":"/logo-b.png","href":"https://brandiseer.com"},{"name":"HubSpot","role":"File Manager, marketing emails, landing pages, and ads placement","href":"https://www.hubspot.com"},{"name":"Cursor","role":"Agent host for Brandiseer MCP or REST"},{"name":"Claude Cowork","role":"Agent host for Brandiseer MCP or REST"}],"workflow":{"audience":"- Marketing teams who send HubSpot marketing emails, publish HubSpot landing pages, or build Facebook or LinkedIn ads in HubSpot, and need a header, hero, thumbnail, or ad still without opening a separate design tool for every campaign\n- Agencies that keep one Brandiseer Brand ID per client and one HubSpot account (or portal) per client\n- Operators who can copy an `imageUrl` into HubSpot's files tool, or who already have a HubSpot token and want a Files API import or a HubDB image cell filled from that URL\n\n**Ideal customer profile:** a team whose campaigns already live in HubSpot, whose brand already lives in Brandiseer, and whose missing piece is a brand-safe still plus a clear handoff into the files tool.","rationale":"HubSpot is where the email, landing page, and ad are built. Cursor or Cowork is the agent that turns a campaign brief into a layout. 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.\n\nA HubSpot campaign drifts when every header is a one-off export from a general image tool. Brandiseer keeps the still on the same brand as the rest of the campaign. HubSpot still decides which module, page, or ad receives the file, and when that content is sent or published.\n\nThis is a different job from the sibling guides:\n\n- [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.\n- [Social media automation](/use-cases/social-media-automation) writes captions and schedules posts with Buffer.\n- [Always-on creative automation](/use-cases/always-on-creative-automation) is the HTTP step in Zapier, Make, or n8n.\n- [Webflow site visuals](/use-cases/webflow-site-visuals) generates site stills and hands `imageUrl` to Webflow.\n- This guide generates campaign stills and hands `imageUrl` to HubSpot. Brandiseer does not push into HubSpot by itself.\n\n![Example strip: email header, landing-page hero, campaign thumbnail, and ad still](https://blog.brandiseer.com/use-case-assets/hubspot-campaign-creatives/example-strip.png)","architecture":"Architecture, from campaign brief to a still sitting in HubSpot:\n\n1. You store the brand once in Brandiseer (logo and reference visuals teach the look).\n2. The agent host (Cursor or Cowork) has Brandiseer MCP or REST, the Brand ID (`bds_c_...`), and the standing instructions in this guide.\n3. You name the slot: email header, landing-page hero, campaign thumbnail, or ad still. The agent rewrites that brief into subject, layout, and on-image text, then sets `aspectRatio`, `resolution`, `mode`, and `useLogo` as fields.\n4. Brandiseer returns `imageUrl`. The agent reports the URL, the crop, the mode, and a one-line placement note (which HubSpot email, page, or ad it is for). It does not claim the email or page changed.\n5. A person uploads the file in the files tool and places it in an image module, a landing page, or an ad. Optional API steps follow HubSpot's docs and stop before send or publish.\n\n![Workflow infographic: brief, Brandiseer still, imageUrl, HubSpot files tool, person places the image](https://blog.brandiseer.com/use-case-assets/hubspot-campaign-creatives/workflow-infographic.png)","prerequisites":"- Company website URL, if the brand is not in Brandiseer yet\n- Brandiseer account with at least one finished brand profile\n- API key (`bds_...`) from [Settings → API](https://brandiseer.com/settings/api) or [Developers](https://brandiseer.com/developers)\n- Brand ID (`bds_c_...`) for every brand the agent may call\n- Credits for the stills you actually generate (see the table in Limits & FAQ)\n- Cursor or Claude Cowork, with Brandiseer MCP or a way to call REST\n- A HubSpot account you can edit\n- Access to **Content > Files**, plus the marketing email, landing page, or ads tool you will place the still in\n- Optional, only for Files API or HubDB: a HubSpot private-app or OAuth token in the agent secret store. Files upload and import need the `files` or `files.write` scopes listed on those endpoint pages. HubDB draft row updates need `hubdb-data-write` (the update page also lists `hubdb-data-append`). Publishing a HubDB table needs `hubdb-publish`. This token is not the Brandiseer key\n- Optional: the HubDB table id or name, the row id, and the real image column name. Read them from HubSpot. Do not guess column names","setup":"### Stage 1: Add your brand on Brandiseer\n\n1. Go to [brandiseer.com](https://brandiseer.com). In the homepage input, enter your company website URL and click **Try My Brand**.\n2. Wait about one minute while Brandiseer analyses the site and picks a logo and visuals.\n3. Review those visuals carefully. They teach Brandiseer your look. Every later HubSpot still is influenced by what you leave here.\n4. Remove anything off-brand (partner logos, stock, irrelevant screenshots). Add campaign creatives or product photography that match the look you want.\n5. Click **Add Brand**, sign up if prompted, then wait about 30 seconds for the brand profile to finish.\n\nAgencies repeat this once per client. Do not point two client portals at one Brand ID.\n\n### Stage 2: API key and Brand ID\n\n1. Open [brandiseer.com/developers](https://brandiseer.com/developers) or [Settings → API](https://brandiseer.com/settings/api).\n2. Create an API key (`bds_...`). Put it in the agent host's secret store. Do not paste it into a HubSpot property, an email, Slack, or a git repo.\n3. Copy the Brand ID (`bds_c_...`).\n4. 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`.\n5. Optional reachability check, no key required: `GET https://brandiseer.com/api/v1/health` returns `{ \"status\": \"ok\" }`.\n\nRead [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.\n\n### Stage 3: Connect Brandiseer to the agent host\n\nUse Cursor or Cowork. One host is enough.\n\n**A. MCP**\n\n1. Add the Brandiseer MCP server at `https://brandiseer.com/api/mcp`.\n2. Authenticate with `Authorization: Bearer` and the API key, in the secret field your host provides.\n3. 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.\n\n**B. REST**\n\n1. On [Developers](https://brandiseer.com/developers), open **View Docs** and use **Copy for LLM** if you want the reference inside the session.\n2. 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`.\n3. 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.\n\n### Stage 4: Save the standing instructions\n\n1. Paste the **System prompt** from this guide into the Cursor rule or Cowork instructions that will run campaign stills.\n2. 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.\n3. Ask the agent to call `brandiseer_list_brands` (or `GET /api/v1/brands`) and confirm the Brand ID exists before the first paid still.\n\n### Stage 5: Smoke test a header in the files tool\n\n1. Ask for one email header with a layout-only brief (the Spring header in Example flows).\n2. Confirm the agent checked the brand, avoided colour and mood words, and returned `imageUrl` plus crop and mode.\n3. In HubSpot, go to **Content > Files** and upload the file, or open a draft marketing email, click the image module, choose **Replace**, and add the image from your computer or via the file URL. Drag-and-drop emails place images in an image module. HubSpot's article says text modules and custom rich text modules in the drag-and-drop email editor cannot contain images. Classic-editor rich text uses the image icon on the toolbar. Marketing emails accept `.png`, `.ico`, `.bmp`, `.jpg`, and `.gif`.\n4. Leave the email unsent if you are only proving the handoff.\n5. Send a second brief that only says \"make the header premium and moody\". The agent should ask what is physically in the frame instead of generating.\n\nLanding pages use the same files. Open **Content > Landing Pages**, click the image module, and choose **Replace**. Ads use **Marketing > Ads**. On a Facebook or LinkedIn ad, the creative step includes **Image/Video**. Upload the still there, then use **Exit** and **Save and Exit** so the ad stays a draft. Google search ads in HubSpot are a different creative. This guide does not claim they take a still.\n\n### Stage 6: Optional Files API\n\nSkip this stage if people will upload by hand. Use it only when a token already exists and the still must land in the files tool without the picker.\n\n1. Create the HubSpot token with the scopes on [Files API](https://developers.hubspot.com/docs/api-reference/latest/files/guide) and [Import file from URL](https://developers.hubspot.com/docs/api-reference/latest/files/files/import-from-url). Requests use `Authorization: Bearer` and that token. This is not the Brandiseer key.\n2. Generate the still in Brandiseer first. HubSpot has to be able to fetch `imageUrl` for an import. If the URL is not public, download the file and upload the bytes instead.\n3. Import from URL with HubSpot's documented call: `POST https://api.hubapi.com/files/2026-09/files/import-from-url/async`. The live schema marks `access`, `duplicateValidationScope`, `duplicateValidationStrategy`, and `overwrite` as required. Set `url` to the Brandiseer `imageUrl`. Set `folderPath` or `folderId` (the property text says one of them must be set). For an email or landing page that must render the image, pick a public access value from the schema (`PUBLIC_INDEXABLE` or `PUBLIC_NOT_INDEXABLE`). The Files API guide says a private file's public URL returns `404`. A `202` body is a task locator with `id`.\n4. Poll `GET https://api.hubapi.com/files/2026-09/files/import-from-url/async/tasks/{taskId}/status` with the same HubSpot token. The Files API guide lists `PENDING`, `PROCESSING`, `CANCELED`, and `COMPLETE`. On `COMPLETE`, read the file with `GET https://api.hubapi.com/files/2026-09/files/{fileId}` and keep `url` for the editor. On `CANCELED`, stop and upload the file by hand.\n5. If you already have the file on disk, the multipart upload is `POST https://api.hubapi.com/files/2026-09/files` with `file`, `options` (JSON, and `access` is required inside it), and either `folderId` or `folderPath`. A `201` body includes `id`, `url`, and `defaultHostingUrl`. That file is in the files tool. It is not yet inside an email, page, or ad.\n6. A person still places the file in the module or ad. Do not send the email in the smoke test.\n\nFile size and image types for the files tool are in [Supported file types and sizes](https://knowledge.hubspot.com/files/supported-file-types): up to 20 MB on free tools, up to 2 GB on paid subscriptions, and image formats `jpg`, `jpeg`, `png`, `tif`, `tiff`, `ico`, `bmp`, and `webp`. If a marketing email rejects the type, export a `.png` or `.jpg` and upload that. Marketing emails do not list `webp`.\n\n### Stage 7: Optional HubDB image column\n\nSkip this stage unless a landing page already reads a HubDB `IMAGE` column and you already have a token. The row update and publish pages list Marketing Hub Professional and CMS Hub Professional in their product tier block.\n\n1. Read the image value shape on the [HubDB guide](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/guide). An `IMAGE` column stores an object with `url`, `width`, `height`, and `type` set to `image`. The sample there uses a HubSpot-hosted file URL. Column names are yours. Do not guess them.\n2. Update the draft row with the call on [Update a row](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/rows/update-hubdb-draft-rowId): `PATCH https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/rows/{rowId}/draft`. Scopes on that page are `hubdb-data-append` and `hubdb-data-write`. The description says you only need the columns you are changing. The schema also lists `childTableId`, `displayIndex`, and `values` as required. If a body that only contains `values` is rejected, copy `childTableId` and `displayIndex` from the current row and change only the image column. Put the image under `values` using the real column name and the object shape from the HubDB guide.\n3. Confirm the draft row in HubSpot. Do not publish during the smoke test.\n4. Publishing is a separate call: `POST https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/draft/publish`, scope `hubdb-publish`, documented on [Publish a table from draft](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/tables/publish-table-draft). HubSpot's description says this copies draft data to the published version and that website pages using the table will be updated. A person runs that only after they have reviewed the still.\n\nA HubDB write does not place a static email header. Email headers stay on the files tool and the email editor.","promptingRules":"When the agent builds `prompt`:\n\n- Keep subject, layout, composition, and on-image text (what the words say and where they sit).\n- Never send brand colours, fonts, mood, or visual style. Brand memory already applies those. Style words fight the brand and produce off-brand stills.\n- Put crop in `aspectRatio`, quality in `mode`, pixel size in `resolution`, and logo on/off in `useLogo`. Those are body fields, not prompt prose.\n- Map the HubSpot slot to a documented ratio. Email header and landing-page hero: `16:9`. Campaign thumbnail: `1:1`. Ad still: `1:1` or `16:9`, matching the placement the human named. Portrait stories: `9:16`. A slide-like module: `4:3`. Brandiseer does not offer network-specific ad ratios. Crop in HubSpot's image editor if the slot is tighter. The ads image editor is documented in [Edit images](https://knowledge.hubspot.com/website-and-landing-pages/edit-images).\n- Prefer `design` for finished campaign stills. `fast` is the API default if you omit `mode`, and it is the right fallback if a design job fails once.\n- Prefer `1K` or `2K` so the file stays comfortable for email. `4K` is optional.\n- Set `useLogo` true only when the brief asked for a logo (or your default says so). Headlines that the email or page will set in HubSpot text should stay off the image. Say \"empty region\" for that area instead of describing a font.\n- Full rules: [Prompt compatibility](https://brandiseer.com/guide/image).","systemPrompts":"Paste this into Cursor or Cowork as the standing instructions for campaign stills. Replace the placeholders before the first generate.\n\n```text\nYou generate on-brand stills for HubSpot campaigns. Brandiseer returns an\nimage URL. You do not upload into HubSpot by yourself, and you do not send\nthe email, publish the landing page, or publish the ad.\n\nBrandiseer:\n- MCP: https://brandiseer.com/api/mcp with Authorization: Bearer.\n  Tools you may call: brandiseer_list_brands, brandiseer_check_credits,\n  brandiseer_generate_image. Do not invent tool names.\n- REST: X-API-Key: bds_... (secret store only).\n  Prefer POST https://brandiseer.com/api/v2/generate\n  or POST https://brandiseer.com/api/v2/generate/async\n  then poll GET https://brandiseer.com/api/v2/jobs/:jobId every 3 to 5 seconds\n  until data.status is done or failed, or about 10 minutes have passed.\n- Live contract: https://brandiseer.com/guide/docs and\n  https://brandiseer.com/guide/image\n\nDefaults for this account (fill in once):\n- Brand ID: bds_c_...\n- Email header and landing-page hero aspectRatio: 16:9\n- Campaign thumbnail aspectRatio: 1:1\n- Ad still aspectRatio: ask if the placement is not known (1:1 or 16:9)\n- mode: design\n- resolution: 2K\n- useLogo when the brief is silent: false\n- Multi-brand map, if any: brand name to bds_c_...\n\nOn every request:\n1. Resolve brandId from the brief or the default. If more than one brand\n   exists and the brief does not name one, ask. Never fall through to\n   another client's Brand ID.\n2. Check credits before a batch (brandiseer_check_credits or\n   GET https://brandiseer.com/api/v1/credits). A single still can proceed\n   if the last known balance covers the mode and resolution in the table\n   you were given. On 402, stop.\n3. Rewrite the brief into subject, layout, composition, and on-image text.\n   Strip colours, fonts, mood, and visual style. If stripping leaves no\n   physical subject, ask what is in the frame. Do not generate.\n4. Choose aspectRatio from the slot. Put resolution, mode, and useLogo in\n   API fields, not in the prompt.\n5. Generate one still. Return imageUrl, aspectRatio, mode, resolution,\n   useLogo, and a placement note: files tool plus the email module, landing\n   page, campaign thumbnail, or ad the human named.\n6. Do not tell the user HubSpot changed unless a HubSpot call you actually\n   performed returned success. A files upload is not an email send.\n\nHubSpot, only when the human already supplied a token and asked for a\nfiles import or a HubDB draft update:\n- Authorization: Bearer, the HubSpot token. Never the Brandiseer key.\n- Files import: POST https://api.hubapi.com/files/2026-09/files/import-from-url/async\n  Follow https://developers.hubspot.com/docs/api-reference/latest/files/files/import-from-url\n  Set url to the public Brandiseer imageUrl. If HubSpot cannot fetch it,\n  tell the human to download and upload in Content > Files.\n- Poll GET https://api.hubapi.com/files/2026-09/files/import-from-url/async/tasks/{taskId}/status\n  until the Files API guide status is COMPLETE or CANCELED.\n- Multipart upload, when you have the file bytes:\n  POST https://api.hubapi.com/files/2026-09/files\n  Follow https://developers.hubspot.com/docs/api-reference/latest/files/guide\n- HubDB image, only with a real table id, row id, and column name:\n  PATCH https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/rows/{rowId}/draft\n  Image object shape from\n  https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/guide\n  Do not call\n  POST https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/draft/publish\n  unless the human explicitly asks after they have reviewed the draft.\n  That publish updates website pages that use the table.\n- Do not patch marketing email content. A person places the file in the\n  email editor.\n\nOut of scope:\n- Slack replies, Buffer scheduling, Zapier, Make, or n8n scenarios, and\n  Webflow Designer.\n- Legal approval of claims, prices, or offers printed on the image.\n- GET https://brandiseer.com/api/v1/usage (browser session only).\n```\n\n### Prompt rewriter\n\nUse 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.\n\n```javascript\n// Local rewriter for a Cursor or Cowork helper script.\n// Keeps subject, layout, composition, and on-image text.\n// Strips colour, type, mood, and visual-style language.\n\nconst STYLE_WORDS =\n  /\\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;\n\nconst SLOT_TO_RATIO = {\n  \"email header\": \"16:9\",\n  header: \"16:9\",\n  email: \"16:9\",\n  hero: \"16:9\",\n  \"landing hero\": \"16:9\",\n  \"landing page\": \"16:9\",\n  banner: \"16:9\",\n  \"16:9\": \"16:9\",\n  thumbnail: \"1:1\",\n  \"campaign thumbnail\": \"1:1\",\n  square: \"1:1\",\n  \"1:1\": \"1:1\",\n  ad: \"1:1\",\n  \"ad still\": \"1:1\",\n  \"4:3\": \"4:3\",\n  slide: \"4:3\",\n  portrait: \"9:16\",\n  story: \"9:16\",\n  \"9:16\": \"9:16\",\n};\n\nfunction rewriteBrandiseerPrompt(input) {\n  const headline = String(input.headline || \"\").trim();\n  const subject = String(input.subject || input.brief || \"\").trim();\n  const slotKey = String(input.slot || input.crop || \"\").trim().toLowerCase();\n  const aspectRatio = SLOT_TO_RATIO[slotKey] || \"\";\n\n  let prompt = [subject, headline ? `On-image text: \"${headline}\".` : \"\"]\n    .filter(Boolean)\n    .join(\" \");\n\n  prompt = prompt\n    .replace(/#[0-9a-f]{3,8}\\b/gi, \" \")\n    .replace(STYLE_WORDS, \" \")\n    .replace(/\\s+/g, \" \")\n    .trim();\n\n  return {\n    prompt,\n    aspectRatio,\n    needsSubject: prompt.length < 12 || !aspectRatio,\n  };\n}\n```\n\nIf `needsSubject` is true, ask the human for a subject and a slot. Do not POST.","addOns":"Add these after the header smoke test passes. They do not change Brandiseer's image contract, and they do not give Brandiseer a HubSpot push.\n\n### Approval before send\n\nAfter `imageUrl` is in the files tool and on the draft email, page, or ad, a named reviewer checks the still in HubSpot. Only then send the email, publish the page, or publish the ad. Until that happens, leave the content in draft. Brandiseer does not approve legal claims, prices, or offers.\n\n### One brand per HubSpot portal\n\nKeep a table: HubSpot portal name, token secret name, and `bds_c_...`. Require a token on every API write when more than one portal exists. If the name misses, stop and list the portals you configured. Confirm Brand IDs with `GET /api/v1/brands`. Never fall through to another client's Brand ID or another portal's token.\n\n### Credit soft-limit\n\nWhen `credits` is under a threshold you choose (for example 40), switch new campaign 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.\n\n### Placement log\n\nKeep a short note next to the work: email, page, or ad, slot, `brandId`, `mode`, `aspectRatio`, `resolution`, `imageUrl`, and whether it was uploaded in the files tool, imported by the Files API, or written to a HubDB draft row. Brandiseer does not write this log. HubSpot does not send it back to Brandiseer.\n\n### Handoff to the sibling guides\n\n- Stills requested in Slack, returned in a thread: [Slack creative desk](/use-cases/slack-creative-desk).\n- Captions and a Buffer schedule: [Social media automation](/use-cases/social-media-automation).\n- A Zapier, Make, or n8n trigger that should deliver `imageUrl` on a schedule: [Always-on creative automation](/use-cases/always-on-creative-automation).\n- Homepage and CMS stills that live on a Webflow site: [Webflow site visuals](/use-cases/webflow-site-visuals).\n\nDo not embed Buffer, a Slack desk, an always-on HTTP scenario, or a Webflow Designer step inside this HubSpot guide.\n\n### Optional motion (not the campaign MVP)\n\nVideo 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. A HubSpot ad that accepts video is a separate upload in the ads tool. Leave this off unless the brief explicitly asks to animate.","limitsAndFaq":"### Does Brandiseer update HubSpot emails, pages, or ads?\n\nNo. Brandiseer returns `imageUrl`. A person uploads the file in the files tool and places it in an email image module, a landing page, or an ad. A Files API upload only adds a file to the files tool. A HubDB draft update only changes table data. Neither call sends an email or publishes an ad.\n\n### Is there a Brandiseer app inside HubSpot?\n\nNo. There is no Brandiseer panel in the email editor in this guide. Do not look for a native \"send to HubSpot\" button on the Brandiseer side.\n\n### What if HubSpot rejects the image?\n\nCheck [Supported file types and sizes](https://knowledge.hubspot.com/files/supported-file-types) and the marketing-email note on [Use images in HubSpot content](https://knowledge.hubspot.com/website-pages/use-images-in-hubspot-content). Marketing emails accept `.png`, `.ico`, `.bmp`, `.jpg`, and `.gif`. The files tool also lists `webp`, `tif`, and `tiff`, which the email note does not. If the picker rejects the file, export PNG or JPEG and upload that. Files on free tools are limited to 20 MB. An import also fails when HubSpot cannot fetch `imageUrl`. Download the still and upload the bytes.\n\n### Which HubSpot calls are in this guide?\n\nOnly calls confirmed on HubSpot's developer pages, and only at the level those pages describe:\n\n- Files upload: `POST https://api.hubapi.com/files/2026-09/files` on the [Files API guide](https://developers.hubspot.com/docs/api-reference/latest/files/guide)\n- Import from URL: `POST https://api.hubapi.com/files/2026-09/files/import-from-url/async` and status `GET https://api.hubapi.com/files/2026-09/files/import-from-url/async/tasks/{taskId}/status` on [Import file from URL](https://developers.hubspot.com/docs/api-reference/latest/files/files/import-from-url) and the Files API guide\n- HubDB image value: the create-row example on the [HubDB guide](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/guide)\n- HubDB draft row: `PATCH https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/rows/{rowId}/draft` on [Update a row](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/rows/update-hubdb-draft-rowId)\n- HubDB publish, after review: `POST https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/draft/publish` on [Publish a table from draft](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/tables/publish-table-draft)\n\nFolder ids, table ids, row ids, and column names come from your portal and from those pages. This guide does not invent a \"set email header\" endpoint.\n\n### Can I use HubSpot's own MCP?\n\nHubSpot documents a remote MCP server at `https://mcp.hubspot.com` ([AI tools](https://developers.hubspot.com/ai-tools/mcp), [remote server](https://developers.hubspot.com/docs/apps/developer-platform/build-apps/integrate-with-the-remote-hubspot-mcp-server)). This guide does not depend on it and does not name its tools. If you connect it, call only tools that server actually exposes. Brandiseer still only returns the still. A HubSpot tool that matches the Files API or a HubDB image column is fine when its schema matches those pages. Do not assume a tool writes an email module.\n\n### Where do the keys live?\n\nThe Brandiseer key (`bds_...`) and the HubSpot token live in the agent host's secret store. Never in a CRM property, a Slack message, a prompt you commit, or a workflow export in git. Rotate either key if it leaks. Poll a Brandiseer job with the same Brandiseer key that submitted it. Call HubSpot with the HubSpot token.\n\n### What do stills cost?\n\nCredits per still. Failures refund. Async submits deduct immediately and refund if the job fails.\n\n| Mode | 1K | 2K | 4K |\n| --- | --- | --- | --- |\n| Fast | 4 | 6 | 8 |\n| Design | 5 | 6 | 8 |\n| Pro | 6 | 8 | 10 |\n\n`402` means not enough credits. Pricing context: [brandiseer.com/pricing](https://brandiseer.com/pricing).\n\n### Why is the still off-brand?\n\nAlmost always because the prompt contained colours, fonts, mood, or visual style. Strip them and generate again. See [guide/image](https://brandiseer.com/guide/image).\n\n### Why does the crop look wrong in the ad preview?\n\nBrandiseer aspect ratios are `1:1`, `16:9`, `9:16`, and `4:3`. Generate the closest slot, then crop in HubSpot. Network pixel rules belong to the ad network and to HubSpot's ads editor. This guide does not invent a Facebook or LinkedIn pixel size.\n\n### How long can I poll?\n\nAbout 10 minutes, then the Brandiseer 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.\n\n### Which generate URL should new campaign work use?\n\n`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.\n\n### Does the agent approve claims on the image?\n\nNo. If the still has a price, a discount, or a legal line, a person reads it before send or publish. Brandiseer does not review the claim.\n\n### Are files public?\n\nHubSpot's upload article says files in the files tool are hosted on a public file URL by default. The Files API guide says a private file's returned URL results in `404`, and a signed URL is the way to view it. Emails and landing pages that must render the image need a public file. Choose the public access value on the import schema when you use the API, and follow HubSpot's file visibility settings when you upload by hand.","demo":"**Motion brief only. This is not an embed, and there is no walkthrough URL yet.**\n\n**Working title:** HubSpot campaign creatives\n**Length:** 45 to 75 seconds\n\n**Story beats:**\n\n1. A person asks Cursor or Cowork for an email header with a layout-only brief\n2. The agent calls Brandiseer (MCP or REST v2) and shows an on-brand still\n3. `imageUrl` is uploaded in HubSpot's files tool and placed on a draft marketing email\n4. Optional cut: the same still is selected on a draft landing page or a draft ad, still unsent\n5. A human sends or publishes only after the offer reads correctly\n\n**On screen:** the agent transcript with the prompt (no colour or mood words), one finished still, and the HubSpot files tool. Blur the Brandiseer API key and the HubSpot token. Do not show a fake video player in the guide."},"sections":[{"id":"overview","heading":"Overview","markdown":"**Brandiseer + HubSpot (+ Cursor or Claude Cowork)**\n\n![Cover: an on-brand email header ready to place in HubSpot](https://blog.brandiseer.com/use-case-assets/hubspot-campaign-creatives/cover-hubspot-campaign-creatives.png)\n\nBy the end of this guide you will have a repeatable way to make on-brand stills for HubSpot campaigns. An agent in Cursor or Claude Cowork calls Brandiseer, gets an `imageUrl` for an email header, a landing-page hero, a campaign thumbnail, or an ad still, and a person places that file in HubSpot.\n\nBrandiseer owns the brand memory and the still. HubSpot owns the email, the landing page, and the ad. Brandiseer does not open HubSpot, does not upload into the files tool by itself, and does not send the email or publish the page or ad. A person downloads the file or copies `imageUrl`, uploads it in the files tool (or pastes a file URL in the image picker), and assigns it to an image module, a landing page, or an ad. Optional Files API and HubDB writes are documented only where HubSpot's own developer pages describe them.\n\n> 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). Site heroes that live in Webflow should use [Webflow site visuals](/use-cases/webflow-site-visuals). This guide does not recreate any of those."},{"id":"audience","heading":"Who it's for","markdown":"- Marketing teams who send HubSpot marketing emails, publish HubSpot landing pages, or build Facebook or LinkedIn ads in HubSpot, and need a header, hero, thumbnail, or ad still without opening a separate design tool for every campaign\n- Agencies that keep one Brandiseer Brand ID per client and one HubSpot account (or portal) per client\n- Operators who can copy an `imageUrl` into HubSpot's files tool, or who already have a HubSpot token and want a Files API import or a HubDB image cell filled from that URL\n\n**Ideal customer profile:** a team whose campaigns already live in HubSpot, whose brand already lives in Brandiseer, and whose missing piece is a brand-safe still plus a clear handoff into the files tool."},{"id":"why-brandiseer","heading":"Why Brandiseer in this stack","markdown":"HubSpot is where the email, landing page, and ad are built. Cursor or Cowork is the agent that turns a campaign brief into a layout. 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.\n\nA HubSpot campaign drifts when every header is a one-off export from a general image tool. Brandiseer keeps the still on the same brand as the rest of the campaign. HubSpot still decides which module, page, or ad receives the file, and when that content is sent or published.\n\nThis is a different job from the sibling guides:\n\n- [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.\n- [Social media automation](/use-cases/social-media-automation) writes captions and schedules posts with Buffer.\n- [Always-on creative automation](/use-cases/always-on-creative-automation) is the HTTP step in Zapier, Make, or n8n.\n- [Webflow site visuals](/use-cases/webflow-site-visuals) generates site stills and hands `imageUrl` to Webflow.\n- This guide generates campaign stills and hands `imageUrl` to HubSpot. Brandiseer does not push into HubSpot by itself.\n\n![Example strip: email header, landing-page hero, campaign thumbnail, and ad still](https://blog.brandiseer.com/use-case-assets/hubspot-campaign-creatives/example-strip.png)"},{"id":"stack","heading":"Stack","markdown":"| Layer | Tool | Role |\n| --- | --- | --- |\n| Brand visuals | Brandiseer MCP and/or REST v2 | Generate on-brand stills. MCP uses `Authorization: Bearer`. REST uses `X-API-Key: bds_...` |\n| Agent host (pick one) | Cursor | Read the campaign brief, call Brandiseer, return `imageUrl` and a placement note |\n| Agent host (pick one) | Claude Cowork | Same contract as Cursor for interactive campaign stills |\n| Campaign home | HubSpot | Files tool, marketing email image modules, landing pages, and the ads tool |\n\n![Stack diagram: Cursor or Cowork, Brandiseer, and HubSpot](https://blog.brandiseer.com/use-case-assets/hubspot-campaign-creatives/stack-diagram.png)\n\nYou only need one agent host. The Brandiseer contract is the same on both. HubSpot has no Brandiseer app that drops a still into an email. The handoff is an image URL, a download, or a HubSpot API call you perform by following HubSpot's docs.\n\n**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)\n\n**HubSpot docs:** [Files API](https://developers.hubspot.com/docs/api-reference/latest/files/guide) · [Import from URL](https://developers.hubspot.com/docs/api-reference/latest/files/files/import-from-url) · [Files tool](https://developers.hubspot.com/docs/cms/start-building/features/storage/file-manager) · [Upload files](https://knowledge.hubspot.com/files/upload-files-to-use-in-your-hubspot-content) · [Use images in content](https://knowledge.hubspot.com/website-pages/use-images-in-hubspot-content) · [File types and sizes](https://knowledge.hubspot.com/files/supported-file-types) · [HubDB](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/guide) · [Facebook ads in HubSpot](https://knowledge.hubspot.com/ads/create-facebook-and-linkedin-lead-ads-in-hubspot) · [LinkedIn ads in HubSpot](https://knowledge.hubspot.com/ads/create-linkedin-ad-campaigns-in-hubspot)\n\nHubSpot's overview articles sometimes still print an older date segment such as `2026-03`. The endpoint pages used below are the `2026-09` pages fetched for this guide. Call the path on the page you open. Do not invent a neighbouring version.\n\nEndpoint tables and HTTP contracts are in API reference at the end of this guide.\n\n### HubSpot (placement, not generation)\n\nThree practical paths. Use the first one until a files import or a HubDB cell is actually needed.\n\n1. **Files tool, then the editor (default).** Download the file or copy `imageUrl`. In HubSpot, open **Content > Files** and click **Upload files**, or drag the file into a folder. You need Super Admin or Edit permission for files. Then open the marketing email, landing page, or ad and select that file. The image picker can also add an image from your computer or via a file URL. Brandiseer stops at the URL. See [Upload files](https://knowledge.hubspot.com/files/upload-files-to-use-in-your-hubspot-content) and [Use images in HubSpot content](https://knowledge.hubspot.com/website-pages/use-images-in-hubspot-content).\n2. **Files API (optional).** When you already have a HubSpot token with the files scopes on the Files API guide, upload the bytes or import the public `imageUrl`. A successful upload puts the file in the files tool. It does not assign the file to an email module, a landing-page hero, or an ad. See Setup stage 6.\n3. **HubDB image column (optional).** When a landing page already reads an `IMAGE` column, update the draft row through the HubDB API HubSpot documents. That updates table data. It does not send an email, and publishing the table is a separate call that HubSpot says updates website pages using the table. See Setup stage 7.\n\nThis guide does not update marketing email HTML or email modules through the marketing emails API. A person places the still in the email editor."},{"id":"architecture","heading":"How it works","markdown":"Architecture, from campaign brief to a still sitting in HubSpot:\n\n1. You store the brand once in Brandiseer (logo and reference visuals teach the look).\n2. The agent host (Cursor or Cowork) has Brandiseer MCP or REST, the Brand ID (`bds_c_...`), and the standing instructions in this guide.\n3. You name the slot: email header, landing-page hero, campaign thumbnail, or ad still. The agent rewrites that brief into subject, layout, and on-image text, then sets `aspectRatio`, `resolution`, `mode`, and `useLogo` as fields.\n4. Brandiseer returns `imageUrl`. The agent reports the URL, the crop, the mode, and a one-line placement note (which HubSpot email, page, or ad it is for). It does not claim the email or page changed.\n5. A person uploads the file in the files tool and places it in an image module, a landing page, or an ad. Optional API steps follow HubSpot's docs and stop before send or publish.\n\n![Workflow infographic: brief, Brandiseer still, imageUrl, HubSpot files tool, person places the image](https://blog.brandiseer.com/use-case-assets/hubspot-campaign-creatives/workflow-infographic.png)"},{"id":"prerequisites","heading":"What you need","markdown":"- Company website URL, if the brand is not in Brandiseer yet\n- Brandiseer account with at least one finished brand profile\n- API key (`bds_...`) from [Settings → API](https://brandiseer.com/settings/api) or [Developers](https://brandiseer.com/developers)\n- Brand ID (`bds_c_...`) for every brand the agent may call\n- Credits for the stills you actually generate (see the table in Limits & FAQ)\n- Cursor or Claude Cowork, with Brandiseer MCP or a way to call REST\n- A HubSpot account you can edit\n- Access to **Content > Files**, plus the marketing email, landing page, or ads tool you will place the still in\n- Optional, only for Files API or HubDB: a HubSpot private-app or OAuth token in the agent secret store. Files upload and import need the `files` or `files.write` scopes listed on those endpoint pages. HubDB draft row updates need `hubdb-data-write` (the update page also lists `hubdb-data-append`). Publishing a HubDB table needs `hubdb-publish`. This token is not the Brandiseer key\n- Optional: the HubDB table id or name, the row id, and the real image column name. Read them from HubSpot. Do not guess column names"},{"id":"setup","heading":"Setup","markdown":"### Stage 1: Add your brand on Brandiseer\n\n1. Go to [brandiseer.com](https://brandiseer.com). In the homepage input, enter your company website URL and click **Try My Brand**.\n2. Wait about one minute while Brandiseer analyses the site and picks a logo and visuals.\n3. Review those visuals carefully. They teach Brandiseer your look. Every later HubSpot still is influenced by what you leave here.\n4. Remove anything off-brand (partner logos, stock, irrelevant screenshots). Add campaign creatives or product photography that match the look you want.\n5. Click **Add Brand**, sign up if prompted, then wait about 30 seconds for the brand profile to finish.\n\nAgencies repeat this once per client. Do not point two client portals at one Brand ID.\n\n### Stage 2: API key and Brand ID\n\n1. Open [brandiseer.com/developers](https://brandiseer.com/developers) or [Settings → API](https://brandiseer.com/settings/api).\n2. Create an API key (`bds_...`). Put it in the agent host's secret store. Do not paste it into a HubSpot property, an email, Slack, or a git repo.\n3. Copy the Brand ID (`bds_c_...`).\n4. 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`.\n5. Optional reachability check, no key required: `GET https://brandiseer.com/api/v1/health` returns `{ \"status\": \"ok\" }`.\n\nRead [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.\n\n### Stage 3: Connect Brandiseer to the agent host\n\nUse Cursor or Cowork. One host is enough.\n\n**A. MCP**\n\n1. Add the Brandiseer MCP server at `https://brandiseer.com/api/mcp`.\n2. Authenticate with `Authorization: Bearer` and the API key, in the secret field your host provides.\n3. 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.\n\n**B. REST**\n\n1. On [Developers](https://brandiseer.com/developers), open **View Docs** and use **Copy for LLM** if you want the reference inside the session.\n2. 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`.\n3. 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.\n\n### Stage 4: Save the standing instructions\n\n1. Paste the **System prompt** from this guide into the Cursor rule or Cowork instructions that will run campaign stills.\n2. 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.\n3. Ask the agent to call `brandiseer_list_brands` (or `GET /api/v1/brands`) and confirm the Brand ID exists before the first paid still.\n\n### Stage 5: Smoke test a header in the files tool\n\n1. Ask for one email header with a layout-only brief (the Spring header in Example flows).\n2. Confirm the agent checked the brand, avoided colour and mood words, and returned `imageUrl` plus crop and mode.\n3. In HubSpot, go to **Content > Files** and upload the file, or open a draft marketing email, click the image module, choose **Replace**, and add the image from your computer or via the file URL. Drag-and-drop emails place images in an image module. HubSpot's article says text modules and custom rich text modules in the drag-and-drop email editor cannot contain images. Classic-editor rich text uses the image icon on the toolbar. Marketing emails accept `.png`, `.ico`, `.bmp`, `.jpg`, and `.gif`.\n4. Leave the email unsent if you are only proving the handoff.\n5. Send a second brief that only says \"make the header premium and moody\". The agent should ask what is physically in the frame instead of generating.\n\nLanding pages use the same files. Open **Content > Landing Pages**, click the image module, and choose **Replace**. Ads use **Marketing > Ads**. On a Facebook or LinkedIn ad, the creative step includes **Image/Video**. Upload the still there, then use **Exit** and **Save and Exit** so the ad stays a draft. Google search ads in HubSpot are a different creative. This guide does not claim they take a still.\n\n### Stage 6: Optional Files API\n\nSkip this stage if people will upload by hand. Use it only when a token already exists and the still must land in the files tool without the picker.\n\n1. Create the HubSpot token with the scopes on [Files API](https://developers.hubspot.com/docs/api-reference/latest/files/guide) and [Import file from URL](https://developers.hubspot.com/docs/api-reference/latest/files/files/import-from-url). Requests use `Authorization: Bearer` and that token. This is not the Brandiseer key.\n2. Generate the still in Brandiseer first. HubSpot has to be able to fetch `imageUrl` for an import. If the URL is not public, download the file and upload the bytes instead.\n3. Import from URL with HubSpot's documented call: `POST https://api.hubapi.com/files/2026-09/files/import-from-url/async`. The live schema marks `access`, `duplicateValidationScope`, `duplicateValidationStrategy`, and `overwrite` as required. Set `url` to the Brandiseer `imageUrl`. Set `folderPath` or `folderId` (the property text says one of them must be set). For an email or landing page that must render the image, pick a public access value from the schema (`PUBLIC_INDEXABLE` or `PUBLIC_NOT_INDEXABLE`). The Files API guide says a private file's public URL returns `404`. A `202` body is a task locator with `id`.\n4. Poll `GET https://api.hubapi.com/files/2026-09/files/import-from-url/async/tasks/{taskId}/status` with the same HubSpot token. The Files API guide lists `PENDING`, `PROCESSING`, `CANCELED`, and `COMPLETE`. On `COMPLETE`, read the file with `GET https://api.hubapi.com/files/2026-09/files/{fileId}` and keep `url` for the editor. On `CANCELED`, stop and upload the file by hand.\n5. If you already have the file on disk, the multipart upload is `POST https://api.hubapi.com/files/2026-09/files` with `file`, `options` (JSON, and `access` is required inside it), and either `folderId` or `folderPath`. A `201` body includes `id`, `url`, and `defaultHostingUrl`. That file is in the files tool. It is not yet inside an email, page, or ad.\n6. A person still places the file in the module or ad. Do not send the email in the smoke test.\n\nFile size and image types for the files tool are in [Supported file types and sizes](https://knowledge.hubspot.com/files/supported-file-types): up to 20 MB on free tools, up to 2 GB on paid subscriptions, and image formats `jpg`, `jpeg`, `png`, `tif`, `tiff`, `ico`, `bmp`, and `webp`. If a marketing email rejects the type, export a `.png` or `.jpg` and upload that. Marketing emails do not list `webp`.\n\n### Stage 7: Optional HubDB image column\n\nSkip this stage unless a landing page already reads a HubDB `IMAGE` column and you already have a token. The row update and publish pages list Marketing Hub Professional and CMS Hub Professional in their product tier block.\n\n1. Read the image value shape on the [HubDB guide](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/guide). An `IMAGE` column stores an object with `url`, `width`, `height`, and `type` set to `image`. The sample there uses a HubSpot-hosted file URL. Column names are yours. Do not guess them.\n2. Update the draft row with the call on [Update a row](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/rows/update-hubdb-draft-rowId): `PATCH https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/rows/{rowId}/draft`. Scopes on that page are `hubdb-data-append` and `hubdb-data-write`. The description says you only need the columns you are changing. The schema also lists `childTableId`, `displayIndex`, and `values` as required. If a body that only contains `values` is rejected, copy `childTableId` and `displayIndex` from the current row and change only the image column. Put the image under `values` using the real column name and the object shape from the HubDB guide.\n3. Confirm the draft row in HubSpot. Do not publish during the smoke test.\n4. Publishing is a separate call: `POST https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/draft/publish`, scope `hubdb-publish`, documented on [Publish a table from draft](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/tables/publish-table-draft). HubSpot's description says this copies draft data to the published version and that website pages using the table will be updated. A person runs that only after they have reviewed the still.\n\nA HubDB write does not place a static email header. Email headers stay on the files tool and the email editor."},{"id":"prompting-rules","heading":"Prompting rules for Brandiseer images","markdown":"When the agent builds `prompt`:\n\n- Keep subject, layout, composition, and on-image text (what the words say and where they sit).\n- Never send brand colours, fonts, mood, or visual style. Brand memory already applies those. Style words fight the brand and produce off-brand stills.\n- Put crop in `aspectRatio`, quality in `mode`, pixel size in `resolution`, and logo on/off in `useLogo`. Those are body fields, not prompt prose.\n- Map the HubSpot slot to a documented ratio. Email header and landing-page hero: `16:9`. Campaign thumbnail: `1:1`. Ad still: `1:1` or `16:9`, matching the placement the human named. Portrait stories: `9:16`. A slide-like module: `4:3`. Brandiseer does not offer network-specific ad ratios. Crop in HubSpot's image editor if the slot is tighter. The ads image editor is documented in [Edit images](https://knowledge.hubspot.com/website-and-landing-pages/edit-images).\n- Prefer `design` for finished campaign stills. `fast` is the API default if you omit `mode`, and it is the right fallback if a design job fails once.\n- Prefer `1K` or `2K` so the file stays comfortable for email. `4K` is optional.\n- Set `useLogo` true only when the brief asked for a logo (or your default says so). Headlines that the email or page will set in HubSpot text should stay off the image. Say \"empty region\" for that area instead of describing a font.\n- Full rules: [Prompt compatibility](https://brandiseer.com/guide/image)."},{"id":"system-prompts","heading":"System prompt","markdown":"Paste this into Cursor or Cowork as the standing instructions for campaign stills. Replace the placeholders before the first generate.\n\n```text\nYou generate on-brand stills for HubSpot campaigns. Brandiseer returns an\nimage URL. You do not upload into HubSpot by yourself, and you do not send\nthe email, publish the landing page, or publish the ad.\n\nBrandiseer:\n- MCP: https://brandiseer.com/api/mcp with Authorization: Bearer.\n  Tools you may call: brandiseer_list_brands, brandiseer_check_credits,\n  brandiseer_generate_image. Do not invent tool names.\n- REST: X-API-Key: bds_... (secret store only).\n  Prefer POST https://brandiseer.com/api/v2/generate\n  or POST https://brandiseer.com/api/v2/generate/async\n  then poll GET https://brandiseer.com/api/v2/jobs/:jobId every 3 to 5 seconds\n  until data.status is done or failed, or about 10 minutes have passed.\n- Live contract: https://brandiseer.com/guide/docs and\n  https://brandiseer.com/guide/image\n\nDefaults for this account (fill in once):\n- Brand ID: bds_c_...\n- Email header and landing-page hero aspectRatio: 16:9\n- Campaign thumbnail aspectRatio: 1:1\n- Ad still aspectRatio: ask if the placement is not known (1:1 or 16:9)\n- mode: design\n- resolution: 2K\n- useLogo when the brief is silent: false\n- Multi-brand map, if any: brand name to bds_c_...\n\nOn every request:\n1. Resolve brandId from the brief or the default. If more than one brand\n   exists and the brief does not name one, ask. Never fall through to\n   another client's Brand ID.\n2. Check credits before a batch (brandiseer_check_credits or\n   GET https://brandiseer.com/api/v1/credits). A single still can proceed\n   if the last known balance covers the mode and resolution in the table\n   you were given. On 402, stop.\n3. Rewrite the brief into subject, layout, composition, and on-image text.\n   Strip colours, fonts, mood, and visual style. If stripping leaves no\n   physical subject, ask what is in the frame. Do not generate.\n4. Choose aspectRatio from the slot. Put resolution, mode, and useLogo in\n   API fields, not in the prompt.\n5. Generate one still. Return imageUrl, aspectRatio, mode, resolution,\n   useLogo, and a placement note: files tool plus the email module, landing\n   page, campaign thumbnail, or ad the human named.\n6. Do not tell the user HubSpot changed unless a HubSpot call you actually\n   performed returned success. A files upload is not an email send.\n\nHubSpot, only when the human already supplied a token and asked for a\nfiles import or a HubDB draft update:\n- Authorization: Bearer, the HubSpot token. Never the Brandiseer key.\n- Files import: POST https://api.hubapi.com/files/2026-09/files/import-from-url/async\n  Follow https://developers.hubspot.com/docs/api-reference/latest/files/files/import-from-url\n  Set url to the public Brandiseer imageUrl. If HubSpot cannot fetch it,\n  tell the human to download and upload in Content > Files.\n- Poll GET https://api.hubapi.com/files/2026-09/files/import-from-url/async/tasks/{taskId}/status\n  until the Files API guide status is COMPLETE or CANCELED.\n- Multipart upload, when you have the file bytes:\n  POST https://api.hubapi.com/files/2026-09/files\n  Follow https://developers.hubspot.com/docs/api-reference/latest/files/guide\n- HubDB image, only with a real table id, row id, and column name:\n  PATCH https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/rows/{rowId}/draft\n  Image object shape from\n  https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/guide\n  Do not call\n  POST https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/draft/publish\n  unless the human explicitly asks after they have reviewed the draft.\n  That publish updates website pages that use the table.\n- Do not patch marketing email content. A person places the file in the\n  email editor.\n\nOut of scope:\n- Slack replies, Buffer scheduling, Zapier, Make, or n8n scenarios, and\n  Webflow Designer.\n- Legal approval of claims, prices, or offers printed on the image.\n- GET https://brandiseer.com/api/v1/usage (browser session only).\n```\n\n### Prompt rewriter\n\nUse 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.\n\n```javascript\n// Local rewriter for a Cursor or Cowork helper script.\n// Keeps subject, layout, composition, and on-image text.\n// Strips colour, type, mood, and visual-style language.\n\nconst STYLE_WORDS =\n  /\\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;\n\nconst SLOT_TO_RATIO = {\n  \"email header\": \"16:9\",\n  header: \"16:9\",\n  email: \"16:9\",\n  hero: \"16:9\",\n  \"landing hero\": \"16:9\",\n  \"landing page\": \"16:9\",\n  banner: \"16:9\",\n  \"16:9\": \"16:9\",\n  thumbnail: \"1:1\",\n  \"campaign thumbnail\": \"1:1\",\n  square: \"1:1\",\n  \"1:1\": \"1:1\",\n  ad: \"1:1\",\n  \"ad still\": \"1:1\",\n  \"4:3\": \"4:3\",\n  slide: \"4:3\",\n  portrait: \"9:16\",\n  story: \"9:16\",\n  \"9:16\": \"9:16\",\n};\n\nfunction rewriteBrandiseerPrompt(input) {\n  const headline = String(input.headline || \"\").trim();\n  const subject = String(input.subject || input.brief || \"\").trim();\n  const slotKey = String(input.slot || input.crop || \"\").trim().toLowerCase();\n  const aspectRatio = SLOT_TO_RATIO[slotKey] || \"\";\n\n  let prompt = [subject, headline ? `On-image text: \"${headline}\".` : \"\"]\n    .filter(Boolean)\n    .join(\" \");\n\n  prompt = prompt\n    .replace(/#[0-9a-f]{3,8}\\b/gi, \" \")\n    .replace(STYLE_WORDS, \" \")\n    .replace(/\\s+/g, \" \")\n    .trim();\n\n  return {\n    prompt,\n    aspectRatio,\n    needsSubject: prompt.length < 12 || !aspectRatio,\n  };\n}\n```\n\nIf `needsSubject` is true, ask the human for a subject and a slot. Do not POST."},{"id":"add-ons","heading":"Add-ons","markdown":"Add these after the header smoke test passes. They do not change Brandiseer's image contract, and they do not give Brandiseer a HubSpot push.\n\n### Approval before send\n\nAfter `imageUrl` is in the files tool and on the draft email, page, or ad, a named reviewer checks the still in HubSpot. Only then send the email, publish the page, or publish the ad. Until that happens, leave the content in draft. Brandiseer does not approve legal claims, prices, or offers.\n\n### One brand per HubSpot portal\n\nKeep a table: HubSpot portal name, token secret name, and `bds_c_...`. Require a token on every API write when more than one portal exists. If the name misses, stop and list the portals you configured. Confirm Brand IDs with `GET /api/v1/brands`. Never fall through to another client's Brand ID or another portal's token.\n\n### Credit soft-limit\n\nWhen `credits` is under a threshold you choose (for example 40), switch new campaign 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.\n\n### Placement log\n\nKeep a short note next to the work: email, page, or ad, slot, `brandId`, `mode`, `aspectRatio`, `resolution`, `imageUrl`, and whether it was uploaded in the files tool, imported by the Files API, or written to a HubDB draft row. Brandiseer does not write this log. HubSpot does not send it back to Brandiseer.\n\n### Handoff to the sibling guides\n\n- Stills requested in Slack, returned in a thread: [Slack creative desk](/use-cases/slack-creative-desk).\n- Captions and a Buffer schedule: [Social media automation](/use-cases/social-media-automation).\n- A Zapier, Make, or n8n trigger that should deliver `imageUrl` on a schedule: [Always-on creative automation](/use-cases/always-on-creative-automation).\n- Homepage and CMS stills that live on a Webflow site: [Webflow site visuals](/use-cases/webflow-site-visuals).\n\nDo not embed Buffer, a Slack desk, an always-on HTTP scenario, or a Webflow Designer step inside this HubSpot guide.\n\n### Optional motion (not the campaign MVP)\n\nVideo 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. A HubSpot ad that accepts video is a separate upload in the ads tool. Leave this off unless the brief explicitly asks to animate."},{"id":"limits-and-faq","heading":"Limits & FAQ","markdown":"### Does Brandiseer update HubSpot emails, pages, or ads?\n\nNo. Brandiseer returns `imageUrl`. A person uploads the file in the files tool and places it in an email image module, a landing page, or an ad. A Files API upload only adds a file to the files tool. A HubDB draft update only changes table data. Neither call sends an email or publishes an ad.\n\n### Is there a Brandiseer app inside HubSpot?\n\nNo. There is no Brandiseer panel in the email editor in this guide. Do not look for a native \"send to HubSpot\" button on the Brandiseer side.\n\n### What if HubSpot rejects the image?\n\nCheck [Supported file types and sizes](https://knowledge.hubspot.com/files/supported-file-types) and the marketing-email note on [Use images in HubSpot content](https://knowledge.hubspot.com/website-pages/use-images-in-hubspot-content). Marketing emails accept `.png`, `.ico`, `.bmp`, `.jpg`, and `.gif`. The files tool also lists `webp`, `tif`, and `tiff`, which the email note does not. If the picker rejects the file, export PNG or JPEG and upload that. Files on free tools are limited to 20 MB. An import also fails when HubSpot cannot fetch `imageUrl`. Download the still and upload the bytes.\n\n### Which HubSpot calls are in this guide?\n\nOnly calls confirmed on HubSpot's developer pages, and only at the level those pages describe:\n\n- Files upload: `POST https://api.hubapi.com/files/2026-09/files` on the [Files API guide](https://developers.hubspot.com/docs/api-reference/latest/files/guide)\n- Import from URL: `POST https://api.hubapi.com/files/2026-09/files/import-from-url/async` and status `GET https://api.hubapi.com/files/2026-09/files/import-from-url/async/tasks/{taskId}/status` on [Import file from URL](https://developers.hubspot.com/docs/api-reference/latest/files/files/import-from-url) and the Files API guide\n- HubDB image value: the create-row example on the [HubDB guide](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/guide)\n- HubDB draft row: `PATCH https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/rows/{rowId}/draft` on [Update a row](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/rows/update-hubdb-draft-rowId)\n- HubDB publish, after review: `POST https://api.hubapi.com/cms/hubdb/2026-09/tables/{tableIdOrName}/draft/publish` on [Publish a table from draft](https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/tables/publish-table-draft)\n\nFolder ids, table ids, row ids, and column names come from your portal and from those pages. This guide does not invent a \"set email header\" endpoint.\n\n### Can I use HubSpot's own MCP?\n\nHubSpot documents a remote MCP server at `https://mcp.hubspot.com` ([AI tools](https://developers.hubspot.com/ai-tools/mcp), [remote server](https://developers.hubspot.com/docs/apps/developer-platform/build-apps/integrate-with-the-remote-hubspot-mcp-server)). This guide does not depend on it and does not name its tools. If you connect it, call only tools that server actually exposes. Brandiseer still only returns the still. A HubSpot tool that matches the Files API or a HubDB image column is fine when its schema matches those pages. Do not assume a tool writes an email module.\n\n### Where do the keys live?\n\nThe Brandiseer key (`bds_...`) and the HubSpot token live in the agent host's secret store. Never in a CRM property, a Slack message, a prompt you commit, or a workflow export in git. Rotate either key if it leaks. Poll a Brandiseer job with the same Brandiseer key that submitted it. Call HubSpot with the HubSpot token.\n\n### What do stills cost?\n\nCredits per still. Failures refund. Async submits deduct immediately and refund if the job fails.\n\n| Mode | 1K | 2K | 4K |\n| --- | --- | --- | --- |\n| Fast | 4 | 6 | 8 |\n| Design | 5 | 6 | 8 |\n| Pro | 6 | 8 | 10 |\n\n`402` means not enough credits. Pricing context: [brandiseer.com/pricing](https://brandiseer.com/pricing).\n\n### Why is the still off-brand?\n\nAlmost always because the prompt contained colours, fonts, mood, or visual style. Strip them and generate again. See [guide/image](https://brandiseer.com/guide/image).\n\n### Why does the crop look wrong in the ad preview?\n\nBrandiseer aspect ratios are `1:1`, `16:9`, `9:16`, and `4:3`. Generate the closest slot, then crop in HubSpot. Network pixel rules belong to the ad network and to HubSpot's ads editor. This guide does not invent a Facebook or LinkedIn pixel size.\n\n### How long can I poll?\n\nAbout 10 minutes, then the Brandiseer 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.\n\n### Which generate URL should new campaign work use?\n\n`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.\n\n### Does the agent approve claims on the image?\n\nNo. If the still has a price, a discount, or a legal line, a person reads it before send or publish. Brandiseer does not review the claim.\n\n### Are files public?\n\nHubSpot's upload article says files in the files tool are hosted on a public file URL by default. The Files API guide says a private file's returned URL results in `404`, and a signed URL is the way to view it. Emails and landing pages that must render the image need a public file. Choose the public access value on the import schema when you use the API, and follow HubSpot's file visibility settings when you upload by hand."},{"id":"demo","heading":"Demo / motion","markdown":"**Motion brief only. This is not an embed, and there is no walkthrough URL yet.**\n\n**Working title:** HubSpot campaign creatives\n**Length:** 45 to 75 seconds\n\n**Story beats:**\n\n1. A person asks Cursor or Cowork for an email header with a layout-only brief\n2. The agent calls Brandiseer (MCP or REST v2) and shows an on-brand still\n3. `imageUrl` is uploaded in HubSpot's files tool and placed on a draft marketing email\n4. Optional cut: the same still is selected on a draft landing page or a draft ad, still unsent\n5. A human sends or publishes only after the offer reads correctly\n\n**On screen:** the agent transcript with the prompt (no colour or mood words), one finished still, and the HubSpot files tool. Blur the Brandiseer API key and the HubSpot token. Do not show a fake video player in the guide."},{"id":"additional-1-example-flows","heading":"Example flows","markdown":"### Flow A: Email header, placed in a draft email\n\nThe brief: \"Email header for the spring drop. Product on the left. Leave the right half empty. The email heading will sit there. No logo on the image.\"\n\nThe agent selects the default `brandId`, sets `aspectRatio` to `16:9`, `mode` to `design`, `resolution` to `2K`, and `useLogo` to false, and returns `imageUrl`. You upload the file in **Content > Files** and assign it to the email image module. You send later, after the heading and the offer have been read by a person.\n\n### Flow B: Landing-page hero\n\nThe brief: \"Landing-page hero. Product along the bottom. Leave the top empty for the page heading. No on-image text.\"\n\nThe agent uses `16:9` and returns `imageUrl`. You upload the file and replace the hero image on the landing page. Leave the page unpublished if you are only proving the handoff. One Design 2K still costs 6 credits. A failure refunds that still.\n\n### Flow C: Campaign thumbnail\n\nThe brief: \"Square thumbnail for the spring campaign. Bottle in the centre. On-image text Spring drop along the bottom.\"\n\nThe agent uses `1:1`. \"Campaign thumbnail\" here means that square still. It is not a hidden property on the HubSpot campaign object. You upload it and use it wherever that campaign surface already accepts an image (the email, the landing page, or the ad). This guide does not invent a campaign-image API.\n\n### Flow D: Ad still, saved as a draft\n\nThe brief: \"Square still for the Facebook website-visit ad. Bottle centred. On-image text Spring drop in the top third.\"\n\nThe agent uses `1:1` and says the network may want a different frame. You upload the file, open **Marketing > Ads**, and set **Image/Video** on the draft. If the preview crops badly, use HubSpot's clone-and-edit crop on that image. Save and exit. Do not click **Publish** in the smoke test. LinkedIn image ads in HubSpot use the same idea: a person uploads the still on the ad. This flow is not Buffer scheduling.\n\n### Flow E: Credit check before a campaign set\n\nBefore a set of four stills (header, hero, thumbnail, ad), 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.\n\n### Flow F: Style-only brief\n\nThe brief: \"Make the header feel premium and moody.\"\n\nThe agent does not generate. It asks which email or page, 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."},{"id":"additional-2-related-use-cases","heading":"Related use cases","markdown":"- [Webflow site visuals](/use-cases/webflow-site-visuals): an agent generates site stills and a person places `imageUrl` in Webflow\n- [Always-on creative automation](/use-cases/always-on-creative-automation): Zapier, Make, or n8n calls Brandiseer REST and delivers `imageUrl` downstream\n- [Slack creative desk](/use-cases/slack-creative-desk): people request stills in Slack and get them back in-thread\n- [Social media automation](/use-cases/social-media-automation): on-brand images, captions, and Buffer scheduling"},{"id":"additional-3-links","heading":"Links","markdown":"| Resource | URL |\n| --- | --- |\n| Brandiseer | https://brandiseer.com |\n| Developers | https://brandiseer.com/developers |\n| API reference (guide/docs) | https://brandiseer.com/guide/docs |\n| Image prompt compatibility | https://brandiseer.com/guide/image |\n| Video prompting (optional motion) | https://brandiseer.com/guide/video |\n| MCP endpoint (agent hosts) | https://brandiseer.com/api/mcp |\n| API keys | https://brandiseer.com/settings/api |\n| Pricing / credits | https://brandiseer.com/pricing |\n| HubSpot | https://www.hubspot.com |\n| HubSpot Files API | https://developers.hubspot.com/docs/api-reference/latest/files/guide |\n| HubSpot import from URL | https://developers.hubspot.com/docs/api-reference/latest/files/files/import-from-url |\n| HubSpot files tool (CMS) | https://developers.hubspot.com/docs/cms/start-building/features/storage/file-manager |\n| Upload files | https://knowledge.hubspot.com/files/upload-files-to-use-in-your-hubspot-content |\n| Use images in HubSpot content | https://knowledge.hubspot.com/website-pages/use-images-in-hubspot-content |\n| Supported file types and sizes | https://knowledge.hubspot.com/files/supported-file-types |\n| Edit images | https://knowledge.hubspot.com/website-and-landing-pages/edit-images |\n| HubDB guide | https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/guide |\n| HubDB update draft row | https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/rows/update-hubdb-draft-rowId |\n| HubDB publish draft table | https://developers.hubspot.com/docs/api-reference/latest/cms/hubdb/tables/publish-table-draft |\n| Facebook ads in HubSpot | https://knowledge.hubspot.com/ads/create-facebook-and-linkedin-lead-ads-in-hubspot |\n| LinkedIn ads in HubSpot | https://knowledge.hubspot.com/ads/create-linkedin-ad-campaigns-in-hubspot |\n| HubSpot MCP (not required) | https://developers.hubspot.com/ai-tools/mcp |\n| Visual pack manifest | `assets/MANIFEST.md` |\n| Sibling: Webflow site visuals | https://blog.brandiseer.com/use-cases/webflow-site-visuals |\n| Sibling: Always-on creative automation | https://blog.brandiseer.com/use-cases/always-on-creative-automation |\n| Sibling: Slack creative desk | https://blog.brandiseer.com/use-cases/slack-creative-desk |\n| Sibling: Social media automation | https://blog.brandiseer.com/use-cases/social-media-automation |"},{"id":"additional-4-source","heading":"Source","markdown":"Public Use case README for HubSpot campaign creatives. Brandiseer MCP and REST v2 image generation from Cursor or Claude Cowork, then a human places `imageUrl` in HubSpot's files tool, a marketing email, a landing page, or an ad. Aligned with [guide/docs](https://brandiseer.com/guide/docs) and [guide/image](https://brandiseer.com/guide/image) (23 September 2026). Optional Files API and HubDB calls follow HubSpot's `2026-09` endpoint pages. Brandiseer does not push into HubSpot. Distinct from Webflow site visuals, Slack creative desk, Buffer social scheduling, and Zapier, Make, or n8n always-on HTTP."},{"id":"api-reference","heading":"API reference","markdown":"Wiring reference for agents and HTTP modules. The sections above are the human path.\n\n### MCP (interactive stills in Cursor or Cowork)\n\nConnect `https://brandiseer.com/api/mcp` with `Authorization: Bearer` and the API key. The only tools this guide uses are:\n\n- `brandiseer_list_brands`\n- `brandiseer_check_credits`\n- `brandiseer_generate_image`\n\nDo not invent extra Brandiseer tool names. If the host needs explicit `mode`, `aspectRatio`, or async polling, use REST v2 below. MCP does not edit HubSpot.\n\n### REST (prefer v2 images)\n\nSend `X-API-Key: bds_...` on every authenticated Brandiseer call. There is no official SDK. Any HTTP client the agent host can run is enough.\n\n| Call | What you get |\n| --- | --- |\n| `POST https://brandiseer.com/api/v2/generate` | Sync still. `200` body `{ \"imageUrl\", \"creditsUsed\" }`. Design mode often takes 40 to 70 seconds. |\n| `POST https://brandiseer.com/api/v2/generate/async` | `202` body `{ \"data\": { \"jobId\" } }` (ids look like `bds_job_...`). Credits are deducted when you submit. |\n| `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. |\n| `POST https://brandiseer.com/api/v1/generate` | Legacy only. `proMode` boolean. Fast and Pro only. Prefer v2. |\n| `GET https://brandiseer.com/api/v1/credits` | JSON includes `credits`, the current balance for that key. |\n| `GET https://brandiseer.com/api/v1/brands` | Brands for the key. Each brand `id` looks like `bds_c_...`. |\n| `GET https://brandiseer.com/api/v1/health` | `{ \"status\": \"ok\" }`. No API key. |\n\nImage 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`.\n\nSync 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.\n\nDone job body: `{ \"data\": { \"status\": \"done\", \"imageUrl\", \"creditsUsed\", \"referenceImage\" } }`. Hand `data.imageUrl` to HubSpot. Failed job body: `{ \"data\": { \"status\": \"failed\", \"error\": { \"code\", \"message\" } } }`.\n\nCursor 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 HubSpot at the Brandiseer MCP URL.\n\n### Field mapping\n\n| Incoming field | API | Rule |\n| --- | --- | --- |\n| Slot (email header, landing hero, thumbnail, ad) | `aspectRatio` | Header and landing hero: `16:9`. Thumbnail: `1:1`. Ad: `1:1` or `16:9`. Portrait: `9:16`. Slide: `4:3`. |\n| headline | inside `prompt` only | On-image text and placement. Not a separate body field. Leave it out when HubSpot text will set the headline. |\n| brandId | `brandId` | `bds_c_...`. Required. |\n| mode | `mode` | `fast`, `design`, or `pro`. Omit and the API uses `fast`. Prefer `design` for campaign stills. |\n| useLogo | `useLogo` | `true` or `false`. |\n| subject or brief | `prompt` | After the rewriter. If the cleaned text has no subject, do not call Brandiseer. |\n| resolution | `resolution` | `1K`, `2K`, or `4K`. Prefer `2K` or `1K` for email. |\n\n### Example JSON\n\nUse this body for both sync and async. Only the URL and the response change.\n\n```json\n{\n  \"brandId\": \"bds_c_...\",\n  \"prompt\": \"Wide email header. Product centred on the left third. Empty right half for a headline the email will set in HubSpot. No on-image text.\",\n  \"aspectRatio\": \"16:9\",\n  \"resolution\": \"2K\",\n  \"mode\": \"design\",\n  \"useLogo\": false\n}\n```\n\nSync: `POST https://brandiseer.com/api/v2/generate`. A Design 2K still costs 6 credits, so a success body looks like:\n\n```json\n{\n  \"imageUrl\": \"https://...\",\n  \"creditsUsed\": 6\n}\n```\n\nAsync: `POST https://brandiseer.com/api/v2/generate/async`. HTTP `202`:\n\n```json\n{\n  \"data\": {\n    \"jobId\": \"bds_job_...\"\n  }\n}\n```\n\nPoll `GET https://brandiseer.com/api/v2/jobs/bds_job_...` with the same `X-API-Key`. When it finishes:\n\n```json\n{\n  \"data\": {\n    \"status\": \"done\",\n    \"imageUrl\": \"https://...\",\n    \"creditsUsed\": 6,\n    \"referenceImage\": null\n  }\n}\n```\n\nWhen it fails (credits are refunded):\n\n```json\n{\n  \"data\": {\n    \"status\": \"failed\",\n    \"error\": {\n      \"code\": \"...\",\n      \"message\": \"...\"\n    }\n  }\n}\n```\n\nIgnore `referenceImage` for delivery. HubSpot gets `imageUrl` (or a file you downloaded from it).\n\nSlot prompts that stay layout-only:\n\n| Slot | aspectRatio | Prompt |\n| --- | --- | --- |\n| Email header | `16:9` | Wide email header. Product centred on the left third. Empty right half for a headline the email will set in HubSpot. No on-image text. |\n| Landing-page hero | `16:9` | Wide landing-page hero. Product cluster along the bottom edge. Upper two thirds empty for a page heading. No on-image text. |\n| Campaign thumbnail | `1:1` | Square campaign thumbnail. Single product in the centre. On-image text: \"Spring drop\" along the bottom edge. |\n| Ad still | `1:1` | Square ad still. Product centred. On-image text: \"Spring drop\" in the top third. Empty corner bottom right. |"}],"actions":{"tryBrandiseer":"https://brandiseer.com","createApiKey":"https://brandiseer.com/settings/api","developerDocs":"https://brandiseer.com/developers","mcpEndpoint":"https://brandiseer.com/api/mcp"},"representations":{"html":"https://blog.brandiseer.com/use-cases/hubspot-campaign-creatives","markdown":"https://blog.brandiseer.com/use-cases/hubspot-campaign-creatives/agent.md","json":"https://blog.brandiseer.com/use-cases/hubspot-campaign-creatives/guide.json"}}