- Upload your images with
POST /files. - Create the kit with
POST /brand_kits. It answers apreview_url. - Show
preview_urlto a human. - Change the kit with
PATCH /brand_kits/{id}until they approve it. Nothing is live yet. - Apply it: set
branding.brand_kit_idin a workspace’s settings. - Optionally, send its summary emails from your own domain.
1. Upload your images
Upload each image once, asmultipart/form-data with purpose=brand_kit: a logo, and a 16:9
picture if you want your own video tile.
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.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
workspace_id names the workspace that owns the files and the kit; send the same one on
POST /files (as a form field) and on POST /brand_kits. Without it, both answer 400 missing
on workspace_id, like every endpoint that acts in a workspace.
workspace_id reads null when the key does not belong to the workspace that owns the kit.
3. Show the preview
Givepreview_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 12 hours
(preview_expires_at). Every GET or PATCH of the kit answers a fresh one:
4. Iterate
Send only what changes. Here the human wants their own picture on the tile:{ "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:
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 Company settings.
A single bot can still override the name, avatar and greeting when you
send it.
6. Send from your domain
Summary emails come fromsummaries@aefer.ai until you give the kit an address on a domain you
control. Use a subdomain such as mail.acme.com: your root domain’s SPF and DMARC stay as they are.
-
Add the domain with your account key. The answer lists four DNS records: three CNAMEs and a TXT.
-
Create the four records at your DNS provider, then call
POST /email_domains/{id}/verify, or wait for the hourly check. The domain turnsverifiedonce all four resolve. Keep them in place after that. The email domain explains each status. -
Set the sender on the kit. You can do it right away: until the domain is
verified, emails go out fromsummaries@aefer.aiunder yourname, so none waits on DNS.
email.sender.sending_as shows the From line that goes out right now. A domain
that stops resolving turns failing, and emails fall back to summaries@aefer.ai until it
resolves again. A domain a kit sends from can’t be deleted (409 domain_in_use): change the kit’s
email.sender.address first.
What a kit holds
Each choice is atype plus an object named after it. A read returns only the chosen type’s
object; the options of the others stay stored.
The bot
bot.tile.color.background_color and bot.tile.logo.background_color are one value: sending
both with different colors is 422 invalid.
The tile shows the same picture in every state of the bot (joining, recording, paused), so
don’t put a state such as “Recording” in it.
Write both chat messages in the brand’s voice, and keep {{user}}: it becomes the name of
the person the notetaker records for, as you named them on the member. A message you don’t write
reads as the standard one. The standard messages use bot.name.
The email
Theemail group is how the summary email looks. _æfer sends it after a meeting when
summary.email.enabled is on in settings, which is off by
default, from summaries@aefer.ai or your own domain: under a
bot_name sent with the bot, else email.sender.name, else the bot’s name with the branded or
custom email, and as “_æfer Notetaker” otherwise. The preview shows that same email. To write the
email yourself and still have _æfer send it, use a custom email. To send it
yourself, listen for bot.summary_ready and read
the summary with GET /meetings/{meeting_id}/results (A finished meeting).
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:
If your users have no _æfer 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 alinkwhose url
names{{meeting_id}}.
Your own HTML
Withemail.type: "custom", the email is your HTML, whole: _æfer adds no header, footer or
unsubscribe link. Write email.custom.html and, optionally, email.custom.subject in
Liquid:
- Strict. An unknown variable or filter is an error, and so is reading a field of
null: write{% if item.assignee %}{{ item.assignee.name }}{% endif %}.includeandrenderaren’t available. - Escaped. Values are HTML-escaped where they land;
summary.htmlis markup _æfer wrote. - What HTML is allowed. Inline
style,<style>, tables and images. Everyhrefandsrcishttps:,mailto:ortel:.<script>,<form>,<iframe>,<object>,<embed>,<noscript>, SVG animation,<link rel="stylesheet">,@importandon*attributes are refused, never removed, so the preview is what’s sent. - Sizes. At most 100 KB as written and 102 KB rendered, where Gmail starts clipping. The subject
is one line of at most 200 characters;
nullsends the standard one. - Checked when saved. A
PATCHrenders the email for a sample meeting, and again with no organizer, participants, time, meeting id or names, as a meeting may have. It refuses a template that fails either with a422saying what failed, with the line for a Liquid error. Check it in the preview. - Checked again when sent. A copy that can’t be rendered, such as a URL built from a meeting’s
data that isn’t
https, goes out as yourbrandedemail instead, andemail.custom.last_errorsays why until the template changes.
PATCH email.type: "branded" goes back to the branded email and keeps your HTML for later.
Writing rules
- Partial at every depth. On
POSTandPATCH, a group, an object or a field you leave out keeps its value.typecan be left out: the current one stays. nullresets a text (bot.name, the chat messages,color,website,description) to its default.- A read’s
botandemailcan be sent back unchanged. Send those groups only, not the whole object:id,object,preview_urland the other read-only fields are422 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 afile_id,null, or the{ id, url }a read returned. From that object onlyidcounts: 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 }.urlis the kit’s copy, short-lived (at most seven days, often less) and fresh on every read.idisnullfor an image uploaded in the dashboard. nullremoves an image.email.branded.logo: nullgoes back to the tile’s logo. Alogoorimagetile can’t lose its file: choose another tile first.
Errors
Every error is{ "errors": [{ "code", "field", "message" }] }. See
Errors.
field is the dotted path into your request, such as bot.tile.logo.background_color.