> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meetingkit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Branding

> Make the notetaker and its summary email look like your product: upload a logo, create a brand kit, show its preview to a human, iterate, then apply it to a workspace.

A brand kit is how the notetaker presents itself in your customer's calls and in the summary
email. You build one in five steps:

1. Upload your images with `POST /files`.
2. Create the kit with `POST /brand_kits`. It answers a `preview_url`.
3. Show `preview_url` to a human.
4. Change the kit with `PATCH /brand_kits/{id}` until they approve it. Nothing is live yet.
5. Apply it: set `branding.brand_kit_id` in a workspace's settings.

Every field is on [the brand kit object](/api-reference/brand-kits/object).

## 1. Upload your images

Upload each image once, as `multipart/form-data` with `purpose=brand_kit`: a logo, and a 16:9
picture if you want your own video tile.

```bash theme={null}
curl -X POST "https://api.meetingkit.com/api/v1/files" \
  -H "Authorization: $MEETINGKIT_API_KEY" \
  -H "Happyscribe-Version: 2026-10-12" \
  -F file=@logo.png \
  -F purpose=brand_kit
```

```json theme={null}
{
  "id": "file_01k6d8q4z7m2n5p8r1s3t6v9wx",
  "object": "file",
  "purpose": "brand_kit",
  "workspace_id": "wks_01k6a2r9s8x7c2dvq3m5n6p4ab",
  "filename": "logo.png",
  "content_type": "image/png",
  "size": 48213,
  "url": "https://d3sr83esc6q22p.cloudfront.net/kh8wgfikrt8zf30ghdu2j3itx8rd?Expires=1822382401&Signature=…",
  "created_at": "2026-10-01T09:20:00Z"
}
```

A file is a PNG, JPEG, GIF, WebP or SVG of at most 10 MB. **Use a PNG for the logo the email
shows**: most mail clients don't render SVG, and an SVG's `url` downloads instead of
displaying. A workspace takes 60 uploads a minute; past that, `429 rate_limited`.

## 2. Create the kit

Send what you know; every group is optional and takes its default when left out.

```bash theme={null}
curl -X POST "https://api.meetingkit.com/api/v1/brand_kits" \
  -H "Authorization: $MEETINGKIT_API_KEY" \
  -H "Happyscribe-Version: 2026-10-12" \
  -H "Content-Type: application/json" \
  -d '{
    "bot": {
      "name": "Acme Notetaker",
      "tile": {
        "type": "logo",
        "logo": { "file": "file_01k6d8q4z7m2n5p8r1s3t6v9wx", "background_color": "#0B1F3A", "scale": 70 }
      },
      "chat": { "recording_message": "Acme Notetaker is taking notes for {{user}}." }
    },
    "email": {
      "type": "branded",
      "branded": {
        "color": "#0052FF",
        "website": "https://acme.com",
        "description": "Acme, meeting notes for sales teams",
        "cta": { "type": "link", "link": { "label": "Open in Acme", "url": "https://acme.com/meetings/{{meeting_id}}" } }
      }
    }
  }'
```

```json theme={null}
{
  "id": "brk_01k6c3v7w2q9d8m4n5p6r7s8tx",
  "object": "brand_kit",
  "workspace_id": "wks_01k6a2r9s8x7c2dvq3m5n6p4ab",
  "workspace_ids": [],
  "bot": { "name": "Acme Notetaker", "tile": { "type": "logo", "logo": { … } }, "chat": { … } },
  "email": { "type": "branded", "branded": { … } },
  "preview_url": "https://api.meetingkit.com/app/shared/brand-kits/brk_01k6c3v7w2q9d8m4n5p6r7s8tx/preview?token=WyJicmtf…",
  "preview_expires_at": "2026-10-01T09:30:16Z",
  "metadata": {},
  "created_at": "2026-10-01T09:20:16Z"
}
```

The kit changes nothing yet: `workspace_ids` is empty until a workspace applies it in step 5.
`workspace_ids` is read-only; settings decide which workspaces use a kit.

