curl --request POST \
--url https://api.meetingkit.com/api/v1/webhook_endpoints \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"workspace_id": "wks_01k6a2r9s8x7c2dvq3m5n6p4ab",
"url": "https://api.acme.com/meetingkit/webhooks",
"enabled_events": [
"meeting.finished",
"bot.summary_ready"
],
"metadata": {
"gurusup_user_id": "usr_8812",
"old_key": ""
},
"name": "<string>",
"secret": "<string>",
"api_version": "2026-10-09"
}
'import requests
url = "https://api.meetingkit.com/api/v1/webhook_endpoints"
payload = {
"workspace_id": "wks_01k6a2r9s8x7c2dvq3m5n6p4ab",
"url": "https://api.acme.com/meetingkit/webhooks",
"enabled_events": ["meeting.finished", "bot.summary_ready"],
"metadata": {
"gurusup_user_id": "usr_8812",
"old_key": ""
},
"name": "<string>",
"secret": "<string>",
"api_version": "2026-10-09"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
workspace_id: 'wks_01k6a2r9s8x7c2dvq3m5n6p4ab',
url: 'https://api.acme.com/meetingkit/webhooks',
enabled_events: ['meeting.finished', 'bot.summary_ready'],
metadata: {gurusup_user_id: 'usr_8812', old_key: ''},
name: '<string>',
secret: '<string>',
api_version: '2026-10-09'
})
};
fetch('https://api.meetingkit.com/api/v1/webhook_endpoints', 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/webhook_endpoints",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'workspace_id' => 'wks_01k6a2r9s8x7c2dvq3m5n6p4ab',
'url' => 'https://api.acme.com/meetingkit/webhooks',
'enabled_events' => [
'meeting.finished',
'bot.summary_ready'
],
'metadata' => [
'gurusup_user_id' => 'usr_8812',
'old_key' => ''
],
'name' => '<string>',
'secret' => '<string>',
'api_version' => '2026-10-09'
]),
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/webhook_endpoints"
payload := strings.NewReader("{\n \"workspace_id\": \"wks_01k6a2r9s8x7c2dvq3m5n6p4ab\",\n \"url\": \"https://api.acme.com/meetingkit/webhooks\",\n \"enabled_events\": [\n \"meeting.finished\",\n \"bot.summary_ready\"\n ],\n \"metadata\": {\n \"gurusup_user_id\": \"usr_8812\",\n \"old_key\": \"\"\n },\n \"name\": \"<string>\",\n \"secret\": \"<string>\",\n \"api_version\": \"2026-10-09\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.meetingkit.com/api/v1/webhook_endpoints")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"workspace_id\": \"wks_01k6a2r9s8x7c2dvq3m5n6p4ab\",\n \"url\": \"https://api.acme.com/meetingkit/webhooks\",\n \"enabled_events\": [\n \"meeting.finished\",\n \"bot.summary_ready\"\n ],\n \"metadata\": {\n \"gurusup_user_id\": \"usr_8812\",\n \"old_key\": \"\"\n },\n \"name\": \"<string>\",\n \"secret\": \"<string>\",\n \"api_version\": \"2026-10-09\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.meetingkit.com/api/v1/webhook_endpoints")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"workspace_id\": \"wks_01k6a2r9s8x7c2dvq3m5n6p4ab\",\n \"url\": \"https://api.acme.com/meetingkit/webhooks\",\n \"enabled_events\": [\n \"meeting.finished\",\n \"bot.summary_ready\"\n ],\n \"metadata\": {\n \"gurusup_user_id\": \"usr_8812\",\n \"old_key\": \"\"\n },\n \"name\": \"<string>\",\n \"secret\": \"<string>\",\n \"api_version\": \"2026-10-09\"\n}"
response = http.request(request)
puts response.read_body{
"secret": "whsec_5f0c2a9e1b7d4c3a8e6f0b2d9c1a7e4f3b8d6c0a2e9f1b4d",
"id": "whe_01k6d4a1b2c3d4e5f6g7h8j9km",
"object": "<string>",
"workspace_id": "wks_01k6a2r9s8x7c2dvq3m5n6p4ab",
"name": "Acme production",
"url": "https://api.acme.com/meetingkit/webhooks",
"enabled_events": [
"meeting.finished",
"bot.summary_ready"
],
"status": "enabled",
"api_version": "2026-10-09",
"metadata": {
"gurusup_user_id": "usr_8812"
},
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"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"
}
]
}Create a webhook endpoint
Registers a receiver for a workspace’s events. The key must be an owner or admin of the workspace, and a workspace holds at most 10 endpoints.
The response is the only one that carries secret: store it to
verify each request. Send your own secret to use
the same one everywhere; otherwise one starting with whsec_ is generated. If you lose it,
delete the endpoint and create it again.
The endpoint is pinned to the API version this request was served at, unless you send
api_version. Its events are named and shaped as that version has them.
curl --request POST \
--url https://api.meetingkit.com/api/v1/webhook_endpoints \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"workspace_id": "wks_01k6a2r9s8x7c2dvq3m5n6p4ab",
"url": "https://api.acme.com/meetingkit/webhooks",
"enabled_events": [
"meeting.finished",
"bot.summary_ready"
],
"metadata": {
"gurusup_user_id": "usr_8812",
"old_key": ""
},
"name": "<string>",
"secret": "<string>",
"api_version": "2026-10-09"
}
'import requests
url = "https://api.meetingkit.com/api/v1/webhook_endpoints"
payload = {
"workspace_id": "wks_01k6a2r9s8x7c2dvq3m5n6p4ab",
"url": "https://api.acme.com/meetingkit/webhooks",
"enabled_events": ["meeting.finished", "bot.summary_ready"],
"metadata": {
"gurusup_user_id": "usr_8812",
"old_key": ""
},
"name": "<string>",
"secret": "<string>",
"api_version": "2026-10-09"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
workspace_id: 'wks_01k6a2r9s8x7c2dvq3m5n6p4ab',
url: 'https://api.acme.com/meetingkit/webhooks',
enabled_events: ['meeting.finished', 'bot.summary_ready'],
metadata: {gurusup_user_id: 'usr_8812', old_key: ''},
name: '<string>',
secret: '<string>',
api_version: '2026-10-09'
})
};
fetch('https://api.meetingkit.com/api/v1/webhook_endpoints', 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/webhook_endpoints",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'workspace_id' => 'wks_01k6a2r9s8x7c2dvq3m5n6p4ab',
'url' => 'https://api.acme.com/meetingkit/webhooks',
'enabled_events' => [
'meeting.finished',
'bot.summary_ready'
],
'metadata' => [
'gurusup_user_id' => 'usr_8812',
'old_key' => ''
],
'name' => '<string>',
'secret' => '<string>',
'api_version' => '2026-10-09'
]),
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/webhook_endpoints"
payload := strings.NewReader("{\n \"workspace_id\": \"wks_01k6a2r9s8x7c2dvq3m5n6p4ab\",\n \"url\": \"https://api.acme.com/meetingkit/webhooks\",\n \"enabled_events\": [\n \"meeting.finished\",\n \"bot.summary_ready\"\n ],\n \"metadata\": {\n \"gurusup_user_id\": \"usr_8812\",\n \"old_key\": \"\"\n },\n \"name\": \"<string>\",\n \"secret\": \"<string>\",\n \"api_version\": \"2026-10-09\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.meetingkit.com/api/v1/webhook_endpoints")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"workspace_id\": \"wks_01k6a2r9s8x7c2dvq3m5n6p4ab\",\n \"url\": \"https://api.acme.com/meetingkit/webhooks\",\n \"enabled_events\": [\n \"meeting.finished\",\n \"bot.summary_ready\"\n ],\n \"metadata\": {\n \"gurusup_user_id\": \"usr_8812\",\n \"old_key\": \"\"\n },\n \"name\": \"<string>\",\n \"secret\": \"<string>\",\n \"api_version\": \"2026-10-09\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.meetingkit.com/api/v1/webhook_endpoints")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"workspace_id\": \"wks_01k6a2r9s8x7c2dvq3m5n6p4ab\",\n \"url\": \"https://api.acme.com/meetingkit/webhooks\",\n \"enabled_events\": [\n \"meeting.finished\",\n \"bot.summary_ready\"\n ],\n \"metadata\": {\n \"gurusup_user_id\": \"usr_8812\",\n \"old_key\": \"\"\n },\n \"name\": \"<string>\",\n \"secret\": \"<string>\",\n \"api_version\": \"2026-10-09\"\n}"
response = http.request(request)
puts response.read_body{
"secret": "whsec_5f0c2a9e1b7d4c3a8e6f0b2d9c1a7e4f3b8d6c0a2e9f1b4d",
"id": "whe_01k6d4a1b2c3d4e5f6g7h8j9km",
"object": "<string>",
"workspace_id": "wks_01k6a2r9s8x7c2dvq3m5n6p4ab",
"name": "Acme production",
"url": "https://api.acme.com/meetingkit/webhooks",
"enabled_events": [
"meeting.finished",
"bot.summary_ready"
],
"status": "enabled",
"api_version": "2026-10-09",
"metadata": {
"gurusup_user_id": "usr_8812"
},
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"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.
Body
The workspace whose events it receives. A wks_ id; integer workspace ids are still accepted.
"wks_01k6a2r9s8x7c2dvq3m5n6p4ab"
A public HTTPS URL. Redirects are not followed.
2048"https://api.acme.com/meetingkit/webhooks"
Event types, or * for every event this workspace and version send, now and later.
1["meeting.finished", "bot.summary_ready"]
Merged into the object's metadata: the keys you send are added or overwritten and the
others kept. "" as a value removes that key; metadata: "" removes every key. Numbers and
booleans are stored as their text; objects, arrays and null are refused.
Show child attributes
Show child attributes
{
"gurusup_user_id": "usr_8812",
"old_key": ""
}
Defaults to the URL's host.
100Your own signing secret, at least 16 characters. Omit it to have one generated.
255Pin the endpoint to this version instead of the one serving the request.
"2026-10-09"
Response
Endpoint created, with its secret.
The signing secret. Shown only in this response.
"whsec_5f0c2a9e1b7d4c3a8e6f0b2d9c1a7e4f3b8d6c0a2e9f1b4d"
Webhook endpoint ID, beginning with whe_. Treat it as an opaque string.
"whe_01k6d4a1b2c3d4e5f6g7h8j9km"
Always webhook_endpoint.
Workspace ID, beginning with wks_. Treat it as an opaque string.
"wks_01k6a2r9s8x7c2dvq3m5n6p4ab"
Defaults to the URL's host.
"Acme production"
The public HTTPS URL events are sent to.
"https://api.acme.com/meetingkit/webhooks"
The events it receives, named as its api_version names them. * is every event.
["meeting.finished", "bot.summary_ready"]
Whether it receives events.
enabled: receives events.disabled: receives nothing; disabling cancels its pending deliveries.
enabled, disabled The version its events are named and shaped at.
"2026-10-09"
Your own key-value pairs, for your ids and context. MeetingKit stores them, returns them on the object and in every webhook that carries it, and never acts on them. Up to 50 keys of up to 40 characters (no square brackets), values up to 500 characters. See metadata.
Show child attributes
Show child attributes
{ "gurusup_user_id": "usr_8812" }
When it was created, in ISO 8601.
When it last changed, in ISO 8601.