From 29a3529a121ca160a5e70edf31b468139f0b13c7 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 3 Sep 2026 06:45:27 +0000 Subject: [PATCH] Update OpenAPI specs (v1 + v2) and generated docs - 2026-09-03 06:45:27 [Checksum: 2422d232d479dbb0e2d2b87c63f90d2f987374f899d6b3032ec9c29e0c0beac1] --- .../api-v2/reference/bots/batchCreateBots.mdx | 4 +- .../bots/batchCreateScheduledBots.mdx | 6 +- .../docs/api-v2/reference/bots/createBot.mdx | 4 +- .../reference/bots/createScheduledBot.mdx | 4 +- .../reference/bots/updateScheduledBot.mdx | 4 +- .../reference/calendars/createCalendarBot.mdx | 4 +- .../reference/calendars/updateCalendarBot.mdx | 6 +- .../meet-workspaces/createMeetWorkspace.mdx | 18 +- .../sub-accounts/createSubAccount.mdx | 60 + .../sub-accounts/deleteSubAccount.mdx | 53 + .../sub-accounts/deleteSubAccountWebhook.mdx | 54 + .../reference/sub-accounts/getSubAccount.mdx | 53 + .../sub-accounts/getSubAccountUsage.mdx | 63 + .../sub-accounts/getSubAccountWebhook.mdx | 55 + .../sub-accounts/getSubAccountsUsage.mdx | 52 + .../sub-accounts/listSubAccounts.mdx | 48 + .../sub-accounts/rotateSubAccountKey.mdx | 59 + .../sub-accounts/setSubAccountWebhook.mdx | 65 + .../sub-accounts/updateSubAccount.mdx | 59 + .../webhooks/bot_webhook_documentation.mdx | 8 +- .../webhooks/webhook_documentation.mdx | 8 +- openapi-v2.json | 2390 ++++++++++++++++- openapi.json | 6 +- 23 files changed, 3019 insertions(+), 64 deletions(-) create mode 100644 content/docs/api-v2/reference/sub-accounts/createSubAccount.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/deleteSubAccount.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/deleteSubAccountWebhook.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/getSubAccount.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/getSubAccountUsage.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/getSubAccountWebhook.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/getSubAccountsUsage.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/listSubAccounts.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/rotateSubAccountKey.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/setSubAccountWebhook.mdx create mode 100644 content/docs/api-v2/reference/sub-accounts/updateSubAccount.mdx diff --git a/content/docs/api-v2/reference/bots/batchCreateBots.mdx b/content/docs/api-v2/reference/bots/batchCreateBots.mdx index b9275543..4abb4acc 100644 --- a/content/docs/api-v2/reference/bots/batchCreateBots.mdx +++ b/content/docs/api-v2/reference/bots/batchCreateBots.mdx @@ -12,7 +12,7 @@ _openapi: Processes each bot creation request sequentially (index 0, 1, 2...). Each item is validated and processed independently. If some bots fail to create, the request still returns 201 with a `data` array containing successful creations and an `errors` array containing failures. Each error includes the `index` of the failed item in the original request array. - **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through the same validation and checks as a single bot creation: platform detection, BYOK transcription check, daily bot cap check, token availability check, and deduplication lock acquisition. + **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through the same validation and checks as a single bot creation: platform detection, transcription key availability, daily bot cap check, token availability check, and deduplication lock acquisition. **Partial Success:** The response always has `success: true`, even if all items fail. Check the `errors` array to identify failed items. The `data` array contains successfully created bots with their `bot_id` and preserved `extra` metadata. The `errors` array contains failed items with `index`, `code`, `message`, `details`, and preserved `extra` metadata. @@ -54,7 +54,7 @@ Create multiple bots in a single request with partial success support. Processes each bot creation request sequentially (index 0, 1, 2...). Each item is validated and processed independently. If some bots fail to create, the request still returns 201 with a `data` array containing successful creations and an `errors` array containing failures. Each error includes the `index` of the failed item in the original request array. - **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through the same validation and checks as a single bot creation: platform detection, BYOK transcription check, daily bot cap check, token availability check, and deduplication lock acquisition. + **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through the same validation and checks as a single bot creation: platform detection, transcription key availability, daily bot cap check, token availability check, and deduplication lock acquisition. **Partial Success:** The response always has `success: true`, even if all items fail. Check the `errors` array to identify failed items. The `data` array contains successfully created bots with their `bot_id` and preserved `extra` metadata. The `errors` array contains failed items with `index`, `code`, `message`, `details`, and preserved `extra` metadata. diff --git a/content/docs/api-v2/reference/bots/batchCreateScheduledBots.mdx b/content/docs/api-v2/reference/bots/batchCreateScheduledBots.mdx index d2a2bca4..fcabf083 100644 --- a/content/docs/api-v2/reference/bots/batchCreateScheduledBots.mdx +++ b/content/docs/api-v2/reference/bots/batchCreateScheduledBots.mdx @@ -13,7 +13,7 @@ _openapi: Processes each scheduled bot creation request sequentially. Each item is validated and processed independently. Token reservation and daily bot cap checks are NOT performed at creation time - they are performed when each bot actually joins the meeting. - **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through validation: platform detection, BYOK transcription check, and join time validation. Unlike immediate bot creation, daily bot cap and token availability are not checked at creation time. + **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through validation: platform detection, transcription key availability, and join time validation. Unlike immediate bot creation, daily bot cap and token availability are not checked at creation time. **Partial Success:** The response always has `success: true`, even if all items fail. Check the `errors` array to identify failed items. The `data` array contains successfully scheduled bots with their `bot_id` and preserved `extra` metadata. @@ -22,7 +22,6 @@ _openapi: **Error Scenarios:** - Validation errors: Invalid join time, invalid meeting URL, invalid configuration - Platform detection failures: `INVALID_MEETING_PLATFORM` - - BYOK not enabled: `BYOK_TRANSCRIPTION_NOT_ENABLED_ON_PLAN` - System failures: `BOT_CREATE_FAILED` **Note:** Daily bot cap and token availability are checked when each bot joins, not at creation time. If these checks fail at join time, the bot will transition to `failed` status and send a failure webhook. @@ -59,7 +58,7 @@ Create multiple scheduled bots in a single request with partial success support. Processes each scheduled bot creation request sequentially. Each item is validated and processed independently. Token reservation and daily bot cap checks are NOT performed at creation time - they are performed when each bot actually joins the meeting. - **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through validation: platform detection, BYOK transcription check, and join time validation. Unlike immediate bot creation, daily bot cap and token availability are not checked at creation time. + **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through validation: platform detection, transcription key availability, and join time validation. Unlike immediate bot creation, daily bot cap and token availability are not checked at creation time. **Partial Success:** The response always has `success: true`, even if all items fail. Check the `errors` array to identify failed items. The `data` array contains successfully scheduled bots with their `bot_id` and preserved `extra` metadata. @@ -68,7 +67,6 @@ Create multiple scheduled bots in a single request with partial success support. **Error Scenarios:** - Validation errors: Invalid join time, invalid meeting URL, invalid configuration - Platform detection failures: `INVALID_MEETING_PLATFORM` - - BYOK not enabled: `BYOK_TRANSCRIPTION_NOT_ENABLED_ON_PLAN` - System failures: `BOT_CREATE_FAILED` **Note:** Daily bot cap and token availability are checked when each bot joins, not at creation time. If these checks fail at join time, the bot will transition to `failed` status and send a failure webhook. diff --git a/content/docs/api-v2/reference/bots/createBot.mdx b/content/docs/api-v2/reference/bots/createBot.mdx index f7ddfe62..6e6ade21 100644 --- a/content/docs/api-v2/reference/bots/createBot.mdx +++ b/content/docs/api-v2/reference/bots/createBot.mdx @@ -166,7 +166,7 @@ _openapi: participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard - cap on total recording time (up to 6 hours). + cap on total recording time (up to 12 hours). - content: >- timeout_config.grace_period: The grace period in seconds at the start of the meeting during which no timeout conditions (waiting room, no @@ -183,7 +183,7 @@ _openapi: When null, the default 4-hour internal timeout applies. - Range: 7200–21600 seconds (2–6 hours) + Range: 7200–43200 seconds (2–12 hours) - content: >- timeout_config.no_one_joined_timeout: The timeout in seconds for the bot to wait for participants to join before leaving the meeting. diff --git a/content/docs/api-v2/reference/bots/createScheduledBot.mdx b/content/docs/api-v2/reference/bots/createScheduledBot.mdx index aeae8f05..bce8b95e 100644 --- a/content/docs/api-v2/reference/bots/createScheduledBot.mdx +++ b/content/docs/api-v2/reference/bots/createScheduledBot.mdx @@ -165,7 +165,7 @@ _openapi: participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard - cap on total recording time (up to 6 hours). + cap on total recording time (up to 12 hours). - content: >- timeout_config.grace_period: The grace period in seconds at the start of the meeting during which no timeout conditions (waiting room, no @@ -182,7 +182,7 @@ _openapi: When null, the default 4-hour internal timeout applies. - Range: 7200–21600 seconds (2–6 hours) + Range: 7200–43200 seconds (2–12 hours) - content: >- timeout_config.no_one_joined_timeout: The timeout in seconds for the bot to wait for participants to join before leaving the meeting. diff --git a/content/docs/api-v2/reference/bots/updateScheduledBot.mdx b/content/docs/api-v2/reference/bots/updateScheduledBot.mdx index 36da45c8..c3895a71 100644 --- a/content/docs/api-v2/reference/bots/updateScheduledBot.mdx +++ b/content/docs/api-v2/reference/bots/updateScheduledBot.mdx @@ -176,7 +176,7 @@ _openapi: participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard - cap on total recording time (up to 6 hours). + cap on total recording time (up to 12 hours). - content: >- timeout_config.grace_period: The grace period in seconds at the start of the meeting during which no timeout conditions (waiting room, no @@ -193,7 +193,7 @@ _openapi: When null, the default 4-hour internal timeout applies. - Range: 7200–21600 seconds (2–6 hours) + Range: 7200–43200 seconds (2–12 hours) - content: >- timeout_config.no_one_joined_timeout: The timeout in seconds for the bot to wait for participants to join before leaving the meeting. diff --git a/content/docs/api-v2/reference/calendars/createCalendarBot.mdx b/content/docs/api-v2/reference/calendars/createCalendarBot.mdx index 11cd01e9..a8aefbef 100644 --- a/content/docs/api-v2/reference/calendars/createCalendarBot.mdx +++ b/content/docs/api-v2/reference/calendars/createCalendarBot.mdx @@ -145,7 +145,7 @@ _openapi: participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard - cap on total recording time (up to 6 hours). + cap on total recording time (up to 12 hours). - content: >- timeout_config.grace_period: The grace period in seconds at the start of the meeting during which no timeout conditions (waiting room, no @@ -162,7 +162,7 @@ _openapi: When null, the default 4-hour internal timeout applies. - Range: 7200–21600 seconds (2–6 hours) + Range: 7200–43200 seconds (2–12 hours) - content: >- timeout_config.no_one_joined_timeout: The timeout in seconds for the bot to wait for participants to join before leaving the meeting. diff --git a/content/docs/api-v2/reference/calendars/updateCalendarBot.mdx b/content/docs/api-v2/reference/calendars/updateCalendarBot.mdx index f7e39a85..8866f4b7 100644 --- a/content/docs/api-v2/reference/calendars/updateCalendarBot.mdx +++ b/content/docs/api-v2/reference/calendars/updateCalendarBot.mdx @@ -257,7 +257,7 @@ _openapi: participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard - cap on total recording time (up to 6 hours). + cap on total recording time (up to 12 hours). - content: >- timeout_config.grace_period: The grace period in seconds at the start of the meeting during which no timeout conditions (waiting room, no @@ -274,7 +274,7 @@ _openapi: When null, the default 4-hour internal timeout applies. - Range: 7200–21600 seconds (2–6 hours) + Range: 7200–43200 seconds (2–12 hours) - content: >- timeout_config.no_one_joined_timeout: The timeout in seconds for the bot to wait for participants to join before leaving the meeting. @@ -337,7 +337,7 @@ _openapi: gladia, deepgram, assemblyai, speechmatics, soniox - `api_key`: Your own API key for the provider (BYOK - available on - Pro plans and above) + all plans) - `region`: Provider region (e.g. "eu", "us"). Required for some providers like Speechmatics diff --git a/content/docs/api-v2/reference/meet-workspaces/createMeetWorkspace.mdx b/content/docs/api-v2/reference/meet-workspaces/createMeetWorkspace.mdx index 298be72c..ef42743d 100644 --- a/content/docs/api-v2/reference/meet-workspaces/createMeetWorkspace.mdx +++ b/content/docs/api-v2/reference/meet-workspaces/createMeetWorkspace.mdx @@ -24,11 +24,10 @@ _openapi: **After creation, you must:** 1. Upload the returned `cert_pem` to Google Admin Console → Security → Set up SSO with third-party IdP → Legacy SSO profile. - 2. Set Sign-in URL to `https://api.meetingbaas.com/v2/meet-sso/sign-in` and Sign-out URL to `https://api.meetingbaas.com/v2/meet-sso/sign-out` in the same SSO profile. Enable "Use a domain-specific issuer". Do not assign the profile yet. - 3. Create one or more Workspace users that bots will sign in as. Sign in to each new account in a browser and complete the "Welcome to Workspace" first-run flow before the SSO profile is assigned to it — once SSO applies, the account password stops working and this flow can no longer be completed. Set language to "English (United States)". - 4. Assign the SSO profile to the bot group or organizational unit only (never to all users), now that each bot account has completed its welcome flow. - 5. Add `meet_logins` (one per Workspace user) referencing this `workspace_id`. - 6. Optionally call `POST /v2/meet-workspaces/:workspace_id/verify` to run pre-flight checks. + 2. Set Sign-in URL to `https://api.meetingbaas.com/v2/meet-sso/sign-in` and Sign-out URL to `https://api.meetingbaas.com/v2/meet-sso/sign-out` in the same SSO profile. Enable "Use a domain-specific issuer" and assign the SSO profile to all users. + 3. Create one or more Workspace users that bots will sign in as, complete the "Welcome to Workspace" interactive login for each, and set language to "English (United States)". + 4. Add `meet_logins` (one per Workspace user) referencing this `workspace_id`. + 5. Optionally call `POST /v2/meet-workspaces/:workspace_id/verify` to run pre-flight checks. **Security:** The cert and key are encrypted at rest using AES-256-GCM. `private_key_pem` is never echoed in any response — including subsequent GETs. If you need it back, you must rotate via PATCH. @@ -115,11 +114,10 @@ Create a meet workspace — the parent resource that holds your SAML cert + priv **After creation, you must:** 1. Upload the returned `cert_pem` to Google Admin Console → Security → Set up SSO with third-party IdP → Legacy SSO profile. - 2. Set Sign-in URL to `https://api.meetingbaas.com/v2/meet-sso/sign-in` and Sign-out URL to `https://api.meetingbaas.com/v2/meet-sso/sign-out` in the same SSO profile. Enable "Use a domain-specific issuer". Do not assign the profile yet. - 3. Create one or more Workspace users that bots will sign in as. Sign in to each new account in a browser and complete the "Welcome to Workspace" first-run flow before the SSO profile is assigned to it — once SSO applies, the account password stops working and this flow can no longer be completed. Set language to "English (United States)". - 4. Assign the SSO profile to the bot group or organizational unit only (never to all users), now that each bot account has completed its welcome flow. - 5. Add `meet_logins` (one per Workspace user) referencing this `workspace_id`. - 6. Optionally call `POST /v2/meet-workspaces/:workspace_id/verify` to run pre-flight checks. + 2. Set Sign-in URL to `https://api.meetingbaas.com/v2/meet-sso/sign-in` and Sign-out URL to `https://api.meetingbaas.com/v2/meet-sso/sign-out` in the same SSO profile. Enable "Use a domain-specific issuer" and assign the SSO profile to all users. + 3. Create one or more Workspace users that bots will sign in as, complete the "Welcome to Workspace" interactive login for each, and set language to "English (United States)". + 4. Add `meet_logins` (one per Workspace user) referencing this `workspace_id`. + 5. Optionally call `POST /v2/meet-workspaces/:workspace_id/verify` to run pre-flight checks. **Security:** The cert and key are encrypted at rest using AES-256-GCM. `private_key_pem` is never echoed in any response — including subsequent GETs. If you need it back, you must rotate via PATCH. diff --git a/content/docs/api-v2/reference/sub-accounts/createSubAccount.mdx b/content/docs/api-v2/reference/sub-accounts/createSubAccount.mdx new file mode 100644 index 00000000..55f06560 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/createSubAccount.mdx @@ -0,0 +1,60 @@ +--- +title: Create a sub-account +full: true +_openapi: + method: POST + toc: [] + structuredData: + headings: [] + contents: + - content: >- + Creates a sub-account under your master account and returns its API + key. The key is shown once: store it server-side, keyed to your + customer. + - content: >- + external_id: Your own identifier for this customer, returned as-is on + reads + - content: name + - content: data + - content: 'data.api_key: Shown once; store it now, it cannot be retrieved later' + - content: data.external_id + - content: data.name + - content: data.sub_account_id + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + +Creates a sub-account under your master account and returns its API key. The key is shown once: store it server-side, keyed to your customer. + + diff --git a/content/docs/api-v2/reference/sub-accounts/deleteSubAccount.mdx b/content/docs/api-v2/reference/sub-accounts/deleteSubAccount.mdx new file mode 100644 index 00000000..1cc22ca8 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/deleteSubAccount.mdx @@ -0,0 +1,53 @@ +--- +title: Delete a sub-account +full: true +_openapi: + method: DELETE + toc: [] + structuredData: + headings: [] + contents: + - content: >- + Soft-deletes the sub-account and disables its API keys. Recorded data + follows the normal retention policy. + - content: data + - content: data.deleted + - content: data.sub_account_id + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + +Soft-deletes the sub-account and disables its API keys. Recorded data follows the normal retention policy. + + diff --git a/content/docs/api-v2/reference/sub-accounts/deleteSubAccountWebhook.mdx b/content/docs/api-v2/reference/sub-accounts/deleteSubAccountWebhook.mdx new file mode 100644 index 00000000..865bdb12 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/deleteSubAccountWebhook.mdx @@ -0,0 +1,54 @@ +--- +title: Remove a sub-account's webhook endpoint +full: true +_openapi: + method: DELETE + toc: [] + structuredData: + headings: [] + contents: + - content: data + - content: data.deleted + - content: data.sub_account_id + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + + diff --git a/content/docs/api-v2/reference/sub-accounts/getSubAccount.mdx b/content/docs/api-v2/reference/sub-accounts/getSubAccount.mdx new file mode 100644 index 00000000..70395c61 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/getSubAccount.mdx @@ -0,0 +1,53 @@ +--- +title: Get a sub-account +full: true +_openapi: + method: GET + toc: [] + structuredData: + headings: [] + contents: + - content: data + - content: data.calendar_integrations_limit + - content: data.created_at + - content: data.daily_bot_cap + - content: data.external_id + - content: data.name + - content: data.status + - content: data.sub_account_id + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + + diff --git a/content/docs/api-v2/reference/sub-accounts/getSubAccountUsage.mdx b/content/docs/api-v2/reference/sub-accounts/getSubAccountUsage.mdx new file mode 100644 index 00000000..680d2b53 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/getSubAccountUsage.mdx @@ -0,0 +1,63 @@ +--- +title: Get a sub-account's usage over a period +full: true +_openapi: + method: GET + toc: [] + structuredData: + headings: [] + contents: + - content: >- + Aggregated consumption of the sub-account between start_date + (inclusive) and end_date (exclusive) — the data you invoice your + customer from. Still resolves after you delete the sub-account, so a + closed customer's final period is billable. + - content: data + - content: data.bot_count + - content: data.byok_transcription_tokens + - content: data.duration_seconds + - content: data.end_date + - content: data.recording_tokens + - content: data.refunded_tokens + - content: data.start_date + - content: data.sub_account_id + - content: data.total_tokens + - content: data.transcription_tokens + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + +Aggregated consumption of the sub-account between start_date (inclusive) and end_date (exclusive) — the data you invoice your customer from. Still resolves after you delete the sub-account, so a closed customer's final period is billable. + + diff --git a/content/docs/api-v2/reference/sub-accounts/getSubAccountWebhook.mdx b/content/docs/api-v2/reference/sub-accounts/getSubAccountWebhook.mdx new file mode 100644 index 00000000..526ecaf4 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/getSubAccountWebhook.mdx @@ -0,0 +1,55 @@ +--- +title: Get a sub-account's webhook endpoint +full: true +_openapi: + method: GET + toc: [] + structuredData: + headings: [] + contents: + - content: data + - content: data.created_at + - content: data.sub_account_id + - content: data.url + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + + diff --git a/content/docs/api-v2/reference/sub-accounts/getSubAccountsUsage.mdx b/content/docs/api-v2/reference/sub-accounts/getSubAccountsUsage.mdx new file mode 100644 index 00000000..bbd895a2 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/getSubAccountsUsage.mdx @@ -0,0 +1,52 @@ +--- +title: Get usage for every sub-account over a period +full: true +_openapi: + method: GET + toc: [] + structuredData: + headings: [] + contents: + - content: >- + One row per sub-account, including ones you have deleted — a customer + closed mid-period still has to be invoiced for it. This is the + endpoint to build a billing run on. + - content: data + - content: data.end_date + - content: data.start_date + - content: data.sub_accounts + - content: >- + next_cursor: Pass back as `cursor` to fetch the next page; null when + this is the last page + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + +One row per sub-account, including ones you have deleted — a customer closed mid-period still has to be invoiced for it. This is the endpoint to build a billing run on. + + diff --git a/content/docs/api-v2/reference/sub-accounts/listSubAccounts.mdx b/content/docs/api-v2/reference/sub-accounts/listSubAccounts.mdx new file mode 100644 index 00000000..7b736c76 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/listSubAccounts.mdx @@ -0,0 +1,48 @@ +--- +title: List your sub-accounts +full: true +_openapi: + method: GET + toc: [] + structuredData: + headings: [] + contents: + - content: >- + Paginated with an opaque cursor. There is no limit on how many + sub-accounts you may open — the page size only bounds the response. + - content: data + - content: >- + next_cursor: Pass back as `cursor` to fetch the next page; null when + this is the last page + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + +Paginated with an opaque cursor. There is no limit on how many sub-accounts you may open — the page size only bounds the response. + + diff --git a/content/docs/api-v2/reference/sub-accounts/rotateSubAccountKey.mdx b/content/docs/api-v2/reference/sub-accounts/rotateSubAccountKey.mdx new file mode 100644 index 00000000..5f32bea9 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/rotateSubAccountKey.mdx @@ -0,0 +1,59 @@ +--- +title: Rotate a sub-account's API key +full: true +_openapi: + method: POST + toc: [] + structuredData: + headings: [] + contents: + - content: >- + Mints a new key and permanently revokes all previous keys of the + sub-account. Refused while suspended. + - content: data + - content: 'data.api_key: Shown once; all previous keys are disabled' + - content: data.sub_account_id + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + +Mints a new key and permanently revokes all previous keys of the sub-account. Refused while suspended. + + diff --git a/content/docs/api-v2/reference/sub-accounts/setSubAccountWebhook.mdx b/content/docs/api-v2/reference/sub-accounts/setSubAccountWebhook.mdx new file mode 100644 index 00000000..3c8fbe04 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/setSubAccountWebhook.mdx @@ -0,0 +1,65 @@ +--- +title: Set a sub-account's webhook endpoint +full: true +_openapi: + method: PUT + toc: [] + structuredData: + headings: [] + contents: + - content: >- + Where this sub-account's bot events are delivered. One endpoint per + sub-account: setting a new URL replaces the previous one. Your + customers have no dashboard of their own, so this is the only way to + point their events anywhere. + - content: >- + url: HTTPS endpoint that this sub-account's bot events are delivered + to + - content: data + - content: data.created_at + - content: data.sub_account_id + - content: data.url + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + +Where this sub-account's bot events are delivered. One endpoint per sub-account: setting a new URL replaces the previous one. Your customers have no dashboard of their own, so this is the only way to point their events anywhere. + + diff --git a/content/docs/api-v2/reference/sub-accounts/updateSubAccount.mdx b/content/docs/api-v2/reference/sub-accounts/updateSubAccount.mdx new file mode 100644 index 00000000..4a7c4861 --- /dev/null +++ b/content/docs/api-v2/reference/sub-accounts/updateSubAccount.mdx @@ -0,0 +1,59 @@ +--- +title: Suspend or reactivate a sub-account +full: true +_openapi: + method: PATCH + toc: [] + structuredData: + headings: [] + contents: + - content: >- + calendar_integrations_limit: Calendar connections allowed for this + sub-account; capped at your master account's own limit + - content: >- + daily_bot_cap: Per-day bot limit for this sub-account; capped at your + master account's own limit + - content: >- + status: suspended blocks all bot dispatch and disables every API key + of the sub-account + - content: data + - content: data.calendar_integrations_limit + - content: data.daily_bot_cap + - content: data.status + - content: data.sub_account_id + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'error: Error name' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'retryAfter: Number of seconds to wait before retrying' + - content: 'statusCode: HTTP status code' + - content: success + - content: 'code: Error code for programmatic handling' + - content: 'details: Additional error details (string or null)' + - content: 'error: Human-readable error message' + - content: 'message: Human-readable error message' + - content: 'statusCode: HTTP status code' + - content: success +--- + +{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} + + diff --git a/content/docs/api/reference/webhooks/bot_webhook_documentation.mdx b/content/docs/api/reference/webhooks/bot_webhook_documentation.mdx index 21a6d6d6..b22af109 100644 --- a/content/docs/api/reference/webhooks/bot_webhook_documentation.mdx +++ b/content/docs/api/reference/webhooks/bot_webhook_documentation.mdx @@ -50,8 +50,8 @@ _openapi: } ], \"speakers\": [ - \"John Doe\", - \"Jane Smith\" + \"Jane Smith\", + \"John Doe\" ], \"mp4\": \"https://storage.example.com/recordings/video123.mp4?token=abc\", \"audio\": \"https://storage.example.com/recordings/audio123.wav?token=abc\", @@ -236,8 +236,8 @@ Sent when a bot successfully completes recording a meeting. } ], \"speakers\": [ - \"John Doe\", - \"Jane Smith\" + \"Jane Smith\", + \"John Doe\" ], \"mp4\": \"https://storage.example.com/recordings/video123.mp4?token=abc\", \"audio\": \"https://storage.example.com/recordings/audio123.wav?token=abc\", diff --git a/content/docs/api/reference/webhooks/webhook_documentation.mdx b/content/docs/api/reference/webhooks/webhook_documentation.mdx index 85386183..7516ccb4 100644 --- a/content/docs/api/reference/webhooks/webhook_documentation.mdx +++ b/content/docs/api/reference/webhooks/webhook_documentation.mdx @@ -48,8 +48,8 @@ _openapi: } ], \"speakers\": [ - \"Jane Smith\", - \"John Doe\" + \"John Doe\", + \"Jane Smith\" ], \"mp4\": \"https://storage.example.com/recordings/video123.mp4?token=abc\", \"audio\": \"https://storage.example.com/recordings/audio123.wav?token=abc\", @@ -291,8 +291,8 @@ Sent when a bot successfully completes recording a meeting. Contains full transc } ], \"speakers\": [ - \"Jane Smith\", - \"John Doe\" + \"John Doe\", + \"Jane Smith\" ], \"mp4\": \"https://storage.example.com/recordings/video123.mp4?token=abc\", \"audio\": \"https://storage.example.com/recordings/audio123.wav?token=abc\", diff --git a/openapi-v2.json b/openapi-v2.json index e8458688..4320cbc7 100644 --- a/openapi-v2.json +++ b/openapi-v2.json @@ -4288,6 +4288,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -4432,7 +4433,7 @@ "silence_timeout": 600, "waiting_room_timeout": 600 }, - "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 6 hours).", + "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 12 hours).", "properties": { "grace_period": { "default": 0, @@ -4445,7 +4446,7 @@ "max_recording_duration": { "anyOf": [ { - "maximum": 21600, + "maximum": 43200, "minimum": 7200, "type": "integer" }, @@ -4454,7 +4455,7 @@ } ], "default": null, - "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–21600 seconds (2–6 hours)", + "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–43200 seconds (2–12 hours)", "example": null }, "no_one_joined_timeout": { @@ -4497,6 +4498,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -4984,6 +4986,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -5143,7 +5146,7 @@ "silence_timeout": 600, "waiting_room_timeout": 600 }, - "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 6 hours).", + "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 12 hours).", "properties": { "grace_period": { "default": 0, @@ -5156,7 +5159,7 @@ "max_recording_duration": { "anyOf": [ { - "maximum": 21600, + "maximum": 43200, "minimum": 7200, "type": "integer" }, @@ -5165,7 +5168,7 @@ } ], "default": null, - "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–21600 seconds (2–6 hours)", + "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–43200 seconds (2–12 hours)", "example": null }, "no_one_joined_timeout": { @@ -5216,6 +5219,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -5683,6 +5687,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -5827,7 +5832,7 @@ "silence_timeout": 600, "waiting_room_timeout": 600 }, - "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 6 hours).", + "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 12 hours).", "properties": { "grace_period": { "default": 0, @@ -5840,7 +5845,7 @@ "max_recording_duration": { "anyOf": [ { - "maximum": 21600, + "maximum": 43200, "minimum": 7200, "type": "integer" }, @@ -5849,7 +5854,7 @@ } ], "default": null, - "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–21600 seconds (2–6 hours)", + "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–43200 seconds (2–12 hours)", "example": null }, "no_one_joined_timeout": { @@ -5892,6 +5897,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -13404,6 +13410,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -13556,7 +13563,7 @@ "silence_timeout": 600, "waiting_room_timeout": 600 }, - "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 6 hours).", + "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 12 hours).", "properties": { "grace_period": { "default": 0, @@ -13569,7 +13576,7 @@ "max_recording_duration": { "anyOf": [ { - "maximum": 21600, + "maximum": 43200, "minimum": 7200, "type": "integer" }, @@ -13578,7 +13585,7 @@ } ], "default": null, - "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–21600 seconds (2–6 hours)", + "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–43200 seconds (2–12 hours)", "example": null }, "no_one_joined_timeout": { @@ -13617,7 +13624,7 @@ }, "transcription_config": { "additionalProperties": false, - "description": "The transcription configuration for the bot.\n\nRequired when `transcription_enabled` is `true`. Must not be provided when `transcription_enabled` is `false`.\n\n- `provider`: Speech-to-text provider (default: \"gladia\"). Supported: gladia, deepgram, assemblyai, speechmatics, soniox\n- `api_key`: Your own API key for the provider (BYOK - available on Pro plans and above)\n- `region`: Provider region (e.g. \"eu\", \"us\"). Required for some providers like Speechmatics\n- `custom_params`: Custom parameters for the transcription provider\n\nOmit this field to leave transcription configuration unchanged.", + "description": "The transcription configuration for the bot.\n\nRequired when `transcription_enabled` is `true`. Must not be provided when `transcription_enabled` is `false`.\n\n- `provider`: Speech-to-text provider (default: \"gladia\"). Supported: gladia, deepgram, assemblyai, speechmatics, soniox\n- `api_key`: Your own API key for the provider (BYOK - available on all plans)\n- `region`: Provider region (e.g. \"eu\", \"us\"). Required for some providers like Speechmatics\n- `custom_params`: Custom parameters for the transcription provider\n\nOmit this field to leave transcription configuration unchanged.", "example": { "api_key": null, "custom_params": null, @@ -13628,6 +13635,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -14060,6 +14068,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -14197,7 +14206,7 @@ "silence_timeout": 600, "waiting_room_timeout": 600 }, - "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 6 hours).", + "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 12 hours).", "properties": { "grace_period": { "default": 0, @@ -14210,7 +14219,7 @@ "max_recording_duration": { "anyOf": [ { - "maximum": 21600, + "maximum": 43200, "minimum": 7200, "type": "integer" }, @@ -14219,7 +14228,7 @@ } ], "default": null, - "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–21600 seconds (2–6 hours)", + "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–43200 seconds (2–12 hours)", "example": null }, "no_one_joined_timeout": { @@ -14250,7 +14259,7 @@ "type": "object" }, "transcription_config": { - "description": "The transcription configuration for the bot.\n\nRequired when `transcription_enabled` is `true`. Must not be provided when `transcription_enabled` is `false`.\n\n- `provider`: Speech-to-text provider (default: \"gladia\"). Supported: gladia, deepgram, assemblyai, speechmatics, soniox\n- `api_key`: Your own API key for the provider (BYOK - available on Pro plans and above)\n- `region`: Provider region (e.g. \"eu\", \"us\"). Required for some providers like Speechmatics\n- `custom_params`: Custom parameters for the transcription provider\n\nOmit this field to leave transcription configuration unchanged.", + "description": "The transcription configuration for the bot.\n\nRequired when `transcription_enabled` is `true`. Must not be provided when `transcription_enabled` is `false`.\n\n- `provider`: Speech-to-text provider (default: \"gladia\"). Supported: gladia, deepgram, assemblyai, speechmatics, soniox\n- `api_key`: Your own API key for the provider (BYOK - available on all plans)\n- `region`: Provider region (e.g. \"eu\", \"us\"). Required for some providers like Speechmatics\n- `custom_params`: Custom parameters for the transcription provider\n\nOmit this field to leave transcription configuration unchanged.", "example": { "api_key": null, "custom_params": null, @@ -14261,6 +14270,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -15036,6 +15046,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -15195,7 +15206,7 @@ "silence_timeout": 600, "waiting_room_timeout": 600 }, - "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 6 hours).", + "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 12 hours).", "properties": { "grace_period": { "default": 0, @@ -15208,7 +15219,7 @@ "max_recording_duration": { "anyOf": [ { - "maximum": 21600, + "maximum": 43200, "minimum": 7200, "type": "integer" }, @@ -15217,7 +15228,7 @@ } ], "default": null, - "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–21600 seconds (2–6 hours)", + "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–43200 seconds (2–12 hours)", "example": null }, "no_one_joined_timeout": { @@ -15268,6 +15279,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -15702,6 +15714,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -15846,7 +15859,7 @@ "silence_timeout": 600, "waiting_room_timeout": 600 }, - "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 6 hours).", + "description": "Configuration for automatic meeting exit behavior. For Google Meet and Microsoft Teams, the bot uses waiting_room_timeout to wait in the waiting room, then no_one_joined_timeout to wait for participants when first joining the meeting, and finally switches to silence_timeout monitoring once participants are detected. Zoom only uses waiting_room_timeout. Optional max_recording_duration sets a hard cap on total recording time (up to 12 hours).", "properties": { "grace_period": { "default": 0, @@ -15859,7 +15872,7 @@ "max_recording_duration": { "anyOf": [ { - "maximum": 21600, + "maximum": 43200, "minimum": 7200, "type": "integer" }, @@ -15868,7 +15881,7 @@ } ], "default": null, - "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–21600 seconds (2–6 hours)", + "description": "The maximum recording duration in seconds. When set, the bot will automatically end the recording after this duration regardless of silence or participant activity. When null, the default 4-hour internal timeout applies.\n\nRange: 7200–43200 seconds (2–12 hours)", "example": null }, "no_one_joined_timeout": { @@ -15911,6 +15924,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -16738,7 +16752,7 @@ }, "/v2/bots/batch": { "post": { - "description": "Create multiple bots in a single request with partial success support.\n \n Processes each bot creation request sequentially (index 0, 1, 2...). Each item is validated and processed independently. If some bots fail to create, the request still returns 201 with a `data` array containing successful creations and an `errors` array containing failures. Each error includes the `index` of the failed item in the original request array.\n \n **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through the same validation and checks as a single bot creation: platform detection, BYOK transcription check, daily bot cap check, token availability check, and deduplication lock acquisition.\n \n **Partial Success:** The response always has `success: true`, even if all items fail. Check the `errors` array to identify failed items. The `data` array contains successfully created bots with their `bot_id` and preserved `extra` metadata. The `errors` array contains failed items with `index`, `code`, `message`, `details`, and preserved `extra` metadata.\n \n **Daily Bot Cap:** The daily bot cap is checked per item, not per batch. If the cap is reached mid-batch, subsequent items will fail with `DAILY_BOT_CAP_REACHED` error. The cap is based on bots created in the last 24 hours.\n \n **Token Reservation:** Tokens are reserved individually for each successful bot creation (0.5 tokens per bot). If token availability becomes insufficient mid-batch, subsequent items will fail with `INSUFFICIENT_TOKENS`.\n \n **Error Index Mapping:** Each error includes an `index` field (0-based) that corresponds to the item's position in the request array. Use this to correlate errors with your original request. Validation errors include detailed validation issues in the `details` field.\n \n **Error Isolation:** Each bot creation is processed independently. If one bot creation fails, it does not affect other bots in the batch. Failed items are included in the `errors` array while successful items are in the `data` array.\n \n Returns 201 with partial success response. All items may succeed, all may fail, or any combination. Always check both `data` and `errors` arrays.", + "description": "Create multiple bots in a single request with partial success support.\n \n Processes each bot creation request sequentially (index 0, 1, 2...). Each item is validated and processed independently. If some bots fail to create, the request still returns 201 with a `data` array containing successful creations and an `errors` array containing failures. Each error includes the `index` of the failed item in the original request array.\n \n **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through the same validation and checks as a single bot creation: platform detection, transcription key availability, daily bot cap check, token availability check, and deduplication lock acquisition.\n \n **Partial Success:** The response always has `success: true`, even if all items fail. Check the `errors` array to identify failed items. The `data` array contains successfully created bots with their `bot_id` and preserved `extra` metadata. The `errors` array contains failed items with `index`, `code`, `message`, `details`, and preserved `extra` metadata.\n \n **Daily Bot Cap:** The daily bot cap is checked per item, not per batch. If the cap is reached mid-batch, subsequent items will fail with `DAILY_BOT_CAP_REACHED` error. The cap is based on bots created in the last 24 hours.\n \n **Token Reservation:** Tokens are reserved individually for each successful bot creation (0.5 tokens per bot). If token availability becomes insufficient mid-batch, subsequent items will fail with `INSUFFICIENT_TOKENS`.\n \n **Error Index Mapping:** Each error includes an `index` field (0-based) that corresponds to the item's position in the request array. Use this to correlate errors with your original request. Validation errors include detailed validation issues in the `details` field.\n \n **Error Isolation:** Each bot creation is processed independently. If one bot creation fails, it does not affect other bots in the batch. Failed items are included in the `errors` array while successful items are in the `data` array.\n \n Returns 201 with partial success response. All items may succeed, all may fail, or any combination. Always check both `data` and `errors` arrays.", "operationId": "batchCreateBots", "requestBody": { "content": { @@ -17281,7 +17295,7 @@ }, "/v2/bots/scheduled/batch": { "post": { - "description": "Create multiple scheduled bots in a single request with partial success support.\n \n Processes each scheduled bot creation request sequentially. Each item is validated and processed independently. Token reservation and daily bot cap checks are NOT performed at creation time - they are performed when each bot actually joins the meeting.\n \n **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through validation: platform detection, BYOK transcription check, and join time validation. Unlike immediate bot creation, daily bot cap and token availability are not checked at creation time.\n \n **Partial Success:** The response always has `success: true`, even if all items fail. Check the `errors` array to identify failed items. The `data` array contains successfully scheduled bots with their `bot_id` and preserved `extra` metadata.\n \n **Join Time Validation:** Each scheduled bot's `join_at` time must be in the future (at least 1 minute ahead). If a join time is invalid, that item will fail with a validation error, but other items will continue processing.\n \n **Error Scenarios:** \n - Validation errors: Invalid join time, invalid meeting URL, invalid configuration\n - Platform detection failures: `INVALID_MEETING_PLATFORM`\n - BYOK not enabled: `BYOK_TRANSCRIPTION_NOT_ENABLED_ON_PLAN`\n - System failures: `BOT_CREATE_FAILED`\n \n **Note:** Daily bot cap and token availability are checked when each bot joins, not at creation time. If these checks fail at join time, the bot will transition to `failed` status and send a failure webhook.\n \n Returns 201 with partial success response. All items may succeed, all may fail, or any combination.", + "description": "Create multiple scheduled bots in a single request with partial success support.\n \n Processes each scheduled bot creation request sequentially. Each item is validated and processed independently. Token reservation and daily bot cap checks are NOT performed at creation time - they are performed when each bot actually joins the meeting.\n \n **Processing Order:** Items are processed in the order they appear in the request array. Each item goes through validation: platform detection, transcription key availability, and join time validation. Unlike immediate bot creation, daily bot cap and token availability are not checked at creation time.\n \n **Partial Success:** The response always has `success: true`, even if all items fail. Check the `errors` array to identify failed items. The `data` array contains successfully scheduled bots with their `bot_id` and preserved `extra` metadata.\n \n **Join Time Validation:** Each scheduled bot's `join_at` time must be in the future (at least 1 minute ahead). If a join time is invalid, that item will fail with a validation error, but other items will continue processing.\n \n **Error Scenarios:** \n - Validation errors: Invalid join time, invalid meeting URL, invalid configuration\n - Platform detection failures: `INVALID_MEETING_PLATFORM`\n - System failures: `BOT_CREATE_FAILED`\n \n **Note:** Daily bot cap and token availability are checked when each bot joins, not at creation time. If these checks fail at join time, the bot will transition to `failed` status and send a failure webhook.\n \n Returns 201 with partial success response. All items may succeed, all may fail, or any combination.", "operationId": "batchCreateScheduledBots", "requestBody": { "content": { @@ -18818,6 +18832,7 @@ "api_key": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -23963,7 +23978,7 @@ ] }, "post": { - "description": "Create a meet workspace — the parent resource that holds your SAML cert + private key for one Google Workspace's SSO config.\n\n A meet workspace represents one Google Workspace whose Legacy SSO profile points at our `/v2/meet-sso/*` endpoints. The cert and key on the workspace are shared by every `meet_login` (Workspace user identity) you attach to it, mirroring how Google Workspace stores a single verification certificate per SSO profile.\n\n **Two creation paths, same response shape:**\n\n - **Server-generated keypair** — pass `generate_keypair: true`. The server creates a self-signed RSA-2048 keypair with 10-year validity. Use this if you don't already have a SAML cert and want the simplest setup.\n - **Bring-your-own keypair** — pass `cert_pem` and `private_key_pem` together. Use this if you want to manage your own crypto or already have a cert/key pair you trust.\n\n Mutually exclusive: provide either `generate_keypair: true` OR (`cert_pem` + `private_key_pem`), not both.\n\n **Response always includes `cert_pem`** so you can upload it to Google's Legacy SSO profile in your Workspace admin console. `private_key_pem` is never returned.\n\n **After creation, you must:**\n 1. Upload the returned `cert_pem` to Google Admin Console → Security → Set up SSO with third-party IdP → Legacy SSO profile.\n 2. Set Sign-in URL to `https://api.meetingbaas.com/v2/meet-sso/sign-in` and Sign-out URL to `https://api.meetingbaas.com/v2/meet-sso/sign-out` in the same SSO profile. Enable \"Use a domain-specific issuer\". Do not assign the profile yet.\n 3. Create one or more Workspace users that bots will sign in as. Sign in to each new account in a browser and complete the \"Welcome to Workspace\" first-run flow before the SSO profile is assigned to it — once SSO applies, the account password stops working and this flow can no longer be completed. Set language to \"English (United States)\".\n 4. Assign the SSO profile to the bot group or organizational unit only (never to all users), now that each bot account has completed its welcome flow.\n 5. Add `meet_logins` (one per Workspace user) referencing this `workspace_id`.\n 6. Optionally call `POST /v2/meet-workspaces/:workspace_id/verify` to run pre-flight checks.\n\n **Security:** The cert and key are encrypted at rest using AES-256-GCM. `private_key_pem` is never echoed in any response — including subsequent GETs. If you need it back, you must rotate via PATCH.\n\n **Per-team uniqueness:** Each `domain` may exist at most once per team. Attempting to create a duplicate returns 409.\n\n **Error Scenarios:**\n - `409 Conflict`: A workspace for this `domain` already exists.\n - `422 Unprocessable Entity`: Invalid cert/key (parse failure or modulus mismatch); both `generate_keypair` and `cert_pem` provided; neither provided.", + "description": "Create a meet workspace — the parent resource that holds your SAML cert + private key for one Google Workspace's SSO config.\n\n A meet workspace represents one Google Workspace whose Legacy SSO profile points at our `/v2/meet-sso/*` endpoints. The cert and key on the workspace are shared by every `meet_login` (Workspace user identity) you attach to it, mirroring how Google Workspace stores a single verification certificate per SSO profile.\n\n **Two creation paths, same response shape:**\n\n - **Server-generated keypair** — pass `generate_keypair: true`. The server creates a self-signed RSA-2048 keypair with 10-year validity. Use this if you don't already have a SAML cert and want the simplest setup.\n - **Bring-your-own keypair** — pass `cert_pem` and `private_key_pem` together. Use this if you want to manage your own crypto or already have a cert/key pair you trust.\n\n Mutually exclusive: provide either `generate_keypair: true` OR (`cert_pem` + `private_key_pem`), not both.\n\n **Response always includes `cert_pem`** so you can upload it to Google's Legacy SSO profile in your Workspace admin console. `private_key_pem` is never returned.\n\n **After creation, you must:**\n 1. Upload the returned `cert_pem` to Google Admin Console → Security → Set up SSO with third-party IdP → Legacy SSO profile.\n 2. Set Sign-in URL to `https://api.meetingbaas.com/v2/meet-sso/sign-in` and Sign-out URL to `https://api.meetingbaas.com/v2/meet-sso/sign-out` in the same SSO profile. Enable \"Use a domain-specific issuer\" and assign the SSO profile to all users.\n 3. Create one or more Workspace users that bots will sign in as, complete the \"Welcome to Workspace\" interactive login for each, and set language to \"English (United States)\".\n 4. Add `meet_logins` (one per Workspace user) referencing this `workspace_id`.\n 5. Optionally call `POST /v2/meet-workspaces/:workspace_id/verify` to run pre-flight checks.\n\n **Security:** The cert and key are encrypted at rest using AES-256-GCM. `private_key_pem` is never echoed in any response — including subsequent GETs. If you need it back, you must rotate via PATCH.\n\n **Per-team uniqueness:** Each `domain` may exist at most once per team. Attempting to create a duplicate returns 409.\n\n **Error Scenarios:**\n - `409 Conflict`: A workspace for this `domain` already exists.\n - `422 Unprocessable Entity`: Invalid cert/key (parse failure or modulus mismatch); both `generate_keypair` and `cert_pem` provided; neither provided.", "operationId": "createMeetWorkspace", "requestBody": { "content": { @@ -25777,6 +25792,2329 @@ ] } }, + "/v2/sub_accounts": { + "get": { + "description": "Paginated with an opaque cursor. There is no limit on how many sub-accounts you may open — the page size only bounds the response.", + "operationId": "listSubAccounts", + "parameters": [ + { + "description": "Maximum number of sub-accounts to return (default: 100, max: 250).", + "in": "query", + "name": "limit", + "required": true, + "schema": { + "default": 100, + "exclusiveMinimum": 0, + "maximum": 250, + "type": "integer" + } + }, + { + "description": "Cursor from the previous response's `next_cursor`. Leave as `null` for the first page.", + "in": "query", + "name": "cursor", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "format": "date-time", + "type": "string" + }, + "external_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "status": { + "enum": [ + "active", + "suspended" + ], + "type": "string" + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + }, + "required": [ + "sub_account_id", + "name", + "external_id", + "status", + "created_at" + ], + "type": "object" + }, + "type": "array" + }, + "next_cursor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Pass back as `cursor` to fetch the next page; null when this is the last page" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data", + "next_cursor" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + } + }, + "summary": "List your sub-accounts", + "tags": [ + "Sub-accounts" + ] + }, + "post": { + "description": "Creates a sub-account under your master account and returns its API key. The key is shown once: store it server-side, keyed to your customer.", + "operationId": "createSubAccount", + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "external_id": { + "description": "Your own identifier for this customer, returned as-is on reads", + "maxLength": 255, + "type": "string" + }, + "name": { + "maxLength": 100, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "api_key": { + "description": "Shown once; store it now, it cannot be retrieved later", + "type": "string" + }, + "external_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + }, + "required": [ + "sub_account_id", + "name", + "external_id", + "api_key" + ], + "type": "object" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Conflict - A live sub-account with this external_id already exists under this master account" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + } + }, + "summary": "Create a sub-account", + "tags": [ + "Sub-accounts" + ] + } + }, + "/v2/sub_accounts/usage": { + "get": { + "description": "One row per sub-account, including ones you have deleted — a customer closed mid-period still has to be invoiced for it. This is the endpoint to build a billing run on.", + "operationId": "getSubAccountsUsage", + "parameters": [ + { + "description": "Inclusive ISO date/datetime lower bound", + "in": "query", + "name": "start_date", + "required": true, + "schema": {} + }, + { + "description": "Exclusive ISO date/datetime upper bound", + "in": "query", + "name": "end_date", + "required": true, + "schema": {} + }, + { + "description": "Maximum number of sub-accounts to return (default: 100, max: 250).", + "in": "query", + "name": "limit", + "required": true, + "schema": { + "default": 100, + "exclusiveMinimum": 0, + "maximum": 250, + "type": "integer" + } + }, + { + "description": "Cursor from the previous response's `next_cursor`. Leave as `null` for the first page.", + "in": "query", + "name": "cursor", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "end_date": { + "format": "date-time", + "type": "string" + }, + "start_date": { + "format": "date-time", + "type": "string" + }, + "sub_accounts": { + "items": { + "additionalProperties": false, + "properties": { + "bot_count": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "byok_transcription_tokens": { + "type": "string" + }, + "duration_seconds": { + "type": "string" + }, + "external_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "recording_tokens": { + "type": "string" + }, + "refunded_tokens": { + "type": "string" + }, + "status": { + "enum": [ + "active", + "suspended", + "deleted" + ], + "type": "string" + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + }, + "total_tokens": { + "type": "string" + }, + "transcription_tokens": { + "type": "string" + } + }, + "required": [ + "bot_count", + "total_tokens", + "recording_tokens", + "transcription_tokens", + "byok_transcription_tokens", + "refunded_tokens", + "duration_seconds", + "sub_account_id", + "name", + "external_id", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "start_date", + "end_date", + "sub_accounts" + ], + "type": "object" + }, + "next_cursor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Pass back as `cursor` to fetch the next page; null when this is the last page" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "next_cursor", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + } + }, + "summary": "Get usage for every sub-account over a period", + "tags": [ + "Sub-accounts" + ] + } + }, + "/v2/sub_accounts/{sub_account_id}": { + "delete": { + "description": "Soft-deletes the sub-account and disables its API keys. Recorded data follows the normal retention policy.", + "operationId": "deleteSubAccount", + "parameters": [ + { + "in": "path", + "name": "sub_account_id", + "required": true, + "schema": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "deleted": { + "enum": [ + true + ], + "type": "boolean" + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + }, + "required": [ + "sub_account_id", + "deleted" + ], + "type": "object" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Found - No such sub-account under this master account" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + } + }, + "summary": "Delete a sub-account", + "tags": [ + "Sub-accounts" + ] + }, + "get": { + "operationId": "getSubAccount", + "parameters": [ + { + "in": "path", + "name": "sub_account_id", + "required": true, + "schema": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "calendar_integrations_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "created_at": { + "format": "date-time", + "type": "string" + }, + "daily_bot_cap": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "external_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "status": { + "enum": [ + "active", + "suspended" + ], + "type": "string" + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + }, + "required": [ + "sub_account_id", + "name", + "external_id", + "status", + "created_at", + "daily_bot_cap", + "calendar_integrations_limit" + ], + "type": "object" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Found - No such sub-account under this master account" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + } + }, + "summary": "Get a sub-account", + "tags": [ + "Sub-accounts" + ] + }, + "patch": { + "operationId": "updateSubAccount", + "parameters": [ + { + "in": "path", + "name": "sub_account_id", + "required": true, + "schema": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "calendar_integrations_limit": { + "description": "Calendar connections allowed for this sub-account; capped at your master account's own limit", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "daily_bot_cap": { + "description": "Per-day bot limit for this sub-account; capped at your master account's own limit", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "status": { + "description": "suspended blocks all bot dispatch and disables every API key of the sub-account", + "enum": [ + "active", + "suspended" + ], + "type": "string" + } + }, + "type": "object" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "calendar_integrations_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "daily_bot_cap": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "status": { + "enum": [ + "active", + "suspended" + ], + "type": "string" + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + }, + "required": [ + "sub_account_id", + "status", + "daily_bot_cap", + "calendar_integrations_limit" + ], + "type": "object" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Found - No such sub-account under this master account" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + } + }, + "summary": "Suspend or reactivate a sub-account", + "tags": [ + "Sub-accounts" + ] + } + }, + "/v2/sub_accounts/{sub_account_id}/keys/rotate": { + "post": { + "description": "Mints a new key and permanently revokes all previous keys of the sub-account. Refused while suspended.", + "operationId": "rotateSubAccountKey", + "parameters": [ + { + "in": "path", + "name": "sub_account_id", + "required": true, + "schema": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "api_key": { + "description": "Shown once; all previous keys are disabled", + "type": "string" + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + }, + "required": [ + "sub_account_id", + "api_key" + ], + "type": "object" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Found - No such sub-account under this master account" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Conflict - The sub-account is suspended; reactivate it before rotating its key" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + } + }, + "summary": "Rotate a sub-account's API key", + "tags": [ + "Sub-accounts" + ] + } + }, + "/v2/sub_accounts/{sub_account_id}/usage": { + "get": { + "description": "Aggregated consumption of the sub-account between start_date (inclusive) and end_date (exclusive) — the data you invoice your customer from. Still resolves after you delete the sub-account, so a closed customer's final period is billable.", + "operationId": "getSubAccountUsage", + "parameters": [ + { + "description": "Inclusive ISO date/datetime lower bound", + "in": "query", + "name": "start_date", + "required": true, + "schema": {} + }, + { + "description": "Exclusive ISO date/datetime upper bound", + "in": "query", + "name": "end_date", + "required": true, + "schema": {} + }, + { + "in": "path", + "name": "sub_account_id", + "required": true, + "schema": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "bot_count": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "byok_transcription_tokens": { + "type": "string" + }, + "duration_seconds": { + "type": "string" + }, + "end_date": { + "format": "date-time", + "type": "string" + }, + "recording_tokens": { + "type": "string" + }, + "refunded_tokens": { + "type": "string" + }, + "start_date": { + "format": "date-time", + "type": "string" + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + }, + "total_tokens": { + "type": "string" + }, + "transcription_tokens": { + "type": "string" + } + }, + "required": [ + "sub_account_id", + "start_date", + "end_date", + "bot_count", + "total_tokens", + "recording_tokens", + "transcription_tokens", + "byok_transcription_tokens", + "refunded_tokens", + "duration_seconds" + ], + "type": "object" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Found - No such sub-account under this master account" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + } + }, + "summary": "Get a sub-account's usage over a period", + "tags": [ + "Sub-accounts" + ] + } + }, + "/v2/sub_accounts/{sub_account_id}/webhook": { + "delete": { + "operationId": "deleteSubAccountWebhook", + "parameters": [ + { + "in": "path", + "name": "sub_account_id", + "required": true, + "schema": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "deleted": { + "enum": [ + true + ], + "type": "boolean" + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + }, + "required": [ + "sub_account_id", + "deleted" + ], + "type": "object" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Found - No such sub-account under this master account" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + }, + "501": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Implemented - Managed webhooks are not enabled on this deployment" + } + }, + "summary": "Remove a sub-account's webhook endpoint", + "tags": [ + "Sub-accounts" + ] + }, + "get": { + "operationId": "getSubAccountWebhook", + "parameters": [ + { + "in": "path", + "name": "sub_account_id", + "required": true, + "schema": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "created_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "sub_account_id", + "url", + "created_at" + ], + "type": "object" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Found - No such sub-account under this master account" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + }, + "501": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Implemented - Managed webhooks are not enabled on this deployment" + } + }, + "summary": "Get a sub-account's webhook endpoint", + "tags": [ + "Sub-accounts" + ] + }, + "put": { + "description": "Where this sub-account's bot events are delivered. One endpoint per sub-account: setting a new URL replaces the previous one. Your customers have no dashboard of their own, so this is the only way to point their events anywhere.", + "operationId": "setSubAccountWebhook", + "parameters": [ + { + "in": "path", + "name": "sub_account_id", + "required": true, + "schema": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "url": { + "description": "HTTPS endpoint that this sub-account's bot events are delivered to", + "format": "uri", + "type": "string" + } + }, + "required": [ + "url" + ], + "type": "object" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": false, + "properties": { + "created_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "sub_account_id": { + "format": "uuid", + "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", + "type": "string" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "sub_account_id", + "url", + "created_at" + ], + "type": "object" + }, + "success": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "success", + "data" + ], + "type": "object" + } + } + }, + "description": "Default Response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request - Invalid input or validation error" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Forbidden - The team is not reseller-enabled, is itself a sub-account, or the caller lacks the owner/admin role" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Found - No such sub-account under this master account" + }, + "429": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "description": "Rate Limited - Exceeded rate limit", + "properties": { + "code": { + "description": "Error code for programmatic handling", + "type": "string" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional error details (string or null)" + }, + "error": { + "description": "Human-readable error message", + "type": "string" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable error message" + }, + "retryAfter": { + "description": "Number of seconds to wait before retrying", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "statusCode": { + "description": "HTTP status code", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "success": { + "default": false, + "enum": [ + false + ], + "type": "boolean" + } + }, + "required": [ + "success", + "error", + "code", + "statusCode" + ], + "type": "object" + } + } + }, + "description": "Rate Limited - Exceeded rate limit" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Internal Server Error - Unexpected server error" + }, + "501": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Not Implemented - Managed webhooks are not enabled on this deployment" + } + }, + "summary": "Set a sub-account's webhook endpoint", + "tags": [ + "Sub-accounts" + ] + } + }, "/v2/teams-login/release-session": { "post": { "responses": { diff --git a/openapi.json b/openapi.json index 27baec6e..2e0c435d 100644 --- a/openapi.json +++ b/openapi.json @@ -378,7 +378,7 @@ "Webhooks" ], "summary": "Webhook Events Documentation", - "description": "Meeting BaaS sends webhook events to your configured webhook URL when specific events occur.\n\n## Webhook Event Types\n\n### 1. `complete`\nSent when a bot successfully completes recording a meeting. Contains full transcription data and a link to the recording.\n```json\n{\n \\\"event\\\": \\\"complete\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"event_uuid\\\": \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"transcript\\\": [\n {\n \\\"speaker\\\": \\\"John Doe\\\",\n \\\"offset\\\": 1.5,\n \\\"start_time\\\": 1.5,\n \\\"end_time\\\": 2.4,\n \\\"words\\\": [\n {\n \\\"start\\\": 1.5,\n \\\"end\\\": 1.9,\n \\\"word\\\": \\\"Hello\\\"\n },\n {\n \\\"start\\\": 2.0,\n \\\"end\\\": 2.4,\n \\\"word\\\": \\\"everyone\\\"\n }\n ]\n }\n ],\n \\\"speakers\\\": [\n \\\"Jane Smith\\\",\n \\\"John Doe\\\"\n ],\n \\\"mp4\\\": \\\"https://storage.example.com/recordings/video123.mp4?token=abc\\\",\n \\\"audio\\\": \\\"https://storage.example.com/recordings/audio123.wav?token=abc\\\",\n \\\"event\\\": \\\"complete\\\",\n \\\"extra\\\": {\n \\\"foo\\\": \\\"bar\\\"\n }\n }\n}\n```\n\nThe `complete` event includes:\n- **bot_id**: Unique identifier for the bot that completed recording\n- **event_uuid**: UUID of the calendar event (if this bot was created from an event)\n- **speakers**: A set of speaker names identified in the meeting\n- **transcript**: Full transcript data with speaker identification and word timing\n- **mp4**: URL to the recording file (valid for 24 hours by default)\n- **event**: Event type identifier (\"complete\")\n\n### 2. `failed`\nSent when a bot fails to join or record a meeting. Contains error details.\n```json\n{\n \\\"event\\\": \\\"failed\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"event_uuid\\\": \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"error\\\": \\\"meeting_not_found\\\",\n \\\"message\\\": \\\"Could not join meeting: The meeting ID was not found or has expired\\\",\n \\\"extra\\\": {\n \\\"foo\\\": \\\"bar\\\"\n }\n }\n}\n```\n\nThe `failed` event includes:\n- **bot_id**: Unique identifier for the bot that failed\n- **event_uuid**: UUID of the calendar event (if this bot was created from an event)\n- **error**: Error code identifying the type of failure\n- **message**: Detailed human-readable error message\n\nCommon error types include:\n- `meeting_not_found`: The meeting ID or link was invalid or expired\n- `access_denied`: The bot was denied access to the meeting\n- `authentication_error`: Failed to authenticate with the meeting platform\n- `network_error`: Network connectivity issues during recording\n- `internal_error`: Internal server error\n\n### 3. `calendar.sync_events`\nSent when calendar events are synced. Contains information about which events were updated.\n```json\n{\n \\\"event\\\": \\\"calendar.sync_events\\\",\n \\\"data\\\": {\n \\\"calendar_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"last_updated_ts\\\": \\\"2023-05-01T12:00:00Z\\\",\n \\\"affected_event_uuids\\\": [\n \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"123e4567-e89b-12d3-a456-426614174002\\\"\n ]\n }\n}\n```\n\nThe `calendar.sync_events` event includes:\n- **calendar_id**: UUID of the calendar that was synced\n- **last_updated_ts**: ISO-8601 timestamp of when the sync occurred\n- **affected_event_uuids**: Array of UUIDs for calendar events that were added, updated, or deleted\n\nThis event is triggered when:\n- Calendar data is synced with the external provider (Google, Microsoft)\n- Multiple events may be created, updated, or deleted in a single sync operation\n- Use this event to update your local cache of calendar events\n\n### 4. `transcription_complete`\nSent when transcription is completed separately from recording (e.g., after retranscribing).\n```json\n{\n \\\"event\\\": \\\"transcription_complete\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\"\n }\n}\n```\n\nThe `transcription_complete` event includes:\n- **bot_id**: Unique identifier for the bot with the completed transcription\n\nThis event is sent when:\n- You request a retranscription via the `/bots/retranscribe` endpoint\n- An asynchronous transcription process completes after the recording has ended\n\n## Setting Up Webhooks\n\nYou can configure webhooks in two ways:\n1. **Account-level webhook URL**: Set a default webhook URL for all bots in your account using the `/accounts/webhook_url` endpoint\n2. **Bot-specific webhook URL**: Provide a `webhook_url` parameter when creating a bot with the `/bots` endpoint\n\nYour webhook endpoint must:\n- Accept POST requests with JSON payload\n- Return a 2xx status code to acknowledge receipt\n- Process requests within 10 seconds to avoid timeouts\n- Handle each event type appropriately based on the event type\n\nAll webhook requests include:\n- `x-meeting-baas-api-key` header with your API key for verification\n- `content-type: application/json` header\n- JSON body containing the event details\n\n## Webhook Reliability\n\nIf your endpoint fails to respond or returns an error, the system will attempt to retry the webhook delivery. For critical events, we recommend implementing:\n\n- Idempotency handling to prevent duplicate processing of the same event\n- Proper logging of webhook receipts for audit purposes\n- Asynchronous processing to quickly acknowledge receipt before handling the event data\n\nFor security, always validate the API key in the `x-meeting-baas-api-key` header matches your API key.", + "description": "Meeting BaaS sends webhook events to your configured webhook URL when specific events occur.\n\n## Webhook Event Types\n\n### 1. `complete`\nSent when a bot successfully completes recording a meeting. Contains full transcription data and a link to the recording.\n```json\n{\n \\\"event\\\": \\\"complete\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"event_uuid\\\": \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"transcript\\\": [\n {\n \\\"speaker\\\": \\\"John Doe\\\",\n \\\"offset\\\": 1.5,\n \\\"start_time\\\": 1.5,\n \\\"end_time\\\": 2.4,\n \\\"words\\\": [\n {\n \\\"start\\\": 1.5,\n \\\"end\\\": 1.9,\n \\\"word\\\": \\\"Hello\\\"\n },\n {\n \\\"start\\\": 2.0,\n \\\"end\\\": 2.4,\n \\\"word\\\": \\\"everyone\\\"\n }\n ]\n }\n ],\n \\\"speakers\\\": [\n \\\"John Doe\\\",\n \\\"Jane Smith\\\"\n ],\n \\\"mp4\\\": \\\"https://storage.example.com/recordings/video123.mp4?token=abc\\\",\n \\\"audio\\\": \\\"https://storage.example.com/recordings/audio123.wav?token=abc\\\",\n \\\"event\\\": \\\"complete\\\",\n \\\"extra\\\": {\n \\\"foo\\\": \\\"bar\\\"\n }\n }\n}\n```\n\nThe `complete` event includes:\n- **bot_id**: Unique identifier for the bot that completed recording\n- **event_uuid**: UUID of the calendar event (if this bot was created from an event)\n- **speakers**: A set of speaker names identified in the meeting\n- **transcript**: Full transcript data with speaker identification and word timing\n- **mp4**: URL to the recording file (valid for 24 hours by default)\n- **event**: Event type identifier (\"complete\")\n\n### 2. `failed`\nSent when a bot fails to join or record a meeting. Contains error details.\n```json\n{\n \\\"event\\\": \\\"failed\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"event_uuid\\\": \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"error\\\": \\\"meeting_not_found\\\",\n \\\"message\\\": \\\"Could not join meeting: The meeting ID was not found or has expired\\\",\n \\\"extra\\\": {\n \\\"foo\\\": \\\"bar\\\"\n }\n }\n}\n```\n\nThe `failed` event includes:\n- **bot_id**: Unique identifier for the bot that failed\n- **event_uuid**: UUID of the calendar event (if this bot was created from an event)\n- **error**: Error code identifying the type of failure\n- **message**: Detailed human-readable error message\n\nCommon error types include:\n- `meeting_not_found`: The meeting ID or link was invalid or expired\n- `access_denied`: The bot was denied access to the meeting\n- `authentication_error`: Failed to authenticate with the meeting platform\n- `network_error`: Network connectivity issues during recording\n- `internal_error`: Internal server error\n\n### 3. `calendar.sync_events`\nSent when calendar events are synced. Contains information about which events were updated.\n```json\n{\n \\\"event\\\": \\\"calendar.sync_events\\\",\n \\\"data\\\": {\n \\\"calendar_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"last_updated_ts\\\": \\\"2023-05-01T12:00:00Z\\\",\n \\\"affected_event_uuids\\\": [\n \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"123e4567-e89b-12d3-a456-426614174002\\\"\n ]\n }\n}\n```\n\nThe `calendar.sync_events` event includes:\n- **calendar_id**: UUID of the calendar that was synced\n- **last_updated_ts**: ISO-8601 timestamp of when the sync occurred\n- **affected_event_uuids**: Array of UUIDs for calendar events that were added, updated, or deleted\n\nThis event is triggered when:\n- Calendar data is synced with the external provider (Google, Microsoft)\n- Multiple events may be created, updated, or deleted in a single sync operation\n- Use this event to update your local cache of calendar events\n\n### 4. `transcription_complete`\nSent when transcription is completed separately from recording (e.g., after retranscribing).\n```json\n{\n \\\"event\\\": \\\"transcription_complete\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\"\n }\n}\n```\n\nThe `transcription_complete` event includes:\n- **bot_id**: Unique identifier for the bot with the completed transcription\n\nThis event is sent when:\n- You request a retranscription via the `/bots/retranscribe` endpoint\n- An asynchronous transcription process completes after the recording has ended\n\n## Setting Up Webhooks\n\nYou can configure webhooks in two ways:\n1. **Account-level webhook URL**: Set a default webhook URL for all bots in your account using the `/accounts/webhook_url` endpoint\n2. **Bot-specific webhook URL**: Provide a `webhook_url` parameter when creating a bot with the `/bots` endpoint\n\nYour webhook endpoint must:\n- Accept POST requests with JSON payload\n- Return a 2xx status code to acknowledge receipt\n- Process requests within 10 seconds to avoid timeouts\n- Handle each event type appropriately based on the event type\n\nAll webhook requests include:\n- `x-meeting-baas-api-key` header with your API key for verification\n- `content-type: application/json` header\n- JSON body containing the event details\n\n## Webhook Reliability\n\nIf your endpoint fails to respond or returns an error, the system will attempt to retry the webhook delivery. For critical events, we recommend implementing:\n\n- Idempotency handling to prevent duplicate processing of the same event\n- Proper logging of webhook receipts for audit purposes\n- Asynchronous processing to quickly acknowledge receipt before handling the event data\n\nFor security, always validate the API key in the `x-meeting-baas-api-key` header matches your API key.", "operationId": "webhook_documentation", "responses": { "200": { @@ -398,7 +398,7 @@ "Webhooks" ], "summary": "Bot Webhook Events Documentation", - "description": "Meeting BaaS sends the following webhook events related to bot recordings.\n\n## Bot Webhook Event Types\n\n### 1. `complete`\nSent when a bot successfully completes recording a meeting.\n\n**Payload Structure:**\n```json\n{\n \\\"event\\\": \\\"complete\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"event_uuid\\\": \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"transcript\\\": [\n {\n \\\"speaker\\\": \\\"John Doe\\\",\n \\\"offset\\\": 1.5,\n \\\"start_time\\\": 1.5,\n \\\"end_time\\\": 2.4,\n \\\"words\\\": [\n {\n \\\"start\\\": 1.5,\n \\\"end\\\": 1.9,\n \\\"word\\\": \\\"Hello\\\"\n },\n {\n \\\"start\\\": 2.0,\n \\\"end\\\": 2.4,\n \\\"word\\\": \\\"everyone\\\"\n }\n ]\n }\n ],\n \\\"speakers\\\": [\n \\\"John Doe\\\",\n \\\"Jane Smith\\\"\n ],\n \\\"mp4\\\": \\\"https://storage.example.com/recordings/video123.mp4?token=abc\\\",\n \\\"audio\\\": \\\"https://storage.example.com/recordings/audio123.wav?token=abc\\\",\n \\\"event\\\": \\\"complete\\\",\n \\\"extra\\\": {\n \\\"foo\\\": \\\"bar\\\"\n }\n }\n}\n```\n\n**When it's triggered:**\n- After a bot successfully records and processes a meeting\n- After the recording is uploaded and made available\n- When all processing of the meeting recording is complete\n\n**What to do with it:**\n- Download the MP4 recording for storage in your system\n- Store the transcript data in your database\n- Update meeting status in your application\n- Notify users that the recording is available\n- Use `event_uuid` to correlate with calendar events (if applicable)\n\n### 2. `failed`\nSent when a bot fails to join or record a meeting.\n\n**Payload Structure:**\n```json\n{\n \\\"event\\\": \\\"failed\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"event_uuid\\\": \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"error\\\": \\\"meeting_not_found\\\",\n \\\"message\\\": \\\"Could not join meeting: The meeting ID was not found or has expired\\\",\n \\\"extra\\\": {\n \\\"foo\\\": \\\"bar\\\"\n }\n }\n}\n```\n\n**Common error types:**\n- `meeting_not_found`: The meeting ID or link was invalid or expired\n- `access_denied`: The bot was denied access to the meeting\n- `authentication_error`: Failed to authenticate with the meeting platform\n- `network_error`: Network connectivity issues during recording\n- `internal_error`: Internal server error\n\n**What to do with it:**\n- Log the failure for troubleshooting\n- Notify administrators or users about the failed recording\n- Attempt to reschedule if appropriate\n- Update meeting status in your system\n- Use `event_uuid` to correlate with calendar events (if applicable)\n\n### 3. `transcription_complete`\nSent when transcription is completed separately from recording.\n\n**Payload Structure:**\n```json\n{\n \\\"event\\\": \\\"transcription_complete\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\"\n }\n}\n```\n\n**When it's triggered:**\n- After requesting retranscription via the API\n- When an asynchronous transcription job completes\n- When a higher quality or different language transcription becomes available\n\n**What to do with it:**\n- Update the transcript data in your system\n- Notify users that improved transcription is available\n- Run any post-processing on the new transcript data\n\n## Webhook Usage Tips\n\n- Each event includes the `bot_id` so you can correlate with your internal data\n- The `event_uuid` field is included when the bot was created from a calendar event (null for direct bots or scheduled bots)\n- The complete event includes speaker identification and full transcript data\n- For downloading recordings, the mp4 URL is valid for 24 hours\n- Handle the webhook asynchronously and return 200 OK quickly to prevent timeouts\n\nFor security, always validate the API key in the `x-meeting-baas-api-key` header matches your API key.", + "description": "Meeting BaaS sends the following webhook events related to bot recordings.\n\n## Bot Webhook Event Types\n\n### 1. `complete`\nSent when a bot successfully completes recording a meeting.\n\n**Payload Structure:**\n```json\n{\n \\\"event\\\": \\\"complete\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"event_uuid\\\": \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"transcript\\\": [\n {\n \\\"speaker\\\": \\\"John Doe\\\",\n \\\"offset\\\": 1.5,\n \\\"start_time\\\": 1.5,\n \\\"end_time\\\": 2.4,\n \\\"words\\\": [\n {\n \\\"start\\\": 1.5,\n \\\"end\\\": 1.9,\n \\\"word\\\": \\\"Hello\\\"\n },\n {\n \\\"start\\\": 2.0,\n \\\"end\\\": 2.4,\n \\\"word\\\": \\\"everyone\\\"\n }\n ]\n }\n ],\n \\\"speakers\\\": [\n \\\"Jane Smith\\\",\n \\\"John Doe\\\"\n ],\n \\\"mp4\\\": \\\"https://storage.example.com/recordings/video123.mp4?token=abc\\\",\n \\\"audio\\\": \\\"https://storage.example.com/recordings/audio123.wav?token=abc\\\",\n \\\"event\\\": \\\"complete\\\",\n \\\"extra\\\": {\n \\\"foo\\\": \\\"bar\\\"\n }\n }\n}\n```\n\n**When it's triggered:**\n- After a bot successfully records and processes a meeting\n- After the recording is uploaded and made available\n- When all processing of the meeting recording is complete\n\n**What to do with it:**\n- Download the MP4 recording for storage in your system\n- Store the transcript data in your database\n- Update meeting status in your application\n- Notify users that the recording is available\n- Use `event_uuid` to correlate with calendar events (if applicable)\n\n### 2. `failed`\nSent when a bot fails to join or record a meeting.\n\n**Payload Structure:**\n```json\n{\n \\\"event\\\": \\\"failed\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\",\n \\\"event_uuid\\\": \\\"123e4567-e89b-12d3-a456-426614174001\\\",\n \\\"error\\\": \\\"meeting_not_found\\\",\n \\\"message\\\": \\\"Could not join meeting: The meeting ID was not found or has expired\\\",\n \\\"extra\\\": {\n \\\"foo\\\": \\\"bar\\\"\n }\n }\n}\n```\n\n**Common error types:**\n- `meeting_not_found`: The meeting ID or link was invalid or expired\n- `access_denied`: The bot was denied access to the meeting\n- `authentication_error`: Failed to authenticate with the meeting platform\n- `network_error`: Network connectivity issues during recording\n- `internal_error`: Internal server error\n\n**What to do with it:**\n- Log the failure for troubleshooting\n- Notify administrators or users about the failed recording\n- Attempt to reschedule if appropriate\n- Update meeting status in your system\n- Use `event_uuid` to correlate with calendar events (if applicable)\n\n### 3. `transcription_complete`\nSent when transcription is completed separately from recording.\n\n**Payload Structure:**\n```json\n{\n \\\"event\\\": \\\"transcription_complete\\\",\n \\\"data\\\": {\n \\\"bot_id\\\": \\\"123e4567-e89b-12d3-a456-426614174000\\\"\n }\n}\n```\n\n**When it's triggered:**\n- After requesting retranscription via the API\n- When an asynchronous transcription job completes\n- When a higher quality or different language transcription becomes available\n\n**What to do with it:**\n- Update the transcript data in your system\n- Notify users that improved transcription is available\n- Run any post-processing on the new transcript data\n\n## Webhook Usage Tips\n\n- Each event includes the `bot_id` so you can correlate with your internal data\n- The `event_uuid` field is included when the bot was created from a calendar event (null for direct bots or scheduled bots)\n- The complete event includes speaker identification and full transcript data\n- For downloading recordings, the mp4 URL is valid for 24 hours\n- Handle the webhook asynchronously and return 200 OK quickly to prevent timeouts\n\nFor security, always validate the API key in the `x-meeting-baas-api-key` header matches your API key.", "operationId": "bot_webhook_documentation", "responses": { "200": { @@ -3502,7 +3502,7 @@ }, "last_updated": { "description": "Timestamp of when this data was generated (in ISO-8601 format)\n\nThis field is maintained for backwards compatibility. It is automatically set to the current time when the response is created.", - "default": "2026-05-27T02:27:30.735912107+00:00", + "default": "2026-08-18T09:35:55.189434712+00:00", "type": "string", "format": "date-time" },