Meeting management API reference
Generated from the OpenAPI specification (version 2026-10-01). Base URL: https://app.meetingize.com/api. All requests need Authorization: Bearer <API key or OAuth token>. Try them in the API explorer.
Create a meeting from an audio file or URL
Section titled “Create a meeting from an audio file or URL”POST /v1/meetingsCreates a meeting and starts its processing: transcription with speaker diarization, then the AI meeting report (summary, action items…), then the documents you asked for. This is the only way to send audio to Meetingize.
Input: either multipart/form-data with file (max 2 GB), or application/json with audio_url (public https URL, downloaded by Meetingize). In multipart, tags, participants, document_templates and metadata are JSON strings (tags and templates also accept comma-separated lists).
Options: title, recorded_at (meeting date), language (default auto-detect), recording_type (meeting = several speakers, solo = dictation), participants (names/emails, optionally with the speaker labels they correspond to; never emailed), tags, document_templates (up to 5 tpl_ ids, generated automatically after the report) or persona (its templates, max 5), metadata (your JSON, echoed in jobs and webhooks).
Client: attach the meeting to a client folder (same as the webapp client column) with client_id (cli_..., see GET /clients) or client: {name, email, phone} (an existing client with this name is reused, otherwise it is created; email/phone optional). Changeable with PATCH, filterable with GET /meetings?client=.
transcribe_only: true: only the transcript is produced (no AI report, no documents, cheaper). The meeting is completed as soon as the transcript is ready.
Response (202): the created meeting (status: queued) with its job. Then either poll GET /jobs/{job.id} (or GET /meetings/{id}) every 10 to 30 seconds, or wait for the webhooks: transcription.completed (transcript readable), then processing.completed (report ready, or end of a transcribe_only processing), and document.generated for each requested document. On error: transcription.failed or processing.failed. Typical duration: 2 to 4 minutes per hour of audio.
Parallel processing quota: same rule as the webapp. Your plan allows N simultaneous processings (meetings being processed + documents being generated, webapp and API together; Free 1 by default). Above it the request is refused with 429 parallel_processing_limit and Retry-After: 30; nothing is queued on our side, retry later.
Billing: consumption (audio minutes, LLM tokens) is measured after completion and debited from the monthly API allowance of your plan, then billed on demand if you enabled it (spend cap). If nothing can pay, the request is refused with 402 (insufficient_balance or spend_cap_reached).
Required scope: write:meetings. Supports Idempotency-Key (strongly recommended: a retried upload must not create two meetings).
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | Optional unique key (max 255 characters, a UUID v4 is recommended) that makes the request safe to retry. If a network error leaves you unsure whether the request was received, send it again with the same key: if it was already processed, you get the original response again (header Idempotent-Replayed: true) and nothing is created twice (no duplicate meeting, no double billing). Keys are kept 24 hours per account. Same key with a different body: 422 idempotency_key_reused; same key while the first request is still being processed: 409 idempotency_key_in_use. Example: Idempotency-Key: 6f1c2a3e-9b7d-4c1e-8f2a-0d3b4c5e6f70. |
Request body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Defaults to the AI-generated title, else file name | |
recorded_at | string (date-time) | Meeting date (ISO 8601). Default: now | |
language | string | ISO 639-1 (fr, en, …) or auto (default) | |
recording_type | meeting, solo | meeting (several speakers, diarization, default) or solo (dictation) | |
transcribe_only | boolean | true: transcript only (no AI report, no documents, cheaper) | |
persona | string | Persona id (GET /personas): without document_templates, generates the persona templates (max 5) after the report | |
metadata | object | Your own JSON object (max 4 KB), echoed in jobs and webhooks | |
client_id | string | Existing client (cli_ | |
file | string (binary) | yes | Audio or video file (max 2 GB): mp3, m4a, wav, flac, ogg, webm, mp4… |
tags | string | JSON array or comma-separated list | |
participants | string | JSON array of {name, email, speaker_labels} | |
document_templates | string | JSON array or comma-separated tpl_ ids | |
client | string | JSON object {name, email, phone} or just a client name |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Defaults to the AI-generated title, else file name | |
recorded_at | string (date-time) | Meeting date (ISO 8601). Default: now | |
language | string | ISO 639-1 (fr, en, …) or auto (default) | |
recording_type | meeting, solo | meeting (several speakers, diarization, default) or solo (dictation) | |
transcribe_only | boolean | true: transcript only (no AI report, no documents, cheaper) | |
persona | string | Persona id (GET /personas): without document_templates, generates the persona templates (max 5) after the report | |
metadata | object | Your own JSON object (max 4 KB), echoed in jobs and webhooks | |
client_id | string | Existing client (cli_ | |
audio_url | string (uri) | yes | Public https URL of the audio/video file, downloaded by Meetingize |
tags | array of string | ||
participants | array of object | ||
document_templates | array of string | Templates to generate after the AI report (max 5) | |
client | object | Client found by name or created (alternative to client_id) |
Responses
202:400: Validation error401: Missing or invalid credential402: Insufficient balance or spend cap reached403: Insufficient scope404: Not found (also for resources of other accounts)429: Rate limit (rate_limited) or parallel processing quota (parallel_processing_limit) exceeded; seeRetry-After
Response fields (202)
| Field | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | yes | |
object | string | yes | |
title | string | yes | |
status | draft, queued, processing, completed, failed | yes | draft (no audio yet, webapp only), queued, processing (transcription then AI report), completed (transcript + report ready; transcript only when transcribe_only), failed |
transcribe_only | boolean | yes | Created with transcribe_only=true: no AI report, no documents |
recorded_at | string (date-time) | yes | Date of the meeting (recorded_at at creation, else upload date) |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | yes | |
duration_seconds | integer | null | ||
language | string | null | ||
source | upload, live_recording, text, url, api | null | ||
recording_type | meeting, solo | null | ||
tags | array of string | yes | |
client | object | null | Client folder the meeting belongs to | |
has_transcript | boolean | yes | |
has_summary | boolean | yes | |
web_url | string (uri) | yes | |
summary | object | null | ||
participants | array of object | yes | |
documents | array of object | yes | |
job | object | null | Latest processing job of the meeting when created via the API (null for webapp meetings): what to poll with GET /jobs/{job_id} |
curl -s -X POST "https://app.meetingize.com/api/v1/meetings" \ -H "Authorization: Bearer $MEETINGIZE_API_KEY" \ -H "Content-Type: application/json" \ -d '{}'Update a meeting (title, date, tags, participants)
Section titled “Update a meeting (title, date, tags, participants)”PATCH /v1/meetings/{meeting_id}Partial update; only the fields sent are changed.
title: replaces the title (it then stays fixed even if the AI report is regenerated).recorded_at: meeting date.tags: replaces the whole tag list ([]removes all).client_id/client: attach to an existing client or find/create one by name;client: nulldetaches the meeting from its client.participants:add(name/email/speaker_labels),update(bypar_id, only fields present;speaker_labelsreplaces the participant’s labels),remove(bypar_id). A speaker label belongs to one participant at most: assigning it moves it. Labels must exist in the transcript (SPEAKER_00…). Speaker names then appear in the transcript (speaker_name) and exports. Removing a person the meeting is shared with (webapp sharing) only removes them from the participants, their access is kept.
No email is ever sent by this endpoint. The AI report is not regenerated. Required scope: write:meetings.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
meeting_id | path | string | yes |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
title | string | ||
recorded_at | string (date-time) | ||
tags | array of string | Replaces all tags | |
participants | object | ||
client_id | string | null | Attach to an existing client | |
client | object | null | Find/create by name; null detaches |
Responses
200:400: Validation error401: Missing or invalid credential403: Insufficient scope404: Not found (also for resources of other accounts)429: Rate limit (rate_limited) or parallel processing quota (parallel_processing_limit) exceeded; seeRetry-After
Response fields (200)
| Field | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | yes | |
object | string | yes | |
title | string | yes | |
status | draft, queued, processing, completed, failed | yes | draft (no audio yet, webapp only), queued, processing (transcription then AI report), completed (transcript + report ready; transcript only when transcribe_only), failed |
transcribe_only | boolean | yes | Created with transcribe_only=true: no AI report, no documents |
recorded_at | string (date-time) | yes | Date of the meeting (recorded_at at creation, else upload date) |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | yes | |
duration_seconds | integer | null | ||
language | string | null | ||
source | upload, live_recording, text, url, api | null | ||
recording_type | meeting, solo | null | ||
tags | array of string | yes | |
client | object | null | Client folder the meeting belongs to | |
has_transcript | boolean | yes | |
has_summary | boolean | yes | |
web_url | string (uri) | yes | |
summary | object | null | ||
participants | array of object | yes | |
documents | array of object | yes | |
job | object | null | Latest processing job of the meeting when created via the API (null for webapp meetings): what to poll with GET /jobs/{job_id} |
curl -s -X PATCH "https://app.meetingize.com/api/v1/meetings/<meeting_id>" \ -H "Authorization: Bearer $MEETINGIZE_API_KEY" \ -H "Content-Type: application/json" \ -d '{}'Delete a meeting
Section titled “Delete a meeting”DELETE /v1/meetings/{meeting_id}Deletes the meeting and everything attached (audio, transcript, report, documents), exactly like the webapp. A processing in progress is cancelled. Irreversible. Usage already consumed stays in the ledger and the deleted documents keep counting in the webapp quotas. Required scope: write:meetings.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
meeting_id | path | string | yes |
Responses
204: No response body400: Validation error401: Missing or invalid credential403: Insufficient scope404: Not found (also for resources of other accounts)429: Rate limit (rate_limited) or parallel processing quota (parallel_processing_limit) exceeded; seeRetry-After
curl -s -X DELETE "https://app.meetingize.com/api/v1/meetings/<meeting_id>" \ -H "Authorization: Bearer $MEETINGIZE_API_KEY" \ -H "Content-Type: application/json" \ -d '{}'