### Which workspace owns it

A key that belongs to one workspace needs nothing more: that workspace owns the files and the
kit. A key that belongs to several must send `workspace_id` on `POST /files` (as a form field)
and on `POST /brand_kits`; without it, both answer `400 missing` on `workspace_id`.
`workspace_id` reads `null` when the key does not belong to the workspace that owns the kit.

## 3. Show the preview

Give `preview_url` to a human: it shows the notetaker's tile in a call, its chat messages and
the summary email, exactly as the kit is saved. It needs no sign-in and lasts 10 minutes
(`preview_expires_at`). Every `GET` or `PATCH` of the kit answers a fresh one:

```bash theme={null}
curl "https://api.meetingkit.com/api/v1/brand_kits/brk_01k6c3v7w2q9d8m4n5p6r7s8tx" \
  -H "Authorization: $MEETINGKIT_API_KEY" \
  -H "Happyscribe-Version: 2026-10-12"
```

An expired link shows that it expired; get a new one rather than retrying it.

## 4. Iterate

Send only what changes. Here the human wants their own picture on the tile:

```bash theme={null}
curl -X PATCH "https://api.meetingkit.com/api/v1/brand_kits/brk_01k6c3v7w2q9d8m4n5p6r7s8tx" \
  -H "Authorization: $MEETINGKIT_API_KEY" \
  -H "Happyscribe-Version: 2026-10-12" \
  -H "Content-Type: application/json" \
  -d '{ "bot": { "tile": { "type": "image", "image": { "file": "file_01k6d9b2c4e6g8j0k2m4p6r8tv" } } } }'
```

The name, the chat and the email stay as they were, and the logo tile's options stay stored:
`{ "bot": { "tile": { "type": "logo" } } }` switches back to it. Show the new `preview_url`.

While no workspace uses the kit, nothing a customer sees changes. Once one does, every `PATCH`
reaches its next calls and emails straight away.

## 5. Apply it

A workspace uses a kit through its settings, set on the workspace alone
(`["workspaces:wks_…"]`). A new workspace has none of its own: it inherits your account's. Give
it settings that apply the kit:

```bash theme={null}
curl -X POST "https://api.meetingkit.com/api/v1/settings" \
  -H "Authorization: $MEETINGKIT_API_KEY" \
  -H "Happyscribe-Version: 2026-10-12" \
  -H "Content-Type: application/json" \
  -d '{
    "branding": { "brand_kit_id": "brk_01k6c3v7w2q9d8m4n5p6r7s8tx" },
    "assignments": [{ "scope": ["workspaces:wks_01k6a2r9s8x7c2dvq3m5n6p4ab"] }]
  }'
```

If the workspace has its own settings already, that answers `409 scope_taken` naming the
assignment: `PATCH` its settings with the same `branding` instead. A kit is set on a workspace
alone; on an account, a member or a meeting category it answers `422 not_supported`.

The kit's read-only `workspace_ids` now lists the workspace. One kit can brand many workspaces: apply it
to each. `"brand_kit_id": "none"` goes back to the default look. See [Settings](/meetingkit/settings).

