Skip to content
Skip to main content

Notetaker custom video output

Last updated:

By default, the Notetaker bot appears in a meeting as a blank participant tile. Custom video output replaces that tile with an image you upload: your product logo, a recording-notice card, or any other branding. The image appears as the bot’s camera feed, so the bot looks like a participant with their camera on. This feature is sometimes called the bot avatar.

You upload the image once on a configuration (or per Notetaker), and every bot governed by that configuration uses it. No avatar field or separate avatar API exists; everything goes through notetaker_settings.video_output.

video_output is an object inside notetaker_settings that holds a static image. When the bot joins a meeting on Google Meet, Microsoft Teams, or Zoom, the image shows as the bot’s camera feed. On any other meeting provider, the bot joins normally without showing the image.

Two things to know when designing the image:

  • Author it at a 16:9 aspect ratio, for example 1280x720; other ratios are letterboxed or cropped.
  • Text in the image appears backwards (mirrored) in the recording. Keep that in mind if the image carries a readable message, such as a recording notice.

A broken image never blocks a recording: if the image can’t be used at meeting time, the bot still joins, just without it.

You can set video_output in four places. It follows the standard inheritance chain, so the nearest layer that sets it wins:

EndpointMultipart JSON part name
POST /v3/notetakers/configsconfig
PATCH /v3/notetakers/configs/<CONFIG_ID>config
POST /v3/notetakers (or the grant-based invite)notetaker
PATCH /v3/notetakers/<NOTETAKER_ID> (or the grant-based update)notetaker

Calendar sync and event sync requests don’t accept video_output. Set it on an application or workspace configuration instead so calendar-scheduled bots inherit it.

Multipart is the recommended upload path: the file part limit is 4 MiB (4,194,304 bytes), roughly 3 times the base64 budget, with no encoding overhead. Send the request as multipart/form-data with the JSON body in one part and the image in another, and point video_output.file_key at the image part’s name.

curl --request PATCH \
--url "https://api.us.nylas.com/v3/notetakers/configs/<CONFIG_ID>" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
-F 'config={"notetaker_settings":{"video_output":{"file_key":"avatar"}}};type=application/json' \
-F "avatar=@./brand.png;type=image/png"

A few rules keep multipart requests unambiguous:

  • The JSON part must be named config on the configuration endpoints and notetaker on the Notetaker endpoints (see the table above). The wrong name returns 400 Bad Request with multipart config part is required or multipart notetaker part is required.
  • file_key can be any string, but it must match the name of exactly one file part in the same request. In the example, avatar is just a label; image or brand work equally well.
  • Every file part in the request must be referenced by a file_key, or the request fails with multipart request includes unreferenced file parts.
  • The Content-Type you declare on the file part isn’t trusted. Nylas detects the format from the file bytes.

For small images, skip multipart and send the bytes inline on a normal application/json request. Pass media_type and data together; the decoded image must be 1,376,256 bytes (about 1.31 MB) or smaller, and the whole JSON body is capped at 6.25 MiB.

curl --request PATCH \
--url "https://api.us.nylas.com/v3/notetakers/configs/<CONFIG_ID>" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
--header "Content-Type: application/json" \
--data '{
"notetaker_settings": {
"video_output": {
"media_type": "image/png",
"data": "<BASE64_IMAGE_BYTES>"
}
}
}'

The two envelopes don’t mix. file_key on a JSON request returns video_output.file_key requires multipart/form-data, and data on a multipart request returns video_output.data requires application/json. Likewise, file_key can’t be combined with media_type or data in the same object, and the declared media_type must match what the bytes actually are.

Nylas validates every upload by inspecting the actual file content, so a mislabeled file fails with video_output media_type does not match file content rather than being stored incorrectly. Re-uploading an identical image is harmless; it doesn’t create a duplicate copy.

ConstraintValue
FormatsPNG, JPEG, static WebP (animated WebP is rejected)
Maximum dimensions3840x2160 pixels, and a pixel count of at most 8,294,400
Maximum size, multipart part4 MiB (4,194,304 bytes)
Maximum size, base64 (decoded)1,376,256 bytes (about 1.31 MB)
Whole-body cap, multipartAbout 7.6 MiB
Whole-body cap, JSON6.25 MiB

Responses never echo the uploaded bytes, the file_key, or internal storage keys. Instead, both reads and writes return four read-only fields under notetaker_settings.video_output so you can confirm what’s stored and preview it:

{
"notetaker_settings": {
"video_output": {
"media_type": "image/png",
"size": 184320,
"preview_url": "https://storage.googleapis.com/...",
"preview_url_expires_at": 1786128794
}
}
}

preview_url is a signed URL that’s valid for 1 hour; preview_url_expires_at is the Unix timestamp when it stops working. Don’t cache the URL; fetch the configuration again when you need a fresh one. Sending size, preview_url, or preview_url_expires_at on a write returns video_output response metadata is read-only.

PATCH requests are presence-aware, so you control the image without re-sending up to 4 MiB of image bytes on every settings change. The four request shapes behave differently:

Request bodyEffect
video_output omittedThe existing image is preserved.
"video_output": { ...new image... }The existing image is replaced.
"video_output": {}Video output is disabled at this configuration layer.
"notetaker_settings": nullThe whole settings layer is cleared, including the image.

"video_output": null isn’t a supported way to clear the image; use the empty object {}. Disabling at one layer doesn’t delete images stored on other layers, so a per-notetaker {} can switch off an image inherited from the application configuration for one bot.

All validation failures return 400 Bad Request with a specific message, so the error text tells you which rule you hit. The most common ones:

Error messageFix
multipart config part is required / multipart notetaker part is requiredName the JSON part config on config endpoints, notetaker on Notetaker endpoints.
video_output.file_key must reference exactly one multipart fileThe file_key value doesn’t match a file part name (or matches several).
multipart request includes unreferenced file partsRemove file parts that no file_key points to.
video_output.media_type is required when data is presentSend media_type and data together.
video_output.data must decode to 1376256 bytes or smallerThe image is too big for base64; switch to multipart.
video_output must be PNG, JPEG, or static WebPConvert the image; animated WebP is also rejected.
video_output media_type does not match file contentThe declared type doesn’t match the bytes; fix the media_type.
video_output image dimensions must be 3840x2160 pixels or smaller and no more than 8294400 total pixelsResize the image.
request body is too largeStay under 7.6 MiB (multipart) or 6.25 MiB (JSON).

Upload failures outside your control surface as a generic 500 Internal Server Error. A failed request never leaves a partially stored image, so it’s always safe to retry.