curl --request PATCH \
--url https://api.meetingkit.com/api/v1/bots/{id} \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"join_at": "2026-10-01T11:00:00Z"
}
'import requests
url = "https://api.meetingkit.com/api/v1/bots/{id}"
payload = { "join_at": "2026-10-01T11:00:00Z" }
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({join_at: '2026-10-01T11:00:00Z'})
};
fetch('https://api.meetingkit.com/api/v1/bots/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.meetingkit.com/api/v1/bots/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'join_at' => '2026-10-01T11:00:00Z'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.meetingkit.com/api/v1/bots/{id}"
payload := strings.NewReader("{\n \"join_at\": \"2026-10-01T11:00:00Z\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.meetingkit.com/api/v1/bots/{id}")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"join_at\": \"2026-10-01T11:00:00Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.meetingkit.com/api/v1/bots/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"join_at\": \"2026-10-01T11:00:00Z\"\n}"
response = http.request(request)
puts response.read_body{
"id": "bot_01k0h4r9s8x7c2dvq3m5n6p4ab",
"object": "bot",
"meeting_id": "mtg_01k0h4r9s8x7c2dvq3m5n6p4ab",
"meeting_url": "https://zoom.us/j/123456789",
"join_at": "2026-07-20T14:00:00Z",
"status": "queued",
"bot_name": "Acme Notetaker",
"welcome_message": "Recording this meeting for Acme",
"language": "en",
"recording_start": "on_join",
"recording_mode": "audio_only",
"silence_alert": true,
"summary_language": "en",
"summary_template": "discovery_call",
"participants": [
{
"email": "carmen@example.com",
"name": "Carmen"
}
],
"metadata": {
"partner_meeting_id": "meeting-123"
},
"created_at": "2026-07-20T13:58:12Z",
"ended_at": null
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}Update a bot
Moves a bot created through the API when its meeting moves, or replaces its participants or metadata. Send only the fields you are changing. A field sent with the value the bot already has is ignored, so a retried request is safe.
join_atandmeeting_urlcan change while the bot isqueued. The bot keeps its ID.participantscan change until the call ends. They are used to name speakers when the recording is processed. A new address also gets access to the recording; removing an address from the list does not take access away.metadatacan change until the bot iscompleted,failed, orcancelled.
Updating a bot sends no webhook.
curl --request PATCH \
--url https://api.meetingkit.com/api/v1/bots/{id} \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"join_at": "2026-10-01T11:00:00Z"
}
'import requests
url = "https://api.meetingkit.com/api/v1/bots/{id}"
payload = { "join_at": "2026-10-01T11:00:00Z" }
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({join_at: '2026-10-01T11:00:00Z'})
};
fetch('https://api.meetingkit.com/api/v1/bots/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.meetingkit.com/api/v1/bots/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'join_at' => '2026-10-01T11:00:00Z'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.meetingkit.com/api/v1/bots/{id}"
payload := strings.NewReader("{\n \"join_at\": \"2026-10-01T11:00:00Z\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.meetingkit.com/api/v1/bots/{id}")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"join_at\": \"2026-10-01T11:00:00Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.meetingkit.com/api/v1/bots/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"join_at\": \"2026-10-01T11:00:00Z\"\n}"
response = http.request(request)
puts response.read_body{
"id": "bot_01k0h4r9s8x7c2dvq3m5n6p4ab",
"object": "bot",
"meeting_id": "mtg_01k0h4r9s8x7c2dvq3m5n6p4ab",
"meeting_url": "https://zoom.us/j/123456789",
"join_at": "2026-07-20T14:00:00Z",
"status": "queued",
"bot_name": "Acme Notetaker",
"welcome_message": "Recording this meeting for Acme",
"language": "en",
"recording_start": "on_join",
"recording_mode": "audio_only",
"silence_alert": true,
"summary_language": "en",
"summary_template": "discovery_call",
"participants": [
{
"email": "carmen@example.com",
"name": "Carmen"
}
],
"metadata": {
"partner_meeting_id": "meeting-123"
},
"created_at": "2026-07-20T13:58:12Z",
"ended_at": null
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}{
"errors": [
{
"code": "invalid",
"field": "recording.methods.bot.mode",
"message": "must be one of: audio_and_video, audio_only, inherit"
}
]
}Authorizations
Your API key, sent bare. See Authentication.
Headers
Serve this request as the API was on this date. Any ISO date works — it resolves to the newest version on or before it — and it never changes your key's pin. See Versioning.
"2026-09-01"
Path Parameters
Bot ID, beginning with bot_. Treat it as an opaque string.
"bot_01k0h4r9s8x7c2dvq3m5n6p4ab"
Body
New future ISO 8601 timestamp with a UTC offset. Only while the bot is queued.
New Zoom, Google Meet, or Microsoft Teams join URL. Only while the bot is queued.
Replaces the participant list used to name speakers. Until the call ends. New addresses get access to the recording; removed ones keep it.
100Show child attributes
Show child attributes
Merged into the bot's metadata until the bot is completed, failed, or cancelled. Before 2026-10-12, any JSON object (up to 16 KB, five levels deep) that replaces it.
Show child attributes
Show child attributes
{
"gurusup_user_id": "usr_8812",
"old_key": ""
}
Response
The updated bot.
A bot is one way of recording a meeting. It carries its identity in the call and the
meeting's recording choices; what the meeting produced (transcript, speakers, summary,
media) is read from GET /meetings/{id}/results.
Stable typed bot ID beginning with bot_. Treat it as an opaque string.
Always bot.
The meeting this bot records, beginning with mtg_. It exists from the moment the bot is queued; read its results with GET /meetings/{meeting_id}/results.
Normalized URL supplied at creation. Treat as sensitive — it may contain credentials.
Requested ISO 8601 join time, or null for an immediate dispatch.
Current lifecycle state:
queued: the provider accepted the bot and the notetaker is pendingjoining: the notetaker is joining the callin_call: the notetaker is in the call and recordingprocessing: the recording is being transcribed or summarizedcompleted: the transcript and summary are ready on the meetingfailed: the bot ended without a usable resultcancelled: the bot was cancelled
queued, joining, in_call, processing, completed, failed, cancelled Display name of the notetaker in the call.
Chat message the notetaker posts when it joins, or null when it posts none.
Transcription language as a BCP-47 code, auto or multi. The meeting's settings.transcription.language.
When the notetaker starts recording. The meeting's settings.recording.methods.bot.start.
on_join: as soon as it joins the callon_command: when someone in the call asks it to
on_join, on_command What the notetaker records. The meeting's settings.recording.methods.bot.mode.
audio_and_video: audio and videoaudio_only: audio only
audio_and_video, audio_only Whether the notetaker posts an audible and chat alert after a long silence, in case it is recording nothing. The meeting's settings.recording.methods.bot.silence_detection.alert.
Language of the summary as a BCP-47 code, or null to follow the transcription. The meeting's settings.summary.language.
The summary template that runs, a built-in slug or a custom template's tpl_ id. The meeting's settings.summary.template.
Everyone invited to the meeting. Meeting rooms and the notetaker itself are excluded.
Show child attributes
Show child attributes
A flat map of strings from 2026-10-12. Before it, the object stored at creation, returned as stored; a value stored as a nested object reads as its JSON text from 2026-10-12.
Show child attributes
Show child attributes
{ "gurusup_user_id": "usr_8812" }
When the bot was created.
When the recording first became available. null until then, and for a bot that never recorded. Reprocessing does not change it.
Machine-readable failure reason. Present only for failed bots.
no_recording: the call ended without anything recordedinvalid_meeting_url: the meeting URL could not be joinedbot_error: the notetaker failed in the calltranscription_failed: the recording could not be transcribed
no_recording, invalid_meeting_url, bot_error, transcription_failed Human-readable failure detail for debugging. Present only for failed bots. Do not match on its text; use reason.