A single bot can still override the name, avatar and greeting when you
[send it](/meetingkit/send-bot#how-the-bot-looks-and-records).

## What a kit holds

Each choice is a `type` plus an object named after it. A read returns only the chosen type's
object; the options of the others stay stored.

### The bot

| Field | What it sets |
| - | - |
| `bot.name` | The notetaker's name in the call, up to 64 characters. |
| `bot.tile` | Its video tile, below. |
| `bot.chat.enabled` | Whether it posts in the call's chat. |
| `bot.chat.recording_message` | Posted when it joins and starts recording, up to 300 characters. |
| `bot.chat.paused_message` | Posted while recording is paused, up to 300 characters. |

| `bot.tile.type` | The tile shows | Needs |
| - | - | - |
| `default` | The default logo on the background color. | Nothing. |
| `color` | A plain background color. | `color.background_color` |
| `logo` | Your logo on the background color, at `scale` (10 to 100) percent. | `logo.file`; `background_color` and `scale` |
| `image` | Your own 16:9 picture, filling the tile. | `image.file` |

`bot.tile.color.background_color` and `bot.tile.logo.background_color` are one value: sending
both with different colors is `422 invalid`.

Write both chat messages in the brand's voice, and keep `{{user}}`: it becomes the name of
the person the notetaker records for. A message you don't write reads as the standard one.

### The email

| `email.type` | The summary email |
| - | - |
| `default` | The default email. A new kit starts here. |
| `branded` | Your logo, `color`, `website`, `description` and button, under the bot's name. |

`email.branded.logo` is the tile's logo until you set one of its own. `email.branded.cta` is
the button under the meeting's name:

| `cta.type` | The button |
| - | - |
| `open_meeting` | Opens the meeting in MeetingKit, for a reader who can open it there. |
| `none` | No button. |
| `link` | Opens your `link.url` with the text `link.label`. Both are required. |

If your users have no MeetingKit account, set `cta` to `none` or to a `link`. In `link.url`,
`{{meeting_id}}` is replaced by the meeting's `mtg_` id; write it exactly so, with no spaces.
An email with no meeting to name shows the "Open meeting" button instead of a `link` whose url
names `{{meeting_id}}`.

## Writing rules

* **Partial at every depth.** On `POST` and `PATCH`, a group, an object or a field you leave
  out keeps its value. `type` can be left out: the current one stays.
* **`null` resets a text** (`bot.name`, the chat messages, `color`, `website`, `description`)
  to its default.
* **A read's `bot` and `email` can be sent back unchanged.** Send those groups only, not the
  whole object: `id`, `object`, `preview_url` and the other read-only fields are
  `422 unknown_field`. A name or message equal to the default the read showed stays unset, so it
  keeps following the default.
* **Files** (`bot.tile.logo.file`, `bot.tile.image.file`, `email.branded.logo`) take a `file_`
  id, `null`, or the `{ id, url }` a read returned. From that object only `id` counts: the
  same id keeps the image, another id copies that file. The kit keeps its own copy, so it
  doesn't depend on the file afterwards.
* **A file reads as `{ id, url }`.** `url` is the kit's copy, signed for a year and fresh on
  every read. `id` is `null` for an image uploaded in the dashboard.
* **`null` removes an image.** `email.branded.logo: null` goes back to the tile's logo. A
  `logo` or `image` tile can't lose its file: choose another tile first.

## Errors

Every error is `{ "errors": [{ "code", "field", "message" }] }`. See
[Errors](/api-reference/errors).

| Status | `code` | When |
| - | - | - |
| `400` | `missing` | The key belongs to several workspaces and `workspace_id` was not sent. |
| `403` | `workspace_update_not_allowed` | The key is not an owner or admin of the workspace. |
| `404` | `not_found` | A `file_` or `brk_` id the key can't read. |
| `422` | `unknown_field` | A field the kit doesn't have: a read-only one (`id`, `object`, `created_at`, `preview_url`), a flat name such as `bot_name`, or a typo. |
| `422` | `inclusion` | A `type` outside its list. |
| `422` | `invalid` | `email.type: custom`, which is not available yet; two different tile background colors; a file that is not an id, `null` or `{ id, url }`; a URL that is not http(s). |
| `422` | `invalid_format`, `too_long`, `too_low`, `too_high` | A color that is not HEX, such as `#0B1F3A`; a text over its limit; a `scale` outside 10 to 100. |
| `422` | `missing` | A `logo` or `image` tile with no file, on `bot.tile.logo.file` or `bot.tile.image.file`. |
| `422` | `blank` | A `link` button with no `label` or `url`. |
| `429` | `rate_limited` | More than 60 uploads a minute in one workspace. Wait `retry_in_seconds`. |

`field` is the dotted path into your request, such as `bot.tile.logo.background_color`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.