Download OpenAPI specification:
See usage on GitHub.
Authentication
Authenticate every request with your personal API key. Contact the sales team to get one.
Recommended: X-API-KEY header
Send the key in the X-API-KEY HTTP header. This is the preferred method and
works on every endpoint:
X-API-KEY: YOUR_API_KEY
Deprecated: api_key in the request body
Passing the key as an api_key field in the request body (used by
POST /api/record-meeting and POST /api/video) is deprecated. It still
works for backward compatibility, but will be removed in a future version —
please migrate to the X-API-KEY header.
Webhooks
Instead of polling GET /api/meeting/status, pass an optional webhook_url
(plus an optional webhook_secret, 16-128 chars) when creating a meeting via
POST /api/record-meeting or POST /api/video. When processing finishes,
mymeet sends a POST notification to your URL and you fetch the report with
GET /api/video/report as usual.
Step 0 — prepare an endpoint. Expose an HTTPS endpoint on a public address
that accepts POST with a JSON body and responds 2xx quickly (under 10s).
Private/internal addresses (localhost, 10.x, 192.168.x, cloud metadata,
docker hostnames) are rejected with 400. Minimal FastAPI receiver
(pip install fastapi uvicorn, run: uvicorn receiver:app):
import hashlib, hmac, time
from fastapi import FastAPI, Request, Response
app = FastAPI()
SECRET = "YOUR_WEBHOOK_SECRET" # the same value you passed as webhook_secret
@app.post("/mymeet-webhook")
async def hook(request: Request):
raw_body = await request.body()
ts = request.headers.get("x-mymeet-timestamp", "")
signature = request.headers.get("x-mymeet-signature", "")
expected = "sha256=" + hmac.new(
SECRET.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected):
return Response("bad signature", status_code=401)
if abs(time.time() - int(ts)) > 300: # anti-replay: reject timestamps older than 5 min
return Response("stale timestamp", status_code=401)
event = await request.json()
print(event["event"], event["meeting_id"], event["data"])
return Response(status_code=200)
Step 1 — pass the URL when creating a meeting (see code samples of both
endpoints): webhook_url + optional webhook_secret.
Step 2 — receive notifications. Two events are sent:
meeting.completed — the report is ready:
POST {webhook_url}
Content-Type: application/json
User-Agent: mymeet-webhook/1.0
X-Mymeet-Event: meeting.completed
X-Mymeet-Delivery: 0b0e9a3e-8b0e-4a52-9c8e-2f6f3f1c2d4e
X-Mymeet-Timestamp: 1783425600
X-Mymeet-Signature: sha256=<hex> (only when webhook_secret is set)
{"event": "meeting.completed", "meeting_id": "...",
"timestamp": "2026-07-07T12:00:00Z",
"data": {"title": "Daily sync", "is_transcript_empty": false,
"report_url": "https://backend.mymeet.ai/api/video/report?meeting_id=..."}}
meeting.failed — the bot could not record the meeting, or processing
failed. Sent with the same headers as meeting.completed. data contains
a short reason string: the recording-failure reason reported by the bot
when there is one (the same value GET /api/meeting/status shows for such
meetings), or a generic Recording failed / Processing failed /
Limit is reached (the workspace ran out of minutes mid-processing):
{"event": "meeting.failed", "meeting_id": "...",
"timestamp": "2026-07-07T12:00:00Z",
"data": {"reason": "Recording failed"}}
Step 3 — verify the signature (when you set webhook_secret):
X-Mymeet-Signature = "sha256=" + hex(HMAC_SHA256(webhook_secret, "{X-Mymeet-Timestamp}.{raw_request_body}")) — see the receiver above; always
compare with hmac.compare_digest and reject stale timestamps.
Step 4 — fetch the report. On meeting.completed, call the report_url
from the payload (it is GET /api/video/report?meeting_id=...) with your
API key.
Delivery & retries. Timeout 10s; any 2xx counts as delivered. On
connection errors, timeouts, 5xx, 408 or 429 mymeet retries up to 5
times (~1m, 5m, 15m, 1h, 3h, with jitter); other 4xx are not retried.
Delivery is at-least-once: after a manual restart of a failed meeting
you may receive meeting.failed and later meeting.completed — deduplicate
by meeting_id + event. Webhooks are not available for cron schedules
yet (400). Recordings longer than ~3 hours are split into parts on
processing; the webhook covers the original meeting (the first part)
only — additional parts are created as separate meetings, same as they
appear to status polling.
Record online meeting Google meet, Zoom, Yandex Telemost, SberJazz, TrueConf, Konturtalk, MSteams, Jitsi
| api_key | string <string> Deprecated Deprecated. Use the |
| link required | string <string> Meeting url |
| meeting_password | string <string> Meeting password (optional) |
| cron | string <string> UTC DateTime of meeting in cron format. See this link. Leave it empty to post NOW request |
| participants | string list of emails to send followup |
| local_date_time required | string <date-time> Local DateTime of meeting |
| title required | string Any title of your meeting. It will be the name of report |
| source required | string Enum: "gmeet" "zoom" "yandextelemost" "sberjazz" "trueconf" "konturtalk" "msteams" "jitsi" |
| template_name required | string (Templates) Enum: "default-meeting" "sales-meeting" "sales-coaching" "hr-interview" "research-interview" "team-sync" "article" "lecture-notes" "one-to-one" "protocol" "medicine" Template type for meeting processing. Defines the structure and style of output |
| webhook_url | string <= 2048 characters Optional. Public HTTPS URL that receives meeting.completed / meeting.failed notifications when processing finishes (see the Webhooks section). Not compatible with cron (400). |
| webhook_secret | string [ 16 .. 128 ] characters Optional. When set, every notification is signed with X-Mymeet-Signature (HMAC-SHA256, see Webhooks section). Requires webhook_url. |
{- "api_key": "string",
- "meeting_password": "string",
- "cron": "30 12 25 4 *",
- "participants": "example1@example.com, example2@examole.com",
- "local_date_time": "2026-04-25T15:30:00+03:00",
- "title": "Daily sync",
- "source": "gmeet",
- "template_name": "default-meeting",
- "webhook_secret": "stringstringstri"
}Upload an audio or video file in zero-based data chunks, then send one
empty finalize marker. chunk_total includes that marker. For reliable
retries, keep id stable for the recording and generate a new
upload_session_id for every full upload attempt. Supplying
expected_file_size and expected_sha256 enables end-to-end integrity
validation before a meeting is created.
Uploads that send data in the final request (chunk_total = number of
data chunks, no empty marker) are also supported.
| api_key | string <string> Deprecated Deprecated. Use the |
| chunk_number required | integer >= 0 Zero-based chunk index. The final index is an empty marker. |
| chunk_total required | integer [ 1 .. 10000 ] Preferred protocol: number of data chunks plus one empty finalize marker. In-band-final uploads (data in the last request) may pass just the data-chunk count; a single-request upload uses chunk_number=0 with chunk_total=1. |
| id required | string <uuid> Unique file id. Use uuid for this |
| filename required | string File name with extension |
| upload_session_id | string <= 128 characters ^[A-Za-z0-9][A-Za-z0-9._-]*$ Optional: unique id for this full upload attempt. Without it the
server tracks one implicit attempt per |
| expected_file_size | integer >= 1 Optional byte size of the complete source file. |
| expected_sha256 | string^[A-Fa-f0-9]{64}$ Optional SHA-256 digest of the complete source file. |
| error_format | string Value: "json" Return machine-readable JSON for upload protocol errors. |
| localTime | string <date-time> String local datetime |
| file required | string <binary> Bytes of current chunk |
| title | string Meeting title |
| webhook_url | string <= 2048 characters Optional. Public HTTPS URL that receives meeting.completed / meeting.failed notifications when processing finishes (see the Webhooks section). Send with the chunks (like title). Available only with API-key authorization. |
| webhook_secret | string [ 16 .. 128 ] characters Optional. When set, every notification is signed with X-Mymeet-Signature (HMAC-SHA256, see Webhooks section). Requires webhook_url. |
| template_name required | string (Templates) Enum: "default-meeting" "sales-meeting" "sales-coaching" "hr-interview" "research-interview" "team-sync" "article" "lecture-notes" "one-to-one" "protocol" "medicine" Template type for meeting processing. Defines the structure and style of output |
| speakers_number | integer >= 0 Default: 0 Number of speakers in the recording. 0 - auto |
| meeting_id | string <uuid> Unique meeting identifier. Auto-generated if not provided |
import uuid import os import math import requests API_KEY = "YOUR_API_KEY" headers = {'X-API-KEY': API_KEY} file_path = "PATH_TO_FILE" file_id = str(uuid.uuid4()) file_name = os.path.basename(file_path) file_size = os.path.getsize(file_path) chunk_size = 20 * 1024 * 1024 # 20 MB per data chunk data_chunks = max(1, math.ceil(file_size / chunk_size)) chunk_total = data_chunks + 1 # + one empty finalize marker common = { 'id': file_id, 'chunk_total': chunk_total, 'filename': file_name, 'localTime': '2026-04-25T15:30:00+03:00', 'template_name': 'default', # Required by schema 'title': 'Meeting Upload', # Optional 'webhook_url': 'https://example.com/mymeet-webhook', # optional: get notified when the report is ready 'webhook_secret': 'YOUR_WEBHOOK_SECRET_16_128', # optional: sign notifications # Optional retry/integrity fields: # 'upload_session_id': str(uuid.uuid4()), # new value per upload attempt # 'expected_file_size': file_size, } with open(file_path, 'rb') as f: for chunk_number in range(data_chunks): # zero-based data chunks chunk = f.read(chunk_size) data = dict(common, chunk_number=chunk_number) files = {'file': (file_name, chunk, 'application/octet-stream')} response = requests.post("https://backend.mymeet.ai/api/video", data=data, files=files, headers=headers) response.raise_for_status() print(f"Chunk {chunk_number + 1}/{data_chunks} uploaded.") # Empty finalize marker: the server validates the upload and returns meeting_id data = dict(common, chunk_number=chunk_total - 1) files = {'file': (file_name, b'', 'application/octet-stream')} response = requests.post("https://backend.mymeet.ai/api/video", data=data, files=files, headers=headers) print(response.json()) # {"meeting_id": ..., "user_id": ...}
{- "meeting_id": "string",
- "user_id": "string"
}Returns a paginated list of active meetings for the authenticated workspace.
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| page required | integer <int32> Default: 0 Page index (starts from 0) |
| perPage required | integer <int32> Default: 10 Number of meetings per page |
import requests API_KEY = "YOUR_API_KEY" headers = {'X-API-KEY': API_KEY} params = { 'page': 0, # Page index (starts from 0) 'perPage': 10 # Number of meetings per page } response = requests.get( "https://backend.mymeet.ai/api/workspaces/active/all-meetings", params=params, headers=headers ) if response.status_code == 200: print(response.json()) else: print(f"Error {response.status_code}: {response.text}")
See sample code here.
Pass either meeting_id (single meeting, plain-text response) or
meeting_ids (up to 100 comma-separated ids, JSON response) — when
both are present, meeting_ids wins.
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| meeting_id | string <string> Meeting ID (single-meeting mode, plain-text response) |
| meeting_ids | string <string> Comma-separated list of meeting IDs (batch mode, max 100 per request). Returns a JSON object with a per-id result, so one request replaces up to 100 single-id polls:
For each id the value is either |
import requests API_KEY = "YOUR_API_KEY" MEETING_ID = "YOUR_MEETING_ID" headers = {'X-API-KEY': API_KEY} params = { 'meeting_id': MEETING_ID } response = requests.get( "https://backend.mymeet.ai/api/meeting/status", params=params, headers=headers ) if response.status_code == 200: # Returns status: processing, processed, failed, queued, or new. # For a failed recording: "failed: rejected" or "failed: error" print(f"Status: {response.text}") else: print(f"Error {response.status_code}: {response.text}") # Batch: up to 100 ids in one request (JSON response) params = {'meeting_ids': ",".join(["MEETING_ID_1", "MEETING_ID_2"])} response = requests.get( "https://backend.mymeet.ai/api/meeting/status", params=params, headers=headers ) if response.status_code == 200: # {"statuses": {"MEETING_ID_1": {"status": "processed", "reason": None}, # "MEETING_ID_2": {"error": "not_found"}}} for meeting_id, info in response.json()["statuses"].items(): print(meeting_id, info)
See sample code here.
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| meeting_id required | string <string> Meeting ID |
import requests API_KEY = "YOUR_API_KEY" MEETING_ID = "YOUR_MEETING_ID" headers = {'X-API-KEY': API_KEY} params = { 'meeting_id': MEETING_ID } response = requests.get( "https://backend.mymeet.ai/api/video/report", params=params, headers=headers ) if response.status_code == 200: data = response.json() print(data) else: print(f"Error {response.status_code}: {response.text}")
{ }Download the followup in PDF, Docx, JSON or Markdown format. See sample code here.
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| meeting_id required | string <string> Meeting ID |
| template_name | string (Templates) Enum: "default-meeting" "sales-meeting" "sales-coaching" "hr-interview" "research-interview" "team-sync" "article" "lecture-notes" "one-to-one" "protocol" "medicine" Template type for meeting processing. Defines the structure and style of output |
| format | string <string> Default: "pdf" Enum: "pdf" "md" "json" "docx" |
| timezone | string <string> Example: timezone=UTC |
import requests API_KEY = "YOUR_API_KEY" MEETING_ID = "YOUR_MEETING_ID" file_format = 'pdf' # Available values: pdf, md, json, docx headers = {'X-API-KEY': API_KEY} params = { 'meeting_id': MEETING_ID, 'format': file_format, 'timezone': 'UTC', # Optional #'template_name': 'default' # Optional } response = requests.get( "https://backend.mymeet.ai/api/storage/download", params=params, headers=headers, stream=True ) if response.status_code == 200: # Save binary content to file filename = f"meeting_report.{file_format}" with open(filename, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) print(f"File saved as {filename}") else: print(f"Error {response.status_code}: {response.text}")
See sample code here.
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| meeting_id required | string <string> Meeting ID |
import requests API_KEY = "YOUR_API_KEY" MEETING_ID = "YOUR_MEETING_ID" headers = {'X-API-KEY': API_KEY} params = { 'meeting_id': MEETING_ID } response = requests.delete( "https://backend.mymeet.ai/api/video/report", params=params, headers=headers ) if response.status_code == 200: print("Meeting deleted successfully") else: print(f"Error {response.status_code}: {response.text}")
Generate a new template type for an already processed meeting. Each applied template instance is assigned a unique id on creation, so the same template can be applied multiple times to one meeting without collisions. The new instance id is returned as created_template_id and should be used to address the template afterwards (e.g. when calling PUT /api/meeting/{meetingId}/summary).
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| meeting_id required | string Meeting ID for which to generate new template |
| template_name required | string (Templates) Enum: "default-meeting" "sales-meeting" "sales-coaching" "hr-interview" "research-interview" "team-sync" "article" "lecture-notes" "one-to-one" "protocol" "medicine" Template type for meeting processing. Defines the structure and style of output |
{- "meeting_id": "string",
- "template_name": "default-meeting"
}{- "followup": { },
- "created_template_id": "d6a34448-c8bb-4ec5-8e4a-acbc06c07eee"
}Clear transcript for specific meeting
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| meeting_id required | string Meeting ID for which to clear transcript |
{- "meeting_id": "string"
}Restores previously cleared meeting transcript
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| meeting_id required | string Meeting ID for transcript restoration |
{- "meeting_id": "string"
}{- "followup": { }
}Change meeting title
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| meetingId required | string Meeting ID to update |
| newName required | string New meeting title |
{- "meetingId": "string",
- "newName": "string"
}Update a specific part of a meeting summary. The applied template is addressed by its unique templateId (the id field of an entry in followup_v2.templates, also returned as created_template_id by /api/generate-new-template). Addressing by id — instead of template name — ensures that editing one applied report does not affect other applied reports that share the same template name.
| meetingId required | string Meeting ID |
| api_key | string <string> API key as a query parameter. Optional alternative to the recommended
|
| templateId required | string Unique id of the applied template instance to update. This is the |
| entityName required | string (Entities) Enum: "summary" "summary_agenda" "sales_general" "sales_coach" "hr_summary" "questions_and_answers" "research_insights" "team_sync_agenda" "summary_by_speaker" "workshop-double" "seo-article-double" "one_to_one" "med-anamnesis" "protocol" "template-recommendation" Available entity types in templates |
| newSummaryText required | string New summary text |
{- "templateId": "d6a34448-c8bb-4ec5-8e4a-acbc06c07eee",
- "entityName": "summary",
- "newSummaryText": "string"
}