Skip to content
Skip to main content

Notetaker custom announcements

Last updated:

By default, the Notetaker bot posts a short notice in the meeting chat a few minutes after it joins, telling attendees that the bot is recording and that consent is the meeting host’s responsibility. Custom announcements let you write that notice yourself and add a second message that fires when a new participant joins.

You configure announcements through the messages field on notetaker_settings. Like the rest of notetaker_settings, you can set them on a single Notetaker, save them on a configuration so every bot picks them up, or attach them to a calendar or event so calendar sync uses them.

Custom announcements have two triggers, and you can configure either, both, or neither:

  • on_join: Messages posted after the bot joins the meeting. Each message has its own send_after_ms delay, measured from the moment the bot joins, and messages post in the order their delays expire. Use this for greetings, consent notices, or links to a recording policy.
  • on_participant_join: Messages posted when a new participant joins. Each message uses a trailing debounce_ms window: the bot waits that long after a join before posting, and another join inside the window resets the timer, so a burst of 5 arrivals produces 1 message. Use this to welcome late arrivals or to tell them recording is already in progress.

Pass an empty array to disable a trigger while keeping the other one active. Messages post sequentially, so order is preserved, and if one message fails to post because of a temporary provider-side issue, the bot moves on to the next. The bot can’t post at all if the meeting provider’s chat is unavailable, restricted to specific roles, or disabled by the host.

The messages object has two fields, each an array of up to 10 message objects:

FieldTypeDescription
on_joinOnJoinMessage[]Messages posted after the bot joins. Up to 10 messages.
on_participant_joinOnParticipantJoinMessage[]Messages posted when a new participant joins. Up to 10 messages.
FieldTypeRequiredConstraintsDescription
typestringYesMust be "text"Message format. Only text is supported today; the field exists so new formats can be added without a breaking change.
contentstringYes1 to 1,000 charactersThe text the bot posts to the meeting chat. HTML is stripped before sending, and content that’s empty after stripping is rejected.
send_after_msintegerYes1 to 600,000 (10 minutes)Delay in milliseconds between the bot joining and this message posting.
FieldTypeRequiredConstraintsDescription
typestringYesMust be "text"Message format. Only text is supported today.
contentstringYes1 to 1,000 charactersThe text the bot posts to the meeting chat. HTML is stripped before sending, and content that’s empty after stripping is rejected.
debounce_msintegerYes1 to 600,000 (10 minutes)Trailing debounce window in milliseconds. Another join inside the window resets the timer.

Anything outside these constraints returns 400 Bad Request with a validation error.

You can set messages anywhere notetaker_settings is accepted. On a single Notetaker it applies to that bot only; on a configuration it applies to every bot that inherits from it; and on a calendar sync or event request Nylas saves it as a calendar or event configuration that every Notetaker from that sync uses.

Pass messages inside notetaker_settings on a POST /v3/notetakers or POST /v3/grants/<NYLAS_GRANT_ID>/notetakers request. Per-Notetaker settings are the most specific layer, so they override anything inherited from a configuration, calendar, or event. This example posts a greeting 5 seconds after joining and a welcome 3 seconds after each burst of late arrivals.

curl --request POST \
--url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/notetakers' \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"meeting_link": "https://meet.google.com/abc-defg-hij",
"notetaker_settings": {
"recording_type": "audio_video",
"transcription": true,
"messages": {
"on_join": [
{
"type": "text",
"content": "👋 Hey team! I am your AI notetaker, here to capture the key points. Recording and transcription are running.",
"send_after_ms": 5000
}
],
"on_participant_join": [
{
"type": "text",
"content": "👋 Welcome! Recording and transcription are running.",
"debounce_ms": 3000
}
]
}
}
}'

The legacy meeting_settings shape also accepts messages in the same form. See Migrate to notetaker_settings.

To use the same announcements across many Notetakers, save them on a Notetaker configuration at the application or workspace scope. Every Notetaker that inherits from that configuration uses the announcements automatically, and changing them later updates every bot that hasn’t joined yet. This example sets a single consent notice that posts 3 seconds after joining.

curl --request POST \
--url 'https://api.us.nylas.com/v3/notetakers/configs' \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"display_name": "Company defaults",
"notetaker_settings": {
"recording_type": "audio_video",
"transcription": true,
"messages": {
"on_join": [
{
"type": "text",
"content": "Recording and transcription are running. By staying in the meeting, you consent to being recorded.",
"send_after_ms": 3000
}
]
}
}
}'

messages follows the standard inheritance chain: the most specific layer that sets it wins, and if no layer sets it, the bot posts the platform default consent notice.

Webhook payloads carry settings under the legacy name meeting_settings (see the migration note for why). When announcements are configured, the resolved messages object appears inside meeting_settings on the notetaker.created, notetaker.updated, notetaker.meeting_state, and notetaker.media triggers. If no layer sets messages, the field is omitted from the payload. The example below shows a notetaker.created payload with one on_join message and an empty on_participant_join array.

{
"type": "notetaker.created",
"data": {
"application_id": "<NYLAS_APPLICATION_ID>",
"object": {
"id": "<NOTETAKER_ID>",
"meeting_settings": {
"video_recording": true,
"audio_recording": true,
"transcription": true,
"messages": {
"on_join": [
{
"type": "text",
"content": "👋 Hey team! Recording is running.",
"send_after_ms": 5000
}
],
"on_participant_join": []
}
}
}
}
}