---
slug: drive-slides-deck-visuals
title: Drive & Slides deck visuals
outcome: "An agent generates on-brand stills with Brandiseer for Google Slides decks and Google Drive files (title slide heroes, section dividers, product or feature slide stills, chart or agenda thumbs); a person then downloads imageUrl and inserts into Slides or uploads to Drive, or an agent with Google OAuth / service account credentials uploads to Drive and/or places the image in Slides via presentations.batchUpdate createImage. Brandiseer does not create Drive files or Slides presentations and does not sync."
category: creative-mcp
featured: false
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: Google Drive
    role: File storage and optional public share for Slides-hosted URLs
    href: https://drive.google.com
  - name: Google Slides
    role: Presentation slides and createImage placement
    href: https://docs.google.com/presentation/
  - name: Cursor
    role: Agent host for Brandiseer MCP or REST (optional Google API write)
  - name: Claude Cowork
    role: Agent host for Brandiseer MCP or REST (optional Google API write)
developerDocs: https://brandiseer.com/developers
updated: "2026-10-03"
draft: false
status: ready-to-publish
---

# Drive & Slides deck visuals

**Brandiseer + Google Drive + Google Slides (+ Cursor or Claude Cowork)**

![Cover: an on-brand still landing on a deck slide](https://blog.brandiseer.com/use-case-assets/drive-slides-deck-visuals/cover-drive-slides-deck-visuals.png)

By the end of this guide you will have a repeatable way to make on-brand stills for Google Slides decks and Google Drive files. An agent in Cursor or Claude Cowork calls Brandiseer, gets an `imageUrl` for a title slide hero, a section divider, a product or feature slide still, or a chart or agenda thumb, and that file is inserted in Slides or stored in Drive.

Brandiseer owns the brand memory and the still. Google Drive owns the file. Google Slides owns the presentation and where the image sits on a slide. Brandiseer returns `imageUrl` only. It does not create Drive files, it does not create Slides presentations, and it does not sync. There is no Brandiseer Google app in this guide, and there is no Drive MCP or Slides MCP in this guide. The default handoff is a person: download the file (or open `imageUrl`) and use Insert, then Image in the Slides UI, or upload the file to Drive and insert it from there. Optionally, an agent that already holds Google OAuth or a service account can upload the PNG bytes with Drive `files.create`, and can place a publicly accessible HTTPS URL with Slides `presentations.batchUpdate` `createImage`. A person still reviews the deck before it is presented as final.

> People who keep issue and project stills in Linear should use [Linear issue visuals](/use-cases/linear-issue-visuals). People who keep campaign records in Airtable should use [Airtable record visuals](/use-cases/airtable-record-visuals). 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, product, and ops teams who already build decks in Google Slides, or keep files in Google Drive, and need an on-brand still without opening a separate design tool for every slide
- Agencies that keep one Brandiseer Brand ID per client and one Google account, shared drive, or named Drive folder per client
- Operators who can download an `imageUrl` and insert it in the Slides UI, or who already give an agent Google OAuth or a service account and want that agent to upload the PNG or place a public URL on a slide that already exists

**Ideal customer profile:** a team whose decks already live in Google Slides, whose files already live in Google Drive, whose brand already lives in Brandiseer, and whose missing piece is a brand-safe still plus a clear handoff into the Slides UI, a Drive folder, or a `createImage` call on a deck the human already named.

## Why Brandiseer in this stack

Google Slides is where the deck lives. Google Drive is where the file lives when someone wants a copy in a folder. Cursor or Cowork is the agent that turns a 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 deck drifts when every hero is a one-off export from a general image tool. Brandiseer keeps the still on the same brand as the rest of the work. Slides still decides which presentation and which slide hold the image. Drive still decides which folder holds the file.

This is a different job from the sibling guides:

- [Linear issue visuals](/use-cases/linear-issue-visuals) hands `imageUrl` to a Linear issue or project.
- [Airtable record visuals](/use-cases/airtable-record-visuals) hands `imageUrl` into an Airtable Attachment field.
- [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 deck stills and hands `imageUrl` to Google Slides or Google Drive. Brandiseer does not push into Drive or Slides by itself.

![Example strip: title slide hero, section divider, product or feature slide, and chart or agenda thumb](https://blog.brandiseer.com/use-case-assets/drive-slides-deck-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 brief, call Brandiseer, return `imageUrl` and a placement note. Optional Google API write |
| Agent host (pick one) | Claude Cowork | Same contract as Cursor for interactive deck stills |
| File storage | Google Drive | Store the PNG when the human wants it in a folder. Optional anyone-with-link reader share when Slides must fetch a Drive URL |
| Deck | Google Slides | Slides in a presentation that already exists. A person inserts by default. Optional `createImage` on a public HTTPS URL |

![Stack diagram: Cursor or Cowork, Brandiseer, and Google Drive plus Slides](https://blog.brandiseer.com/use-case-assets/drive-slides-deck-visuals/stack-diagram.png)

You only need one agent host. The Brandiseer contract is the same on both. There is no Brandiseer Google app that drops a still onto a slide or into a Drive folder. The handoff is an image URL, a download, or a Google API call that you perform with Google's own APIs. This guide does not use a Drive MCP or a Slides MCP. Do not invent either.

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

**Google docs:** [Add an image (Slides)](https://developers.google.com/workspace/slides/api/guides/add-image) · [Slides batchUpdate](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/batchUpdate) · [Drive upload](https://developers.google.com/workspace/drive/api/guides/manage-uploads) · [Drive files.create](https://developers.google.com/workspace/drive/api/reference/rest/v3/files/create) · [Drive permissions.create](https://developers.google.com/workspace/drive/api/reference/rest/v3/permissions/create)

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

### Google Drive and Google Slides (placement, not generation)

Three practical paths. Use the first one until a Google API write is actually needed. Brandiseer is finished when it returns `imageUrl`.

1. **Slides UI (default).** Download the file or open `imageUrl`. On the deck the human named, use Insert, then Image, and place the still. You can also upload the file to Drive in the Drive UI, then insert that Drive file into the slide. Brandiseer stops at the URL. Drive and Slides store their own copies.
2. **Slides `createImage` with the public Brandiseer `imageUrl` (simplest agent path).** Call `presentations.batchUpdate` with a `createImage` request. `createImage.url` must be a publicly accessible HTTPS URL, and that URL must be at most 2 KB long. A public Brandiseer `imageUrl` works directly. Slides fetches the image once and stores a copy in the presentation. `presentationId` and `pageObjectId` come from the deck the human already has. See [Add an image](https://developers.google.com/workspace/slides/api/guides/add-image). This is a Google call with the human's OAuth token or service account. It is not a Brandiseer push.
3. **Drive upload, then share only if Slides must fetch a Drive URL.** Download the PNG bytes from `imageUrl`. Upload those bytes with Drive `files.create` as a multipart upload (`uploadType=multipart`, files of 5 MB or less). Use this when the human wants the file in a Drive folder, or as an archive next to the deck. If the next step is `createImage` and the URL must be Drive-hosted, call `permissions.create` with `type` `anyone` and `role` `reader`, then pass `https://drive.google.com/uc?id=FILE_ID` (or an equivalent `export=view` or `export=download` URL). That Drive URL works for Slides only after the anyone-with-link reader share. A private Drive file is not publicly accessible, and `createImage` will fail. Prefer path 2 when `imageUrl` is already public.

`presentationId` is the id in `https://docs.google.com/presentation/d/PRESENTATION_ID/edit`. `pageObjectId` is the slide id. In the Slides URL it is the value after `#slide=id.`. You can also read `slides[].objectId` from `presentations.get`. Do not guess either id. This guide does not create a new presentation as the default. The still goes on a deck that already exists.

Google credentials belong to the human's Google Cloud project. Brandiseer does not manage that OAuth and does not issue a service account. Typical scopes are `https://www.googleapis.com/auth/drive.file` (files this client creates, including the uploaded PNG) and `https://www.googleapis.com/auth/presentations` (Slides the Google account can already edit). `drive.file` does not open every file in Drive. A service account can write only what has been shared with its email, unless a Workspace admin has set domain-wide delegation.

A person still reviews the deck before it is presented as final.

## How it works

Architecture, from brief to a still sitting on a slide or in a Drive folder:

1. **Brief.** You name the slot: title slide hero, section divider, product or feature slide still, or chart or agenda thumb. The agent rewrites that brief into subject, layout, and on-image text.
2. **Generate.** The agent calls Brandiseer with `aspectRatio`, `resolution`, `mode`, and `useLogo` as fields. Deck slots use `16:9`. A chart or agenda thumb uses `1:1` only when the human asks. Prefer `design` and `2K`.
3. **`imageUrl`.** Brandiseer returns `imageUrl` only. The agent reports the URL, the crop, the mode, and a one-line placement note (which deck, which slide, or which Drive folder). It does not claim Drive or Slides changed unless a Google call you actually performed returned success.
4. **Drive upload or Slides place.** A person downloads the file and inserts it in the Slides UI, or uploads it to Drive and then inserts it. Optionally, an agent with Google credentials places the public `imageUrl` with `createImage`, or uploads the PNG bytes to Drive and shares the file before using a Drive URL.
5. **Human reviews and presents.** A person checks the slide. The deck is not treated as final until that review happens. Brandiseer does not present the deck and does not sync it.

![Workflow infographic: brief, generate, imageUrl, Drive upload or Slides place, human reviews](https://blog.brandiseer.com/use-case-assets/drive-slides-deck-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
- A Google account that can edit the Slides deck, and a Drive folder if the file should be stored there
- For any Google API write: `presentationId` and `pageObjectId` copied from the existing deck. Do not guess them. A folder id, only when the upload must land in a named folder
- Optional, only for Google API writes: OAuth credentials for a Google Cloud project with the Drive API and the Slides API enabled, or a service account key. Typical scopes are `https://www.googleapis.com/auth/drive.file` and `https://www.googleapis.com/auth/presentations`. Brandiseer is not the OAuth app
- For a service account: the target presentation shared with the service account email (Editor), and the destination Drive folder shared the same way if you set `parents`. Domain-wide delegation is the Workspace alternative, and a domain admin sets that up. A service account has no consumer Drive storage of its own, so set `parents` to a folder a person owns
- Store the Brandiseer key and the Google credential in the agent secret store. Never in a slide, 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 deck 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 decks 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 a slide, a Drive file, 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 deck 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 Google API writes are in scope, also note that the Google credential lives in the secret store. Leave `presentationId`, `pageObjectId`, and folder ids blank until the human names them.
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 title slide in the Slides UI

1. Ask for one title slide 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 Google Slides deck, use Insert, then Image, place that file, and confirm the image shows.
4. Leave the deck unmarked as final if you are only proving the handoff.
5. Send a second brief that only says "make the title slide premium and moody". The agent should ask what is physically in the frame instead of generating.

### Stage 6: Optional Google OAuth or service account write

Skip this stage if people will insert stills by hand. Use it only when a Google credential is already in the secret store and the human named the deck, the slide, and, if needed, the Drive folder.

1. In a Google Cloud project the human owns, enable the Google Drive API and the Google Slides API. Brandiseer does not create this project and does not hold the client secret.
2. **OAuth.** Create an OAuth client and obtain an access token for the Google account that can edit the deck. Request `https://www.googleapis.com/auth/drive.file` and `https://www.googleapis.com/auth/presentations`. Send Google calls with `Authorization: Bearer ACCESS_TOKEN`. `drive.file` lets this client upload files it creates. It does not list the person's whole Drive. `presentations` lets that same account edit Slides it can already open. See [OAuth 2.0](https://developers.google.com/identity/protocols/oauth2).
3. **Service account.** Create a service account and download its key into the secret store. Share the target presentation with the service account email as Editor. Share the destination Drive folder with that same email when the upload uses `parents`. The other path is domain-wide delegation, which a Workspace admin configures so the service account can impersonate a user. See [Service accounts](https://developers.google.com/identity/protocols/oauth2/service-account). A service account has no consumer My Drive quota. Create the PNG inside a folder a person owns (`parents`), or the upload can fail because the service account's own storage is empty.
4. **Prefer a direct Slides place.** When `imageUrl` is public, call `POST https://slides.googleapis.com/v1/presentations/PRESENTATION_ID:batchUpdate` with one `createImage` request whose `url` is that `imageUrl`. Set `elementProperties.pageObjectId` to the slide the human named. Slides fetches the URL once. If the fetch fails, the URL is not publicly accessible, it is longer than 2 KB, or the bytes are not a PNG, JPEG, or GIF under 50 MB and 25 megapixels. See [Add an image](https://developers.google.com/workspace/slides/api/guides/add-image).
5. **Drive upload when the human wants the file in Drive.** Download the PNG bytes from `imageUrl`. `POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart` with metadata JSON first and the PNG bytes second. Multipart is for files of 5 MB or less. The response `id` is `FILE_ID`. See [Upload file data](https://developers.google.com/workspace/drive/api/guides/manage-uploads).
6. **Share only when Slides must use a Drive URL.** `POST https://www.googleapis.com/drive/v3/files/FILE_ID/permissions` with `{ "type": "anyone", "role": "reader" }`. Omit `sendNotificationEmail` for an `anyone` permission. Then `createImage` may use `https://drive.google.com/uc?id=FILE_ID` or `https://drive.google.com/uc?export=view&id=FILE_ID`. Skip this share when you already passed the public Brandiseer `imageUrl` to `createImage`.
7. Confirm the Google response has no error. Then stop. A person reviews the deck. Do not tell the human the slide updated when the call failed. Do not create a new presentation unless the human asked for that separate add-on.

## 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 deck slot to a documented ratio. Title slide hero: `16:9`. Section divider: `16:9`. Product or feature slide still: `16:9`. Chart or agenda thumb: `16:9`, or `1:1` only when the human asks for a square. Portrait, only when the brief truly needs it: `9:16`. Brandiseer also offers `4:3`. None of the slots above require it. Use `4:3` only when the human asks for that frame.
- Prefer `design` for finished deck stills. `fast` is the API default if you omit `mode`, and it is the right fallback if a design job fails once.
- Prefer `2K` for these stills. Use `1K` when file size or speed matters. Use `4K` only when the brief asks for it.
- Set `useLogo` true only when the brief asked for a logo (or your default says so). Titles that the slide title placeholder 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 deck stills. Replace the placeholders before the first generate.

```text
You generate on-brand stills for Google Slides decks and Google Drive
files. Brandiseer returns an image URL. You do not create Drive files,
you do not create Slides presentations, you do not sync Drive or Slides,
and you do not claim a file or a slide changed unless a Google call 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 a Google integration. There is no Brandiseer
  Google app in this guide. There is no Drive MCP and no Slides MCP.

Defaults for this workspace (fill in once):
- Brand ID: bds_c_...
- Title slide hero aspectRatio: 16:9
- Section divider aspectRatio: 16:9
- Product or feature slide still aspectRatio: 16:9
- Chart or agenda thumb aspectRatio: 16:9 (1:1 only if the human asks)
- Portrait aspectRatio, only if the brief truly needs it: 9:16
- 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_...

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. Deck slots are 16:9. Use 1:1 for a
   chart or agenda thumb only when the human asked for a square. Put
   resolution, mode, and useLogo in API fields, not in the prompt.
5. Generate one still. Return imageUrl, aspectRatio, mode, resolution,
   useLogo, and a placement note: which deck and slide, or which Drive
   folder, the human named, and which path (Slides UI insert, createImage
   with the public imageUrl, or Drive upload).
6. Do not tell the user Drive or Slides changed unless a Google API call
   you actually performed returned success and no error.

Google placement, only when the human already asked for it:
- Default path: the human downloads imageUrl (or opens it) and uses
  Insert, then Image in the Slides UI. Or they upload the file to Drive
  and insert it from Drive. You do not claim that happened.
- There is no Brandiseer Google app. Do not invent a Drive MCP or a
  Slides MCP. Credentials are the human's OAuth token or service account.
  Header: Authorization: Bearer ACCESS_TOKEN.
  Typical scopes:
  https://www.googleapis.com/auth/drive.file
  https://www.googleapis.com/auth/presentations
- presentationId and pageObjectId come from the existing deck. Copy
  presentationId from
  https://docs.google.com/presentation/d/PRESENTATION_ID/edit
  Copy pageObjectId from the URL after #slide=id. or from
  GET https://slides.googleapis.com/v1/presentations/PRESENTATION_ID
  (slides[].objectId). Do not guess. Do not call presentations.create
  unless the human asked to make a new deck.
- Simplest agent path: presentations.batchUpdate createImage with the
  public Brandiseer imageUrl. Slides fetches that URL once. The URL must
  be publicly accessible HTTPS and at most 2 KB long. The image must be
  PNG, JPEG, or GIF, under 50 MB and 25 megapixels.
  POST https://slides.googleapis.com/v1/presentations/PRESENTATION_ID:batchUpdate
  Docs: https://developers.google.com/workspace/slides/api/guides/add-image
- Drive upload is for a folder archive, or when the human wants the file
  in Drive first. Download the PNG bytes from imageUrl. Then
  POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart
  Metadata JSON first, PNG bytes second. Multipart is for files of 5 MB
  or less. Docs:
  https://developers.google.com/workspace/drive/api/guides/manage-uploads
- A Drive URL works in createImage only after
  POST https://www.googleapis.com/drive/v3/files/FILE_ID/permissions
  with type anyone and role reader. Then use
  https://drive.google.com/uc?id=FILE_ID
  or https://drive.google.com/uc?export=view&id=FILE_ID
  Docs: https://developers.google.com/workspace/drive/api/reference/rest/v3/permissions/create
- Prefer the public imageUrl in createImage when it is already public.
  Do not upload to Drive only to obtain a URL.
- Service accounts: the presentation, and any parent folder, must be
  shared with the service account email, or the domain must use
  domain-wide delegation. Set parents to a folder a person owns.
- A person still reviews the deck before it is presented as final.

Out of scope:
- Slack replies, Buffer scheduling, and Zapier, Make, or n8n scenarios.
- Linear, Airtable, Webflow, WordPress, and Framer handoffs (use those guides).
- Creating Drive files or Slides presentations as the default outcome.
- 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 = {
  title: "16:9",
  "title slide": "16:9",
  "title slide hero": "16:9",
  hero: "16:9",
  divider: "16:9",
  "section divider": "16:9",
  section: "16:9",
  product: "16:9",
  feature: "16:9",
  "product slide": "16:9",
  "feature slide": "16:9",
  "product still": "16:9",
  "feature still": "16:9",
  "slide still": "16:9",
  chart: "16:9",
  agenda: "16:9",
  thumb: "16:9",
  "chart thumb": "16:9",
  "agenda thumb": "16:9",
  "chart or agenda thumb": "16:9",
  "16:9": "16:9",
  square: "1:1",
  "1:1": "1:1",
  portrait: "9:16",
  "9:16": "9:16",
  "4:3": "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. Chart and agenda keys above default to `16:9`. If the human asked for a square thumb, pass slot `square` or `1:1` before you generate. Use `9:16` only when the brief truly needs a portrait. Use `4:3` only when the human names that frame.

## Example flows

### Flow A: Title slide, inserted by a person

The brief: "Title slide hero for the spring deck. Product on the left. Leave the right half empty. The slide title will hold the headline. No logo on the image. 16:9."

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 use Insert, then Image on that slide. You review the deck later, after the still looks right next to the title. Brandiseer did not create the presentation.

### Flow B: Four deck stills, inserted by a person

The brief lists four slots: a title slide hero, a section divider, a product or feature slide still, and a chart or agenda thumb. Each one says what is in the frame, asks for `16:9`, and keeps the slide title in Slides rather than on the image. The agent generates four stills, all `16:9`, and labels them with the slot. You insert each file on its slide, or you upload the four files to the Drive folder and insert from there. Four Design 2K stills cost 24 credits if all succeed. Failures refund. A square chart thumb is a different request. Use `1:1` only if the human asked for it.

### Flow C: Slides createImage with the public imageUrl

The deck already exists. You have asked for an API write, and the Google credential is in the secret store. The brief names a `16:9` title slide hero and gives `presentationId` plus `pageObjectId`. The agent generates the still, then `presentations.batchUpdate` with `createImage.url` set to the public Brandiseer `imageUrl`. It does not upload to Drive. Slides fetches that URL once and stores a copy. You open the deck, confirm the image shows, and leave the deck unfinal until a person reviews it. If the call errors, the agent says so and does not claim the slide changed.

### Flow D: Drive upload, share, then createImage

The human wants the PNG in a named Drive folder and also on a slide, and they asked for a Drive-hosted URL. The agent downloads the bytes from `imageUrl`, uploads them with `files.create` multipart into that folder, then `permissions.create` with `type` `anyone` and `role` `reader`. It places `https://drive.google.com/uc?id=FILE_ID` with `createImage`. It does not call `createImage` with a private Drive link. If `imageUrl` is already public and the human only needed the slide, Flow C is the shorter path. Drive upload here is the archive, or the step the human asked for before placement. A person still reviews the deck before it is presented as final.

### Flow E: Credit check before a four-still deck

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 title slide feel premium and moody."

The agent does not generate. It asks which deck, what is physically in the frame, whether any words must appear on the image, and whether the logo is on. The frame stays `16:9` unless the human names another documented ratio. Colour, font, and mood stay out of the prompt.

## Add-ons

Add these after the title-slide smoke test passes. They do not change Brandiseer's image contract, and they do not give Brandiseer a Drive or Slides sync.

### Approval before the deck is presented as final

After `imageUrl` is on the slide or in Drive, a named reviewer checks the still in Slides. Until that happens, leave the deck as a draft in whatever status your team already uses. Brandiseer does not approve legal claims, prices, or offers. Brandiseer also does not know your review labels. Do not invent one, and do not mark the deck final as part of generating a still.

### One brand per client

Keep a table: Google account or shared drive, folder ids the credential may write, presentation ids the human has allowed, secret name, and `bds_c_...`. Require a named deck on every Slides write when more than one client exists. If the name misses, stop and list the clients you configured. Confirm Brand IDs with `GET /api/v1/brands`. Never fall through to another client's Brand ID or another account's credential.

### Credit soft-limit

When `credits` is under a threshold you choose (for example 40), switch new deck 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: presentation id, page object id or folder id, slot, `brandId`, `mode`, `aspectRatio`, `resolution`, `imageUrl`, Drive file id if you uploaded, and whether a person inserted it, `createImage` used the public `imageUrl`, or a Drive upload plus share placed it. Brandiseer does not write this log. Drive and Slides do not send it back to Brandiseer.

### Handoff to the sibling guides

- Issue and project stills in Linear: [Linear issue visuals](/use-cases/linear-issue-visuals).
- Record stills on Airtable Attachment fields: [Airtable record visuals](/use-cases/airtable-record-visuals).
- 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 a Linear workspace, an Airtable base, a Buffer schedule, a Slack desk, an always-on HTTP scenario, Webflow, WordPress, or Framer inside this Drive and Slides guide.

### Optional new presentation

The default in this guide is an existing deck. If the human explicitly asks for a new presentation, `POST https://slides.googleapis.com/v1/presentations` with a `title` creates an empty presentation and returns `presentationId` plus a first slide `objectId`. That call needs the `presentations` scope. It is still a Google API call, not a Brandiseer call. Then place the still with `createImage` on that returned page id. Skip this unless the human asked.

### Optional motion (not the deck 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. A slide can hold that video only after a person inserts the file, or after a separate Slides video request the human asked for. This guide's image path is `createImage`, not video. Leave motion off unless the brief explicitly asks to animate.

## Limits & FAQ

### Does Brandiseer create the Drive file or the Slides deck?

No. Brandiseer returns `imageUrl`. A person downloads that file and inserts it in Slides, or uploads it to Drive. An agent with Google OAuth or a service account can upload the bytes with Drive `files.create` and can place a public HTTPS URL with Slides `presentations.batchUpdate` `createImage`. None of those paths are a Brandiseer sync.

### Is there a Brandiseer app for Google Drive or Google Slides?

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

### Do I need a Drive MCP or a Slides MCP?

No. This guide uses the Slides UI, or the documented Drive and Slides REST APIs with the human's OAuth token or service account. Do not invent a Drive MCP or a Slides MCP. Brandiseer still only returns the still.

### Which Google calls are in this guide?

Only calls confirmed on Google's developer docs:

- Slides place: `POST https://slides.googleapis.com/v1/presentations/{presentationId}:batchUpdate` with `createImage`. The URL must be publicly accessible and at most 2 KB. Docs: [Add an image](https://developers.google.com/workspace/slides/api/guides/add-image)
- Read the existing deck: `GET https://slides.googleapis.com/v1/presentations/{presentationId}` for `slides[].objectId` and `pageSize`
- Drive upload: `POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart` with the PNG bytes. Docs: [Upload file data](https://developers.google.com/workspace/drive/api/guides/manage-uploads)
- Drive share, only for a Drive-hosted URL: `POST https://www.googleapis.com/drive/v3/files/{fileId}/permissions` with `type` `anyone` and `role` `reader`. Docs: [permissions.create](https://developers.google.com/workspace/drive/api/reference/rest/v3/permissions/create)

`presentationId` and `pageObjectId` come from the human's deck. This guide does not invent a "set slide background" Brandiseer endpoint, and it does not create presentations unless the human uses the optional add-on.

### Where do the keys live?

The Brandiseer key (`bds_...`) and the Google OAuth token or service account key live in the agent host's secret store. Never in a slide, a Drive doc, a Slack message, a prompt you commit, or a workflow export in git. Google credentials are created in the human's Google Cloud project. Brandiseer does not store them. Rotate either secret if it leaks. Poll a Brandiseer job with the same Brandiseer key that submitted it. Send Google calls as `Authorization: Bearer ACCESS_TOKEN`.

### 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 on the slide?

Brandiseer aspect ratios are `1:1`, `16:9`, `9:16`, and `4:3`. Generate the title slide hero, the section divider, the product or feature slide still, and the chart or agenda thumb at `16:9`. Use `1:1` only when the human asked for a square thumb. Use `9:16` only for a real portrait slot. If `createImage` size does not match the image aspect ratio, Slides scales and centers the image inside that box. For a full-slide `16:9` still, set the size from the deck's `pageSize`.

### How long can I poll?

About 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.

### Which generate URL should new deck 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.

### Why did createImage fail?

Check the constraints on [CreateImageRequest](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#CreateImageRequest). The URL must be publicly accessible HTTPS, at most 2 KB long. The file must be PNG, JPEG, or GIF, under 50 MB, and at most 25 megapixels. A private Drive link fails because Slides fetches the URL without the viewer's login. Share the file as anyone with role reader first, or pass the public Brandiseer `imageUrl` instead. `presentationId` and `pageObjectId` must be real ids from that deck. The token needs `https://www.googleapis.com/auth/presentations`, and the Google account must be able to edit the deck. A service account also needs the presentation shared with its email, unless domain-wide delegation is already in place.

### Why did the Drive upload fail?

Multipart upload is for files of 5 MB or less. A larger PNG needs `uploadType=resumable` on the same `files.create` method. See [Upload file data](https://developers.google.com/workspace/drive/api/guides/manage-uploads). The token needs `https://www.googleapis.com/auth/drive.file` or a broader Drive scope the human already chose. `drive.file` can create files for this client. It cannot browse the person's entire Drive. A service account upload into its own My Drive can fail for storage quota, because service accounts do not have consumer Drive storage. Set `parents` to a folder a person owns and has shared with the service account email.

### Does a Drive file stay private after upload?

Yes, until you change permissions. `files.create` does not make the file public. `createImage` cannot fetch a private Drive URL. Call `permissions.create` with `type` `anyone` and `role` `reader` only when a Drive-hosted URL must be public. Anyone with the link can then read that file. Prefer the Brandiseer `imageUrl` in `createImage` when you do not need a public Drive copy.

### 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 deck is presented 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:** Drive & Slides deck visuals
**Length:** 45 to 75 seconds

**Story beats:**

1. A person asks Cursor or Cowork for a title slide hero with a layout-only brief
2. The agent calls Brandiseer (MCP or REST v2) and shows an on-brand still
3. `imageUrl` is inserted on a Google Slides slide in the UI
4. Optional cut: `createImage` places the public URL on an existing slide, still unreviewed
5. A human reviews the deck only after the still looks right next to the title

**On screen:** the agent transcript with the prompt (no colour or mood words), one finished still, and the Slides slide with the image visible. Blur the Brandiseer API key and the Google credential. Do not show a fake video player in the guide.

## Related use cases

- [Linear issue visuals](/use-cases/linear-issue-visuals): Brandiseer stills placed on Linear issues and projects
- [Airtable record visuals](/use-cases/airtable-record-visuals): Brandiseer stills placed on Airtable Attachment fields
- [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 |
| Google Drive | https://drive.google.com |
| Google Slides | https://docs.google.com/presentation/ |
| Slides: add an image | https://developers.google.com/workspace/slides/api/guides/add-image |
| Slides: batchUpdate | https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/batchUpdate |
| Slides: CreateImageRequest | https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#CreateImageRequest |
| Drive: upload file data | https://developers.google.com/workspace/drive/api/guides/manage-uploads |
| Drive: files.create | https://developers.google.com/workspace/drive/api/reference/rest/v3/files/create |
| Drive: permissions.create | https://developers.google.com/workspace/drive/api/reference/rest/v3/permissions/create |
| Google OAuth 2.0 | https://developers.google.com/identity/protocols/oauth2 |
| Google service accounts | https://developers.google.com/identity/protocols/oauth2/service-account |
| Visual pack manifest | `assets/MANIFEST.md` |
| Live: Linear issue visuals | https://blog.brandiseer.com/use-cases/linear-issue-visuals |
| Live: Airtable record visuals | https://blog.brandiseer.com/use-cases/airtable-record-visuals |
| Live: Slack creative desk | https://blog.brandiseer.com/use-cases/slack-creative-desk |
| Live: Social media automation | https://blog.brandiseer.com/use-cases/social-media-automation |
| Live: Always-on creative automation | https://blog.brandiseer.com/use-cases/always-on-creative-automation |
| Live: Webflow site visuals | https://blog.brandiseer.com/use-cases/webflow-site-visuals |
| Live: WordPress site visuals | https://blog.brandiseer.com/use-cases/wordpress-site-visuals |
| Live: Framer site visuals | https://blog.brandiseer.com/use-cases/framer-site-visuals |
| Sibling: Linear issue visuals | https://blog.brandiseer.com/use-cases/linear-issue-visuals |
| Sibling: Airtable record visuals | https://blog.brandiseer.com/use-cases/airtable-record-visuals |
| 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 Drive and Slides deck visuals. Brandiseer MCP and REST v2 image generation from Cursor or Claude Cowork, then a human downloads `imageUrl` and inserts it in Google Slides or uploads it to Google Drive, or an agent with Google OAuth or a service account uploads the PNG with Drive `files.create` and places a publicly accessible HTTPS URL with Slides `presentations.batchUpdate` `createImage`. Aligned with [guide/docs](https://brandiseer.com/guide/docs) and [guide/image](https://brandiseer.com/guide/image) (3 October 2026), and with Google's Slides add-image guide plus Drive `files.create` and `permissions.create`. Brandiseer returns `imageUrl` only. It does not create Drive files or Slides presentations and does not sync. There is no Brandiseer Google app and no Drive or Slides MCP. Distinct from Linear issue visuals, Airtable record visuals, 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 Drive or Slides. Do not invent a Drive MCP or a Slides 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 the person, to Slides `createImage`, or to a Drive upload of those bytes. 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 Drive or Slides at the Brandiseer MCP URL.

### Google auth (the human's credential)

Send every Google call with `Authorization: Bearer ACCESS_TOKEN`. Brandiseer does not mint this token.

| Credential | What to configure |
| --- | --- |
| OAuth access token | Google Cloud project with the Drive API and the Slides API enabled. Scopes: `https://www.googleapis.com/auth/drive.file` and `https://www.googleapis.com/auth/presentations`. The consented account must already be able to edit the deck. |
| Service account | Share the presentation with the service account email as Editor. Share the destination folder the same way when you set `parents`. Domain-wide delegation is the Workspace alternative and is an admin setup. Put uploads in a user-owned folder. A service account has no consumer Drive quota. |

`drive.file` covers files this client creates or that the user opened with this client. It is enough for `files.create` of the new PNG and for `permissions.create` on that file. It does not list every file in Drive. `presentations` is the scope the Slides samples use for `batchUpdate`.

### Google Slides (placement only)

| Call | What you get |
| --- | --- |
| `GET https://slides.googleapis.com/v1/presentations/{presentationId}` | The existing deck. Read `slides[].objectId` for `pageObjectId` and `pageSize` when the image should match the slide. |
| `POST https://slides.googleapis.com/v1/presentations/{presentationId}:batchUpdate` | Applies `requests`. This guide uses one `createImage` request. |
| `POST https://slides.googleapis.com/v1/presentations` | Optional add-on only. Body `{ "title": "..." }` creates a new presentation. Not the default. |

`createImage` fields, from [CreateImageRequest](https://developers.google.com/workspace/slides/api/reference/rest/v1/presentations/request#CreateImageRequest):

| Field | Rule |
| --- | --- |
| `url` | Required. Publicly accessible HTTPS URL, at most 2 KB. Slides fetches it once and stores a copy. PNG, JPEG, or GIF. Under 50 MB. At most 25 megapixels. |
| `elementProperties.pageObjectId` | The slide id from the human or from `presentations.get`. |
| `elementProperties.size` | Optional. Width and height in EMU (`unit`: `EMU`). If the box aspect ratio differs from the image, Slides scales and centers the image inside the box. For a full-slide still, copy `pageSize`. |
| `elementProperties.transform` | Optional. If omitted, the image is placed at the top-left of the page. `scaleX`, `scaleY`, `translateX`, `translateY`, `unit`: `EMU`. |
| `objectId` | Optional. If you set one, it must be unique, 5 to 50 characters, and match Google's id rules. Omit it and Slides generates an id. |

The sample magnitudes in Google's add-image guide (`4000000` EMU on each side, translate `100000`) are an example, not your deck's page size.

### Google Drive (upload and optional share)

| Call | What you get |
| --- | --- |
| `POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart` | Creates a file and uploads bytes in one request. For files of 5 MB or less. `200` body includes `id`. |
| `POST https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable` | Same `files.create` method when the PNG is larger than 5 MB. Follow [Upload file data](https://developers.google.com/workspace/drive/api/guides/manage-uploads). |
| `POST https://www.googleapis.com/drive/v3/files/{fileId}/permissions` | Creates a permission. For a Slides-fetchable Drive URL, body `{ "type": "anyone", "role": "reader" }`. |

Multipart body, from the upload guide. Metadata is the first part (`Content-Type: application/json; charset=UTF-8`). The PNG bytes are the second part (`Content-Type: image/png`). Top-level header: `Content-Type: multipart/related; boundary=foo_bar_baz` plus `Authorization: Bearer ACCESS_TOKEN`.

Metadata JSON inside that first part:

```json
{
  "name": "title-slide-hero.png",
  "mimeType": "image/png",
  "parents": ["FOLDER_ID"]
}
```

Omit `parents` when the human did not name a folder. A service account should set `parents` to a shared folder a person owns.

Permission body. Do not set `sendNotificationEmail` on an `anyone` permission. That flag is for users and groups.

```json
{
  "type": "anyone",
  "role": "reader"
}
```

After that permission succeeds, a Drive URL Slides can fetch is `https://drive.google.com/uc?id=FILE_ID` or `https://drive.google.com/uc?export=view&id=FILE_ID`. If Slides still cannot fetch it, place the public Brandiseer `imageUrl` instead.

### Field mapping

Brandiseer generate body:

| Incoming field | API | Rule |
| --- | --- | --- |
| Slot (title slide hero, section divider, product or feature slide, chart or agenda thumb) | `aspectRatio` | `16:9` for every deck slot. Chart or agenda thumb may be `1:1` only when the human asks. Portrait: `9:16` only when needed. `4:3` only when the human names it. |
| headline | inside `prompt` only | On-image text and placement. Not a separate body field. Leave it out when the slide title will hold the headline. |
| brandId | `brandId` | `bds_c_...`. Required. |
| mode | `mode` | `fast`, `design`, or `pro`. Omit and the API uses `fast`. Prefer `design` for these 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` for these stills. |

Google placement. The deck, slide, and folder below are whatever the human named. Do not invent them.

| Incoming value | Google | Rule |
| --- | --- | --- |
| Public Brandiseer `imageUrl` | `createImage.url` | Preferred agent path when the URL is public. Slides fetches it. It must be HTTPS and at most 2 KB. |
| presentationId | path of `batchUpdate` and `presentations.get` | From the Slides URL. Required for an API place. |
| pageObjectId | `elementProperties.pageObjectId` | From `#slide=id.` or `slides[].objectId`. Required for `createImage`. |
| PNG bytes downloaded from `imageUrl` | multipart body of `files.create` | Drive archive, or the file the human asked to store first. |
| folder id | `parents` | Optional. Required in practice for a service account upload. |
| anyone reader | `permissions.create` | Only when a Drive-hosted URL must be public for `createImage`. |
| Drive file id | `https://drive.google.com/uc?id=FILE_ID` | Use in `createImage` only after the anyone reader share. |

### Example JSON

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

```json
{
  "brandId": "bds_c_...",
  "prompt": "Wide title slide hero. Product centred on the left third. Empty right half for a title the slide 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. Slides and Drive get `imageUrl` (or a file you downloaded from it).

Slides `createImage` with the public Brandiseer URL. `POST` this JSON to `https://slides.googleapis.com/v1/presentations/PRESENTATION_ID:batchUpdate` with `Authorization: Bearer ACCESS_TOKEN` and `Content-Type: application/json`. The size below is the sample from Google's add-image guide, not a claim about your page size.

```json
{
  "requests": [
    {
      "createImage": {
        "url": "https://...",
        "elementProperties": {
          "pageObjectId": "PAGE_OBJECT_ID",
          "size": {
            "height": { "magnitude": 4000000, "unit": "EMU" },
            "width": { "magnitude": 4000000, "unit": "EMU" }
          },
          "transform": {
            "scaleX": 1,
            "scaleY": 1,
            "translateX": 100000,
            "translateY": 100000,
            "unit": "EMU"
          }
        }
      }
    }
  ]
}
```

A successful reply includes `replies[0].createImage.objectId`. Read the error body before you tell the human the slide changed.

Drive permission, after `files.create` returned `id`:

```json
{
  "type": "anyone",
  "role": "reader"
}
```

`POST` that JSON to `https://www.googleapis.com/drive/v3/files/FILE_ID/permissions`.

Slot prompts that stay layout-only:

| Slot | aspectRatio | Prompt |
| --- | --- | --- |
| Title slide hero | `16:9` | Wide title slide hero. Product centred on the left third. Empty right half for a title the slide will hold. No on-image text. |
| Section divider | `16:9` | Landscape section divider. Single subject centred. Empty band along the bottom for a section name the slide will hold. No on-image text. |
| Product or feature slide still | `16:9` | Landscape product still. Subject left of centre. Empty right third for a feature name the slide will hold. No on-image text. |
| Chart or agenda thumb | `16:9` | Landscape thumb. Three items left to right. Empty caption band along the bottom. No on-image text. |
| Chart or agenda thumb | `1:1` | Square thumb. Single subject centred, full item in frame. Plain surrounding space. No on-image text. |
| Portrait | `9:16` | Portrait still. Single subject in the upper two thirds. Empty band along the bottom. No on-image text. |
